volser: take RO volume offline during convertROtoRW 40/14340/6
authorMarcio Barbosa <mbarbosa@sinenomine.net>
Thu, 3 Sep 2020 23:57:34 +0000 (23:57 +0000)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 13 Nov 2020 17:33:46 +0000 (12:33 -0500)
The vos convertROtoRW command converts a RO volume into a RW volume.
Unfortunately, the RO volume is not checked out from the fileserver
during this process. As a result, accesses to the volume being converted
can leave volume objects in an inconsistent state.

Moreover, consider the following scenario:

1. Create a volume on host_b and add replicas on host_a and host_b.

$ vos create host_b a vol_1
$ vos addsite host_b a vol_1
$ vos addiste host_a a vol_1

2. Mount the volume:

$ fs mkmount /afs/.mycell/vol_1 vol_1
$ vos release vol_1
$ vos release root.cell

3. Shutdown dafs on host_b:

$ bos shutdown host_b dafs

4. Remove RO reference to host_b from the vldb:

$ vos remsite host_b a vol_1

5. Attach the RO copy by touching it:

$ fs flushall
$ ls /afs/mycell/vol_1

6. Convert RO copy to RW:

$ vos convertROtoRW host_a a vol_1

Notice that FSYNC_com_VolDone fails silently (FSYNC_BAD_STATE), leaving
the volume object for the RO copy set as VOL_STATE_ATTACHED (on success,
this volume should be set as VOL_STATE_DELETED).

7. Add replica on host_a:

$ vos addsite host_a a vol_1

8. Wait until the "inUse" flag of the RO entry is cleared (or force this
to happen by attaching multiple volumes).

9. Release the volume:

$ vos release vol_1

Failed to start transaction on volume 536870922
Volume not attached, does not exist, or not on line
Error in vos release command.
Volume not attached, does not exist, or not on line

Notice that this happens because we cannot mark an attached volume as
destroyed (FSYNC_com_VolDone).

To avoid the problem mentioned above and to prevent accesses to the
volume being converted, take the RO volume offline before converting it
to RW.

Change-Id: Ifd342e1f420dc42e5da49242a7aa70db7d97a884
Reviewed-on: https://gerrit.openafs.org/14340
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>


index 6c4a239..90c7778 100644 (file)
@@ -3002,11 +3002,33 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
                ret = VOLSERVOLBUSY;
                goto done;
+           ret = FSYNC_VolOp(volumeId, pname, FSYNC_VOL_NEEDVOLUME, V_VOLUPD,
+                             NULL);
+           if (ret != SYNC_OK) {
+               Log("SAFSVolConvertROtoRWvolume: Error %ld trying to check out "
+                   "vol %lu part %s.\n", afs_printable_int32_ld(ret),
+                   afs_printable_uint32_lu(volumeId), pname);
+               ret = VOLSERFAILEDOP;
+               goto done;
+           }
            ret = namei_ConvertROtoRWvolume(pname, volumeId);
            ret = inode_ConvertROtoRWvolume(pname, volumeId);
+           if (ret != 0) {
+               Log("SAFSVolConvertROtoRWvolume: Error %ld trying to convert "
+                   "RO vol %lu to RW. The volume may be in an inconsistent or "
+                   "partially converted state; if the volume seems unusable, "
+                   "you can try salvaging it or restoring from another RO "
+                   "copy.\n", afs_printable_int32_ld(ret),
+                   afs_printable_uint32_lu(volumeId));
+               /*
+                * the volume may or may not be usable at this point; let the
+                * fileserver try to attach and decide.
+                */
+               FSYNC_VolOp(volumeId, pname, FSYNC_VOL_ON, 0, NULL);
+           }