xref: /freebsd/sys/geom/vinum/geom_vinum_raid5.c (revision a0b9e2e854027e6ff61fb075a1309dbc71c42b54)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004, 2007 Lukas Ertl
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/bio.h>
34 #include <sys/lock.h>
35 #include <sys/malloc.h>
36 #include <sys/systm.h>
37 
38 #include <geom/geom.h>
39 #include <geom/geom_dbg.h>
40 #include <geom/vinum/geom_vinum_var.h>
41 #include <geom/vinum/geom_vinum_raid5.h>
42 #include <geom/vinum/geom_vinum.h>
43 
44 static int		gv_raid5_offset(struct gv_plex *, off_t, off_t,
45 			    off_t *, off_t *, int *, int *, int);
46 static struct bio *	gv_raid5_clone_bio(struct bio *, struct gv_sd *,
47 			    struct gv_raid5_packet *, caddr_t, int);
48 static int	gv_raid5_request(struct gv_plex *, struct gv_raid5_packet *,
49 		    struct bio *, caddr_t, off_t, off_t, int *);
50 static int	gv_raid5_check(struct gv_plex *, struct gv_raid5_packet *,
51 		    struct bio *, caddr_t, off_t, off_t);
52 static int	gv_raid5_rebuild(struct gv_plex *, struct gv_raid5_packet *,
53 		    struct bio *, caddr_t, off_t, off_t);
54 
55 struct gv_raid5_packet *
56 gv_raid5_start(struct gv_plex *p, struct bio *bp, caddr_t addr, off_t boff,
57     off_t bcount)
58 {
59 	struct bio *cbp;
60 	struct gv_raid5_packet *wp, *wp2;
61 	struct gv_bioq *bq, *bq2;
62 	int err, delay;
63 
64 	delay = 0;
65 	wp = g_malloc(sizeof(*wp), M_WAITOK | M_ZERO);
66 	wp->bio = bp;
67 	wp->waiting = NULL;
68 	wp->parity = NULL;
69 	TAILQ_INIT(&wp->bits);
70 
71 	if (bp->bio_pflags & GV_BIO_REBUILD)
72 		err = gv_raid5_rebuild(p, wp, bp, addr, boff, bcount);
73 	else if (bp->bio_pflags & GV_BIO_CHECK)
74 		err = gv_raid5_check(p, wp, bp, addr, boff, bcount);
75 	else
76 		err = gv_raid5_request(p, wp, bp, addr, boff, bcount, &delay);
77 
78 	/* Means we have a delayed request. */
79 	if (delay) {
80 		g_free(wp);
81 		return (NULL);
82 	}
83 
84 	/*
85 	 * Building the sub-request failed, we probably need to clean up a lot.
86 	 */
87 	if (err) {
88 		G_VINUM_LOGREQ(0, bp, "raid5 plex request failed.");
89 		TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
90 			TAILQ_REMOVE(&wp->bits, bq, queue);
91 			g_free(bq);
92 		}
93 		if (wp->waiting != NULL) {
94 			if (wp->waiting->bio_cflags & GV_BIO_MALLOC)
95 				g_free(wp->waiting->bio_data);
96 			gv_drive_done(wp->waiting->bio_caller1);
97 			g_destroy_bio(wp->waiting);
98 		}
99 		if (wp->parity != NULL) {
100 			if (wp->parity->bio_cflags & GV_BIO_MALLOC)
101 				g_free(wp->parity->bio_data);
102 			gv_drive_done(wp->parity->bio_caller1);
103 			g_destroy_bio(wp->parity);
104 		}
105 		g_free(wp);
106 
107 		TAILQ_FOREACH_SAFE(wp, &p->packets, list, wp2) {
108 			if (wp->bio != bp)
109 				continue;
110 
111 			TAILQ_REMOVE(&p->packets, wp, list);
112 			TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
113 				TAILQ_REMOVE(&wp->bits, bq, queue);
114 				g_free(bq);
115 			}
116 			g_free(wp);
117 		}
118 
119 		cbp = bioq_takefirst(p->bqueue);
120 		while (cbp != NULL) {
121 			if (cbp->bio_cflags & GV_BIO_MALLOC)
122 				g_free(cbp->bio_data);
123 			gv_drive_done(cbp->bio_caller1);
124 			g_destroy_bio(cbp);
125 			cbp = bioq_takefirst(p->bqueue);
126 		}
127 
128 		/* If internal, stop and reset state. */
129 		if (bp->bio_pflags & GV_BIO_INTERNAL) {
130 			if (bp->bio_pflags & GV_BIO_MALLOC)
131 				g_free(bp->bio_data);
132 			g_destroy_bio(bp);
133 			/* Reset flags. */
134 			p->flags &= ~(GV_PLEX_SYNCING | GV_PLEX_REBUILDING |
135 			    GV_PLEX_GROWING);
136 			return (NULL);
137 		}
138 		g_io_deliver(bp, err);
139 		return (NULL);
140 	}
141 
142 	return (wp);
143 }
144 
145 /*
146  * Check if the stripe that the work packet wants is already being used by
147  * some other work packet.
148  */
149 int
150 gv_stripe_active(struct gv_plex *p, struct bio *bp)
151 {
152 	struct gv_raid5_packet *wp, *owp;
153 	int overlap;
154 
155 	wp = bp->bio_caller2;
156 	if (wp->lockbase == -1)
157 		return (0);
158 
159 	overlap = 0;
160 	TAILQ_FOREACH(owp, &p->packets, list) {
161 		if (owp == wp)
162 			break;
163 		if ((wp->lockbase >= owp->lockbase) &&
164 		    (wp->lockbase <= owp->lockbase + owp->length)) {
165 			overlap++;
166 			break;
167 		}
168 		if ((wp->lockbase <= owp->lockbase) &&
169 		    (wp->lockbase + wp->length >= owp->lockbase)) {
170 			overlap++;
171 			break;
172 		}
173 	}
174 
175 	return (overlap);
176 }
177 
178 static int
179 gv_raid5_check(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
180     caddr_t addr, off_t boff, off_t bcount)
181 {
182 	struct gv_sd *parity, *s;
183 	struct gv_bioq *bq;
184 	struct bio *cbp;
185 	int i, psdno;
186 	off_t real_len, real_off;
187 
188 	if (p == NULL || LIST_EMPTY(&p->subdisks))
189 		return (ENXIO);
190 
191 	gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, &psdno, 1);
192 
193 	/* Find the right subdisk. */
194 	parity = NULL;
195 	i = 0;
196 	LIST_FOREACH(s, &p->subdisks, in_plex) {
197 		if (i == psdno) {
198 			parity = s;
199 			break;
200 		}
201 		i++;
202 	}
203 
204 	/* Parity stripe not found. */
205 	if (parity == NULL)
206 		return (ENXIO);
207 
208 	if (parity->state != GV_SD_UP)
209 		return (ENXIO);
210 
211 	wp->length = real_len;
212 	wp->data = addr;
213 	wp->lockbase = real_off;
214 
215 	/* Read all subdisks. */
216 	LIST_FOREACH(s, &p->subdisks, in_plex) {
217 		/* Skip the parity subdisk. */
218 		if (s == parity)
219 			continue;
220 		/* Skip growing subdisks. */
221 		if (s->flags & GV_SD_GROW)
222 			continue;
223 
224 		cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
225 		if (cbp == NULL)
226 			return (ENOMEM);
227 		cbp->bio_cmd = BIO_READ;
228 
229 		bioq_insert_tail(p->bqueue, cbp);
230 
231 		bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
232 		bq->bp = cbp;
233 		TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
234 	}
235 
236 	/* Read the parity data. */
237 	cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
238 	if (cbp == NULL)
239 		return (ENOMEM);
240 	cbp->bio_cmd = BIO_READ;
241 	wp->waiting = cbp;
242 
243 	/*
244 	 * In case we want to rebuild the parity, create an extra BIO to write
245 	 * it out.  It also acts as buffer for the XOR operations.
246 	 */
247 	cbp = gv_raid5_clone_bio(bp, parity, wp, addr, 1);
248 	if (cbp == NULL)
249 		return (ENOMEM);
250 	wp->parity = cbp;
251 
252 	return (0);
253 }
254 
255 /* Rebuild a degraded RAID5 plex. */
256 static int
257 gv_raid5_rebuild(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
258     caddr_t addr, off_t boff, off_t bcount)
259 {
260 	struct gv_sd *broken, *s;
261 	struct gv_bioq *bq;
262 	struct bio *cbp;
263 	off_t real_len, real_off;
264 
265 	if (p == NULL || LIST_EMPTY(&p->subdisks))
266 		return (ENXIO);
267 
268 	gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, NULL, 1);
269 
270 	/* Find the right subdisk. */
271 	broken = NULL;
272 	LIST_FOREACH(s, &p->subdisks, in_plex) {
273 		if (s->state != GV_SD_UP)
274 			broken = s;
275 	}
276 
277 	/* Broken stripe not found. */
278 	if (broken == NULL)
279 		return (ENXIO);
280 
281 	switch (broken->state) {
282 	case GV_SD_UP:
283 		return (EINVAL);
284 
285 	case GV_SD_STALE:
286 		if (!(bp->bio_pflags & GV_BIO_REBUILD))
287 			return (ENXIO);
288 
289 		G_VINUM_DEBUG(1, "sd %s is reviving", broken->name);
290 		gv_set_sd_state(broken, GV_SD_REVIVING, GV_SETSTATE_FORCE);
291 		/* Set this bit now, but should be set at end. */
292 		broken->flags |= GV_SD_CANGOUP;
293 		break;
294 
295 	case GV_SD_REVIVING:
296 		break;
297 
298 	default:
299 		/* All other subdisk states mean it's not accessible. */
300 		return (ENXIO);
301 	}
302 
303 	wp->length = real_len;
304 	wp->data = addr;
305 	wp->lockbase = real_off;
306 
307 	KASSERT(wp->length >= 0, ("gv_rebuild_raid5: wp->length < 0"));
308 
309 	/* Read all subdisks. */
310 	LIST_FOREACH(s, &p->subdisks, in_plex) {
311 		/* Skip the broken subdisk. */
312 		if (s == broken)
313 			continue;
314 
315 		/* Skip growing subdisks. */
316 		if (s->flags & GV_SD_GROW)
317 			continue;
318 
319 		cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
320 		if (cbp == NULL)
321 			return (ENOMEM);
322 		cbp->bio_cmd = BIO_READ;
323 
324 		bioq_insert_tail(p->bqueue, cbp);
325 
326 		bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
327 		bq->bp = cbp;
328 		TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
329 	}
330 
331 	/* Write the parity data. */
332 	cbp = gv_raid5_clone_bio(bp, broken, wp, NULL, 1);
333 	if (cbp == NULL)
334 		return (ENOMEM);
335 	wp->parity = cbp;
336 
337 	p->synced = boff;
338 
339 	/* Post notification that we're finished. */
340 	return (0);
341 }
342 
343 /* Build a request group to perform (part of) a RAID5 request. */
344 static int
345 gv_raid5_request(struct gv_plex *p, struct gv_raid5_packet *wp,
346     struct bio *bp, caddr_t addr, off_t boff, off_t bcount, int *delay)
347 {
348 	struct g_geom *gp;
349 	struct gv_sd *broken, *original, *parity, *s;
350 	struct gv_bioq *bq;
351 	struct bio *cbp;
352 	int i, psdno, sdno, type, grow;
353 	off_t real_len, real_off;
354 
355 	gp = bp->bio_to->geom;
356 
357 	if (p == NULL || LIST_EMPTY(&p->subdisks))
358 		return (ENXIO);
359 
360 	/* We are optimistic and assume that this request will be OK. */
361 #define	REQ_TYPE_NORMAL		0
362 #define	REQ_TYPE_DEGRADED	1
363 #define	REQ_TYPE_NOPARITY	2
364 
365 	type = REQ_TYPE_NORMAL;
366 	original = parity = broken = NULL;
367 
368 	/* XXX: The resize won't crash with rebuild or sync, but we should still
369 	 * be aware of it. Also this should perhaps be done on rebuild/check as
370 	 * well?
371 	 */
372 	/* If we're over, we must use the old. */
373 	if (boff >= p->synced) {
374 		grow = 1;
375 	/* Or if over the resized offset, we use all drives. */
376 	} else if (boff + bcount <= p->synced) {
377 		grow = 0;
378 	/* Else, we're in the middle, and must wait a bit. */
379 	} else {
380 		bioq_disksort(p->rqueue, bp);
381 		*delay = 1;
382 		return (0);
383 	}
384 	gv_raid5_offset(p, boff, bcount, &real_off, &real_len,
385 	    &sdno, &psdno, grow);
386 
387 	/* Find the right subdisks. */
388 	i = 0;
389 	LIST_FOREACH(s, &p->subdisks, in_plex) {
390 		if (i == sdno)
391 			original = s;
392 		if (i == psdno)
393 			parity = s;
394 		if (s->state != GV_SD_UP)
395 			broken = s;
396 		i++;
397 	}
398 
399 	if ((original == NULL) || (parity == NULL))
400 		return (ENXIO);
401 
402 	/* Our data stripe is missing. */
403 	if (original->state != GV_SD_UP)
404 		type = REQ_TYPE_DEGRADED;
405 
406 	/* If synchronizing request, just write it if disks are stale. */
407 	if (original->state == GV_SD_STALE && parity->state == GV_SD_STALE &&
408 	    bp->bio_pflags & GV_BIO_SYNCREQ && bp->bio_cmd == BIO_WRITE) {
409 		type = REQ_TYPE_NORMAL;
410 	/* Our parity stripe is missing. */
411 	} else if (parity->state != GV_SD_UP) {
412 		/* We cannot take another failure if we're already degraded. */
413 		if (type != REQ_TYPE_NORMAL)
414 			return (ENXIO);
415 		else
416 			type = REQ_TYPE_NOPARITY;
417 	}
418 
419 	wp->length = real_len;
420 	wp->data = addr;
421 	wp->lockbase = real_off;
422 
423 	KASSERT(wp->length >= 0, ("gv_build_raid5_request: wp->length < 0"));
424 
425 	if ((p->flags & GV_PLEX_REBUILDING) && (boff + real_len < p->synced))
426 		type = REQ_TYPE_NORMAL;
427 
428 	if ((p->flags & GV_PLEX_REBUILDING) && (boff + real_len >= p->synced)) {
429 		bioq_disksort(p->rqueue, bp);
430 		*delay = 1;
431 		return (0);
432 	}
433 
434 	switch (bp->bio_cmd) {
435 	case BIO_READ:
436 		/*
437 		 * For a degraded read we need to read in all stripes except
438 		 * the broken one plus the parity stripe and then recalculate
439 		 * the desired data.
440 		 */
441 		if (type == REQ_TYPE_DEGRADED) {
442 			bzero(wp->data, wp->length);
443 			LIST_FOREACH(s, &p->subdisks, in_plex) {
444 				/* Skip the broken subdisk. */
445 				if (s == broken)
446 					continue;
447 				/* Skip growing if within offset. */
448 				if (grow && s->flags & GV_SD_GROW)
449 					continue;
450 				cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
451 				if (cbp == NULL)
452 					return (ENOMEM);
453 
454 				bioq_insert_tail(p->bqueue, cbp);
455 
456 				bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
457 				bq->bp = cbp;
458 				TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
459 			}
460 
461 		/* A normal read can be fulfilled with the original subdisk. */
462 		} else {
463 			cbp = gv_raid5_clone_bio(bp, original, wp, addr, 0);
464 			if (cbp == NULL)
465 				return (ENOMEM);
466 
467 			bioq_insert_tail(p->bqueue, cbp);
468 		}
469 		wp->lockbase = -1;
470 
471 		break;
472 
473 	case BIO_WRITE:
474 		/*
475 		 * A degraded write means we cannot write to the original data
476 		 * subdisk.  Thus we need to read in all valid stripes,
477 		 * recalculate the parity from the original data, and then
478 		 * write the parity stripe back out.
479 		 */
480 		if (type == REQ_TYPE_DEGRADED) {
481 			/* Read all subdisks. */
482 			LIST_FOREACH(s, &p->subdisks, in_plex) {
483 				/* Skip the broken and the parity subdisk. */
484 				if ((s == broken) || (s == parity))
485 					continue;
486 				/* Skip growing if within offset. */
487 				if (grow && s->flags & GV_SD_GROW)
488 					continue;
489 
490 				cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
491 				if (cbp == NULL)
492 					return (ENOMEM);
493 				cbp->bio_cmd = BIO_READ;
494 
495 				bioq_insert_tail(p->bqueue, cbp);
496 
497 				bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
498 				bq->bp = cbp;
499 				TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
500 			}
501 
502 			/* Write the parity data. */
503 			cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
504 			if (cbp == NULL)
505 				return (ENOMEM);
506 			bcopy(addr, cbp->bio_data, wp->length);
507 			wp->parity = cbp;
508 
509 		/*
510 		 * When the parity stripe is missing we just write out the data.
511 		 */
512 		} else if (type == REQ_TYPE_NOPARITY) {
513 			cbp = gv_raid5_clone_bio(bp, original, wp, addr, 1);
514 			if (cbp == NULL)
515 				return (ENOMEM);
516 
517 			bioq_insert_tail(p->bqueue, cbp);
518 
519 			bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
520 			bq->bp = cbp;
521 			TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
522 
523 		/*
524 		 * A normal write request goes to the original subdisk, then we
525 		 * read in all other stripes, recalculate the parity and write
526 		 * out the parity again.
527 		 */
528 		} else {
529 			/* Read old parity. */
530 			cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
531 			if (cbp == NULL)
532 				return (ENOMEM);
533 			cbp->bio_cmd = BIO_READ;
534 
535 			bioq_insert_tail(p->bqueue, cbp);
536 
537 			bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
538 			bq->bp = cbp;
539 			TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
540 
541 			/* Read old data. */
542 			cbp = gv_raid5_clone_bio(bp, original, wp, NULL, 1);
543 			if (cbp == NULL)
544 				return (ENOMEM);
545 			cbp->bio_cmd = BIO_READ;
546 
547 			bioq_insert_tail(p->bqueue, cbp);
548 
549 			bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
550 			bq->bp = cbp;
551 			TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
552 
553 			/* Write new data. */
554 			cbp = gv_raid5_clone_bio(bp, original, wp, addr, 1);
555 			if (cbp == NULL)
556 				return (ENOMEM);
557 
558 			/*
559 			 * We must not write the new data until the old data
560 			 * was read, so hold this BIO back until we're ready
561 			 * for it.
562 			 */
563 			wp->waiting = cbp;
564 
565 			/* The final bio for the parity. */
566 			cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
567 			if (cbp == NULL)
568 				return (ENOMEM);
569 
570 			/* Remember that this is the BIO for the parity data. */
571 			wp->parity = cbp;
572 		}
573 		break;
574 
575 	default:
576 		return (EINVAL);
577 	}
578 
579 	return (0);
580 }
581 
582 /*
583  * Calculate the offsets in the various subdisks for a RAID5 request. Also take
584  * care of new subdisks in an expanded RAID5 array.
585  * XXX: This assumes that the new subdisks are inserted after the others (which
586  * is okay as long as plex_offset is larger). If subdisks are inserted into the
587  * plexlist before, we get problems.
588  */
589 static int
590 gv_raid5_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
591     off_t *real_len, int *sdno, int *psdno, int growing)
592 {
593 	struct gv_sd *s;
594 	int sd, psd, sdcount;
595 	off_t len_left, stripeend, stripeoff, stripestart;
596 
597 	sdcount = p->sdcount;
598 	if (growing) {
599 		LIST_FOREACH(s, &p->subdisks, in_plex) {
600 			if (s->flags & GV_SD_GROW)
601 				sdcount--;
602 		}
603 	}
604 
605 	/* The number of the subdisk containing the parity stripe. */
606 	psd = sdcount - 1 - ( boff / (p->stripesize * (sdcount - 1))) %
607 	    sdcount;
608 	KASSERT(psdno >= 0, ("gv_raid5_offset: psdno < 0"));
609 
610 	/* Offset of the start address from the start of the stripe. */
611 	stripeoff = boff % (p->stripesize * (sdcount - 1));
612 	KASSERT(stripeoff >= 0, ("gv_raid5_offset: stripeoff < 0"));
613 
614 	/* The number of the subdisk where the stripe resides. */
615 	sd = stripeoff / p->stripesize;
616 	KASSERT(sdno >= 0, ("gv_raid5_offset: sdno < 0"));
617 
618 	/* At or past parity subdisk. */
619 	if (sd >= psd)
620 		sd++;
621 
622 	/* The offset of the stripe on this subdisk. */
623 	stripestart = (boff - stripeoff) / (sdcount - 1);
624 	KASSERT(stripestart >= 0, ("gv_raid5_offset: stripestart < 0"));
625 
626 	stripeoff %= p->stripesize;
627 
628 	/* The offset of the request on this subdisk. */
629 	*real_off = stripestart + stripeoff;
630 
631 	stripeend = stripestart + p->stripesize;
632 	len_left = stripeend - *real_off;
633 	KASSERT(len_left >= 0, ("gv_raid5_offset: len_left < 0"));
634 
635 	*real_len = (bcount <= len_left) ? bcount : len_left;
636 
637 	if (sdno != NULL)
638 		*sdno = sd;
639 	if (psdno != NULL)
640 		*psdno = psd;
641 
642 	return (0);
643 }
644 
645 static struct bio *
646 gv_raid5_clone_bio(struct bio *bp, struct gv_sd *s, struct gv_raid5_packet *wp,
647     caddr_t addr, int use_wp)
648 {
649 	struct bio *cbp;
650 
651 	cbp = g_clone_bio(bp);
652 	if (cbp == NULL)
653 		return (NULL);
654 	if (addr == NULL) {
655 		cbp->bio_data = g_malloc(wp->length, M_WAITOK | M_ZERO);
656 		cbp->bio_cflags |= GV_BIO_MALLOC;
657 	} else
658 		cbp->bio_data = addr;
659 	cbp->bio_offset = wp->lockbase + s->drive_offset;
660 	cbp->bio_length = wp->length;
661 	cbp->bio_done = gv_done;
662 	cbp->bio_caller1 = s;
663 	s->drive_sc->active++;
664 	if (use_wp)
665 		cbp->bio_caller2 = wp;
666 
667 	return (cbp);
668 }
669