return 0;
}
-/* Find the link table. This should be associated with the RW volume or, if
- * a RO only site, then the RO volume. For now, be cautious and hunt carefully.
+/* Find the link table. This should be associated with the RW volume, even
+ * if there is only an RO volume at this site.
*/
Inode
FindLinkHandle(struct InodeSummary *isp, int nVols,
for (i = 0; i < nVols; i++) {
ip = allInodes + isp[i].index;
for (j = 0; j < isp[i].nSpecialInodes; j++) {
- if (ip[j].u.special.type == VI_LINKTABLE)
+ if (ip[j].u.special.volumeId == isp->RWvolumeId &&
+ ip[j].u.special.parentId == isp->RWvolumeId &&
+ ip[j].u.special.type == VI_LINKTABLE) {
return ip[j].inodeNumber;
+ }
}
}
return (Inode) - 1;
}
+#ifdef AFS_NAMEI_ENV
+static int
+CheckDupLinktable(struct SalvInfo *salvinfo, struct InodeSummary *isp, struct ViceInodeInfo *ip)
+{
+ afs_ino_str_t stmp;
+ if (ip->u.vnode.vnodeNumber != INODESPECIAL) {
+ /* not a linktable; process as a normal file */
+ return 0;
+ }
+ if (ip->u.special.type != VI_LINKTABLE) {
+ /* not a linktable; process as a normal file */
+ return 0;
+ }
+
+ /* make sure nothing inc/decs it */
+ ip->linkCount = 0;
+
+ if (ip->u.special.volumeId == ip->u.special.parentId) {
+ /* This is a little weird, but shouldn't break anything, and there is
+ * no known way that this can happen; just do nothing, in case deleting
+ * it would screw something up. */
+ Log("Inode %s appears to be a valid linktable for id (%u), but it's not\n",
+ PrintInode(stmp, ip->inodeNumber), ip->u.special.parentId);
+ Log("the linktable for our volume group (%u). This is unusual, since\n",
+ isp->RWvolumeId);
+ Log("there should only be one linktable per volume group. I'm leaving\n");
+ Log("it alone, just to be safe.\n");
+ return -1;
+ }
+
+ Log("Linktable %s appears to be invalid (parentid/volumeid mismatch: %u != %u)\n",
+ PrintInode(stmp, ip->inodeNumber), ip->u.special.parentId, ip->u.special.volumeId);
+ if (Testing) {
+ Log("Would have deleted linktable inode %s\n", PrintInode(stmp, ip->inodeNumber));
+ } else {
+ IHandle_t *tmpH;
+ namei_t ufs_name;
+
+ Log("Deleting linktable inode %s\n", PrintInode(stmp, ip->inodeNumber));
+ IH_INIT(tmpH, salvinfo->fileSysDevice, isp->RWvolumeId, ip->inodeNumber);
+ namei_HandleToName(&ufs_name, tmpH);
+ if (unlink(ufs_name.n_path) < 0) {
+ Log("Error %d unlinking path %s\n", errno, ufs_name.n_path);
+ }
+ }
+
+ return -1;
+}
+#endif
+
int
CreateLinkTable(struct SalvInfo *salvinfo, struct InodeSummary *isp, Inode ino)
{
dec_VGLinkH = ip->linkCount - salvinfo->VGLinkH_cnt;
VGLinkH_p1 = ip->u.param[0];
continue; /* Deal with this last. */
+ } else if (CheckDupLinktable(salvinfo, isp, ip)) {
+ /* Don't touch this inode; CheckDupLinktable has handled it */
+ continue;
}
#endif
if (ip->linkCount != 0 && TraceBadLinkCounts) {