Avoid salvager vol header read assert
[openafs.git] / src / vol / vol-salvage.c
index 2f5866c..72f9ecf 100644 (file)
@@ -2716,8 +2716,16 @@ DistilVnodeEssence(VolumeId rwVId, VnodeClass class, Inode ino, Unique * maxu)
            vep->owner = vnode->owner;
            vep->group = vnode->group;
            if (vnode->type == vDirectory) {
-               assert(class == vLarge);
-               vip->inodes[vnodeIndex] = VNDISK_GET_INO(vnode);
+               if (class != vLarge) {
+                   VnodeId vnodeNumber = bitNumberToVnodeNumber(vnodeIndex, class);
+                   vip->nAllocatedVnodes--;
+                   memset(vnode, 0, sizeof(vnode));
+                   IH_IWRITE(vnodeInfo[vSmall].handle,
+                             vnodeIndexOffset(vcp, vnodeNumber),
+                             (char *)&vnode, sizeof(vnode));
+                   VolumeChanged = 1;
+               } else
+                   vip->inodes[vnodeIndex] = VNDISK_GET_INO(vnode);
            }
        }
     }
@@ -3237,6 +3245,61 @@ AskOffline(VolumeId volumeId, char * partition)
        Log("AskOffline:  request for fileserver to take volume offline failed; salvage aborting.\n");
        Abort("Salvage aborted\n");
     }
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    /* set inUse = programType in the volume header. We do this in case
+     * the fileserver restarts/crashes while we are salvaging.
+     * Otherwise, the fileserver could attach the volume again on
+     * startup while we are salvaging, which would be very bad, or
+     * schedule another salvage while we are salvaging, which would be
+     * annoying. */
+    if (!Testing) {
+       int fd;
+       IHandle_t *h;
+       char name[VMAXPATHLEN];
+       struct VolumeHeader header;
+       struct VolumeDiskHeader diskHeader;
+       struct VolumeDiskData volHeader;
+
+       afs_snprintf(name, sizeof(name), "%s/" VFORMAT, fileSysPathName,
+           afs_printable_uint32_lu(volumeId));
+
+       fd = afs_open(name, O_RDONLY);
+       if (fd < 0) {
+           return;
+       }
+       if (read(fd, &diskHeader, sizeof(diskHeader)) != sizeof(diskHeader) ||
+           diskHeader.stamp.magic != VOLUMEHEADERMAGIC) {
+
+           close(fd);
+           return;
+       }
+       close(fd);
+
+       DiskToVolumeHeader(&header, &diskHeader);
+
+       IH_INIT(h, fileSysDevice, header.parent, header.volumeInfo);
+       if (IH_IREAD(h, 0, (char*)&volHeader, sizeof(volHeader)) != sizeof(volHeader) ||
+           volHeader.stamp.magic != VOLUMEINFOMAGIC) {
+
+           IH_RELEASE(h);
+           return;
+       }
+
+       volHeader.inUse = programType;
+
+       /* If we can't re-write the header, bail out and error. We don't
+        * assert when reading the header, since it's possible the
+        * header isn't really there (when there's no data associated
+        * with the volume; we just delete the vol header file in that
+        * case). But if it's there enough that we can read it, but
+        * somehow we cannot write to it to signify we're salvaging it,
+        * we've got a big problem and we cannot continue. */
+       assert(IH_IWRITE(h, 0, (char*)&volHeader, sizeof(volHeader)) == sizeof(volHeader));
+
+       IH_RELEASE(h);
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
 }
 
 void