Add code for locking individual volumes on disk
[openafs.git] / src / vol / volume.h
index 779ec00..ee66af2 100644 (file)
@@ -68,6 +68,7 @@ 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 ih_init_params vol_io_params;
 extern int vol_attach_threads;
 #ifdef VOL_LOCK_DEBUG
 extern pthread_t vol_glock_holder;
@@ -118,18 +119,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
@@ -191,6 +194,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 */
@@ -222,8 +226,30 @@ 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) */
+} VolumePackageOptions;
 
 /* Magic numbers and version stamps for each type of file */
 #define VOLUMEHEADERMAGIC      ((bit32)0x88a1bb3c)
@@ -561,6 +587,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.
  */
@@ -746,11 +784,13 @@ extern void VFreeBitMapEntry_r(Error * ec, register struct vnodeIndex *index,
                               unsigned bitNumber);
 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);
@@ -767,15 +807,26 @@ 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 AssignVolumeName(VolumeDiskData * vol, char *name, char *ext);
 extern void VTakeOffline_r(register Volume * vp);
 extern void VTakeOffline(register 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);
+
+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);
@@ -797,13 +848,84 @@ 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);
+
+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 */
 extern int VVolOpLeaveOnline_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 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
@@ -864,4 +986,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 */