1/*- 2 * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/geom/raid3/g_raid3.c 134124 2004-08-21 18:11:46Z pjd $"); |
29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/kernel.h> 33#include <sys/module.h> 34#include <sys/limits.h> 35#include <sys/lock.h> 36#include <sys/mutex.h> --- 830 unchanged lines hidden (view full) --- 867 } 868} 869 870static void 871g_raid3_gather(struct bio *pbp) 872{ 873 struct g_raid3_softc *sc; 874 struct g_raid3_disk *disk; |
875 struct bio *xbp, *fbp, *cbp; |
876 off_t atom, cadd, padd, left; 877 878 sc = pbp->bio_to->geom->softc; |
879 /* 880 * Find bio for which we have to calculate data. 881 * While going through this path, check if all requests 882 * succeeded, if not, deny whole request. 883 * If we're in COMPLETE mode, we allow one request to fail, 884 * so if we find one, we're sending it to the parity consumer. 885 * If there are more failed requests, we deny whole request. 886 */ 887 xbp = fbp = NULL; 888 G_RAID3_FOREACH_BIO(pbp, cbp) { 889 if ((cbp->bio_cflags & G_RAID3_BIO_CFLAG_PARITY) != 0) { 890 KASSERT(xbp == NULL, ("More than one parity bio.")); 891 xbp = cbp; 892 } 893 if (cbp->bio_error == 0) 894 continue; |
895 /* |
896 * Found failed request. |
897 */ |
898 G_RAID3_LOGREQ(0, cbp, "Request failed."); 899 disk = cbp->bio_caller2; 900 if (disk != NULL) { |
901 /* |
902 * Actually this is pointless to bump syncid, 903 * because whole device is fucked up. |
904 */ |
905 sc->sc_bump_syncid = G_RAID3_BUMP_IMMEDIATELY; 906 g_raid3_event_send(disk, 907 G_RAID3_DISK_STATE_DISCONNECTED, 908 G_RAID3_EVENT_DONTWAIT); 909 } 910 if (fbp == NULL) { 911 if ((pbp->bio_pflags & G_RAID3_BIO_PFLAG_DEGRADED) != 0) { |
912 /* |
913 * We are already in degraded mode, so we can't 914 * accept any failures. |
915 */ |
916 if (pbp->bio_error == 0) 917 pbp->bio_error = fbp->bio_error; 918 } else { 919 fbp = cbp; |
920 } |
921 } else { |
922 /* |
923 * Next failed request, that's too many. |
924 */ |
925 if (pbp->bio_error == 0) 926 pbp->bio_error = fbp->bio_error; 927 } 928 } 929 if (pbp->bio_error != 0) 930 goto finish; 931 if (fbp != NULL) { 932 struct g_consumer *cp; 933 934 /* 935 * One request failed, so send the same request to 936 * the parity consumer. 937 */ 938 disk = pbp->bio_driver2; 939 if (disk->d_state != G_RAID3_DISK_STATE_ACTIVE) { 940 pbp->bio_error = fbp->bio_error; |
941 goto finish; 942 } |
943 pbp->bio_pflags |= G_RAID3_BIO_PFLAG_DEGRADED; 944 pbp->bio_inbed--; 945 fbp->bio_flags &= ~(BIO_DONE | BIO_ERROR); 946 if (disk->d_no == sc->sc_ndisks - 1) 947 fbp->bio_cflags |= G_RAID3_BIO_CFLAG_PARITY; 948 fbp->bio_error = 0; 949 fbp->bio_completed = 0; 950 fbp->bio_children = 0; 951 fbp->bio_inbed = 0; 952 cp = disk->d_consumer; 953 fbp->bio_caller2 = disk; 954 fbp->bio_to = cp->provider; 955 G_RAID3_LOGREQ(3, fbp, "Sending request (recover)."); 956 KASSERT(cp->acr > 0 && cp->ace > 0, 957 ("Consumer %s not opened (r%dw%de%d).", cp->provider->name, 958 cp->acr, cp->acw, cp->ace)); 959 g_io_request(fbp, cp); 960 return; 961 } 962 if (xbp != NULL) { |
963 /* 964 * Calculate parity. 965 */ 966 G_RAID3_FOREACH_BIO(pbp, cbp) { 967 if ((cbp->bio_cflags & G_RAID3_BIO_CFLAG_PARITY) != 0) 968 continue; |
969 g_raid3_xor(cbp->bio_data, xbp->bio_data, xbp->bio_data, 970 xbp->bio_length); |
971 } |
972 xbp->bio_cflags &= ~G_RAID3_BIO_CFLAG_PARITY; |
973 } 974 atom = sc->sc_sectorsize / (sc->sc_ndisks - 1); 975 cadd = padd = 0; 976 for (left = pbp->bio_length; left > 0; left -= sc->sc_sectorsize) { 977 G_RAID3_FOREACH_BIO(pbp, cbp) { 978 bcopy(cbp->bio_data + cadd, pbp->bio_data + padd, atom); 979 pbp->bio_completed += atom; 980 padd += atom; --- 300 unchanged lines hidden (view full) --- 1281g_raid3_register_request(struct bio *pbp) 1282{ 1283 struct g_raid3_softc *sc; 1284 struct g_raid3_disk *disk; 1285 struct g_consumer *cp; 1286 struct bio *cbp; 1287 off_t offset, length; 1288 u_int n, ndisks; |
1289 int round_robin; |
1290 1291 ndisks = 0; 1292 sc = pbp->bio_to->geom->softc; 1293 if ((pbp->bio_cflags & G_RAID3_BIO_CFLAG_REGSYNC) != 0 && 1294 sc->sc_syncdisk == NULL) { 1295 g_io_deliver(pbp, EIO); 1296 return (0); 1297 } 1298 g_raid3_init_bio(pbp); 1299 length = pbp->bio_length / (sc->sc_ndisks - 1); 1300 offset = pbp->bio_offset / (sc->sc_ndisks - 1); 1301 switch (pbp->bio_cmd) { 1302 case BIO_READ: 1303 ndisks = sc->sc_ndisks - 1; |
1304 pbp->bio_driver2 = &sc->sc_disks[sc->sc_ndisks - 1]; |
1305 break; 1306 case BIO_WRITE: 1307 case BIO_DELETE: 1308 ndisks = sc->sc_ndisks; 1309 break; 1310 } |
1311 if (sc->sc_state == G_RAID3_DEVICE_STATE_COMPLETE && 1312 (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) { 1313 round_robin = 1; 1314 } else { 1315 round_robin = 0; 1316 } |
1317 for (n = 0; n < ndisks; n++) { 1318 disk = &sc->sc_disks[n]; 1319 cbp = g_raid3_clone_bio(sc, pbp); 1320 if (cbp == NULL) { 1321 while ((cbp = G_RAID3_HEAD_BIO(pbp)) != NULL) 1322 g_raid3_destroy_bio(sc, cbp); 1323 return (ENOMEM); 1324 } --- 5 unchanged lines hidden (view full) --- 1330 if (disk->d_state != G_RAID3_DISK_STATE_ACTIVE) { 1331 /* 1332 * Replace invalid component with the parity 1333 * component. 1334 */ 1335 disk = &sc->sc_disks[sc->sc_ndisks - 1]; 1336 cbp->bio_cflags |= G_RAID3_BIO_CFLAG_PARITY; 1337 pbp->bio_pflags |= G_RAID3_BIO_PFLAG_DEGRADED; |
1338 } else if (round_robin && 1339 disk->d_no == sc->sc_round_robin) { 1340 /* 1341 * In round-robin mode skip one data component 1342 * and use parity component when reading. 1343 */ 1344 pbp->bio_driver2 = disk; 1345 disk = &sc->sc_disks[sc->sc_ndisks - 1]; 1346 cbp->bio_cflags |= G_RAID3_BIO_CFLAG_PARITY; 1347 sc->sc_round_robin++; 1348 round_robin = 0; |
1349 } 1350 break; 1351 case BIO_WRITE: 1352 case BIO_DELETE: 1353 if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE || 1354 disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) { 1355 if (n == ndisks - 1) { 1356 /* --- 21 unchanged lines hidden (view full) --- 1378 } 1379 break; 1380 } 1381 if (cbp != NULL) 1382 cbp->bio_caller2 = disk; 1383 } 1384 switch (pbp->bio_cmd) { 1385 case BIO_READ: |
1386 if (round_robin) { 1387 /* 1388 * If we are in round-robin mode and 'round_robin' is 1389 * still 1, it means, that we skipped parity component 1390 * for this read and must reset sc_round_robin field. 1391 */ 1392 sc->sc_round_robin = 0; 1393 } |
1394 G_RAID3_FOREACH_BIO(pbp, cbp) { 1395 disk = cbp->bio_caller2; 1396 cp = disk->d_consumer; 1397 cbp->bio_to = cp->provider; 1398 G_RAID3_LOGREQ(3, cbp, "Sending request."); 1399 KASSERT(cp->acr > 0 && cp->ace > 0, 1400 ("Consumer %s not opened (r%dw%de%d).", 1401 cp->provider->name, cp->acr, cp->acw, cp->ace)); --- 1076 unchanged lines hidden (view full) --- 2478 gp->orphan = g_raid3_orphan; 2479 gp->access = g_raid3_access; 2480 gp->dumpconf = g_raid3_dumpconf; 2481 2482 sc->sc_id = md->md_id; 2483 sc->sc_mediasize = md->md_mediasize; 2484 sc->sc_sectorsize = md->md_sectorsize; 2485 sc->sc_ndisks = md->md_all; |
2486 sc->sc_round_robin = 0; |
2487 sc->sc_flags = md->md_mflags; 2488 sc->sc_bump_syncid = 0; 2489 for (n = 0; n < sc->sc_ndisks; n++) 2490 sc->sc_disks[n].d_state = G_RAID3_DISK_STATE_NODISK; 2491 bioq_init(&sc->sc_queue); 2492 mtx_init(&sc->sc_queue_mtx, "graid3:queue", NULL, MTX_DEF); 2493 TAILQ_INIT(&sc->sc_events); 2494 mtx_init(&sc->sc_events_mtx, "graid3:events", NULL, MTX_DEF); --- 262 unchanged lines hidden (view full) --- 2757 if (!first) \ 2758 sbuf_printf(sb, ", "); \ 2759 else \ 2760 first = 0; \ 2761 sbuf_printf(sb, name); \ 2762 } \ 2763} while (0) 2764 ADD_FLAG(G_RAID3_DEVICE_FLAG_NOAUTOSYNC, "NOAUTOSYNC"); |
2765 ADD_FLAG(G_RAID3_DEVICE_FLAG_ROUND_ROBIN, 2766 "ROUND-ROBIN"); |
2767#undef ADD_FLAG 2768 } 2769 sbuf_printf(sb, "</Flags>\n"); 2770 sbuf_printf(sb, "%s<Components>%u</Components>\n", indent, 2771 sc->sc_ndisks); 2772 sbuf_printf(sb, "%s<State>%s</State>\n", indent, 2773 g_raid3_device_state2str(sc->sc_state)); 2774 } 2775} 2776 2777DECLARE_GEOM_CLASS(g_raid3_class, g_raid3); |