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:
parent
24cd998f34
commit
fe8b826551
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=61352
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user