add AFS_DEMAND_ATTACH_UTIL
[openafs.git] / src / vol / volume.h
index 779ec00..a0ad8f5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -36,9 +36,9 @@ typedef bit32 FileOffset;     /* Offset in this file */
 
 #ifdef VOL_LOCK_DEBUG
 #define VOL_LOCK_ASSERT_HELD \
-    assert(vol_glock_holder == pthread_self())
+    osi_Assert(vol_glock_holder == pthread_self())
 #define VOL_LOCK_ASSERT_UNHELD \
-    assert(vol_glock_holder == 0)
+    osi_Assert(vol_glock_holder == 0)
 #define _VOL_LOCK_SET_HELD \
     vol_glock_holder = pthread_self()
 #define _VOL_LOCK_SET_UNHELD \
@@ -62,48 +62,44 @@ typedef bit32 FileOffset;   /* Offset in this file */
 
 
 #ifdef AFS_PTHREAD_ENV
-#include <assert.h>
 #include <pthread.h>
 extern pthread_mutex_t vol_glock_mutex;
 extern pthread_mutex_t vol_trans_mutex;
 extern pthread_cond_t vol_put_volume_cond;
 extern pthread_cond_t vol_sleep_cond;
+extern pthread_cond_t vol_vinit_cond;
+extern ih_init_params vol_io_params;
 extern int vol_attach_threads;
 #ifdef VOL_LOCK_DEBUG
 extern pthread_t vol_glock_holder;
 #define VOL_LOCK \
     do { \
-        assert(pthread_mutex_lock(&vol_glock_mutex) == 0); \
-        assert(vol_glock_holder == 0); \
-        vol_glock_holder = pthread_self(); \
+       MUTEX_ENTER(&vol_glock_mutex); \
+       VOL_LOCK_ASSERT_UNHELD; \
+       _VOL_LOCK_SET_HELD; \
     } while (0)
 #define VOL_UNLOCK \
     do { \
         VOL_LOCK_ASSERT_HELD; \
-        vol_glock_holder = 0; \
-        assert(pthread_mutex_unlock(&vol_glock_mutex) == 0); \
+       _VOL_LOCK_SET_UNHELD; \
+       MUTEX_EXIT(&vol_glock_mutex); \
     } while (0)
 #define VOL_CV_WAIT(cv) \
     do { \
         VOL_LOCK_DBG_CV_WAIT_BEGIN; \
-        assert(pthread_cond_wait((cv), &vol_glock_mutex) == 0); \
+       CV_WAIT((cv), &vol_glock_mutex); \
         VOL_LOCK_DBG_CV_WAIT_END; \
     } while (0)
 #else /* !VOL_LOCK_DEBUG */
-#define VOL_LOCK \
-    assert(pthread_mutex_lock(&vol_glock_mutex) == 0)
-#define VOL_UNLOCK \
-    assert(pthread_mutex_unlock(&vol_glock_mutex) == 0)
-#define VOL_CV_WAIT(cv) assert(pthread_cond_wait((cv), &vol_glock_mutex) == 0)
+#define VOL_LOCK MUTEX_ENTER(&vol_glock_mutex)
+#define VOL_UNLOCK MUTEX_EXIT(&vol_glock_mutex)
+#define VOL_CV_WAIT(cv) CV_WAIT((cv), &vol_glock_mutex)
 #endif /* !VOL_LOCK_DEBUG */
-#define VSALVSYNC_LOCK \
-    assert(pthread_mutex_lock(&vol_salvsync_mutex) == 0)
-#define VSALVSYNC_UNLOCK \
-    assert(pthread_mutex_unlock(&vol_salvsync_mutex) == 0)
-#define VTRANS_LOCK \
-    assert(pthread_mutex_lock(&vol_trans_mutex) == 0)
-#define VTRANS_UNLOCK \
-    assert(pthread_mutex_unlock(&vol_trans_mutex) == 0)
+
+#define VSALVSYNC_LOCK MUTEX_ENTER(&vol_salvsync_mutex)
+#define VSALVSYNC_UNLOCK MUTEX_EXIT(&vol_salvsync_mutex)
+#define VTRANS_LOCK MUTEX_ENTER(&vol_trans_mutex)
+#define VTRANS_UNLOCK MUTEX_EXIT(&vol_trans_mutex)
 #else /* AFS_PTHREAD_ENV */
 #define VOL_LOCK
 #define VOL_UNLOCK
