173679edcSLukas Ertl /*- 23728855aSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 33728855aSPedro F. Giffuni * 4c0b9797aSUlf Lilleengen * Copyright (c) 2007 Lukas Ertl 573679edcSLukas Ertl * All rights reserved. 673679edcSLukas Ertl * 773679edcSLukas Ertl * Redistribution and use in source and binary forms, with or without 873679edcSLukas Ertl * modification, are permitted provided that the following conditions 973679edcSLukas Ertl * are met: 1073679edcSLukas Ertl * 1. Redistributions of source code must retain the above copyright 1173679edcSLukas Ertl * notice, this list of conditions and the following disclaimer. 1273679edcSLukas Ertl * 2. Redistributions in binary form must reproduce the above copyright 1373679edcSLukas Ertl * notice, this list of conditions and the following disclaimer in the 1473679edcSLukas Ertl * documentation and/or other materials provided with the distribution. 1573679edcSLukas Ertl * 1673679edcSLukas Ertl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1773679edcSLukas Ertl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1873679edcSLukas Ertl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1973679edcSLukas Ertl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2073679edcSLukas Ertl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2173679edcSLukas Ertl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2273679edcSLukas Ertl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2373679edcSLukas Ertl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2473679edcSLukas Ertl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2573679edcSLukas Ertl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2673679edcSLukas Ertl * SUCH DAMAGE. 2773679edcSLukas Ertl */ 2873679edcSLukas Ertl 2973679edcSLukas Ertl #include <sys/cdefs.h> 3073679edcSLukas Ertl __FBSDID("$FreeBSD$"); 3173679edcSLukas Ertl 3273679edcSLukas Ertl #include <sys/param.h> 3373679edcSLukas Ertl #include <sys/bio.h> 3473679edcSLukas Ertl #include <sys/lock.h> 3573679edcSLukas Ertl #include <sys/malloc.h> 3673679edcSLukas Ertl #include <sys/systm.h> 3773679edcSLukas Ertl 3873679edcSLukas Ertl #include <geom/geom.h> 3973679edcSLukas Ertl #include <geom/vinum/geom_vinum_var.h> 4073679edcSLukas Ertl #include <geom/vinum/geom_vinum.h> 4173679edcSLukas Ertl 42c0b9797aSUlf Lilleengen void 43c0b9797aSUlf Lilleengen gv_volume_flush(struct gv_volume *v) 44c0b9797aSUlf Lilleengen { 45c0b9797aSUlf Lilleengen struct gv_softc *sc; 46c0b9797aSUlf Lilleengen struct bio *bp; 4767e3ab6eSLukas Ertl 48c0b9797aSUlf Lilleengen KASSERT(v != NULL, ("NULL v")); 49c0b9797aSUlf Lilleengen sc = v->vinumconf; 50c0b9797aSUlf Lilleengen KASSERT(sc != NULL, ("NULL sc")); 51c0b9797aSUlf Lilleengen 52c0b9797aSUlf Lilleengen bp = bioq_takefirst(v->wqueue); 53c0b9797aSUlf Lilleengen while (bp != NULL) { 54c0b9797aSUlf Lilleengen gv_volume_start(sc, bp); 55c0b9797aSUlf Lilleengen bp = bioq_takefirst(v->wqueue); 56c0b9797aSUlf Lilleengen } 57c0b9797aSUlf Lilleengen } 58c0b9797aSUlf Lilleengen 59c0b9797aSUlf Lilleengen void 60c0b9797aSUlf Lilleengen gv_volume_start(struct gv_softc *sc, struct bio *bp) 6173679edcSLukas Ertl { 6273679edcSLukas Ertl struct g_geom *gp; 6399b536d8SLukas Ertl struct gv_volume *v; 64c0b9797aSUlf Lilleengen struct gv_plex *p, *lp; 65c0b9797aSUlf Lilleengen int numwrites; 6673679edcSLukas Ertl 67c0b9797aSUlf Lilleengen gp = sc->geom; 68c0b9797aSUlf Lilleengen v = bp->bio_to->private; 69c0b9797aSUlf Lilleengen if (v == NULL || v->state != GV_VOL_UP) { 7067e3ab6eSLukas Ertl g_io_deliver(bp, ENXIO); 7167e3ab6eSLukas Ertl return; 7267e3ab6eSLukas Ertl } 7367e3ab6eSLukas Ertl 7467e3ab6eSLukas Ertl switch (bp->bio_cmd) { 7567e3ab6eSLukas Ertl case BIO_READ: 76d8688e11SLukas Ertl /* 77c0b9797aSUlf Lilleengen * Try to find a good plex where we can send the request to, 78c0b9797aSUlf Lilleengen * round-robin-style. The plex either has to be up, or it's a 79c0b9797aSUlf Lilleengen * degraded RAID5 plex. Check if we have delayed requests. Put 80c0b9797aSUlf Lilleengen * this request on the delayed queue if so. This makes sure that 81c0b9797aSUlf Lilleengen * we don't read old values. 82d8688e11SLukas Ertl */ 83c0b9797aSUlf Lilleengen if (bioq_first(v->wqueue) != NULL) { 84c0b9797aSUlf Lilleengen bioq_insert_tail(v->wqueue, bp); 85c0b9797aSUlf Lilleengen break; 86c0b9797aSUlf Lilleengen } 877ad68986SLukas Ertl lp = v->last_read_plex; 887ad68986SLukas Ertl if (lp == NULL) 897ad68986SLukas Ertl lp = LIST_FIRST(&v->plexes); 907ad68986SLukas Ertl p = LIST_NEXT(lp, in_volume); 917ad68986SLukas Ertl if (p == NULL) 927ad68986SLukas Ertl p = LIST_FIRST(&v->plexes); 93c0b9797aSUlf Lilleengen do { 94c0b9797aSUlf Lilleengen if (p == NULL) { 95c0b9797aSUlf Lilleengen p = lp; 96c0b9797aSUlf Lilleengen break; 97c0b9797aSUlf Lilleengen } 98d8688e11SLukas Ertl if ((p->state > GV_PLEX_DEGRADED) || 99d8688e11SLukas Ertl (p->state >= GV_PLEX_DEGRADED && 100d8688e11SLukas Ertl p->org == GV_PLEX_RAID5)) 10167e3ab6eSLukas Ertl break; 1027ad68986SLukas Ertl p = LIST_NEXT(p, in_volume); 103c0b9797aSUlf Lilleengen if (p == NULL) 104c0b9797aSUlf Lilleengen p = LIST_FIRST(&v->plexes); 1057ad68986SLukas Ertl } while (p != lp); 1067ad68986SLukas Ertl 107c0b9797aSUlf Lilleengen if ((p == NULL) || 1087ad68986SLukas Ertl (p->org == GV_PLEX_RAID5 && p->state < GV_PLEX_DEGRADED) || 109fdb9eda8SLukas Ertl (p->org != GV_PLEX_RAID5 && p->state <= GV_PLEX_DEGRADED)) { 110d8688e11SLukas Ertl g_io_deliver(bp, ENXIO); 111d8688e11SLukas Ertl return; 112d8688e11SLukas Ertl } 1137ad68986SLukas Ertl v->last_read_plex = p; 11467e3ab6eSLukas Ertl 115c0b9797aSUlf Lilleengen /* Hand it down to the plex logic. */ 116c0b9797aSUlf Lilleengen gv_plex_start(p, bp); 11767e3ab6eSLukas Ertl break; 11867e3ab6eSLukas Ertl 11967e3ab6eSLukas Ertl case BIO_WRITE: 12067e3ab6eSLukas Ertl case BIO_DELETE: 121c0b9797aSUlf Lilleengen /* Delay write-requests if any plex is synchronizing. */ 122c0b9797aSUlf Lilleengen LIST_FOREACH(p, &v->plexes, in_volume) { 123c0b9797aSUlf Lilleengen if (p->flags & GV_PLEX_SYNCING) { 124c0b9797aSUlf Lilleengen bioq_insert_tail(v->wqueue, bp); 125c0b9797aSUlf Lilleengen return; 126c0b9797aSUlf Lilleengen } 127c0b9797aSUlf Lilleengen } 128c0b9797aSUlf Lilleengen 129c0b9797aSUlf Lilleengen numwrites = 0; 130c0b9797aSUlf Lilleengen /* Give the BIO to each plex of this volume. */ 13167e3ab6eSLukas Ertl LIST_FOREACH(p, &v->plexes, in_volume) { 13267e3ab6eSLukas Ertl if (p->state < GV_PLEX_DEGRADED) 13367e3ab6eSLukas Ertl continue; 134c0b9797aSUlf Lilleengen gv_plex_start(p, bp); 135c0b9797aSUlf Lilleengen numwrites++; 1367ad68986SLukas Ertl } 137c0b9797aSUlf Lilleengen if (numwrites == 0) 138c0b9797aSUlf Lilleengen g_io_deliver(bp, ENXIO); 13967e3ab6eSLukas Ertl break; 14067e3ab6eSLukas Ertl } 14173679edcSLukas Ertl } 14273679edcSLukas Ertl 143c0b9797aSUlf Lilleengen void 144c0b9797aSUlf Lilleengen gv_bio_done(struct gv_softc *sc, struct bio *bp) 14573679edcSLukas Ertl { 14673679edcSLukas Ertl struct gv_volume *v; 14773679edcSLukas Ertl struct gv_plex *p; 148c0b9797aSUlf Lilleengen struct gv_sd *s; 14973679edcSLukas Ertl 150c0b9797aSUlf Lilleengen s = bp->bio_caller1; 151c0b9797aSUlf Lilleengen KASSERT(s != NULL, ("gv_bio_done: NULL s")); 152c0b9797aSUlf Lilleengen p = s->plex_sc; 153c0b9797aSUlf Lilleengen KASSERT(p != NULL, ("gv_bio_done: NULL p")); 154c0b9797aSUlf Lilleengen v = p->vol_sc; 155c0b9797aSUlf Lilleengen KASSERT(v != NULL, ("gv_bio_done: NULL v")); 15673679edcSLukas Ertl 157c0b9797aSUlf Lilleengen switch (p->org) { 158c0b9797aSUlf Lilleengen case GV_PLEX_CONCAT: 159c0b9797aSUlf Lilleengen case GV_PLEX_STRIPED: 160c0b9797aSUlf Lilleengen gv_plex_normal_done(p, bp); 161c0b9797aSUlf Lilleengen break; 162c0b9797aSUlf Lilleengen case GV_PLEX_RAID5: 163c0b9797aSUlf Lilleengen gv_plex_raid5_done(p, bp); 164c0b9797aSUlf Lilleengen break; 1654328802cSLukas Ertl } 166a29df733SAlexander Motin 167a29df733SAlexander Motin gv_drive_done(s->drive_sc); 1684328802cSLukas Ertl } 169