viced: VNOVOL on deleted volumes
authorAndrew Deason <adeason@sinenomine.net>
Tue, 10 Aug 2010 19:16:39 +0000 (14:16 -0500)
committerDerrick Brashear <shadow@dementia.org>
Thu, 12 Aug 2010 04:26:59 +0000 (21:26 -0700)
When the volserver deletes a volume, the fileserver should respond to
future access to that volume with VNOVOL and not VOFFLINE, since the
volume doesn't exist anymore. Do this in DAFS via a new state,
VOL_STATE_DELETED, and in non-DAFS by just setting specialStatus to
VNOVOL.

In the future we should also make sure the vp's for deleted volumes
get freed after a couple of hours, but not yet.

Change-Id: I6dec3e0a5e9e54f6ad09fad9f2355b513cce3bf6
Reviewed-on: http://gerrit.openafs.org/2533
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/vol/fssync-debug.c
src/vol/fssync-server.c
src/vol/volume.c
src/vol/volume.h
src/vol/volume_inline.h

index 0f4ced9..ec02d31 100644 (file)
@@ -554,6 +554,7 @@ vol_state_to_string(VolState state)
        ENUMCASE(VOL_STATE_VNODE_CLOSE);
        ENUMCASE(VOL_STATE_VNODE_RELEASE);
        ENUMCASE(VOL_STATE_VLRU_ADD);
+       ENUMCASE(VOL_STATE_DELETED);
        ENUMCASE(VOL_STATE_FREED);
     default:
        return "**UNKNOWN**";
