#include <sys/file.h>
#endif
-#include <rx/xdr.h>
+#include <afs/opr.h>
#include <afs/afsint.h>
#ifndef AFS_NT40_ENV
#endif
-#define VOLUME_BITMAP_GROWSIZE 16 /* bytes, => 128vnodes */
- /* Must be a multiple of 4 (1 word) !! */
-
/* this parameter needs to be tunable at runtime.
* 128 was really inadequate for largish servers -- at 16384 volumes this
* puts average chain length at 128, thus an average 65 deref's to find a volptr.
static void VVByPListWait_r(struct DiskPartition64 * dp);
/* online salvager */
+typedef enum {
+ VCHECK_SALVAGE_OK = 0, /**< no pending salvage */
+ VCHECK_SALVAGE_SCHEDULED = 1, /**< salvage has been scheduled */
+ VCHECK_SALVAGE_ASYNC = 2, /**< salvage being scheduled */
+ VCHECK_SALVAGE_DENIED = 3, /**< salvage not scheduled; denied */
+ VCHECK_SALVAGE_FAIL = 4 /**< salvage not scheduled; failed */
+} vsalvage_check;
static int VCheckSalvage(Volume * vp);
#if defined(SALVSYNC_BUILD_CLIENT) || defined(FSSYNC_BUILD_CLIENT)
static int VScheduleSalvage_r(Volume * vp);
} else {
VLRU_SetOptions(VLRU_SET_ENABLED, 0);
}
- osi_Assert(pthread_key_create(&VThread_key, NULL) == 0);
+ opr_Verify(pthread_key_create(&VThread_key, NULL) == 0);
#endif
MUTEX_INIT(&vol_glock_mutex, "vol glock", MUTEX_DEFAULT, 0);
#if defined(AFS_DEMAND_ATTACH_FS) && defined(SALVSYNC_BUILD_CLIENT)
if (VCanUseSALVSYNC()) {
/* establish a connection to the salvager at this point */
- osi_Assert(VConnectSALV() != 0);
+ opr_Verify(VConnectSALV() != 0);
}
#endif /* AFS_DEMAND_ATTACH_FS */
int
VInitAttachVolumes(ProgramType pt)
{
- osi_Assert(VInit==1);
+ opr_Assert(VInit==1);
if (pt == fileServer) {
struct DiskPartition64 *diskP;
/* Attach all the volumes in this partition */
for (diskP = DiskPartitionList; diskP; diskP = diskP->next) {
int nAttached = 0, nUnattached = 0;
- osi_Assert(VAttachVolumesByPartition(diskP, &nAttached, &nUnattached) == 0);
+ opr_Verify(VAttachVolumesByPartition(diskP,
+ &nAttached, &nUnattached)
+ == 0);
}
}
VOL_LOCK;
int
VInitAttachVolumes(ProgramType pt)
{
- osi_Assert(VInit==1);
+ opr_Assert(VInit==1);
if (pt == fileServer) {
struct DiskPartition64 *diskP;
struct vinitvolumepackage_thread_t params;
/* create partition work queue */
for (parts=0, diskP = DiskPartitionList; diskP; diskP = diskP->next, parts++) {
- dpq = (diskpartition_queue_t *) malloc(sizeof(struct diskpartition_queue_t));
- osi_Assert(dpq != NULL);
+ dpq = malloc(sizeof(struct diskpartition_queue_t));
+ opr_Assert(dpq != NULL);
dpq->diskP = diskP;
queue_Append(¶ms,dpq);
}
- threads = MIN(parts, vol_attach_threads);
+ threads = min(parts, vol_attach_threads);
if (threads > 1) {
/* spawn off a bunch of initialization threads */
- osi_Assert(pthread_attr_init(&attrs) == 0);
- osi_Assert(pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED) == 0);
+ opr_Verify(pthread_attr_init(&attrs) == 0);
+ opr_Verify(pthread_attr_setdetachstate(&attrs,
+ PTHREAD_CREATE_DETACHED)
+ == 0);
Log("VInitVolumePackage: beginning parallel fileserver startup\n");
Log("VInitVolumePackage: using %d threads to attach volumes on %d partitions\n",
for (i=0; i < threads; i++) {
AFS_SIGSET_DECL;
AFS_SIGSET_CLEAR();
- osi_Assert(pthread_create
- (&tid, &attrs, &VInitVolumePackageThread,
- ¶ms) == 0);
+ opr_Verify(pthread_create(&tid, &attrs,
+ &VInitVolumePackageThread,
+ ¶ms) == 0);
AFS_SIGSET_RESTORE();
}
}
VOL_UNLOCK;
- osi_Assert(pthread_attr_destroy(&attrs) == 0);
+ opr_Verify(pthread_attr_destroy(&attrs) == 0);
} else {
/* if we're only going to run one init thread, don't bother creating
* another LWP */
diskP = dpq->diskP;
free(dpq);
- osi_Assert(VAttachVolumesByPartition(diskP, &nAttached, &nUnattached) == 0);
+ opr_Verify(VAttachVolumesByPartition(diskP, &nAttached,
+ &nUnattached) == 0);
VOL_LOCK;
}
int
VInitAttachVolumes(ProgramType pt)
{
- osi_Assert(VInit==1);
+ opr_Assert(VInit==1);
if (pt == fileServer) {
struct DiskPartition64 *diskP;
MUTEX_INIT(&(pq.mutex), "partq", MUTEX_DEFAULT, 0);
for (parts = 0, diskP = DiskPartitionList; diskP; diskP = diskP->next, parts++) {
struct diskpartition_queue_t *dp;
- dp = (struct diskpartition_queue_t*)malloc(sizeof(struct diskpartition_queue_t));
- osi_Assert(dp != NULL);
+ dp = malloc(sizeof(struct diskpartition_queue_t));
+ opr_Assert(dp != NULL);
dp->diskP = diskP;
queue_Append(&pq, dp);
}
/* number of worker threads; at least one, not to exceed the number of partitions */
- threads = MIN(parts, vol_attach_threads);
+ threads = min(parts, vol_attach_threads);
/* create volume work queue */
queue_Init(&vq);
CV_INIT(&(vq.cv), "volq", CV_DEFAULT, 0);
MUTEX_INIT(&(vq.mutex), "volq", MUTEX_DEFAULT, 0);
- osi_Assert(pthread_attr_init(&attrs) == 0);
- osi_Assert(pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED) == 0);
+ opr_Verify(pthread_attr_init(&attrs) == 0);
+ opr_Verify(pthread_attr_setdetachstate(&attrs,
+ PTHREAD_CREATE_DETACHED) == 0);
Log("VInitVolumePackage: beginning parallel fileserver startup\n");
Log("VInitVolumePackage: using %d threads to pre-attach volumes on %d partitions\n",
struct vinitvolumepackage_thread_param *params;
AFS_SIGSET_DECL;
- params = (struct vinitvolumepackage_thread_param *)malloc(sizeof(struct vinitvolumepackage_thread_param));
- osi_Assert(params);
+ params = malloc(sizeof(struct vinitvolumepackage_thread_param));
+ opr_Assert(params);
params->pq = &pq;
params->vq = &vq;
params->nthreads = threads;
params->thread = i+1;
AFS_SIGSET_CLEAR();
- osi_Assert(pthread_create (&tid, &attrs, &VInitVolumePackageThread, (void*)params) == 0);
+ opr_Verify(pthread_create(&tid, &attrs,
+ &VInitVolumePackageThread,
+ (void*)params) == 0);
AFS_SIGSET_RESTORE();
}
VInitPreAttachVolumes(threads, &vq);
- osi_Assert(pthread_attr_destroy(&attrs) == 0);
+ opr_Verify(pthread_attr_destroy(&attrs) == 0);
CV_DESTROY(&pq.cv);
MUTEX_DESTROY(&pq.mutex);
CV_DESTROY(&vq.cv);
struct volume_init_queue *vq;
struct volume_init_batch *vb;
- osi_Assert(args);
+ opr_Assert(args);
params = (struct vinitvolumepackage_thread_param *)args;
pq = params->pq;
vq = params->vq;
- osi_Assert(pq);
- osi_Assert(vq);
+ opr_Assert(pq);
+ opr_Assert(vq);
- vb = (struct volume_init_batch*)malloc(sizeof(struct volume_init_batch));
- osi_Assert(vb);
+ vb = malloc(sizeof(struct volume_init_batch));
+ opr_Assert(vb);
vb->thread = params->thread;
vb->last = 0;
vb->size = 0;
continue;
}
while ((vid = VInitNextVolumeId(dirp))) {
- Volume *vp = (Volume*)malloc(sizeof(Volume));
- osi_Assert(vp);
- memset(vp, 0, sizeof(Volume));
+ Volume *vp = calloc(1, sizeof(Volume));
+ opr_Assert(vp);
vp->device = partition->device;
vp->partition = partition;
vp->hashid = vid;
CV_BROADCAST(&vq->cv);
MUTEX_EXIT(&vq->mutex);
- vb = (struct volume_init_batch*)malloc(sizeof(struct volume_init_batch));
- osi_Assert(vb);
+ vb = malloc(sizeof(struct volume_init_batch));
+ opr_Assert(vb);
vb->thread = params->thread;
vb->size = 0;
vb->last = 0;
queue_Remove(dp);
MUTEX_EXIT(&pq->mutex);
- osi_Assert(dp);
- osi_Assert(dp->diskP);
+ opr_Assert(dp);
+ opr_Assert(dp->diskP);
partition = dp->diskP;
free(dp);
MUTEX_INIT(¶ms.lock, "params", MUTEX_DEFAULT, 0);
CV_INIT(¶ms.cv, "params", CV_DEFAULT, 0);
CV_INIT(¶ms.master_cv, "params master", CV_DEFAULT, 0);
- osi_Assert(pthread_attr_init(&attrs) == 0);
- osi_Assert(pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED) == 0);
+ opr_Verify(pthread_attr_init(&attrs) == 0);
+ opr_Verify(pthread_attr_setdetachstate(&attrs,
+ PTHREAD_CREATE_DETACHED) == 0);
queue_Init(¶ms);
/* setup the basic partition information structures for
/* build up the pass 0 shutdown work queue */
- dpq = (struct diskpartition_queue_t *) malloc(sizeof(struct diskpartition_queue_t));
- osi_Assert(dpq != NULL);
+ dpq = malloc(sizeof(struct diskpartition_queue_t));
+ opr_Assert(dpq != NULL);
dpq->diskP = diskP;
queue_Prepend(¶ms, dpq);
/* do pass 0 shutdown */
MUTEX_ENTER(¶ms.lock);
for (i=0; i < params.n_threads; i++) {
- osi_Assert(pthread_create
- (&tid, &attrs, &VShutdownThread,
- ¶ms) == 0);
+ opr_Verify(pthread_create(&tid, &attrs, &VShutdownThread,
+ ¶ms) == 0);
}
/* wait for all the pass 0 shutdowns to complete */
VOL_CV_WAIT(¶ms.cv);
}
- osi_Assert(pthread_attr_destroy(&attrs) == 0);
+ opr_Verify(pthread_attr_destroy(&attrs) == 0);
CV_DESTROY(¶ms.cv);
CV_DESTROY(¶ms.master_cv);
MUTEX_DESTROY(¶ms.lock);
void
VShutdown(void)
{
- osi_Assert(VInit>0);
+ opr_Assert(VInit>0);
VOL_LOCK;
VShutdown_r();
VOL_UNLOCK;
VOL_LOCK;
pass = params->pass;
- osi_Assert(pass > 0);
+ opr_Assert(pass > 0);
/* now escalate through the more complicated shutdowns */
while (pass <= 3) {
/* wait for other blocking ops to finish */
VWaitExclusiveState_r(vp);
- osi_Assert(VIsValidState(V_attachState(vp)));
+ opr_Assert(VIsValidState(V_attachState(vp)));
switch(V_attachState(vp)) {
case VOL_STATE_SALVAGING:
/* Header I/O routines */
/***************************************************/
+static const char *
+HeaderName(bit32 magic)
+{
+ switch (magic) {
+ case VOLUMEINFOMAGIC:
+ return "volume info";
+ case SMALLINDEXMAGIC:
+ return "small index";
+ case LARGEINDEXMAGIC:
+ return "large index";
+ case LINKTABLEMAGIC:
+ return "link table";
+ }
+ return "unknown";
+}
+
/* open a descriptor for the inode (h),
* read in an on-disk structure into buffer (to) of size (size),
* verify versionstamp in structure has magic (magic) and
{
struct versionStamp *vsn;
FdHandle_t *fdP;
+ afs_sfsize_t nbytes;
+ afs_ino_str_t stmp;
*ec = 0;
if (h == NULL) {
+ Log("ReadHeader: Null inode handle argument for %s header file.\n",
+ HeaderName(magic));
*ec = VSALVAGE;
return;
}
fdP = IH_OPEN(h);
if (fdP == NULL) {
+ Log("ReadHeader: Failed to open %s header file "
+ "(volume=%u, inode=%s); errno=%d\n", HeaderName(magic), h->ih_vid,
+ PrintInode(stmp, h->ih_ino), errno);
*ec = VSALVAGE;
return;
}
vsn = (struct versionStamp *)to;
- if (FDH_PREAD(fdP, to, size, 0) != size || vsn->magic != magic) {
+ nbytes = FDH_PREAD(fdP, to, size, 0);
+ if (nbytes < 0) {
+ Log("ReadHeader: Failed to read %s header file "
+ "(volume=%u, inode=%s); errno=%d\n", HeaderName(magic), h->ih_vid,
+ PrintInode(stmp, h->ih_ino), errno);
+ *ec = VSALVAGE;
+ FDH_REALLYCLOSE(fdP);
+ return;
+ }
+ if (nbytes != size) {
+ Log("ReadHeader: Incorrect number of bytes read from %s header file "
+ "(volume=%u, inode=%s); expected=%d, read=%d\n",
+ HeaderName(magic), h->ih_vid, PrintInode(stmp, h->ih_ino), size,
+ (int)nbytes);
*ec = VSALVAGE;
FDH_REALLYCLOSE(fdP);
return;
}
+ if (vsn->magic != magic) {
+ Log("ReadHeader: Incorrect magic for %s header file "
+ "(volume=%u, inode=%s); expected=0x%x, read=0x%x\n",
+ HeaderName(magic), h->ih_vid, PrintInode(stmp, h->ih_ino), magic,
+ vsn->magic);
+ *ec = VSALVAGE;
+ FDH_REALLYCLOSE(fdP);
+ return;
+ }
+
FDH_CLOSE(fdP);
/* Check is conditional, in case caller wants to inspect version himself */
if (version && vsn->version != version) {
+ Log("ReadHeader: Incorrect version for %s header file "
+ "(volume=%u, inode=%s); expected=%x, read=%x\n",
+ HeaderName(magic), h->ih_vid, PrintInode(stmp, h->ih_ino),
+ version, vsn->version);
*ec = VSALVAGE;
}
}
*ec = 0;
- osi_Assert(programType == fileServer);
+ opr_Assert(programType == fileServer);
if (!(partp = VGetPartition_r(partition, 0))) {
*ec = VNOVOL;
* - volume is in an error state
* - volume is pre-attached
*/
- Log("VPreattachVolumeByVp_r: volume %u not in quiescent state\n", vid);
+ Log("VPreattachVolumeByVp_r: volume %u not in quiescent state (state %u flags 0x%x)\n",
+ vid, V_attachState(vp), V_attachFlags(vp));
goto done;
} else if (vp) {
/* we're re-attaching a volume; clear out some old state */
VOL_UNLOCK;
/* allocate the volume structure */
- vp = nvp = (Volume *) malloc(sizeof(Volume));
- osi_Assert(vp != NULL);
- memset(vp, 0, sizeof(Volume));
+ vp = nvp = calloc(1, sizeof(Volume));
+ opr_Assert(vp != NULL);
queue_Init(&vp->vnode_list);
queue_Init(&vp->rx_call_list);
CV_INIT(&V_attachCV(vp), "vp attach", CV_DEFAULT, 0);
}
if (VRequiresPartLock()) {
- osi_Assert(VInit == 3);
+ opr_Assert(VInit == 3);
VLockPartition_r(partition);
} else if (programType == fileServer) {
#ifdef AFS_DEMAND_ATTACH_FS
}
}
- osi_Assert(vp != NULL);
+ opr_Assert(vp != NULL);
/* handle pre-attach races
*
if (!vp) {
vp = (Volume *) calloc(1, sizeof(Volume));
- osi_Assert(vp != NULL);
+ opr_Assert(vp != NULL);
vp->hashid = volumeId;
vp->device = partp->device;
vp->partition = partp;
*ec = 0;
/* volume utility should never call AttachByVp */
- osi_Assert(programType == fileServer);
+ opr_Assert(programType == fileServer);
volumeId = vp->hashid;
partp = vp->partition;
}
}
- osi_Assert(vp != NULL);
+ opr_Assert(vp != NULL);
VChangeState_r(vp, VOL_STATE_ATTACHING);
/* restore monotonically increasing stats */
{
int code;
- osi_Assert(programType != fileServer || VIsExclusiveState(V_attachState(vp)));
- osi_Assert(!(V_attachFlags(vp) & VOL_LOCKED));
+ opr_Assert(programType != fileServer
+ || VIsExclusiveState(V_attachState(vp)));
+ opr_Assert(!(V_attachFlags(vp) & VOL_LOCKED));
code = VLockVolumeByIdNB(vp->hashid, vp->partition, locktype);
if (code == 0) {
static void
VUnlockVolume(Volume *vp)
{
- osi_Assert(programType != fileServer || VIsExclusiveState(V_attachState(vp)));
- osi_Assert((V_attachFlags(vp) & VOL_LOCKED));
+ opr_Assert(programType != fileServer
+ || VIsExclusiveState(V_attachState(vp)));
+ opr_Assert((V_attachFlags(vp) & VOL_LOCKED));
VUnlockVolumeById(vp->hashid, vp->partition);
}
if (*ec) {
+ VOL_LOCK;
+ FreeVolumeHeader(vp);
+ VOL_UNLOCK;
return;
}
if (retry) {
switch (vp->pending_vol_op->vol_op_state) {
case FSSYNC_VolOpPending:
/* this should never happen */
- osi_Assert(vp->pending_vol_op->vol_op_state != FSSYNC_VolOpPending);
+ opr_Assert(vp->pending_vol_op->vol_op_state
+ != FSSYNC_VolOpPending);
break;
case FSSYNC_VolOpRunningUnknown:
/* this should never happen; we resolved 'unknown' above */
- osi_Assert(vp->pending_vol_op->vol_op_state != FSSYNC_VolOpRunningUnknown);
+ opr_Assert(vp->pending_vol_op->vol_op_state
+ != FSSYNC_VolOpRunningUnknown);
break;
case FSSYNC_VolOpRunningOffline:
if (*ec == VNOVOL) {
/* if the volume doesn't exist, skip straight to 'error' so we don't
* request a salvage */
- VOL_LOCK;
- goto error_notbroken;
+ goto unlocked_error;
}
if (!*ec) {
if (!*ec) {
struct IndexFileHeader iHead;
-#if OPENAFS_VOL_STATS
/*
* We just read in the diskstuff part of the header. If the detailed
* volume stats area has not yet been initialized, we should bzero the
memset((V_stat_area(vp)), 0, VOL_STATS_BYTES);
V_stat_initialized(vp) = 1;
}
-#endif /* OPENAFS_VOL_STATS */
(void)ReadHeader(ec, vp->vnodeIndex[vSmall].handle,
(char *)&iHead, sizeof(iHead),
} else if (*ec) {
/* volume operation in progress */
VOL_LOCK;
+ /* we have already transitioned the vp away from ATTACHING state, so we
+ * can go right to the end of attach2, and we do not need to transition
+ * to ERROR. */
goto error_notbroken;
}
#else /* AFS_DEMAND_ATTACH_FS */
#ifdef AFS_DEMAND_ATTACH_FS
error_state = VOL_STATE_ERROR;
/* see if we can recover */
- VRequestSalvage_r(ec, vp, SALVSYNC_NEEDED, 0 /*flags*/);
+ VRequestSalvage_r(ec, vp, SALVSYNC_NEEDED, VOL_SALVAGE_NO_OFFLINE);
#endif
}
#ifdef AFS_DEMAND_ATTACH_FS
return vp;
-#ifndef AFS_DEMAND_ATTACH_FS
unlocked_error:
-#endif
-
VOL_LOCK;
locked_error:
#ifdef AFS_DEMAND_ATTACH_FS
if (!VIsErrorState(V_attachState(vp))) {
+ if (VIsErrorState(error_state)) {
+ Log("attach2: forcing vol %u to error state (state %u flags 0x%x ec %d)\n",
+ vp->hashid, V_attachState(vp), V_attachFlags(vp), *ec);
+ }
VChangeState_r(vp, error_state);
}
#endif /* AFS_DEMAND_ATTACH_FS */
VReleaseVolumeHandles_r(vp);
}
- error_notbroken:
#ifdef AFS_DEMAND_ATTACH_FS
- VCheckSalvage(vp);
+ error_notbroken:
+ if (VCheckSalvage(vp) == VCHECK_SALVAGE_FAIL) {
+ /* The salvage could not be scheduled with the salvage server
+ * due to a hard error. Reset the error code to prevent retry loops by
+ * callers. */
+ if (*ec == VSALVAGING) {
+ *ec = VSALVAGE;
+ }
+ }
if (forcefree) {
FreeVolume(vp);
} else {
Error error;
vp = VGetVolume_r(&error, volumeId);
if (vp) {
- osi_Assert(V_inUse(vp) == 0);
+ opr_Assert(V_inUse(vp) == 0);
VDetachVolume_r(ec, vp);
}
return NULL;
VOfflineTimeout(struct timespec *ats)
{
if (vol_shutting_down) {
- osi_Assert(pthread_once(&shutdown_timeout_once, VShutdownTimeoutInit) == 0);
+ opr_Verify(pthread_once(&shutdown_timeout_once,
+ VShutdownTimeoutInit) == 0);
return shutdown_timeout;
} else {
return VCalcTimeout(ats, vol_opts.offline_timeout);
void
VPutVolume_r(Volume * vp)
{
- osi_Assert(--vp->nUsers >= 0);
+ opr_Verify(--vp->nUsers >= 0);
if (vp->nUsers == 0) {
VCheckOffline(vp);
ReleaseVolumeHeader(vp->header);
* - VOL_STATE_SHUTTING_DOWN
*/
if ((V_attachState(vp) == VOL_STATE_ERROR) ||
- (V_attachState(vp) == VOL_STATE_SHUTTING_DOWN) ||
- (V_attachState(vp) == VOL_STATE_GOING_OFFLINE)) {
+ (V_attachState(vp) == VOL_STATE_SHUTTING_DOWN)) {
*ec = VNOVOL;
vp = NULL;
break;
}
/*
- * short circuit with VOFFLINE for VOL_STATE_UNATTACHED and
+ * short circuit with VOFFLINE for VOL_STATE_UNATTACHED/GOING_OFFLINE and
* VNOVOL for VOL_STATE_DELETED
*/
if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+ (V_attachState(vp) == VOL_STATE_GOING_OFFLINE) ||
(V_attachState(vp) == VOL_STATE_DELETED)) {
if (vp->specialStatus) {
*ec = vp->specialStatus;
case VSALVAGING:
break;
case VOFFLINE:
- if (!vp->pending_vol_op) {
- endloop = 1;
+ endloop = 1;
+ if (vp->specialStatus) {
+ *ec = vp->specialStatus;
}
break;
+
default:
- *ec = VNOVOL;
+ if (vp->specialStatus) {
+ *ec = vp->specialStatus;
+ } else {
+ *ec = VNOVOL;
+ }
endloop = 1;
}
if (endloop) {
}
/*
- * this test MUST happen after VAttachVolymeByVp, so vol_op_state is
- * not VolOpRunningUnknown (attach2 would have converted it to Online
- * or Offline)
+ * this test MUST happen after VAttachVolymeByVp, so we have no
+ * conflicting vol op. (attach2 would have errored out if we had one;
+ * specifically attach_check_vop must have detected a conflicting vop)
*/
+ opr_Assert(!vp->pending_vol_op || vp->pending_vol_op->vol_op_state == FSSYNC_VolOpRunningOnline);
- /* only valid before/during demand attachment */
- osi_Assert(!vp->pending_vol_op || vp->pending_vol_op->vol_op_state != FSSYNC_VolOpRunningUnknown);
-
- /* deny getvolume due to running mutually exclusive vol op */
- if (vp->pending_vol_op && vp->pending_vol_op->vol_op_state==FSSYNC_VolOpRunningOffline) {
- /*
- * volume cannot remain online during this volume operation.
- * notify client.
- */
- if (vp->specialStatus) {
- /*
- * special status codes outrank normal VOFFLINE code
- */
- *ec = vp->specialStatus;
- if (client_ec) {
- *client_ec = vp->specialStatus;
- }
- } else {
- if (client_ec) {
- /* see CheckVnode() in afsfileprocs.c for an explanation
- * of this error code logic */
- afs_uint32 now = FT_ApproxTime();
- if ((vp->stats.last_vol_op + (10 * 60)) >= now) {
- *client_ec = VBUSY;
- } else {
- *client_ec = VRESTARTING;
- }
- }
- *ec = VOFFLINE;
- }
- VChangeState_r(vp, VOL_STATE_UNATTACHED);
- FreeVolumeHeader(vp);
- vp = NULL;
- break;
- }
#endif /* AFS_DEMAND_ATTACH_FS */
LoadVolumeHeader(ec, vp);
#else /* AFS_PTHREAD_ENV */
/* LWP has no timed wait, so the caller better not be
* expecting one */
- osi_Assert(!timeout);
+ opr_Assert(!timeout);
LWP_WaitProcess(VPutVolume);
#endif /* AFS_PTHREAD_ENV */
continue;
#endif /* AFS_DEMAND_ATTACH_FS */
not_inited:
- osi_Assert(vp || *ec);
+ opr_Assert(vp || *ec);
return vp;
}
{
Error error;
- osi_Assert(vp->nUsers > 0);
- osi_Assert(programType == fileServer);
+ opr_Assert(vp->nUsers > 0);
+ opr_Assert(programType == fileServer);
VCreateReservation_r(vp);
VWaitExclusiveState_r(vp);
void
VTakeOffline_r(Volume * vp)
{
- osi_Assert(vp->nUsers > 0);
- osi_Assert(programType == fileServer);
+ opr_Assert(vp->nUsers > 0);
+ opr_Assert(programType == fileServer);
vp->goingOffline = 1;
V_needsSalvaged(vp) = 1;
VolumeId vid = V_id(vp);
#endif
- osi_Assert(programType != volumeUtility && programType != volumeServer);
+ opr_Assert(programType != volumeUtility && programType != volumeServer);
if (!V_inUse(vp)) {
VPutVolume_r(vp);
return;
VOfflineForVolOp_r(Error *ec, Volume *vp, char *message)
{
int salvok = 1;
- osi_Assert(vp->pending_vol_op);
+ opr_Assert(vp->pending_vol_op);
if (!V_inUse(vp)) {
VPutVolume_r(vp);
*ec = 1;
VOL_UNLOCK;
#endif
fdP = IH_OPEN(V_diskDataHandle(vp));
- osi_Assert(fdP != NULL);
+ opr_Assert(fdP != NULL);
code = FDH_SYNC(fdP);
- osi_Assert(code == 0);
+ opr_Assert(code == 0);
FDH_CLOSE(fdP);
#ifdef AFS_DEMAND_ATTACH_FS
VOL_LOCK;
if (vp->goingOffline && !vp->nUsers) {
Error error;
- osi_Assert(programType == fileServer);
- osi_Assert((V_attachState(vp) != VOL_STATE_ATTACHED) &&
+ opr_Assert(programType == fileServer);
+ opr_Assert((V_attachState(vp) != VOL_STATE_ATTACHED) &&
(V_attachState(vp) != VOL_STATE_FREED) &&
(V_attachState(vp) != VOL_STATE_PREATTACHED) &&
(V_attachState(vp) != VOL_STATE_UNATTACHED) &&
if (vp->goingOffline && !vp->nUsers) {
Error error;
- osi_Assert(programType == fileServer);
+ opr_Assert(programType == fileServer);
ret = 1;
vp->goingOffline = 0;
void
VCancelReservation_r(Volume * vp)
{
- osi_Assert(--vp->nWaiters >= 0);
+ opr_Verify(--vp->nWaiters >= 0);
if (vp->nWaiters == 0) {
VCheckOffline(vp);
if (!VCheckDetach(vp)) {
FSSYNC_VolOp_info * info;
/* attach a vol op info node to the volume struct */
- info = (FSSYNC_VolOp_info *) malloc(sizeof(FSSYNC_VolOp_info));
- osi_Assert(info != NULL);
+ info = malloc(sizeof(FSSYNC_VolOp_info));
+ opr_Assert(info != NULL);
memcpy(info, vopinfo, sizeof(FSSYNC_VolOp_info));
vp->pending_vol_op = info;
* @param[in] vp pointer to volume object
*
* @return status code
- * @retval 0 no salvage scheduled
- * @retval 1 a salvage has been scheduled with the salvageserver
+ * @retval VCHECK_SALVAGE_OK (0) no pending salvage
+ * @retval VCHECK_SALVAGE_SCHEDULED (1) salvage has been scheduled
+ * @retval VCHECK_SALVAGE_ASYNC (2) salvage being scheduled
+ * @retval VCHECK_SALVAGE_DENIED (3) salvage not scheduled; denied
+ * @retval VCHECK_SALVAGE_FAIL (4) salvage not scheduled; failed
*
* @pre VOL_LOCK is held
*
static int
VCheckSalvage(Volume * vp)
{
- int ret = 0;
+ int ret = VCHECK_SALVAGE_OK;
+
#if defined(SALVSYNC_BUILD_CLIENT) || defined(FSSYNC_BUILD_CLIENT)
- if (vp->nUsers)
- return ret;
if (!vp->salvage.requested) {
- return ret;
+ return VCHECK_SALVAGE_OK;
+ }
+ if (vp->nUsers) {
+ return VCHECK_SALVAGE_ASYNC;
}
/* prevent recursion; some of the code below creates and removes
* lightweight refs, which can call VCheckSalvage */
if (vp->salvage.scheduling) {
- return ret;
+ return VCHECK_SALVAGE_ASYNC;
}
vp->salvage.scheduling = 1;
if (V_attachState(vp) == VOL_STATE_SALVAGE_REQ) {
if (!VOfflineForSalvage_r(vp)) {
vp->salvage.scheduling = 0;
- return ret;
+ return VCHECK_SALVAGE_FAIL;
}
}
if (vp->salvage.requested) {
- VScheduleSalvage_r(vp);
- ret = 1;
+ ret = VScheduleSalvage_r(vp);
}
vp->salvage.scheduling = 0;
#endif /* SALVSYNC_BUILD_CLIENT || FSSYNC_BUILD_CLIENT */
* @param[in] vp pointer to volume object
*
* @return operation status
- * @retval 0 salvage scheduled successfully
- * @retval 1 salvage not scheduled, or SALVSYNC/FSSYNC com error
+ * @retval VCHECK_SALVAGE_OK (0) no pending salvage
+ * @retval VCHECK_SALVAGE_SCHEDULED (1) salvage has been scheduled
+ * @retval VCHECK_SALVAGE_ASYNC (2) salvage being scheduled
+ * @retval VCHECK_SALVAGE_DENIED (3) salvage not scheduled; denied
+ * @retval VCHECK_SALVAGE_FAIL (4) salvage not scheduled; failed
*
* @pre
* @arg VOL_LOCK is held.
static int
VScheduleSalvage_r(Volume * vp)
{
- int ret=0;
+ int ret = VCHECK_SALVAGE_SCHEDULED;
int code = 0;
VolState state_save;
VThreadOptions_t * thread_opts;
char partName[16];
- osi_Assert(VCanUseSALVSYNC() || VCanUseFSSYNC());
+ opr_Verify(VCanUseSALVSYNC() || VCanUseFSSYNC());
if (vp->nWaiters || vp->nUsers) {
- return 1;
+ return VCHECK_SALVAGE_ASYNC;
}
/* prevent endless salvage,attach,salvage,attach,... loops */
- if (vp->stats.salvages >= SALVAGE_COUNT_MAX)
- return 1;
+ if (vp->stats.salvages >= SALVAGE_COUNT_MAX) {
+ return VCHECK_SALVAGE_FAIL;
+ }
/*
* don't perform salvsync ops on certain threads
thread_opts = &VThread_defaults;
}
if (thread_opts->disallow_salvsync || vol_disallow_salvsync) {
- return 1;
+ return VCHECK_SALVAGE_ASYNC;
}
if (vp->salvage.scheduled) {
- return ret;
+ return VCHECK_SALVAGE_SCHEDULED;
}
VCreateReservation_r(vp);
* XXX the scheduling process should really be done asynchronously
* to avoid fssync deadlocks
*/
- if (!vp->salvage.scheduled) {
+ if (vp->salvage.scheduled) {
+ ret = VCHECK_SALVAGE_SCHEDULED;
+ } else {
/* if we haven't previously scheduled a salvage, do so now
*
* set the volume to an exclusive state and drop the lock
state_save = VChangeState_r(vp, VOL_STATE_SALVSYNC_REQ);
VOL_UNLOCK;
- osi_Assert(try_SALVSYNC(vp, partName, &code) ||
- try_FSSYNC(vp, partName, &code));
+ opr_Verify(try_SALVSYNC(vp, partName, &code)
+ || try_FSSYNC(vp, partName, &code));
VOL_LOCK;
VChangeState_r(vp, state_save);
if (code == SYNC_OK) {
+ ret = VCHECK_SALVAGE_SCHEDULED;
vp->salvage.scheduled = 1;
vp->stats.last_salvage_req = FT_ApproxTime();
if (VCanUseSALVSYNC()) {
IncUInt64(&VStats.salvages);
}
} else {
- ret = 1;
switch(code) {
case SYNC_BAD_COMMAND:
case SYNC_COM_ERROR:
+ ret = VCHECK_SALVAGE_FAIL;
break;
case SYNC_DENIED:
+ ret = VCHECK_SALVAGE_DENIED;
Log("VScheduleSalvage_r: Salvage request for volume %lu "
"denied\n", afs_printable_uint32_lu(vp->hashid));
break;
+ case SYNC_FAILED:
+ ret = VCHECK_SALVAGE_FAIL;
+ Log("VScheduleSalvage_r: Salvage request for volume %lu "
+ "failed\n", afs_printable_uint32_lu(vp->hashid));
+ break;
default:
+ ret = VCHECK_SALVAGE_FAIL;
Log("VScheduleSalvage_r: Salvage request for volume %lu "
"received unknown protocol error %d\n",
afs_printable_uint32_lu(vp->hashid), code);
* this, as the caller may reference vp without any refs. Instead, it
* is the duty of the caller to inspect 'vp' after we return to see if
* needs to be freed. */
- osi_Assert(--vp->nWaiters >= 0);
+ opr_Verify(--vp->nWaiters >= 0);
return ret;
}
#endif /* SALVSYNC_BUILD_CLIENT || FSSYNC_BUILD_CLIENT */
VConnectFS_r(void)
{
int rc;
- osi_Assert((VInit == 2) &&
+ opr_Assert((VInit == 2) &&
(programType != fileServer) &&
(programType != salvager));
rc = FSYNC_clientInit();
void
VDisconnectFS_r(void)
{
- osi_Assert((programType != fileServer) &&
+ opr_Assert((programType != fileServer) &&
(programType != salvager));
FSYNC_clientFinis();
VSetVInit_r(2);
/* volume bitmap routines */
/***************************************************/
+/*
+ * Grow the bitmap by the defined increment
+ */
+void
+VGrowBitmap(struct vnodeIndex *index)
+{
+ byte *bp;
+
+ bp = realloc(index->bitmap, index->bitmapSize + VOLUME_BITMAP_GROWSIZE);
+ osi_Assert(bp != NULL);
+ index->bitmap = bp;
+ bp += index->bitmapSize;
+ memset(bp, 0, VOLUME_BITMAP_GROWSIZE);
+ index->bitmapOffset = index->bitmapSize;
+ index->bitmapSize += VOLUME_BITMAP_GROWSIZE;
+
+ return;
+}
+
/**
* allocate a vnode bitmap number for the vnode
*
bp += sizeof(bit32) /* i.e. 4 */ ;
}
/* No bit map entry--must grow bitmap */
- bp = (byte *)
- realloc(index->bitmap, index->bitmapSize + VOLUME_BITMAP_GROWSIZE);
- osi_Assert(bp != NULL);
- index->bitmap = bp;
- bp += index->bitmapSize;
- memset(bp, 0, VOLUME_BITMAP_GROWSIZE);
- index->bitmapOffset = index->bitmapSize;
- index->bitmapSize += VOLUME_BITMAP_GROWSIZE;
+ VGrowBitmap(index);
+ bp = index->bitmap + index->bitmapOffset;
*bp = 1;
ret = index->bitmapOffset * 8;
#ifdef AFS_DEMAND_ATTACH_FS
VOL_UNLOCK;
fdP = IH_OPEN(vip->handle);
- osi_Assert(fdP != NULL);
+ opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r");
- osi_Assert(file != NULL);
- vnode = (VnodeDiskObject *) malloc(vcp->diskSize);
- osi_Assert(vnode != NULL);
+ opr_Assert(file != NULL);
+ vnode = malloc(vcp->diskSize);
+ opr_Assert(vnode != NULL);
size = OS_SIZE(fdP->fd_fd);
- osi_Assert(size != -1);
+ opr_Assert(size != -1);
nVnodes = (size <= vcp->diskSize ? 0 : size - vcp->diskSize)
>> vcp->logSize;
vip->bitmapSize = ((nVnodes / 8) + 10) / 4 * 4; /* The 10 is a little extra so
* it that way */
#ifdef BITMAP_LATER
BitMap = (byte *) calloc(1, vip->bitmapSize);
- osi_Assert(BitMap != NULL);
+ opr_Assert(BitMap != NULL);
#else /* BITMAP_LATER */
vip->bitmap = (byte *) calloc(1, vip->bitmapSize);
- osi_Assert(vip->bitmap != NULL);
+ opr_Assert(vip->bitmap != NULL);
vip->bitmapOffset = 0;
#endif /* BITMAP_LATER */
if (STREAM_ASEEK(file, vcp->diskSize) != -1) {
vip->bitmap = BitMap;
vip->bitmapOffset = 0;
} else
- free((byte *) BitMap);
+ free(BitMap);
#endif /* BITMAP_LATER */
#ifdef AFS_DEMAND_ATTACH_FS
VChangeState_r(vp, state_save);
/* Volume Usage Statistics routines */
/***************************************************/
-#if OPENAFS_VOL_STATS
#define OneDay (86400) /* 24 hours' worth of seconds */
-#else
-#define OneDay (24*60*60) /* 24 hours */
-#endif /* OPENAFS_VOL_STATS */
static time_t
Midnight(time_t t) {
V_dayUse(vp) = 0;
V_dayUseDate(vp) = Midnight(now);
-#if OPENAFS_VOL_STATS
/*
* All we need to do is bzero the entire VOL_STATS_BYTES of
* the detailed volume statistics area.
*/
memset((V_stat_area(vp)), 0, VOL_STATS_BYTES);
-#endif /* OPENAFS_VOL_STATS */
- }
+ }
/*It's been more than a day of collection */
/*
return;
if (UpdateList == NULL) {
updateSize = UPDATE_LIST_SIZE;
- UpdateList = (VolumeId *) malloc(sizeof(VolumeId) * updateSize);
+ UpdateList = malloc(sizeof(VolumeId) * updateSize);
} else {
if (nUpdatedVolumes == updateSize) {
updateSize <<= 1;
Log("warning: there is likely a bug in the volume update scanner\n");
return;
}
- UpdateList =
- (VolumeId *) realloc(UpdateList,
- sizeof(VolumeId) * updateSize);
+ UpdateList = realloc(UpdateList,
+ sizeof(VolumeId) * updateSize);
}
}
- osi_Assert(UpdateList != NULL);
+ opr_Assert(UpdateList != NULL);
UpdateList[nUpdatedVolumes++] = V_id(vp);
#endif /* !AFS_DEMAND_ATTACH_FS */
}
volume_LRU.scanner_state = VLRU_SCANNER_STATE_OFFLINE;
if (programType == fileServer) {
CV_INIT(&volume_LRU.cv, "vol lru", CV_DEFAULT, 0);
- osi_Assert(pthread_attr_init(&attrs) == 0);
- osi_Assert(pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED) == 0);
- osi_Assert(pthread_create(&tid, &attrs, &VLRU_ScannerThread, NULL) == 0);
+ opr_Verify(pthread_attr_init(&attrs) == 0);
+ opr_Verify(pthread_attr_setdetachstate(&attrs,
+ PTHREAD_CREATE_DETACHED) == 0);
+ opr_Verify(pthread_create(&tid, &attrs,
+ &VLRU_ScannerThread, NULL) == 0);
}
}
if (!VLRU_enabled)
return;
- osi_Assert(queue_IsNotOnQueue(&vp->vlru));
+ opr_Assert(queue_IsNotOnQueue(&vp->vlru));
vp->vlru.idx = VLRU_QUEUE_INVALID;
}
if (queue_IsNotOnQueue(&vp->vlru))
return;
- osi_Assert(V_attachFlags(vp) & VOL_ON_VLRU);
+ opr_Assert(V_attachFlags(vp) & VOL_ON_VLRU);
/* update the access timestamp */
vp->stats.last_get = FT_ApproxTime();
Volume ** salv_flag_vec = NULL;
int salv_vec_offset = 0;
- osi_Assert(idx == VLRU_QUEUE_MID || idx == VLRU_QUEUE_OLD);
+ opr_Assert(idx == VLRU_QUEUE_MID || idx == VLRU_QUEUE_OLD);
/* get exclusive access to two chains, and drop the glock */
VLRU_Wait_r(&volume_LRU.q[idx-1]);
/* no big deal if this allocation fails */
if (volume_LRU.q[idx].len) {
- salv_flag_vec = (Volume **) malloc(volume_LRU.q[idx].len * sizeof(Volume *));
+ salv_flag_vec = malloc(volume_LRU.q[idx].len * sizeof(Volume *));
}
now = FT_ApproxTime();
Volume * vp;
int i, locked = 1;
- osi_Assert(idx == VLRU_QUEUE_NEW || idx == VLRU_QUEUE_CANDIDATE);
+ opr_Assert(idx == VLRU_QUEUE_NEW || idx == VLRU_QUEUE_CANDIDATE);
/* gain exclusive access to the idx VLRU */
VLRU_Wait_r(&volume_LRU.q[idx]);
idx = vp->vlru.idx;
- osi_Assert(idx == VLRU_QUEUE_NEW);
+ opr_Assert(idx == VLRU_QUEUE_NEW);
if (vp->stats.last_get <= thresh) {
/* move to candidate pool */
static void
VLRU_BeginExclusive_r(struct VLRU_q * q)
{
- osi_Assert(q->busy == 0);
+ opr_Assert(q->busy == 0);
q->busy = 1;
}
static void
VLRU_EndExclusive_r(struct VLRU_q * q)
{
- osi_Assert(q->busy);
+ opr_Assert(q->busy);
q->busy = 0;
CV_BROADCAST(&q->cv);
}
afs_uint32 ts_save;
int ret = 0;
- osi_Assert(vp->vlru.idx == VLRU_QUEUE_CANDIDATE);
+ opr_Assert(vp->vlru.idx == VLRU_QUEUE_CANDIDATE);
ts_save = vp->stats.last_get;
if (ts_save > thresh)
vp = NULL;
} else {
/* pull it off the VLRU */
- osi_Assert(vp->vlru.idx == VLRU_QUEUE_CANDIDATE);
+ opr_Assert(vp->vlru.idx == VLRU_QUEUE_CANDIDATE);
volume_LRU.q[VLRU_QUEUE_CANDIDATE].len--;
queue_Remove(&vp->vlru);
vp->vlru.idx = VLRU_QUEUE_INVALID;
volume_hdr_LRU.stats.used = howMany;
volume_hdr_LRU.stats.attached = 0;
hp = (struct volHeader *)(calloc(howMany, sizeof(struct volHeader)));
- osi_Assert(hp != NULL);
+ opr_Assert(hp != NULL);
while (howMany--)
/* We are using ReleaseVolumeHeader to initialize the values on the header list
if (programType != fileServer) {
/* for volume utilities, we allocate volHeaders as needed */
if (!vp->header) {
- hd = (struct volHeader *)calloc(1, sizeof(*vp->header));
- osi_Assert(hd != NULL);
+ hd = calloc(1, sizeof(*vp->header));
+ opr_Assert(hd != NULL);
vp->header = hd;
hd->back = vp;
#ifdef AFS_DEMAND_ATTACH_FS
* still available. pull it off the lru and return */
hd = vp->header;
queue_Remove(hd);
- osi_Assert(hd->back == vp);
+ opr_Assert(hd->back == vp);
#ifdef AFS_DEMAND_ATTACH_FS
V_attachFlags(vp) &= ~(VOL_HDR_IN_LRU);
#endif
if (!hd) {
/* LRU is empty, so allocate a new volHeader
* this is probably indicative of a leak, so let the user know */
- hd = (struct volHeader *)calloc(1, sizeof(struct volHeader));
- osi_Assert(hd != NULL);
+ hd = calloc(1, sizeof(struct volHeader));
+ opr_Assert(hd != NULL);
if (!everLogged) {
Log("****Allocated more volume headers, probably leak****\n");
everLogged = 1;
#ifdef AFS_DEMAND_ATTACH_FS
/* GetVolHeaderFromLRU had better not give us back a header
* with a volume in exclusive state... */
- osi_Assert(!VIsExclusiveState(V_attachState(hd->back)));
+ opr_Assert(!VIsExclusiveState(V_attachState(hd->back)));
#endif
if (hd->diskstuff.inUse) {
VolumeHashTable.Table = (VolumeHashChainHead *) calloc(VolumeHashTable.Size,
sizeof(VolumeHashChainHead));
- osi_Assert(VolumeHashTable.Table != NULL);
+ opr_Assert(VolumeHashTable.Table != NULL);
for (i=0; i < VolumeHashTable.Size; i++) {
queue_Init(&VolumeHashTable.Table[i]);
/* search the chain for this volume id */
for(queue_Scan(head, vp, np, Volume)) {
looks++;
- if ((vp->hashid == volumeId)) {
+ if (vp->hashid == volumeId) {
break;
}
}
static void
VHashBeginExclusive_r(VolumeHashChainHead * head)
{
- osi_Assert(head->busy == 0);
+ opr_Assert(head->busy == 0);
head->busy = 1;
}
static void
VHashEndExclusive_r(VolumeHashChainHead * head)
{
- osi_Assert(head->busy);
+ opr_Assert(head->busy);
head->busy = 0;
CV_BROADCAST(&head->chain_busy_cv);
}
static void
VVByPListBeginExclusive_r(struct DiskPartition64 * dp)
{
- osi_Assert(dp->vol_list.busy == 0);
+ opr_Assert(dp->vol_list.busy == 0);
dp->vol_list.busy = 1;
}
static void
VVByPListEndExclusive_r(struct DiskPartition64 * dp)
{
- osi_Assert(dp->vol_list.busy);
+ opr_Assert(dp->vol_list.busy);
dp->vol_list.busy = 0;
CV_BROADCAST(&dp->vol_list.cv);
}