@@ -118,18 +114,20 @@ extern pthread_t vol_glock_holder;
  */
 typedef enum {
     fileServer          = 1,    /**< the fileserver process */
-    volumeUtility       = 2,    /**< volserver, or a 
-                                *   single volume salvager (non-dafs) */
+    volumeUtility       = 2,    /**< any miscellaneous volume utility */
     salvager            = 3,    /**< standalone whole-partition salvager */
     salvageServer       = 4,    /**< dafs online salvager */
-    debugUtility        = 5     /**< fssync-debug or similar utility */
+    debugUtility        = 5,    /**< fssync-debug or similar utility */
+    volumeServer        = 6,    /**< the volserver process */
+    volumeSalvager      = 7     /**< the standalone single-volume salvager */
 } ProgramType;
 extern ProgramType programType;        /* The type of program using the package */
 
 /* Some initialization parameters for the volume package */
 /* Add new initialization parameters here */
-extern int (*V_BreakVolumeCallbacks) ();
-extern int (*vol_PollProc) ();
+extern int (*V_BreakVolumeCallbacks) (VolumeId);
+extern int (*vol_PollProc) (void);
+
 #define        DOPOLL  ((vol_PollProc)? (*vol_PollProc)() : 0)
 
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -174,9 +172,15 @@ 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 */
+    VOL_STATE_SALVAGE_REQ       = 21,   /**< volume has been requested to be salvaged,
+                                         *   but is waiting for other users to go away
+                                         *   so it can be offlined */
+    VOL_STATE_SCANNING_RXCALLS  = 22,   /**< volume is scanning vp->rx_call_list
+                                         *   to interrupt RX calls */
     /* 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             = 23,   /**< debugging aid */
+    VOL_STATE_COUNT             = 24    /**< total number of valid states */
 } VolState;
 
 /**
@@ -191,6 +195,7 @@ enum VolFlags {
     VOL_IS_BUSY           = 0x20,    /**< volume is not to be free()d */
     VOL_ON_VLRU           = 0x40,    /**< volume is on the VLRU */
     VOL_HDR_DONTSALV      = 0x80,    /**< volume header DONTSALVAGE flag is set */
+    VOL_LOCKED            = 0x100    /**< volume is disk-locked (@see VLockVolumeNB) */
 };
 
 /* VPrintExtendedCacheStats flags */
@@ -214,7 +219,7 @@ typedef enum {
     VLRU_QUEUE_CANDIDATE  = 3,  /**< soft detach candidate pool */
     VLRU_QUEUE_HELD       = 4,  /*   volumes which are not allowed
                                 *   to be soft detached */
-    VLRU_QUEUE_INVALID    = 5,  /**< invalid queue id */
+    VLRU_QUEUE_INVALID    = 5   /**< invalid queue id */
 } VLRUQueueName;
 
 /* default scanner timing parameters */
