/*
* 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
#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 \
#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
salvageServer = 4, /**< dafs online salvager */
debugUtility = 5, /**< fssync-debug or similar utility */
volumeServer = 6, /**< the volserver process */
- volumeSalvager = 7, /**< the standalone single-volume salvager */
+ volumeSalvager = 7 /**< the standalone single-volume salvager */
} ProgramType;
extern ProgramType programType; /* The type of program using the package */
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;
/**
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 */
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 */
* 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 */
/* Memory resident volume information */
/**************************************/
-/**
+/**
* global volume package stats.
*/
typedef struct VolPkgStats {
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;
/**
} 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 */
* 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,
* 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 */
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);
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 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 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 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);
#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);
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 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);
/* 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)