summaryrefslogtreecommitdiffstats
path: root/sys/dev/vinum
diff options
context:
space:
mode:
authorgrog <grog@FreeBSD.org>2000-06-07 03:33:09 +0000
committergrog <grog@FreeBSD.org>2000-06-07 03:33:09 +0000
commit5d65db6c806dee112012b31e69d90fd0053d60cf (patch)
tree57a75a2714d9e141316ab79ead0e93d69b7a69a4 /sys/dev/vinum
parenta7727e3464742ae112356fc610bec6bf599199db (diff)
downloadFreeBSD-src-5d65db6c806dee112012b31e69d90fd0053d60cf.zip
FreeBSD-src-5d65db6c806dee112012b31e69d90fd0053d60cf.tar.gz
revive_block:
Fix several instances of breakage in RAID-5 revive code. Tidy up code. parityops: Don't attempt to do anything if the plex is degraded or worse. parityrebuild: Add comments. Perform transfers in correct length.
Diffstat (limited to 'sys/dev/vinum')
-rw-r--r--sys/dev/vinum/vinumrevive.c71
1 files changed, 36 insertions, 35 deletions
diff --git a/sys/dev/vinum/vinumrevive.c b/sys/dev/vinum/vinumrevive.c
index 07b7390..f02c5e8 100644
--- a/sys/dev/vinum/vinumrevive.c
+++ b/sys/dev/vinum/vinumrevive.c
@@ -65,8 +65,8 @@ revive_block(int sdno)
int size; /* size of revive block, bytes */
daddr_t plexblkno; /* lblkno in plex */
int psd; /* parity subdisk number */
- int stripe; /* stripe number */
- int isparity = 0; /* set if this is the parity stripe */
+ u_int64_t stripe; /* stripe number */
+ int paritysd = 0; /* set if this is the parity stripe */
struct rangelock *lock; /* for locking */
daddr_t stripeoffset; /* offset in stripe */
@@ -93,19 +93,6 @@ revive_block(int sdno)
size = min(sd->revive_blocksize >> DEV_BSHIFT, sd->sectors - sd->revived) << DEV_BSHIFT;
sd->reviver = curproc->p_pid; /* note who last had a bash at it */
- s = splbio();
- bp = geteblk(size); /* Get a buffer */
- splx(s);
- if (bp == NULL)
- return ENOMEM;
-
- /*
- * Amount to transfer: block size, unless it
- * would overlap the end
- */
- bp->b_bcount = size;
- bp->b_resid = bp->b_bcount;
-
/* Now decide where to read from */
switch (plex->organization) {
case plex_concat:
@@ -117,7 +104,6 @@ revive_block(int sdno)
plexblkno = sd->plexoffset /* base */
+ (sd->revived - stripeoffset) * plex->subdisks /* offset to beginning of stripe */
+ sd->revived % plex->stripesize; /* offset from beginning of stripe */
- lock = lockrange(plexblkno << DEV_BSHIFT, bp, plex); /* lock it */
break;
case plex_raid4:
@@ -127,11 +113,14 @@ revive_block(int sdno)
+ (sd->revived - stripeoffset) * (plex->subdisks - 1) /* offset to beginning of stripe */
+stripeoffset; /* offset from beginning of stripe */
stripe = (sd->revived / plex->stripesize); /* stripe number */
+
+ /* Make sure we don't go beyond the end of the band. */
+ size = min(size, (plex->stripesize - stripeoffset) << DEV_BSHIFT);
if (plex->organization == plex_raid4)
psd = plex->subdisks - 1; /* parity subdisk for this stripe */
else
psd = plex->subdisks - 1 - stripe % plex->subdisks; /* parity subdisk for this stripe */
- isparity = plex->sdnos[psd] == sdno; /* note if it's the parity subdisk */
+ paritysd = plex->sdnos[psd] == sdno; /* note if it's the parity subdisk */
/*
* Now adjust for the strangenesses
@@ -139,29 +128,33 @@ revive_block(int sdno)
*/
if (sd->plexsdno > psd) /* beyond the parity stripe, */
plexblkno -= plex->stripesize; /* one stripe less */
- if (!isparity)
- lock = lockrange(plexblkno << DEV_BSHIFT, bp, plex); /* lock it */
+ else if (paritysd)
+ plexblkno -= plex->stripesize * sd->plexsdno; /* go back to the beginning of the band */
break;
case plex_disorg: /* to keep the compiler happy */
}
- if (isparity) { /* we're reviving a parity block, */
- /*
- * We have calculated plexblkno assuming it
- * was a data block. Go back to the beginning
- * of the band.
- */
- plexblkno -= plex->stripesize * sd->plexsdno;
-
- /* Don't need that bp after all, we'll get a new one. */
- bp->b_flags |= B_INVAL;
- brelse(bp); /* is this kosher? */
- bp = parityrebuild(plex, plexblkno, size, rebuildparity, &lock, NULL); /* do the grunt work */
+ if (paritysd) { /* we're reviving a parity block, */
+ bp = parityrebuild(plex, sd->revived, size, rebuildparity, &lock, NULL); /* do the grunt work */
if (bp == NULL) /* no buffer space */
return ENOMEM; /* chicken out */
} else { /* data block */
+ s = splbio();
+ bp = geteblk(size); /* Get a buffer */
+ splx(s);
+ if (bp == NULL)
+ return ENOMEM;
+
+ /*
+ * Amount to transfer: block size, unless it
+ * would overlap the end.
+ */
+ bp->b_bcount = size;
+ bp->b_resid = bp->b_bcount;
bp->b_blkno = plexblkno; /* start here */
+ if (isstriped(plex)) /* we need to lock striped plexes */
+ lock = lockrange(plexblkno << DEV_BSHIFT, bp, plex); /* lock it */
if (vol != NULL) /* it's part of a volume, */
/*
* First, read the data from the volume. We
@@ -278,6 +271,10 @@ parityops(struct vinum_ioctl_msg *data)
if (!isparity(plex)) { /* not RAID-4 or RAID-5 */
reply->error = EINVAL;
return;
+ } else if (plex->state < plex_flaky) {
+ reply->error = EIO;
+ strcpy(reply->msg, "Plex is not completely accessible\n");
+ return;
}
pstripe = data->offset;
stripe = pstripe / plex->stripesize; /* stripe number */
@@ -348,6 +345,10 @@ parityops(struct vinum_ioctl_msg *data)
* errorloc. The caller can set the value of
* the pointer to NULL if this is called for
* rebuilding parity.
+ *
+ * pstripe is the subdisk-relative base address of
+ * the data to be reconstructed, size is the size
+ * of the transfer in bytes.
*/
struct buf *
parityrebuild(struct plex *plex,
@@ -360,7 +361,7 @@ parityrebuild(struct plex *plex,
int error;
int s;
int sdno;
- int stripe; /* stripe number */
+ u_int64_t stripe; /* stripe number */
int *parity_buf; /* buffer address for current parity block */
int *newparity_buf; /* and for new parity block */
int mysize; /* I/O transfer size for this transfer */
@@ -418,7 +419,7 @@ parityrebuild(struct plex *plex,
bpp[sdno]->b_dev = VINUM_SD(plex->sdnos[sdno]); /* device number */
bpp[sdno]->b_iocmd = BIO_READ; /* either way, read it */
bpp[sdno]->b_flags = 0;
- bpp[sdno]->b_bcount = bpp[sdno]->b_bufsize;
+ bpp[sdno]->b_bcount = mysize;
bpp[sdno]->b_resid = bpp[sdno]->b_bcount;
bpp[sdno]->b_blkno = pstripe; /* transfer from here */
}
@@ -555,7 +556,7 @@ initsd(int sdno, int verify)
if (bp == NULL)
return ENOMEM;
- bp->b_bcount = bp->b_bufsize;
+ bp->b_bcount = size;
bp->b_resid = bp->b_bcount;
bp->b_blkno = sd->initialized; /* write it to here */
bzero(bp->b_data, bp->b_bcount);
@@ -579,7 +580,7 @@ initsd(int sdno, int verify)
splx(s);
error = ENOMEM;
} else {
- bp->b_bcount = bp->b_bufsize;
+ bp->b_bcount = size;
bp->b_resid = bp->b_bcount;
bp->b_blkno = sd->initialized; /* read from here */
bp->b_dev = VINUM_SD(sdno); /* create the device number */
OpenPOWER on IntegriCloud