1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-19 15:33:56 +00:00

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.
This commit is contained in:
Greg Lehey 2000-06-07 03:33:09 +00:00
parent 24cd998f34
commit fe8b826551
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=61352

View File

@ -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 */