Remove DUX/OSF code
[openafs.git] / src / vol / volume.c
index 384f6de..a3b0662 100644 (file)
@@ -36,6 +36,8 @@
 #else
 # include <opr/lockstub.h>
 #endif
+#include <opr/ffs.h>
+#include <opr/jhash.h>
 
 #include <afs/afsint.h>
 
@@ -43,9 +45,6 @@
 
 #ifndef AFS_NT40_ENV
 #if !defined(AFS_SGI_ENV)
-#ifdef AFS_OSF_ENV
-#include <ufs/fs.h>
-#else /* AFS_OSF_ENV */
 #ifdef AFS_VFSINCL_ENV
 #define VFS
 #ifdef AFS_SUN5_ENV
@@ -63,7 +62,6 @@
 #include <sys/fs.h>
 #endif
 #endif /* AFS_VFSINCL_ENV */
-#endif /* AFS_OSF_ENV */
 #endif /* AFS_SGI_ENV */
 #endif /* !AFS_NT40_ENV */
 
@@ -140,10 +138,6 @@ static volatile sig_atomic_t vol_disallow_salvsync = 0;
  */
 static int vol_shutting_down = 0;
 
-#ifdef AFS_OSF_ENV
-extern void *calloc(), *realloc();
-#endif
-
 /* Forward declarations */
 static Volume *attach2(Error * ec, VolumeId volumeId, char *path,
                       struct DiskPartition64 *partp, Volume * vp,
@@ -174,8 +168,6 @@ static int VCheckDetach(Volume * vp);
 static Volume * GetVolume(Error * ec, Error * client_ec, VolumeId volumeId,
                           Volume * hint, const struct timespec *ts);
 
-int LogLevel;                  /* Vice loglevel--not defined as extern so that it will be
-                                * defined when not linked with vice, XXXX */
 ProgramType programType;       /* The type of program using the package */
 static VolumePackageOptions vol_opts;
 
@@ -195,9 +187,11 @@ pthread_t vol_glock_holder = 0;
  * an AVL or splay tree might work a lot better, but we'll just increase
  * the default hash table size for now
  */
-#define DEFAULT_VOLUME_HASH_SIZE 256   /* Must be a power of 2!! */
-#define DEFAULT_VOLUME_HASH_MASK (DEFAULT_VOLUME_HASH_SIZE-1)
-#define VOLUME_HASH(volumeId) (volumeId&(VolumeHashTable.Mask))
+#define DEFAULT_VOLUME_HASH_BITS 10
+#define DEFAULT_VOLUME_HASH_SIZE opr_jhash_size(DEFAULT_VOLUME_HASH_BITS)
+#define DEFAULT_VOLUME_HASH_MASK opr_jhash_mask(DEFAULT_VOLUME_HASH_BITS)
+#define VOLUME_HASH(volumeId) \
+    (opr_jhash_int(volumeId, 0) & VolumeHashTable.Mask)
 
 /*
  * turn volume hash chains into partially ordered lists.
@@ -218,6 +212,12 @@ pthread_t vol_glock_holder = 0;
  */
 #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"
 
 
@@ -231,24 +231,6 @@ VolumeHashTable_t VolumeHashTable = {
 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
@@ -1133,7 +1115,7 @@ VAttachVolumesByPartition(struct DiskPartition64 *diskP, int * nAttached, int *
       (*(vp ? nAttached : nUnattached))++;
       if (error == VOFFLINE)
        Log("Volume %d stays offline (/vice/offline/%s exists)\n", VolumeNumber(dp->d_name), dp->d_name);
-      else if (LogLevel >= 5) {
+      else if (GetLogLevel() >= 5) {
        Log("Partition %s: attached volume %d (%s)\n",
            diskP->name, VolumeNumber(dp->d_name),
            dp->d_name);
@@ -1364,7 +1346,7 @@ VShutdown_r(void)
        for (queue_Scan(&VolumeHashTable.Table[i],vp,np,Volume)) {
            code = VHold_r(vp);
            if (code == 0) {
-               if (LogLevel >= 5)
+               if (GetLogLevel() >= 5)
                    Log("VShutdown:  Attempting to take volume %" AFS_VOLID_FMT " offline.\n",
                        afs_printable_VolumeId_lu(vp->hashid));
 
@@ -1785,9 +1767,14 @@ ShutdownVByPForPass_r(struct DiskPartition64 * dp, int pass)
 {
     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;
 }
@@ -1847,10 +1834,10 @@ VShutdownVolume_r(Volume * vp)
 
     VCreateReservation_r(vp);
 
-    if (LogLevel >= 5) {
-       Log("VShutdownVolume_r:  vid=%" AFS_VOLID_FMT ", device=%d, state=%hu\n",
+    if (GetLogLevel() >= 5) {
+       Log("VShutdownVolume_r:  vid=%" AFS_VOLID_FMT ", device=%d, state=%u\n",
            afs_printable_VolumeId_lu(vp->hashid), vp->partition->device,
-           V_attachState(vp));
+           (unsigned int) V_attachState(vp));
     }
 
     /* wait for other blocking ops to finish */
@@ -1875,7 +1862,7 @@ VShutdownVolume_r(Volume * vp)
     case VOL_STATE_ATTACHED:
        code = VHold_r(vp);
        if (!code) {
-           if (LogLevel >= 5)
+           if (GetLogLevel() >= 5)
                Log("VShutdown:  Attempting to take volume %" AFS_VOLID_FMT " offline.\n",
                    afs_printable_VolumeId_lu(vp->hashid));
 
@@ -2302,7 +2289,7 @@ VPreAttachVolumeByVp_r(Error * ec,
     VLRU_Init_Node_r(vp);
     VChangeState_r(vp, VOL_STATE_PREATTACHED);
 
-    if (LogLevel >= 5)
+    if (GetLogLevel() >= 5)
        Log("VPreAttachVolumeByVp_r:  volume %" AFS_VOLID_FMT " pre-attached\n", afs_printable_VolumeId_lu(vp->hashid));
 
   done:
@@ -2581,7 +2568,7 @@ VAttachVolumeByName_r(Error * ec, char *partition, char *name, int mode)
                goto done;
            }
        }
-       if (LogLevel)
+       if (GetLogLevel() != 0)
          Log("VOnline:  volume %" AFS_VOLID_FMT " (%s) attached and online\n", afs_printable_VolumeId_lu(V_id(vp)),
                V_name(vp));
     }
@@ -2731,7 +2718,7 @@ VAttachVolumeByVp_r(Error * ec, Volume * vp, int mode)
            goto done;
        }
     }
-    if (LogLevel)
+    if (GetLogLevel() != 0)
        Log("VOnline:  volume %" AFS_VOLID_FMT " (%s) attached and online\n",
            afs_printable_VolumeId_lu(V_id(vp)), V_name(vp));
   done:
@@ -3476,6 +3463,9 @@ attach2(Error * ec, VolumeId volumeId, char *path, struct DiskPartition64 *partp
                FreeVolumeHeader(vp);
            } else if (!V_inService(vp)) {
                Log("Volume %lu offline: not in service\n", afs_printable_uint32_lu(V_id(vp)));
+               /* the volume is offline and should be unattached */
+               *ec = VOFFLINE;
+               error_state = VOL_STATE_UNATTACHED;
                FreeVolumeHeader(vp);
            } else {
                Log("Volume %lu offline: needs salvage\n", afs_printable_uint32_lu(V_id(vp)));
@@ -3496,7 +3486,7 @@ attach2(Error * ec, VolumeId volumeId, char *path, struct DiskPartition64 *partp
        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);
@@ -3518,7 +3508,13 @@ unlocked_error:
 locked_error:
 #ifdef AFS_DEMAND_ATTACH_FS
     if (!VIsErrorState(V_attachState(vp))) {
-       if (VIsErrorState(error_state)) {
+       if (programType != fileServer && *ec == VNOVOL) {
+           /* do not log anything in this case; it is common for
+            * non-fileserver programs to fail here with VNOVOL, since that
+            * is what happens when they simply try to use a volume, but that
+            * volume doesn't exist. */
+
+       } else if (VIsErrorState(error_state)) {
            Log("attach2: forcing vol %" AFS_VOLID_FMT " to error state (state %u flags 0x%x ec %d)\n",
                afs_printable_VolumeId_lu(vp->hashid), V_attachState(vp),
                V_attachFlags(vp), *ec);
@@ -4230,7 +4226,7 @@ GetVolume(Error * ec, Error * client_ec, VolumeId volumeId, Volume * hint,
            VGET_CTR_INC(V6);
            /* Only log the error if it was a totally unexpected error.  Simply
             * a missing inode is likely to be caused by the volume being deleted */
-           if (errno != ENXIO || LogLevel)
+           if (errno != ENXIO || GetLogLevel() != 0)
                Log("Volume %" AFS_VOLID_FMT ": couldn't reread volume header\n",
                    afs_printable_VolumeId_lu(vp->hashid));
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -4478,7 +4474,7 @@ VScanCalls_r(struct Volume *vp)
 #endif /* AFS_DEMAND_ATTACH_FS */
 
     for(queue_Scan(&vp->rx_call_list, cbv, ncbv, VCallByVol)) {
-       if (LogLevel > 0) {
+       if (GetLogLevel() != 0) {
            struct rx_peer *peer;
            char hoststr[16];
            peer = rx_PeerOf(rx_ConnectionOf(cbv->call));
@@ -4923,10 +4919,20 @@ VUpdateVolume_r(Error * ec, Volume * vp, int flags)
 #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);
@@ -5159,7 +5165,7 @@ VCheckOffline(Volume * vp)
        VUpdateVolume_r(&error, vp, 0);
        VCloseVolumeHandles_r(vp);
 
-       if (LogLevel) {
+       if (GetLogLevel() != 0) {
            if (V_offlineMessage(vp)[0]) {
                Log("VOffline: Volume %lu (%s) is now offline (%s)\n",
                    afs_printable_uint32_lu(V_id(vp)), V_name(vp),
@@ -5198,7 +5204,7 @@ VCheckOffline(Volume * vp)
        V_inUse(vp) = 0;
        VUpdateVolume_r(&error, vp, 0);
        VCloseVolumeHandles_r(vp);
-       if (LogLevel) {
+       if (GetLogLevel() != 0) {
            if (V_offlineMessage(vp)[0]) {
                Log("VOffline: Volume %lu (%s) is now offline (%s)\n",
                    afs_printable_uint32_lu(V_id(vp)), V_name(vp),
@@ -5669,6 +5675,37 @@ VRequestSalvage_r(Error * ec, Volume * vp, int reason, int flags)
            *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;
 }
@@ -6377,7 +6414,7 @@ VAllocBitmapEntry_r(Error * ec, Volume * vp,
            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
@@ -6450,7 +6487,9 @@ VFreeBitMapEntry_r(Error * ec, Volume *vp, struct vnodeIndex *index,
 
  done:
 #ifdef AFS_DEMAND_ATTACH_FS
-    VCancelReservation_r(vp);
+    if (flags & VOL_FREE_BITMAP_WAIT) {
+       VCancelReservation_r(vp);
+    }
 #endif
     return; /* make the compiler happy for non-DAFS */
 }
@@ -7172,7 +7211,7 @@ VInitVLRU(void)
     /* setup the timing constants */
     VLRU_ComputeConstants();
 
-    /* XXX put inside LogLevel check? */
+    /* XXX put inside log level check? */
     Log("VLRU: starting scanner with the following configuration parameters:\n");
     Log("VLRU:  offlining volumes after minimum of %d seconds of inactivity\n", VLRU_offline_thresh);
     Log("VLRU:  running VLRU soft detach pass every %d seconds\n", VLRU_offline_interval);
@@ -8377,8 +8416,8 @@ VSetVolHashSize(int logsize)
     }
 
     if (!VInit) {
-        VolumeHashTable.Size = 1 << logsize;
-        VolumeHashTable.Mask = VolumeHashTable.Size - 1;
+        VolumeHashTable.Size = opr_jhash_size(logsize);
+        VolumeHashTable.Mask = opr_jhash_mask(logsize);
     } else {
        /* we can't yet support runtime modification of this
         * parameter. we'll need a configuration rwlock to
@@ -8449,7 +8488,6 @@ AddVolumeToHashTable(Volume * vp, VolumeId hashid)
     head->len++;
     vp->hashid = hashid;
     queue_Append(head, vp);
-    vp->vnodeHashOffset = VolumeHashOffset_r();
 }
 
 /**