salvager: Give back volumes when exiting early
[openafs.git] / src / vol / vol-salvage.c
index 5ce3147..558623b 100644 (file)
@@ -298,6 +298,7 @@ char *tmpdir = NULL;
 static int IsVnodeOrphaned(struct SalvInfo *salvinfo, VnodeId vnode);
 static int AskVolumeSummary(struct SalvInfo *salvinfo,
                             VolumeId singleVolumeNumber);
+static void MaybeAskOnline(struct SalvInfo *salvinfo, VolumeId volumeId);
 
 #ifdef AFS_DEMAND_ATTACH_FS
 static int LockVolume(struct SalvInfo *salvinfo, VolumeId volumeId);
@@ -849,6 +850,11 @@ SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
 
     if (GetInodeSummary(salvinfo, inodeFile, singleVolumeNumber) < 0) {
        OS_CLOSE(inodeFile);
+       if (singleVolumeNumber) {
+           /* the volume group -- let alone the volume -- does not exist,
+            * but we checked it out, so give it back to the fileserver */
+           AskDelete(salvinfo, singleVolumeNumber);
+       }
        return;
     }
     salvinfo->inodeFd = inodeFile;
@@ -857,6 +863,14 @@ SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
     OS_SEEK(salvinfo->inodeFd, 0L, SEEK_SET);
     if (ListInodeOption) {
        PrintInodeList(salvinfo);
+       if (singleVolumeNumber) {
+           /* We've checked out the volume from the fileserver, and we need
+            * to give it back. We don't know if the volume exists or not,
+            * so we don't know whether to AskOnline or not. Try to determine
+            * if the volume exists by trying to read the volume header, and
+            * AskOnline if it is readable. */
+           MaybeAskOnline(salvinfo, singleVolumeNumber);
+       }
        return;
     }
     /* enumerate volumes in the partition.
@@ -936,9 +950,11 @@ SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
        }
 
        if (!foundSVN) {
-           /* singleVolumeNumber generally should always be in the constructed
-            * volumeSummary, but just in case it's not... */
-           AskOnline(salvinfo, singleVolumeNumber);
+           /* If singleVolumeNumber is not in our volumeSummary, it means that
+            * at least one other volume in the VG is on the partition, but the
+            * RW volume is not. We've already AskOffline'd it by now, though,
+            * so make sure we don't still have the volume checked out. */
+           AskDelete(salvinfo, singleVolumeNumber);
        }
 
        for (j = 0; j < salvinfo->nVolumes; j++) {
@@ -4401,6 +4417,19 @@ AskDAFS(void)
     return ret;
 }
 
+static void
+MaybeAskOnline(struct SalvInfo *salvinfo, VolumeId volumeId)
+{
+    struct VolumeDiskHeader diskHdr;
+    int code;
+    code = VReadVolumeDiskHeader(volumeId, salvinfo->fileSysPartition, &diskHdr);
+    if (code) {
+       /* volume probably does not exist; no need to bring back online */
+       return;
+    }
+    AskOnline(salvinfo, volumeId);
+}
+
 void
 AskOnline(struct SalvInfo *salvinfo, VolumeId volumeId)
 {
@@ -4432,10 +4461,12 @@ void
 AskDelete(struct SalvInfo *salvinfo, VolumeId volumeId)
 {
     afs_int32 code, i;
+    SYNC_response res;
 
     for (i = 0; i < 3; i++) {
+       memset(&res, 0, sizeof(res));
        code = FSYNC_VolOp(volumeId, salvinfo->fileSysPartition->name,
-                          FSYNC_VOL_DONE, FSYNC_SALVAGE, NULL);
+                          FSYNC_VOL_DONE, FSYNC_SALVAGE, &res);
 
        if (code == SYNC_OK) {
            break;
@@ -4458,6 +4489,11 @@ AskDelete(struct SalvInfo *salvinfo, VolumeId volumeId)
 #endif
            }
            break;
+       } else if (code == SYNC_FAILED &&
+                    (res.hdr.reason == FSYNC_UNKNOWN_VOLID ||
+                     res.hdr.reason == FSYNC_WRONG_PART)) {
+           /* volume is already effectively 'deleted' */
+           break;
        } else if (i < 2) {
            /* try it again */
            Log("AskOnline:  request for fileserver to delete volume failed; trying again...\n");