summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2004-11-15 13:04:55 +0000
committerle <le@FreeBSD.org>2004-11-15 13:04:55 +0000
commit255694f7fcc31bc747caaa62a7db837cdc9899e7 (patch)
tree79be103502ca94d8eee38fb1c0b5c8560b274cab /sys
parentddaaf2c2ee77cb7c0970dbb19af234fddb6f0b9e (diff)
downloadFreeBSD-src-255694f7fcc31bc747caaa62a7db837cdc9899e7.zip
FreeBSD-src-255694f7fcc31bc747caaa62a7db837cdc9899e7.tar.gz
Move RAID5 offset calculation into a separate function to avoid
code duplication.
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/vinum/geom_vinum_raid5.c106
1 files changed, 56 insertions, 50 deletions
diff --git a/sys/geom/vinum/geom_vinum_raid5.c b/sys/geom/vinum/geom_vinum_raid5.c
index 9ba02e8..11bb931 100644
--- a/sys/geom/vinum/geom_vinum_raid5.c
+++ b/sys/geom/vinum/geom_vinum_raid5.c
@@ -44,6 +44,9 @@ __FBSDID("$FreeBSD$");
#include <geom/vinum/geom_vinum_raid5.h>
#include <geom/vinum/geom_vinum.h>
+int gv_raid5_offset(struct gv_plex *, off_t, off_t, off_t *, off_t *,
+ int *, int *);
+
/*
* Check if the stripe that the work packet wants is already being used by
* some other work packet.
@@ -84,27 +87,12 @@ gv_rebuild_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
struct gv_sd *broken, *s;
struct gv_bioq *bq;
struct bio *cbp, *pbp;
- off_t len_left, real_len, real_off, stripeend, stripeoff, stripestart;
+ off_t real_len, real_off;
if (p == NULL || LIST_EMPTY(&p->subdisks))
return (ENXIO);
- /* Offset of the start address from the start of the stripe. */
- stripeoff = boff % (p->stripesize * (p->sdcount - 1));
- KASSERT(stripeoff >= 0, ("gv_build_raid5_request: stripeoff < 0"));
-
- /* The offset of the stripe on this subdisk. */
- stripestart = (boff - stripeoff) / (p->sdcount - 1);
- KASSERT(stripestart >= 0, ("gv_build_raid5_request: stripestart < 0"));
-
- stripeoff %= p->stripesize;
-
- /* The offset of the request on this subdisk. */
- real_off = stripestart + stripeoff;
-
- stripeend = stripestart + p->stripesize;
- len_left = stripeend - real_off;
- KASSERT(len_left >= 0, ("gv_build_raid5_request: len_left < 0"));
+ gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, NULL);
/* Find the right subdisk. */
broken = NULL;
@@ -137,12 +125,11 @@ gv_rebuild_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
return (ENXIO);
}
- real_len = (bcount <= len_left) ? bcount : len_left;
wp->length = real_len;
wp->data = addr;
wp->lockbase = real_off;
- KASSERT(wp->length >= 0, ("gv_build_raid5_request: wp->length < 0"));
+ KASSERT(wp->length >= 0, ("gv_rebuild_raid5: wp->length < 0"));
/* Read all subdisks. */
LIST_FOREACH(s, &p->subdisks, in_plex) {
@@ -198,7 +185,7 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
struct gv_bioq *bq;
struct bio *cbp, *pbp;
int i, psdno, sdno, type;
- off_t len_left, real_len, real_off, stripeend, stripeoff, stripestart;
+ off_t real_len, real_off;
gp = bp->bio_to->geom;
@@ -213,35 +200,7 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
type = REQ_TYPE_NORMAL;
original = parity = broken = NULL;
- /* The number of the subdisk containing the parity stripe. */
- psdno = p->sdcount - 1 - ( boff / (p->stripesize * (p->sdcount - 1))) %
- p->sdcount;
- KASSERT(psdno >= 0, ("gv_build_raid5_request: psdno < 0"));
-
- /* Offset of the start address from the start of the stripe. */
- stripeoff = boff % (p->stripesize * (p->sdcount - 1));
- KASSERT(stripeoff >= 0, ("gv_build_raid5_request: stripeoff < 0"));
-
- /* The number of the subdisk where the stripe resides. */
- sdno = stripeoff / p->stripesize;
- KASSERT(sdno >= 0, ("gv_build_raid5_request: sdno < 0"));
-
- /* At or past parity subdisk. */
- if (sdno >= psdno)
- sdno++;
-
- /* The offset of the stripe on this subdisk. */
- stripestart = (boff - stripeoff) / (p->sdcount - 1);
- KASSERT(stripestart >= 0, ("gv_build_raid5_request: stripestart < 0"));
-
- stripeoff %= p->stripesize;
-
- /* The offset of the request on this subdisk. */
- real_off = stripestart + stripeoff;
-
- stripeend = stripestart + p->stripesize;
- len_left = stripeend - real_off;
- KASSERT(len_left >= 0, ("gv_build_raid5_request: len_left < 0"));
+ gv_raid5_offset(p, boff, bcount, &real_off, &real_len, &sdno, &psdno);
/* Find the right subdisks. */
i = 0;
@@ -270,7 +229,6 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
type = REQ_TYPE_NOPARITY;
}
- real_len = (bcount <= len_left) ? bcount : len_left;
wp->length = real_len;
wp->data = addr;
wp->lockbase = real_off;
@@ -481,3 +439,51 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
return (0);
}
+
+/* Calculate the offsets in the various subdisks for a RAID5 request. */
+int
+gv_raid5_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
+ off_t *real_len, int *sdno, int *psdno)
+{
+ int sd, psd;
+ off_t len_left, stripeend, stripeoff, stripestart;
+
+ /* The number of the subdisk containing the parity stripe. */
+ psd = p->sdcount - 1 - ( boff / (p->stripesize * (p->sdcount - 1))) %
+ p->sdcount;
+ KASSERT(psdno >= 0, ("gv_raid5_offset: psdno < 0"));
+
+ /* Offset of the start address from the start of the stripe. */
+ stripeoff = boff % (p->stripesize * (p->sdcount - 1));
+ KASSERT(stripeoff >= 0, ("gv_raid5_offset: stripeoff < 0"));
+
+ /* The number of the subdisk where the stripe resides. */
+ sd = stripeoff / p->stripesize;
+ KASSERT(sdno >= 0, ("gv_raid5_offset: sdno < 0"));
+
+ /* At or past parity subdisk. */
+ if (sd >= psd)
+ sd++;
+
+ /* The offset of the stripe on this subdisk. */
+ stripestart = (boff - stripeoff) / (p->sdcount - 1);
+ KASSERT(stripestart >= 0, ("gv_raid5_offset: stripestart < 0"));
+
+ stripeoff %= p->stripesize;
+
+ /* The offset of the request on this subdisk. */
+ *real_off = stripestart + stripeoff;
+
+ stripeend = stripestart + p->stripesize;
+ len_left = stripeend - *real_off;
+ KASSERT(len_left >= 0, ("gv_raid5_offset: len_left < 0"));
+
+ *real_len = (bcount <= len_left) ? bcount : len_left;
+
+ if (sdno != NULL)
+ *sdno = sd;
+ if (psdno != NULL)
+ *psdno = psd;
+
+ return (0);
+}
OpenPOWER on IntegriCloud