index c54ad37..b56eff6 100644 (file)
@@ -1185,10 +1185,8 @@ static afs_int32
 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
 {
     afs_int32 code = SYNC_FAILED;
-#ifdef AFS_DEMAND_ATTACH_FS
     Error error;
     Volume * vp;
-#endif
 
     if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
        res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
@@ -1201,19 +1199,33 @@ FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
     if (vcom->v)
        vcom->v->volumeID = 0;
 
-#ifdef AFS_DEMAND_ATTACH_FS
     vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
     if (vp) {
        if (FSYNC_partMatch(vcom, vp, 1)) {
+#ifdef AFS_DEMAND_ATTACH_FS
            if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
                (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
-               VChangeState_r(vp, VOL_STATE_UNATTACHED);
+
+               /* Change state to DELETED, not UNATTACHED, so clients get
+                * a VNOVOL error when they try to access from now on. */
+
+               VChangeState_r(vp, VOL_STATE_DELETED);
                VDeregisterVolOp_r(vp);
+
+               /* Someday we should free the vp, too, after about 2 hours,
+                * possibly by putting the vp back on the VLRU. */
+
                code = SYNC_OK;
            } else {
                code = SYNC_DENIED;
                res->hdr.reason = FSYNC_BAD_STATE;
            }
+#else /* AFS_DEMAND_ATTACH_FS */
+           if (!vp->specialStatus) {
+               vp->specialStatus = VNOVOL;
+           }
+           code = SYNC_OK;
+#endif /* !AFS_DEMAND_ATTACH_FS */
        } else {
            code = SYNC_OK; /* XXX is this really a good idea? */
            res->hdr.reason = FSYNC_WRONG_PART;
@@ -1221,7 +1233,6 @@ FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
     } else {
        res->hdr.reason = FSYNC_UNKNOWN_VOLID;
     }
-#endif
 
  done:
     return code;
index 2fc88ab..289921c 100644 (file)
@@ -1780,6 +1780,7 @@ ShutdownVolumeWalk_r(struct DiskPartition64 * dp, int pass,
        case 0:
            if ((V_attachState(vp) != VOL_STATE_UNATTACHED) &&
                (V_attachState(vp) != VOL_STATE_ERROR) &&
+               (V_attachState(vp) != VOL_STATE_DELETED) &&
                (V_attachState(vp) != VOL_STATE_PREATTACHED)) {
                break;
            }
@@ -1835,6 +1836,7 @@ VShutdownVolume_r(Volume * vp)
     case VOL_STATE_ERROR:
        VChangeState_r(vp, VOL_STATE_UNATTACHED);
     case VOL_STATE_UNATTACHED:
+    case VOL_STATE_DELETED:
        break;
     case VOL_STATE_GOING_OFFLINE:
     case VOL_STATE_SHUTTING_DOWN:
@@ -2133,7 +2135,8 @@ VPreAttachVolumeByVp_r(Error * ec,
 
     /* check to see if pre-attach already happened */
     if (vp && 
-       (V_attachState(vp) != VOL_STATE_UNATTACHED) && 
+       (V_attachState(vp) != VOL_STATE_UNATTACHED) &&
+       (V_attachState(vp) != VOL_STATE_DELETED) &&
        (V_attachState(vp) != VOL_STATE_PREATTACHED) &&
        !VIsErrorState(V_attachState(vp))) {
        /*
@@ -2285,6 +2288,7 @@ VAttachVolumeByName_r(Error * ec, char *partition, char *name, int mode)
             *   - GOING_OFFLINE
             *   - SALVAGING
             *   - ERROR
+            *   - DELETED
             */
 
            if (vp->specialStatus == VBUSY)
@@ -2317,6 +2321,7 @@ VAttachVolumeByName_r(Error * ec, char *partition, char *name, int mode)
        /* pre-attach volume if it hasn't been done yet */
        if (!vp || 
            (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+           (V_attachState(vp) == VOL_STATE_DELETED) ||
            (V_attachState(vp) == VOL_STATE_ERROR)) {
            svp = vp;
            vp = VPreAttachVolumeByVp_r(ec, partp, vp, volumeId);
@@ -2561,6 +2566,7 @@ VAttachVolumeByVp_r(Error * ec, Volume * vp, int mode)
     /* pre-attach volume if it hasn't been done yet */
     if (!vp || 
        (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+       (V_attachState(vp) == VOL_STATE_DELETED) ||
        (V_attachState(vp) == VOL_STATE_ERROR)) {
        nvp = VPreAttachVolumeByVp_r(ec, partp, vp, volumeId);
        if (*ec) {
@@ -3699,13 +3705,15 @@ GetVolume(Error * ec, Error * client_ec, VolId volumeId, Volume * hint, int nowa
        }
 
        /*
-        * short circuit with VOFFLINE in the following circumstances:
-        *
-        *   - VOL_STATE_UNATTACHED
+        * short circuit with VOFFLINE for VOL_STATE_UNATTACHED and
+        *                    VNOVOL   for VOL_STATE_DELETED
         */
-       if (V_attachState(vp) == VOL_STATE_UNATTACHED) {
+       if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+           (V_attachState(vp) == VOL_STATE_DELETED)) {
           if (vp->specialStatus) {
               *ec = vp->specialStatus;
+          } else if (V_attachState(vp) == VOL_STATE_DELETED) {
+              *ec = VNOVOL;
           } else {
               *ec = VOFFLINE;
           }
@@ -4556,7 +4564,8 @@ VCheckOffline(register Volume * vp)
        assert((V_attachState(vp) != VOL_STATE_ATTACHED) &&
               (V_attachState(vp) != VOL_STATE_FREED) &&
               (V_attachState(vp) != VOL_STATE_PREATTACHED) &&
-              (V_attachState(vp) != VOL_STATE_UNATTACHED));
+              (V_attachState(vp) != VOL_STATE_UNATTACHED) &&
+              (V_attachState(vp) != VOL_STATE_DELETED));
 
        /* valid states:
         *
@@ -7192,6 +7201,7 @@ VSoftDetachVolume_r(Volume * vp, afs_uint32 thresh)
     case VOL_STATE_GOING_OFFLINE:
     case VOL_STATE_SHUTTING_DOWN:
     case VOL_STATE_SALVAGING:
+    case VOL_STATE_DELETED:
        volume_LRU.q[vp->vlru.idx].len--;
 
        /* create and cancel a reservation to
index 426a40a..f7d2712 100644 (file)
@@ -177,9 +177,10 @@ typedef enum {
     VOL_STATE_VNODE_CLOSE       = 17,   /**< volume is busy closing vnodes */
     VOL_STATE_VNODE_RELEASE     = 18,   /**< volume is busy releasing vnodes */
     VOL_STATE_VLRU_ADD          = 19,   /**< volume is busy being added to a VLRU queue */
+    VOL_STATE_DELETED           = 20,   /**< volume has been deleted by the volserver */
     /* please add new states directly above this line */
-    VOL_STATE_FREED             = 20,   /**< debugging aid */
-    VOL_STATE_COUNT             = 21,   /**< total number of valid states */
+    VOL_STATE_FREED             = 21,   /**< debugging aid */
+    VOL_STATE_COUNT             = 22,   /**< total number of valid states */
 } VolState;
 
 /**
index 3049fc3..1ce7baf 100644 (file)
@@ -315,6 +315,7 @@ VIsOfflineState(VolState state)
     case VOL_STATE_UNATTACHED:
     case VOL_STATE_ERROR:
     case VOL_STATE_SALVAGING:
+    case VOL_STATE_DELETED:
        return 1;
     default:
        return 0;