DAFS: Log more for VPreAttachVolumeByVp odd states
[openafs.git] / src / vol / volume.c
index a437e53..8d1cdfc 100644 (file)
@@ -479,6 +479,8 @@ VOptDefaults(ProgramType pt, VolumePackageOptions *opts)
     opts->interrupt_rxcall = NULL;
     opts->offline_timeout = -1;
     opts->offline_shutdown_timeout = -1;
+    opts->usage_threshold = 128;
+    opts->usage_rate_limit = 5;
 
 #ifdef FAST_RESTART
     opts->unsafe_attach = 1;
@@ -2147,7 +2149,8 @@ VPreAttachVolumeByVp_r(Error * ec,
         *   - volume is in an error state
         *   - volume is pre-attached
         */
-       Log("VPreattachVolumeByVp_r: volume %u not in quiescent state\n", vid);
+       Log("VPreattachVolumeByVp_r: volume %u not in quiescent state (state %u flags 0x%x)\n",
+           vid, V_attachState(vp), V_attachFlags(vp));
        goto done;
     } else if (vp) {
        /* we're re-attaching a volume; clear out some old state */
@@ -3112,7 +3115,8 @@ attach2(Error * ec, VolId volumeId, char *path, struct DiskPartition64 *partp,
     if (*ec == VNOVOL) {
        /* if the volume doesn't exist, skip straight to 'error' so we don't
         * request a salvage */
-       goto unlocked_error;
+       VOL_LOCK;
+       goto error_notbroken;
     }
 
     if (!*ec) {
@@ -3206,7 +3210,8 @@ attach2(Error * ec, VolId volumeId, char *path, struct DiskPartition64 *partp,
        goto locked_error;
     } else if (*ec) {
        /* volume operation in progress */
-       goto unlocked_error;
+       VOL_LOCK;
+       goto error_notbroken;
     }
 #else /* AFS_DEMAND_ATTACH_FS */
     if (*ec) {
@@ -3405,7 +3410,10 @@ attach2(Error * ec, VolId volumeId, char *path, struct DiskPartition64 *partp,
 
     return vp;
 
+#ifndef AFS_DEMAND_ATTACH_FS
 unlocked_error:
+#endif
+
     VOL_LOCK;
 locked_error:
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -3418,6 +3426,7 @@ locked_error:
        VReleaseVolumeHandles_r(vp);
     }
 
+ error_notbroken:
 #ifdef AFS_DEMAND_ATTACH_FS
     VCheckSalvage(vp);
     if (forcefree) {
@@ -4077,9 +4086,17 @@ GetVolume(Error * ec, Error * client_ec, VolId volumeId, Volume * hint,
            vp = NULL;
            break;
        }
-#endif
 
-#ifdef AFS_DEMAND_ATTACH_FS
+       if (VIsErrorState(V_attachState(vp))) {
+           /* make sure we don't take a vp in VOL_STATE_ERROR state and use
+            * it, or transition it out of that state */
+           if (!*ec) {
+               *ec = VNOVOL;
+           }
+           vp = NULL;
+           break;
+       }
+
        /*
         * this test MUST happen after VAttachVolymeByVp, so vol_op_state is
         * not VolOpRunningUnknown (attach2 would have converted it to Online
@@ -6674,10 +6691,16 @@ VBumpVolumeUsage_r(Volume * vp)
     if (now - V_dayUseDate(vp) > OneDay)
        VAdjustVolumeStatistics_r(vp);
     /*
-     * Save the volume header image to disk after every 128 bumps to dayUse.
+     * Save the volume header image to disk after a threshold of bumps to dayUse,
+     * at most every usage_rate_limit seconds.
      */
-    if ((V_dayUse(vp)++ & 127) == 0) {
+    V_dayUse(vp)++;
+    vp->usage_bumps_outstanding++;
+    if (vp->usage_bumps_outstanding >= vol_opts.usage_threshold
+       && vp->usage_bumps_next_write <= now) {
        Error error;
+       vp->usage_bumps_outstanding = 0;
+       vp->usage_bumps_next_write = now + vol_opts.usage_rate_limit;
        VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT);
     }
 }
@@ -7905,6 +7928,51 @@ VInitVolumeHeaderCache(afs_uint32 howMany)
        ReleaseVolumeHeader(hp++);
 }
 
+/* get a volume header off of the volume header LRU.
+ *
+ * @return volume header
+ *  @retval NULL no usable volume header is available on the LRU
+ *
+ * @pre VOL_LOCK held
+ *
+ * @post for DAFS, if the returned header is associated with a volume, that
+ *       volume is NOT in an exclusive state
+ *
+ * @internal volume package internal use only.
+ */
+#ifdef AFS_DEMAND_ATTACH_FS
+static struct volHeader*
+GetVolHeaderFromLRU(void)
+{
+    struct volHeader *hd = NULL, *qh, *nqh;
+    /* Usually, a volume in an exclusive state will not have its header on
+     * the LRU. However, it is possible for this to occur when a salvage
+     * request is received over FSSYNC, and possibly in other corner cases.
+     * So just skip over headers whose volumes are in an exclusive state. We
+     * could VWaitExclusiveState_r instead, but not waiting is faster and
+     * easier to do */
+    for (queue_Scan(&volume_hdr_LRU, qh, nqh, volHeader)) {
+       if (!qh->back || !VIsExclusiveState(V_attachState(qh->back))) {
+           queue_Remove(qh);
+           hd = qh;
+           break;
+       }
+    }
+    return hd;
+}
+#else /* AFS_DEMAND_ATTACH_FS */
+static struct volHeader*
+GetVolHeaderFromLRU(void)
+{
+    struct volHeader *hd = NULL;
+    if (queue_IsNotEmpty(&volume_hdr_LRU)) {
+       hd = queue_First(&volume_hdr_LRU, volHeader);
+       queue_Remove(hd);
+    }
+    return hd;
+}
+#endif /* !AFS_DEMAND_ATTACH_FS */
+
 /**
  * get a volume header and attach it to the volume object.
  *
@@ -7973,12 +8041,8 @@ GetVolumeHeader(Volume * vp)
             V_attachFlags(vp) &= ~(VOL_HDR_IN_LRU);
 #endif
        } else {
-           /* we need to grab a new element off the LRU */
-           if (queue_IsNotEmpty(&volume_hdr_LRU)) {
-               /* grab an element and pull off of LRU */
-               hd = queue_First(&volume_hdr_LRU, volHeader);
-               queue_Remove(hd);
-           } else {
+           hd = GetVolHeaderFromLRU();
+           if (!hd) {
                /* LRU is empty, so allocate a new volHeader
                 * this is probably indicative of a leak, so let the user know */
                hd = (struct volHeader *)calloc(1, sizeof(struct volHeader));
@@ -7995,8 +8059,8 @@ GetVolumeHeader(Volume * vp)
                 * be sync'd out to disk */
 
 #ifdef AFS_DEMAND_ATTACH_FS
-               /* if hd->back were in an exclusive state, then
-                * its volHeader would not be on the LRU... */
+               /* GetVolHeaderFromLRU had better not give us back a header
+                * with a volume in exclusive state... */
                osi_Assert(!VIsExclusiveState(V_attachState(hd->back)));
 #endif