Avoid salvager vol header read assert
[openafs.git] / src / vol / vol-salvage.c
index 91b3d33..72f9ecf 100644 (file)
@@ -86,8 +86,6 @@ Vnodes with 0 inode pointers in RW volumes are now deleted.
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
 
 #ifndef AFS_NT40_ENV
 #include <sys/param.h>
@@ -167,6 +165,7 @@ RCSID
 #include <afs/osi_inode.h>
 #endif
 #include <afs/cmd.h>
+#include <afs/dir.h>
 #include <afs/afsutil.h>
 #include <afs/fileutil.h>
 #include <afs/procmgmt.h>      /* signal(), kill(), wait(), etc. */
@@ -189,6 +188,8 @@ RCSID
 #include "salvage.h"
 #include "volinodes.h"         /* header magic number, etc. stuff */
 #include "vol-salvage.h"
+#include "vol_internal.h"
+
 #ifdef AFS_NT40_ENV
 #include <pthread.h>
 #endif
@@ -1293,7 +1294,7 @@ GetVolumeSummary(VolumeId singleVolumeNumber)
                    || (vsp->header.id == singleVolumeNumber
                        || vsp->header.parent == singleVolumeNumber)) {
                    (void)afs_snprintf(nameShouldBe, sizeof nameShouldBe,
-                                      VFORMAT, afs_cast_uint32(vsp->header.id));
+                                      VFORMAT, afs_printable_uint32_lu(vsp->header.id));
                    if (singleVolumeNumber 
                        && vsp->header.id != singleVolumeNumber)
                        AskOffline(vsp->header.id, fileSysPartition->name);
@@ -1744,7 +1745,7 @@ SalvageVolumeHeaderFile(register struct InodeSummary *isp,
     if (isp->volSummary == NULL) {
        char path[64];
        char headerName[64];
-       (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_cast_uint32(isp->volumeId));
+       (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_printable_uint32_lu(isp->volumeId));
        (void)afs_snprintf(path, sizeof path, "%s/%s", fileSysPath, headerName);
        if (check) {
            Log("No header file for volume %u\n", isp->volumeId);
@@ -1773,7 +1774,7 @@ SalvageVolumeHeaderFile(register struct InodeSummary *isp,
            if (isp->volSummary->fileName) {
                strcpy(headerName, isp->volSummary->fileName);
            } else {
-               (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_cast_uint32(isp->volumeId));
+               (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_printable_uint32_lu(isp->volumeId));
                isp->volSummary->fileName = ToString(headerName);
            }
            (void)afs_snprintf(path, sizeof path, "%s/%s", fileSysPath, headerName);
@@ -2414,9 +2415,10 @@ CopyAndSalvage(register struct DirSummary *dir)
 }
 
 int
-JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
-          Unique unique)
+JudgeEntry(void *dirVal, char *name, afs_int32 vnodeNumber,
+          afs_int32 unique)
 {
+    struct DirSummary *dir = (struct DirSummary *)dirVal;
     struct VnodeEssence *vnodeEssence;
     afs_int32 dirOrphaned, todelete;
 
@@ -2487,7 +2489,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
            Log("dir vnode %u: %s/%s (vnode %u): unique changed from %u to %u %s\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, vnodeEssence->unique, (!todelete ? "" : (Testing ? "-- would have deleted" : "-- deleted")));
        }
        if (!Testing) {
-           ViceFid fid;
+           AFSFid fid;
            fid.Vnode = vnodeNumber;
            fid.Unique = vnodeEssence->unique;
            CopyOnWrite(dir);
@@ -2501,7 +2503,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
 
     if (strcmp(name, ".") == 0) {
        if (dir->vnodeNumber != vnodeNumber || (dir->unique != unique)) {
-           ViceFid fid;
+           AFSFid fid;
            if (!Showmode)
                Log("directory vnode %u.%u: bad '.' entry (was %u.%u); fixed\n", dir->vnodeNumber, dir->unique, vnodeNumber, unique);
            if (!Testing) {
@@ -2518,7 +2520,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
        }
        dir->haveDot = 1;
     } else if (strcmp(name, "..") == 0) {
-       ViceFid pa;
+       AFSFid pa;
        if (dir->parent) {
            struct VnodeEssence *dotdot;
            pa.Vnode = dir->parent;
@@ -2714,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);
            }
        }
     }
@@ -2869,7 +2879,7 @@ SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH)
     afs_int32 v, pv;
     IHandle_t *h;
     afs_sfsize_t nBytes;
-    ViceFid pa;
+    AFSFid pa;
     VnodeId LFVnode, ThisVnode;
     Unique LFUnique, ThisUnique;
     char npath[128];
@@ -2953,7 +2963,7 @@ SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH)
                 * won't be visible there.
                 */
                if (class == vLarge) {
-                   ViceFid pa;
+                   AFSFid pa;
                    DirHandle dh;
 
                    /* Remove and recreate the ".." entry in this orphaned directory */
@@ -3235,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