@@ -222,8 +227,51 @@ typedef enum {
 #define VLRU_DEFAULT_OFFLINE_INTERVAL (60*2) /* 2 minutes */
 #define VLRU_DEFAULT_OFFLINE_MAX 8 /* 8 volumes */
 
+
+/**
+ * DAFS thread-specific options structure
+ */
+typedef struct VThreadOptions {
+     int disallow_salvsync;     /**< whether or not salvsync calls are allowed
+                                *   on this thread (deadlock prevention). */
+} VThreadOptions_t;
+extern pthread_key_t VThread_key;
+extern VThreadOptions_t VThread_defaults;
+
 #endif /* AFS_DEMAND_ATTACH_FS */
 
+typedef struct VolumePackageOptions {
+    afs_uint32 nLargeVnodes;      /**< size of large vnode cache */
+    afs_uint32 nSmallVnodes;      /**< size of small vnode cache */
+    afs_uint32 volcache;          /**< size of volume header cache */
+
+    afs_int32 canScheduleSalvage; /**< can we schedule salvages? (DAFS) */
+                                 /* (if 'no', we will just error out if we
+                                   * find a bad vol) */
+    afs_int32 canUseFSSYNC;       /**< can we use the FSSYNC channel? */
+    afs_int32 canUseSALVSYNC;     /**< can we use the SALVSYNC channel? (DAFS) */
+    afs_int32 unsafe_attach;      /**< can we bypass checking the inUse vol
+                                   *   header on attach? */
+    void (*interrupt_rxcall) (struct rx_call *call, afs_int32 error);
+                                  /**< callback to interrupt RX calls accessing
+                                   *   a going-offline volume */
+    afs_int32 offline_timeout;    /**< how long (in seconds) to wait before
+                                   *   interrupting RX calls accessing a
+                                   *   going-offline volume. -1 disables,
+                                   *   0 means immediately. */
+    afs_int32 offline_shutdown_timeout;
+                                  /**< how long (in seconds) to wait before
+                                   *   interrupting RX calls accessing a
+                                   *   going-offline volume during shutdown.
+                                   *   -1 disables, 0 means immediately.
+                                   *   Note that the timeout time is calculated
+                                   *   once, when we encounter the first going-
+                                   *   offline volume during shutdown. So if we
+                                   *   encounter multiple going-offline volumes
+                                   *   during shutdown, we will still only wait
+                                   *   for this amount of time in total, not e.g.
+                                   *   for each going-offline volume encountered. */
+} VolumePackageOptions;
 
 /* Magic numbers and version stamps for each type of file */
 #define VOLUMEHEADERMAGIC      ((bit32)0x88a1bb3c)
@@ -447,7 +495,7 @@ typedef struct VolumeDiskData {
 /* Memory resident volume information */
 /**************************************/
 
-/** 
+/**
  * global volume package stats.
  */
 typedef struct VolPkgStats {
@@ -561,6 +609,18 @@ typedef struct VolumeStats {
     afs_uint32 last_vol_op;      /**< unix timestamp of last volume operation */
 } VolumeStats;
 
+
+#define SALVAGE_PRIO_UPDATE_INTERVAL 3      /**< number of seconds between prio updates */
+#define SALVAGE_COUNT_MAX 16                /**< number of online salvages we
+                                            *   allow before moving the volume
+                                            *   into a permanent error state
+                                            *
+                                            *   once this threshold is reached,
+                                            *   the operator will have to manually
+                                            *   issue a 'bos salvage' to bring
+                                            *   the volume back online
+                                            */
+
 /**
  * DAFS online salvager state.
  */
@@ -569,7 +629,11 @@ typedef struct VolumeOnlineSalvage {
     int reason;                 /**< reason for requesting online salvage */
     byte requested;             /**< flag specifying that salvage should be scheduled */
     byte scheduled;             /**< flag specifying whether online salvage scheduled */
-    byte reserved[2];           /**< padding */
+    byte scheduling;            /**< if nonzero, this volume has entered
+                                 *   VCheckSalvage(), so if we recurse into
+                                 *   VCheckSalvage() with this set, exit immediately
+                                 *   to avoid recursing forever */
+    byte reserved[1];           /**< padding */
 } VolumeOnlineSalvage;
 
 /**
@@ -581,6 +645,14 @@ typedef struct VolumeVLRUState {
 } VolumeVLRUState;
 #endif /* AFS_DEMAND_ATTACH_FS */
 
+/**
+ * node for a volume's rx_call_list.
+ */
+struct VCallByVol {
+    struct rx_queue q;
+    struct rx_call *call;
+};
+
 typedef struct Volume {
     struct rx_queue q;          /* Volume hash chain pointers */
     VolumeId hashid;           /* Volume number -- for hash table lookup */
@@ -605,17 +677,22 @@ typedef struct Volume {
                                 * value nextVnodeVersion */
     IHandle_t *diskDataHandle; /* Unix inode holding general volume info */
     bit16 vnodeHashOffset;     /* Computed by HashOffset function in vnode.h.
-                                * Assigned to the volume when initialized. 
+                                * Assigned to the volume when initialized.
                                 * Added to vnode number for hash table index */
     byte shuttingDown;         /* This volume is going to be detached */
     byte goingOffline;         /* This volume is going offline */
     bit32 cacheCheck;          /* Online sequence number to be used to invalidate vnode cache entries
                                 * that stayed around while a volume was offline */
     short nUsers;              /* Number of users of this volume header */
-    byte needsPutBack;         /* For a volume utility, this flag is set if we need
-                                * to give the volume back when we detach it.  The server has
+#define VOL_PUTBACK 1
+#define VOL_PUTBACK_DELETE 2
+    byte needsPutBack;         /* For a volume utility, this flag is set to VOL_PUTBACK if we
+                                * need to give the volume back when we detach it.  The server has
                                 * certain modes where it doesn't detach the volume, and
-                                * if we give it back spuriously, the server aborts.  This field
+                                * if we give it back spuriously, the server aborts. If set to
+                                * VOL_PUTBACK_DELETE, it indicates that we need to tell the
+                                * fileserver that the volume is gone entirely, instead of just
+                                * giving the volume back to the fileserver. This field
                                 * is meaningless on the file server */
     byte specialStatus;                /* An error code to return on VGetVolume: the
                                 * volume is unavailable for the reason quoted,
@@ -625,6 +702,8 @@ typedef struct Volume {
                                 * volume list--the list of volumes that will be
                                 * salvaged should the file server crash */
     struct rx_queue vnode_list; /**< linked list of cached vnodes for this volume */
+    struct rx_queue rx_call_list; /**< linked list of split RX calls using this
+                                   *   volume (fileserver only) */
 #ifdef AFS_DEMAND_ATTACH_FS
     VolState attach_state;      /* what stage of attachment has been completed */
     afs_uint32 attach_flags;    /* flags related to attachment state */
@@ -720,8 +799,11 @@ struct volHeader {
 extern char *VSalvageMessage;  /* Canonical message when a volume is forced
                                 * offline */
 extern Volume *VGetVolume(Error * ec, Error * client_ec, VolId volumeId);
+extern Volume *VGetVolumeWithCall(Error * ec, Error * client_ec, VolId volumeId,
+                                  const struct timespec *ts, struct VCallByVol *cbv);
 extern Volume *VGetVolume_r(Error * ec, VolId volumeId);
 extern void VPutVolume(Volume *);
+extern void VPutVolumeWithCall(Volume *vp, struct VCallByVol *cbv);
 extern void VPutVolume_r(Volume *);
 extern void VOffline(Volume * vp, char *message);
 extern void VOffline_r(Volume * vp, char *message);
@@ -736,21 +818,23 @@ extern Volume *VCreateVolume(Error * ec, char *partname, VolId volumeId,
                             VolId parentId);
 extern Volume *VCreateVolume_r(Error * ec, char *partname, VolId volumeId,
                               VolId parentId);
-extern VnodeId VAllocBitmapEntry(Error * ec, Volume * vp,
-                                struct vnodeIndex *index);
-extern VnodeId VAllocBitmapEntry_r(Error * ec, Volume * vp,
-                                  struct vnodeIndex *index, int flags);
-extern void VFreeBitMapEntry(Error * ec, register struct vnodeIndex *index,
+extern int VAllocBitmapEntry(Error * ec, Volume * vp,
+                            struct vnodeIndex *index);
+extern int VAllocBitmapEntry_r(Error * ec, Volume * vp,
+                              struct vnodeIndex *index, int flags);
+extern void VFreeBitMapEntry(Error * ec, Volume *vp, struct vnodeIndex *index,
                             unsigned bitNumber);
-extern void VFreeBitMapEntry_r(Error * ec, register struct vnodeIndex *index,
-                              unsigned bitNumber);
+extern void VFreeBitMapEntry_r(Error * ec, Volume *vp, struct vnodeIndex *index,
+                              unsigned bitNumber, int flags);
 extern int VolumeNumber(char *name);
 extern char *VolumeExternalName(VolumeId volumeId);
+extern int VolumeExternalName_r(VolumeId volumeId, char *name, size_t len);
 extern Volume *VAttachVolumeByName(Error * ec, char *partition, char *name,
                                   int mode);
 extern Volume *VAttachVolumeByName_r(Error * ec, char *partition, char *name,
                                     int mode);
 extern void VShutdown(void);
+extern void VSetTranquil(void);
 extern void VUpdateVolume(Error * ec, Volume * vp);
 extern void VUpdateVolume_r(Error * ec, Volume * vp, int flags);
 extern void VAddToVolumeUpdateList(Error * ec, Volume * vp);
@@ -759,29 +843,41 @@ extern void VDetachVolume(Error * ec, Volume * vp);
 extern void VDetachVolume_r(Error * ec, Volume * vp);
 extern void VForceOffline(Volume * vp);
 extern void VForceOffline_r(Volume * vp, int flags);
-extern void VBumpVolumeUsage(register Volume * vp);
-extern void VBumpVolumeUsage_r(register Volume * vp);
+extern void VBumpVolumeUsage(Volume * vp);
+extern void VBumpVolumeUsage_r(Volume * vp);
 extern void VSetDiskUsage(void);
 extern void VPrintCacheStats(void);
 extern void VReleaseVnodeFiles_r(Volume * vp);
 extern void VCloseVnodeFiles_r(Volume * vp);
 extern struct DiskPartition64 *VGetPartition(char *name, int abortp);
 extern struct DiskPartition64 *VGetPartition_r(char *name, int abortp);
-extern int VInitVolumePackage(ProgramType pt, afs_uint32 nLargeVnodes,
-                             afs_uint32 nSmallVnodes, int connect, afs_uint32 volcache);
+extern void VOptDefaults(ProgramType pt, VolumePackageOptions * opts);
+extern int VInitVolumePackage2(ProgramType pt, VolumePackageOptions * opts);
+extern int VInitAttachVolumes(ProgramType pt);
 extern void DiskToVolumeHeader(VolumeHeader_t * h, VolumeDiskHeader_t * dh);
 extern void VolumeHeaderToDisk(VolumeDiskHeader_t * dh, VolumeHeader_t * h);
-extern void VTakeOffline_r(register Volume * vp);
-extern void VTakeOffline(register Volume * vp);
+extern void AssignVolumeName(VolumeDiskData * vol, char *name, char *ext);
+extern void VTakeOffline_r(Volume * vp);
+extern void VTakeOffline(Volume * vp);
 extern Volume * VLookupVolume_r(Error * ec, VolId volumeId, Volume * hint);
 extern void VGetVolumePath(Error * ec, VolId volumeId, char **partitionp,
                           char **namep);
+extern char *vol_DevName(dev_t adev, char *wpath);
+extern afs_int32 VIsGoingOffline(struct Volume *vp);
+
+struct VLockFile;
+extern void VLockFileInit(struct VLockFile *lf, const char *path);
+extern void VLockFileReinit(struct VLockFile *lf);
+extern int VLockFileLock(struct VLockFile *lf, afs_uint32 offset,
+                         int locktype, int nonblock);
+extern void VLockFileUnlock(struct VLockFile *lf, afs_uint32 offset);
+
 #ifdef AFS_DEMAND_ATTACH_FS
 extern Volume *VPreAttachVolumeByName(Error * ec, char *partition, char *name);
 extern Volume *VPreAttachVolumeByName_r(Error * ec, char *partition, char *name);
-extern Volume *VPreAttachVolumeById_r(Error * ec, char * partition, 
+extern Volume *VPreAttachVolumeById_r(Error * ec, char * partition,
                                      VolId volumeId);
-extern Volume *VPreAttachVolumeByVp_r(Error * ec, struct DiskPartition64 * partp, 
+extern Volume *VPreAttachVolumeByVp_r(Error * ec, struct DiskPartition64 * partp,
                                      Volume * vp, VolId volume_id);
 extern Volume *VGetVolumeByVp_r(Error * ec, Volume * vp);
 extern int VShutdownByPartition_r(struct DiskPartition64 * dp);
@@ -797,13 +893,88 @@ extern void VPrintExtendedCacheStats_r(int flags);
 extern void VLRU_SetOptions(int option, afs_uint32 val);
 extern int VSetVolHashSize(int logsize);
 extern int VRequestSalvage_r(Error * ec, Volume * vp, int reason, int flags);
+extern int VUpdateSalvagePriority_r(Volume * vp);
 extern int VRegisterVolOp_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
 extern int VDeregisterVolOp_r(Volume * vp);
 extern void VCancelReservation_r(Volume * vp);
+extern int VChildProcReconnectFS_r(void);
+extern void VOfflineForVolOp_r(Error *ec, Volume *vp, char *message);
 #endif /* AFS_DEMAND_ATTACH_FS */
+
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+struct VDiskLock;
+extern void VDiskLockInit(struct VDiskLock *dl, struct VLockFile *lf,
+                          afs_uint32 offset);
+extern int VGetDiskLock(struct VDiskLock *dl, int locktype, int nonblock);
+extern void VReleaseDiskLock(struct VDiskLock *dl, int locktype);
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
 extern int VVolOpLeaveOnline_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
+extern int VVolOpLeaveOnlineNoHeader_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
 extern int VVolOpSetVBusy_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
 
+extern void VPurgeVolume(Error * ec, Volume * vp);
+
+extern afs_int32 VCanScheduleSalvage(void);
+extern afs_int32 VCanUseFSSYNC(void);
+extern afs_int32 VCanUseSALVSYNC(void);
+extern afs_int32 VCanUnsafeAttach(void);
+extern afs_int32 VReadVolumeDiskHeader(VolumeId volid,
+                                      struct DiskPartition64 * dp,
+                                      VolumeDiskHeader_t * hdr);
+extern afs_int32 VWriteVolumeDiskHeader(VolumeDiskHeader_t * hdr,
+                                       struct DiskPartition64 * dp);
+extern afs_int32 VCreateVolumeDiskHeader(VolumeDiskHeader_t * hdr,
+                                        struct DiskPartition64 * dp);
+extern afs_int32 VDestroyVolumeDiskHeader(struct DiskPartition64 * dp,
+                                         VolumeId volid, VolumeId parent);
+
+/**
+ * VWalkVolumeHeaders header callback.
+ *
+ * @param[in] dp   disk partition
+ * @param[in] name full path to the .vol header file
+ * @param[in] hdr  the header data that was read from the .vol header
+ * @param[in] last 1 if this is the last attempt to read the vol header, 0
+ *                 otherwise. DAFS VWalkVolumeHeaders will retry reading the
+ *                 header once, if a non-fatal error occurs when reading the
+ *                 header, or if this function returns a positive error code.
+ *                 So, if there is a problem, this function will be called
+ *                 first with last=0, then with last=1, then the error function
+ *                 callback will be called. For non-DAFS, this is always 1.
+ * @param[in] rock the rock passed to VWalkVolumeHeaders
+ *
+ * @return operation status
+ *  @retval 0 success
+ *  @retval negative a fatal error that should stop the walk immediately
+ *  @retval positive an error with the volume header was encountered; the walk
+ *          should continue, but the error function should be called on this
+ *          header
+ *
+ * @see VWalkVolumeHeaders
+ */
+typedef int (*VWalkVolFunc)(struct DiskPartition64 *dp, const char *name,
+                            struct VolumeDiskHeader *hdr, int last,
+                            void *rock);
+/**
+ * VWalkVolumeHeaders error callback.
+ *
+ * This is called from VWalkVolumeHeaders when an invalid or otherwise
+ * problematic volume header is encountered. It is typically implemented as a
+ * wrapper to unlink the .vol file.
+ *
+ * @param[in] dp   disk partition
+ * @param[in] name full path to the .vol header file
+ * @param[in] hdr  header read in from the .vol file, or NULL if it could not
+ *                 be read
+ * @param[in] rock rock passed to VWalkVolumeHeaders
+ *
+ * @see VWalkVolumeHeaders
+ */
+typedef void (*VWalkErrFunc)(struct DiskPartition64 *dp, const char *name,
+                             struct VolumeDiskHeader *hdr, void *rock);
+extern int VWalkVolumeHeaders(struct DiskPartition64 *dp, const char *partpath,
+                              VWalkVolFunc volfunc, VWalkErrFunc errfunc,
+                              void *rock);
 
 /* Naive formula relating number of file size to number of 1K blocks in file */
 /* Note:  we charge 1 block for 0 length files so the user can't store
@@ -854,8 +1025,13 @@ extern int VVolOpSetVBusy_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
 /* VAllocBitmapEntry_r flags */
 #define VOL_ALLOC_BITMAP_WAIT    0x1  /* for demand attach, wait for other exclusive ops to end */
 
+/* VFreeBitMapEntry_r flags */
+#define VOL_FREE_BITMAP_WAIT     0x1  /* for demand attach, wait for other exclusive ops to end */
+
 /* VRequestSalvage_r flags */
 #define VOL_SALVAGE_INVALIDATE_HEADER 0x1 /* for demand attach fs, invalidate volume header cache */
+#define VOL_SALVAGE_NO_OFFLINE        0x2 /* we do not need to wait to offline the volume; it has
+                                           * not been fully attached */
 
 
 #if    defined(NEARINODE_HINT)
@@ -864,4 +1040,10 @@ extern int VVolOpSetVBusy_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
 #define V_pref(vp,nearInode)   nearInode = 0
 #endif /* NEARINODE_HINT */
 
+hdr_static_inline(unsigned int)
+afs_printable_VolumeId_u(VolumeId d) { return (unsigned int) d; }
+
+hdr_static_inline(unsigned int)
+afs_printable_VnodeId_u(VnodeId d) { return (unsigned int) d; }
+
 #endif /* __volume_h */