#else
# include <opr/lockstub.h>
#endif
+#include <opr/ffs.h>
#include <afs/afsint.h>
*/
#define VOLUME_HASH_REORDER_CHAIN_THRESH (VOLUME_HASH_REORDER_THRESHOLD / 2)
+/*
+ * The per volume uniquifier is bumped by 200 and and written to disk
+ * every 200 file creates.
+ */
+#define VOLUME_UPDATE_UNIQUIFIER_BUMP 200
+
#include "rx/rx_queue.h"
static void VInitVolumeHash(void);
-#ifndef AFS_HAVE_FFS
-/* This macro is used where an ffs() call does not exist. Was in util/ffs.c */
-ffs(x)
-{
- afs_int32 ffs_i;
- afs_int32 ffs_tmp = x;
- if (ffs_tmp == 0)
- return (-1);
- else
- for (ffs_i = 1;; ffs_i++) {
- if (ffs_tmp & 1)
- return (ffs_i);
- else
- ffs_tmp >>= 1;
- }
-}
-#endif /* !AFS_HAVE_FFS */
-
#ifdef AFS_PTHREAD_ENV
/**
* disk partition queue element
{
struct rx_queue * q = queue_First(&dp->vol_list, rx_queue);
int i = 0;
+ const char *pass_strs[4] = {"{un/pre}attached vols", "vols w/ vol header loaded", "vols w/o vol header loaded", "vols with exclusive state"};
- while (ShutdownVolumeWalk_r(dp, pass, &q))
+ while (ShutdownVolumeWalk_r(dp, pass, &q)) {
i++;
+ if (0 == i%100) {
+ Log("VShutdownByPartition: ... shut down %d volumes on %s in pass %d (%s)\n", i, VPartitionPath(dp), pass, pass_strs[pass]);
+ }
+ }
return i;
}
V_checkoutMode(vp) = mode;
}
- AddVolumeToHashTable(vp, V_id(vp));
+ AddVolumeToHashTable(vp, vp->hashid);
#ifdef AFS_DEMAND_ATTACH_FS
if (VCanUnlockAttached() && (V_attachFlags(vp) & VOL_LOCKED)) {
VUnlockVolume(vp);
#endif
*ec = 0;
- if (programType == fileServer)
- V_uniquifier(vp) =
- (V_inUse(vp) ? V_nextVnodeUnique(vp) +
- 200 : V_nextVnodeUnique(vp));
+ if (programType == fileServer) {
+ if (!V_inUse(vp)) {
+ V_uniquifier(vp) = V_nextVnodeUnique(vp);
+ } else {
+ V_uniquifier(vp) =
+ V_nextVnodeUnique(vp) + VOLUME_UPDATE_UNIQUIFIER_BUMP;
+ if (V_uniquifier(vp) < V_nextVnodeUnique(vp)) {
+ /* uniquifier rolled over; reset the counters */
+ V_nextVnodeUnique(vp) = 2; /* 1 is reserved for the root vnode */
+ V_uniquifier(vp) =
+ V_nextVnodeUnique(vp) + VOLUME_UPDATE_UNIQUIFIER_BUMP;
+ }
+ }
+ }
#ifdef AFS_DEMAND_ATTACH_FS
state_save = VChangeState_r(vp, VOL_STATE_UPDATING);
*ec = VSALVAGE;
code = 1;
}
+ if ((flags & VOL_SALVAGE_NO_OFFLINE)) {
+ /* Here, we free the header for the volume, but make sure to only
+ * do this if VOL_SALVAGE_NO_OFFLINE is specified. The reason for
+ * this requires a bit of explanation.
+ *
+ * Normally, the volume header will be freed when the volume goes
+ * goes offline. However, if VOL_SALVAGE_NO_OFFLINE has been
+ * specified, the volume was in the process of being attached when
+ * we discovered that it needed salvaging. Thus, the volume will
+ * never go offline, since it never went fully online in the first
+ * place. Specifically, we do not call VOfflineForSalvage_r above,
+ * and we never get rid of the volume via VPutVolume_r; the volume
+ * has not been initialized enough for those to work.
+ *
+ * So instead, explicitly free the volume header here. If we do not
+ * do this, we are wasting a header that some other volume could be
+ * using, since the header remains attached to the volume. Also if
+ * we do not free the header here, we end up with a volume where
+ * nUsers == 0, but the volume has a header that is not on the
+ * header LRU. Some code expects that all nUsers == 0 volumes have
+ * their header on the header LRU (or have no header).
+ *
+ * Also note that we must not free the volume header here if
+ * VOL_SALVAGE_NO_OFFLINE is not set. Since, if
+ * VOL_SALVAGE_NO_OFFLINE is not set, someone else may have a
+ * reference to this volume, and they assume they can use the
+ * volume's header. If we free the volume out from under them, they
+ * can easily segfault.
+ */
+ FreeVolumeHeader(vp);
+ }
}
return code;
}
index->bitmapOffset = (afs_uint32) (bp - index->bitmap);
while (*bp == 0xff)
bp++;
- o = ffs(~*bp) - 1; /* ffs is documented in BSTRING(3) */
+ o = opr_ffs(~*bp) - 1;
*bp |= (1 << o);
ret = ((bp - index->bitmap) * 8 + o);
#ifdef AFS_DEMAND_ATTACH_FS
head->len++;
vp->hashid = hashid;
queue_Append(head, vp);
- vp->vnodeHashOffset = VolumeHashOffset_r();
}
/**