#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.
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 */
}
/* 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);
/* 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;
}
}
* - 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 */
}
if (*ec) {
+ VOL_LOCK;
+ FreeVolumeHeader(vp);
+ VOL_UNLOCK;
return;
}
if (retry) {
if (*ec == VNOVOL) {
/* if the volume doesn't exist, skip straight to 'error' so we don't
* request a salvage */
- goto unlocked_error;
+ VOL_LOCK;
+ goto error_notbroken;
}
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),
goto locked_error;
} else if (*ec) {
/* volume operation in progress */
- goto unlocked_error;
+ VOL_LOCK;
+ goto error_notbroken;
}
#else /* AFS_DEMAND_ATTACH_FS */
if (*ec) {
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);
if (forcefree) {
* - 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) {
vp = NULL;
break;
}
-#endif
-#ifdef AFS_DEMAND_ATTACH_FS
+ if (VIsErrorState(V_attachState(vp))) {
+ /* make sure we don't take a vp in VOL_STATE_ERROR state and use
+ * it, or transition it out of that state */
+ if (!*ec) {
+ *ec = VNOVOL;
+ }
+ vp = NULL;
+ break;
+ }
+
/*
- * 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)
*/
+ osi_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);
Log("VScheduleSalvage_r: Salvage request for volume %lu "
"denied\n", afs_printable_uint32_lu(vp->hashid));
break;
+ case SYNC_FAILED:
+ Log("VScheduleSalvage_r: Salvage request for volume %lu "
+ "failed\n", afs_printable_uint32_lu(vp->hashid));
+ break;
default:
Log("VScheduleSalvage_r: Salvage request for volume %lu "
"received unknown protocol error %d\n",
/* 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;
*bp = 1;
ret = index->bitmapOffset * 8;
#ifdef AFS_DEMAND_ATTACH_FS
/* 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 */
/*
/* search the chain for this volume id */
for(queue_Scan(head, vp, np, Volume)) {
looks++;
- if ((vp->hashid == volumeId)) {
+ if (vp->hashid == volumeId) {
break;
}
}