Date: Sun, 29 Jul 2007 22:11:09 GMT From: Ulf Lilleengen <lulf@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 124327 for review Message-ID: <200707292211.l6TMB9wI090007@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=124327 Change 124327 by lulf@lulf_carrot on 2007/07/29 22:11:09 - Refactor a lot of code. - Put all plex-operations in geom_vinum_plex.c - Create a cleaner separation between a plex and a volume. - Make normal plex operation code cleaner like the raid5 code. - Move functions from geom_vinum_event.c to geom_vinum_create.c where they belong now. - Change some error code names. - Cleanup growing of striped plexes. There was a plan putting BIO related functions in geom_vinum_bio.c but it's hard to define a BIO related function in a way that doesn't put them all there since many handles BIOs in one way or the other. - Update copyright on files I've done heavy work on this summer (please comment this if I'm not doing this right). Affected files ... .. //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#14 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#30 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#24 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_create.c#4 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_events.c#9 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_init.c#18 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_move.c#4 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_plex.c#21 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_raid5.c#12 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_rm.c#11 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_state.c#19 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#23 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#24 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_volume.c#14 edit Differences ... ==== //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#14 (text+ko) ==== @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Lukas Ertl, 2005 Chris Jones + * Copyright (c) 2004 Lukas Ertl, 2005 Chris Jones, 2007 Ulf Lilleengen * All rights reserved. * * Portions of this software were developed for the FreeBSD Project ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#30 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004, 2007 Lukas Ertl + * Copyright (c) 2004, 2007 Lukas Ertl, 2007 Ulf Lilleengen * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,9 +50,11 @@ "Debug level"); #endif -int gv_create(struct g_geom *, struct gctl_req *); -void gv_attach(struct gv_softc *, struct gctl_req *); -void gv_detach(struct gv_softc *, struct gctl_req *); +static int gv_create(struct g_geom *, struct gctl_req *); +static void gv_attach(struct gv_softc *, struct gctl_req *); +static void gv_detach(struct gv_softc *, struct gctl_req *); +static void gv_parityop(struct gv_softc *, struct gctl_req *); + static void gv_orphan(struct g_consumer *cp) @@ -196,7 +198,7 @@ } /* Handle userland request of attaching object. */ -void +static void gv_attach(struct gv_softc *sc, struct gctl_req *req) { struct gv_volume *v; @@ -260,7 +262,7 @@ } /* Handle userland request of detaching object. */ -void +static void gv_detach(struct gv_softc *sc, struct gctl_req *req) { struct gv_plex *p; @@ -292,7 +294,7 @@ } /* Handle userland requests for creating new objects. */ -int +static int gv_create(struct g_geom *gp, struct gctl_req *req) { struct gv_softc *sc; @@ -473,6 +475,59 @@ gctl_error(req, "Unknown verb parameter"); } +static void +gv_parityop(struct gv_softc *sc, struct gctl_req *req) +{ + struct gv_plex *p; + int *flags, *rebuild, type; + char *plex; + + plex = gctl_get_param(req, "plex", NULL); + if (plex == NULL) { + gctl_error(req, "no plex given"); + return; + } + + flags = gctl_get_paraml(req, "flags", sizeof(*flags)); + if (flags == NULL) { + gctl_error(req, "no flags given"); + return; + } + + rebuild = gctl_get_paraml(req, "rebuild", sizeof(*rebuild)); + if (rebuild == NULL) { + gctl_error(req, "no operation given"); + return; + } + + type = gv_object_type(sc, plex); + if (type != GV_TYPE_PLEX) { + gctl_error(req, "'%s' is not a plex", plex); + return; + } + p = gv_find_plex(sc, plex); + + if (p->state != GV_PLEX_UP) { + gctl_error(req, "plex %s is not completely accessible", + p->name); + return; + } + + if (p->org != GV_PLEX_RAID5) { + gctl_error(req, "plex %s is not a RAID5 plex", p->name); + return; + } + + /* Put it in the event queue. */ + /* XXX: The state of the plex might have changed when this event is + * picked up ... We should perhaps check this afterwards. */ + if (*rebuild) + gv_post_event(sc, GV_EVENT_PARITY_REBUILD, p, NULL, 0, 0); + else + gv_post_event(sc, GV_EVENT_PARITY_CHECK, p, NULL, 0, 0); +} + + static struct g_geom * gv_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) { ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#24 (text+ko) ==== @@ -117,12 +117,9 @@ void gv_done(struct bio *); void gv_volume_start(struct gv_softc *, struct bio *); -void gv_plex_start(struct gv_plex *, struct bio *); -void gv_plex_done(struct gv_plex *, struct bio *); + void gv_bio_done(struct gv_softc *, struct bio *); void gv_cleanup(struct gv_softc *); -int gv_sync_request(struct gv_plex *, struct gv_plex *, - off_t, off_t, int, caddr_t); void gv_create_drive(struct gv_softc *, struct gv_drive *); void gv_create_volume(struct gv_softc *, struct gv_volume *); void gv_create_plex(struct gv_softc *, struct gv_plex *); @@ -130,10 +127,19 @@ int gv_stripe_active(struct gv_plex *, struct bio *); +/* geom_vinum_plex.c */ +void gv_plex_start(struct gv_plex *, struct bio *); +void gv_plex_raid5_done(struct gv_plex *, struct bio *); +void gv_plex_normal_done(struct gv_plex *, struct bio *); +int gv_grow_request(struct gv_plex *, off_t, off_t, int, caddr_t); +void gv_grow_complete(struct gv_plex *, struct bio *); void gv_init_request(struct gv_sd *, off_t, caddr_t, off_t); +void gv_init_complete(struct gv_plex *, struct bio *); void gv_parity_request(struct gv_plex *, int, off_t); -int gv_grow_request(struct gv_plex *, off_t, off_t, int, caddr_t); -void gv_grow_complete(struct gv_plex *, struct bio *); -void gv_parityop(struct gv_softc *, struct gctl_req *); +void gv_parity_complete(struct gv_plex *, struct bio *); +void gv_rebuild_complete(struct gv_plex *, struct bio *); +int gv_sync_request(struct gv_plex *, struct gv_plex *, off_t, off_t, int, + caddr_t); +int gv_sync_complete(struct gv_plex *, struct bio *); #endif /* !_GEOM_VINUM_H_ */ ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_create.c#4 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2006-2007 Ulf Lilleengen + * Copyright (c) 2007, Lukas Ertl, 2007 Ulf Lilleengen * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +26,7 @@ #include <sys/param.h> +#include <sys/bio.h> #include <sys/conf.h> #include <sys/kernel.h> #include <sys/libkern.h> @@ -39,6 +40,254 @@ #include <geom/vinum/geom_vinum_share.h> /* + * Create a new drive object, either by user request, during taste of the drive + * itself, or because it was referenced by a subdisk during taste. + */ +void +gv_create_drive(struct gv_softc *sc, struct gv_drive *d) +{ + struct g_geom *gp; + struct g_provider *pp; + struct g_consumer *cp, *cp2; + struct gv_drive *d2; + struct gv_hdr *hdr; + struct gv_freelist *fl; + + KASSERT(d != NULL, ("gv_create_drive: NULL d")); + + gp = sc->geom; + + pp = NULL; + cp = cp2 = NULL; + + /* The drive already has a consumer if it was tasted before. */ + if (d->consumer != NULL) { + cp = d->consumer; + cp->private = d; + pp = cp->provider; + } else if (!(d->flags & GV_DRIVE_REFERENCED)) { + if (gv_find_drive(sc, d->name) != NULL) { + printf("VINUM: drive '%s' already exists\n", d->name); + g_free(d); + return; + } + + pp = g_provider_by_name(d->device); + if (pp == NULL) { + printf("VINUM: create '%s': device '%s' disappeared?\n", + d->name, d->device); + g_free(d); + return; + } + + g_topology_lock(); + cp = g_new_consumer(gp); + if (g_attach(cp, pp) != 0) { + g_destroy_consumer(cp); + g_topology_unlock(); + printf("VINUM: create drive '%s': couldn't attach\n", + d->name); + g_free(d); + return; + } + g_topology_unlock(); + + d->consumer = cp; + cp->private = d; + } + + /* + * If this was just a "referenced" drive, we're almost finished, but + * insert this drive not on the head of the drives list, as + * gv_drive_is_newer() expects a "real" drive from LIST_FIRST(). + */ + if (d->flags & GV_DRIVE_REFERENCED) { + snprintf(d->device, GV_MAXDRIVENAME, "???"); + d2 = LIST_FIRST(&sc->drives); + if (d2 == NULL) + LIST_INSERT_HEAD(&sc->drives, d, drive); + else + LIST_INSERT_AFTER(d2, d, drive); + return; + } + + /* + * Update access counts of the new drive to those of an already + * existing drive. + */ + LIST_FOREACH(d2, &sc->drives, drive) { + if ((d == d2) || (d2->consumer == NULL)) + continue; + + cp2 = d2->consumer; + g_topology_lock(); + if ((cp2->acr || cp2->acw || cp2->ace) && + (g_access(cp, cp2->acr, cp2->acw, cp2->ace) != 0)) { + g_detach(cp); + g_destroy_consumer(cp); + g_topology_unlock(); + printf("VINUM: create drive '%s': couldn't update " + "access counts\n", d->name); + if (d->hdr != NULL) + g_free(d->hdr); + g_free(d); + return; + } + g_topology_unlock(); + break; + } + + d->size = pp->mediasize - GV_DATA_START; + d->avail = d->size; + d->vinumconf = sc; + LIST_INIT(&d->subdisks); + LIST_INIT(&d->freelist); + + /* The header might have been set during taste. */ + if (d->hdr == NULL) { + hdr = g_malloc(sizeof(*hdr), M_WAITOK | M_ZERO); + hdr->magic = GV_MAGIC; + hdr->config_length = GV_CFG_LEN; + bcopy(hostname, hdr->label.sysname, GV_HOSTNAME_LEN); + strncpy(hdr->label.name, d->name, GV_MAXDRIVENAME); + microtime(&hdr->label.date_of_birth); + d->hdr = hdr; + } + + /* We also need a freelist entry. */ + fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO); + fl->offset = GV_DATA_START; + fl->size = d->avail; + LIST_INSERT_HEAD(&d->freelist, fl, freelist); + d->freelist_entries = 1; + + if (gv_find_drive(sc, d->name) == NULL) + LIST_INSERT_HEAD(&sc->drives, d, drive); + + gv_set_drive_state(d, GV_DRIVE_UP, 0); +} + +void +gv_create_volume(struct gv_softc *sc, struct gv_volume *v) +{ + KASSERT(v != NULL, ("gv_create_volume: NULL v")); + + v->vinumconf = sc; + v->flags |= GV_VOL_NEWBORN; + LIST_INIT(&v->plexes); + LIST_INSERT_HEAD(&sc->volumes, v, volume); + v->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); + bioq_init(v->wqueue); +} + +void +gv_create_plex(struct gv_softc *sc, struct gv_plex *p) +{ + struct gv_volume *v; + + KASSERT(p != NULL, ("gv_create_plex: NULL p")); + + /* Find the volume this plex should be attached to. */ + v = gv_find_vol(sc, p->volume); + if (v == NULL) { + printf("VINUM: create plex '%s': volume '%s' not found\n", + p->name, p->volume); + g_free(p); + return; + } + if (!(v->flags & GV_VOL_NEWBORN)) + p->flags |= GV_PLEX_ADDED; + p->vol_sc = v; + v->plexcount++; + p->vinumconf = sc; + p->flags |= GV_PLEX_NEWBORN; + LIST_INSERT_HEAD(&v->plexes, p, in_volume); + LIST_INIT(&p->subdisks); + TAILQ_INIT(&p->packets); + LIST_INSERT_HEAD(&sc->plexes, p, plex); + p->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); + bioq_init(p->bqueue); + p->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); + bioq_init(p->wqueue); + p->rqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); + bioq_init(p->rqueue); +} + +void +gv_create_sd(struct gv_softc *sc, struct gv_sd *s) +{ + struct gv_plex *p; + struct gv_drive *d; + + KASSERT(s != NULL, ("gv_create_sd: NULL s")); + + /* Find the drive where this subdisk should be put on. */ + d = gv_find_drive(sc, s->drive); + if (d == NULL) { + /* + * It's possible that the subdisk references a drive that + * doesn't exist yet (during the taste process), so create a + * practically empty "referenced" drive. + */ + if (s->flags & GV_SD_TASTED) { + d = g_malloc(sizeof(struct gv_drive), + M_WAITOK | M_ZERO); + d->flags |= GV_DRIVE_REFERENCED; + strncpy(d->name, s->drive, GV_MAXDRIVENAME); + gv_create_drive(sc, d); + } else { + printf("VINUM: create sd '%s': drive '%s' not found\n", + s->name, s->drive); + g_free(s); + return; + } + } + + /* Find the plex where this subdisk belongs to. */ + p = gv_find_plex(sc, s->plex); + if (p == NULL) { + printf("VINUM: create sd '%s': plex '%s' not found\n", + s->name, s->plex); + g_free(s); + return; + } + + /* + * First we give the subdisk to the drive, to handle autosized + * values ... + */ + if (gv_sd_to_drive(s, d) != 0) { + g_free(s); + return; + } + + /* + * Then, we give the subdisk to the plex; we check if the + * given values are correct and maybe adjust them. + */ + if (gv_sd_to_plex(s, p) != 0) { + printf("VINUM: couldn't give sd '%s' to plex '%s'\n", + s->name, p->name); + if (s->drive_sc) + LIST_REMOVE(s, from_drive); + gv_free_sd(s); + g_free(s); + /* + * If this subdisk can't be created, we won't create + * the attached plex either, if it is also a new one. + */ + if (!(p->flags & GV_PLEX_NEWBORN)) + return; + gv_rm_plex(sc, p); + return; + } + s->flags |= GV_SD_NEWBORN; + + s->vinumconf = sc; + LIST_INSERT_HEAD(&sc->subdisks, s, sd); +} + +/* * Create a concatenated volume from specified drives or drivegroups. */ void ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_events.c#9 (text+ko) ==== @@ -213,251 +213,3 @@ else LIST_INSERT_AFTER(d2, d, drive); } - -/* - * Create a new drive object, either by user request, during taste of the drive - * itself, or because it was referenced by a subdisk during taste. - */ -void -gv_create_drive(struct gv_softc *sc, struct gv_drive *d) -{ - struct g_geom *gp; - struct g_provider *pp; - struct g_consumer *cp, *cp2; - struct gv_drive *d2; - struct gv_hdr *hdr; - struct gv_freelist *fl; - - KASSERT(d != NULL, ("gv_create_drive: NULL d")); - - gp = sc->geom; - - pp = NULL; - cp = cp2 = NULL; - - /* The drive already has a consumer if it was tasted before. */ - if (d->consumer != NULL) { - cp = d->consumer; - cp->private = d; - pp = cp->provider; - } else if (!(d->flags & GV_DRIVE_REFERENCED)) { - if (gv_find_drive(sc, d->name) != NULL) { - printf("VINUM: drive '%s' already exists\n", d->name); - g_free(d); - return; - } - - pp = g_provider_by_name(d->device); - if (pp == NULL) { - printf("VINUM: create '%s': device '%s' disappeared?\n", - d->name, d->device); - g_free(d); - return; - } - - g_topology_lock(); - cp = g_new_consumer(gp); - if (g_attach(cp, pp) != 0) { - g_destroy_consumer(cp); - g_topology_unlock(); - printf("VINUM: create drive '%s': couldn't attach\n", - d->name); - g_free(d); - return; - } - g_topology_unlock(); - - d->consumer = cp; - cp->private = d; - } - - /* - * If this was just a "referenced" drive, we're almost finished, but - * insert this drive not on the head of the drives list, as - * gv_drive_is_newer() expects a "real" drive from LIST_FIRST(). - */ - if (d->flags & GV_DRIVE_REFERENCED) { - snprintf(d->device, GV_MAXDRIVENAME, "???"); - d2 = LIST_FIRST(&sc->drives); - if (d2 == NULL) - LIST_INSERT_HEAD(&sc->drives, d, drive); - else - LIST_INSERT_AFTER(d2, d, drive); - return; - } - - /* - * Update access counts of the new drive to those of an already - * existing drive. - */ - LIST_FOREACH(d2, &sc->drives, drive) { - if ((d == d2) || (d2->consumer == NULL)) - continue; - - cp2 = d2->consumer; - g_topology_lock(); - if ((cp2->acr || cp2->acw || cp2->ace) && - (g_access(cp, cp2->acr, cp2->acw, cp2->ace) != 0)) { - g_detach(cp); - g_destroy_consumer(cp); - g_topology_unlock(); - printf("VINUM: create drive '%s': couldn't update " - "access counts\n", d->name); - if (d->hdr != NULL) - g_free(d->hdr); - g_free(d); - return; - } - g_topology_unlock(); - break; - } - - d->size = pp->mediasize - GV_DATA_START; - d->avail = d->size; - d->vinumconf = sc; - LIST_INIT(&d->subdisks); - LIST_INIT(&d->freelist); - - /* The header might have been set during taste. */ - if (d->hdr == NULL) { - hdr = g_malloc(sizeof(*hdr), M_WAITOK | M_ZERO); - hdr->magic = GV_MAGIC; - hdr->config_length = GV_CFG_LEN; - bcopy(hostname, hdr->label.sysname, GV_HOSTNAME_LEN); - strncpy(hdr->label.name, d->name, GV_MAXDRIVENAME); - microtime(&hdr->label.date_of_birth); - d->hdr = hdr; - } - - /* We also need a freelist entry. */ - fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO); - fl->offset = GV_DATA_START; - fl->size = d->avail; - LIST_INSERT_HEAD(&d->freelist, fl, freelist); - d->freelist_entries = 1; - - if (gv_find_drive(sc, d->name) == NULL) - LIST_INSERT_HEAD(&sc->drives, d, drive); - - gv_set_drive_state(d, GV_DRIVE_UP, 0); -} - -void -gv_create_volume(struct gv_softc *sc, struct gv_volume *v) -{ - KASSERT(v != NULL, ("gv_create_volume: NULL v")); - - v->vinumconf = sc; - v->flags |= GV_VOL_NEWBORN; - LIST_INIT(&v->plexes); - LIST_INSERT_HEAD(&sc->volumes, v, volume); - v->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); - bioq_init(v->wqueue); -} - -void -gv_create_plex(struct gv_softc *sc, struct gv_plex *p) -{ - struct gv_volume *v; - - KASSERT(p != NULL, ("gv_create_plex: NULL p")); - - /* Find the volume this plex should be attached to. */ - v = gv_find_vol(sc, p->volume); - if (v == NULL) { - printf("VINUM: create plex '%s': volume '%s' not found\n", - p->name, p->volume); - g_free(p); - return; - } - if (!(v->flags & GV_VOL_NEWBORN)) - p->flags |= GV_PLEX_ADDED; - p->vol_sc = v; - v->plexcount++; - p->vinumconf = sc; - p->flags |= GV_PLEX_NEWBORN; - LIST_INSERT_HEAD(&v->plexes, p, in_volume); - LIST_INIT(&p->subdisks); - TAILQ_INIT(&p->packets); - LIST_INSERT_HEAD(&sc->plexes, p, plex); - p->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); - bioq_init(p->bqueue); - p->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); - bioq_init(p->wqueue); - p->rqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO); - bioq_init(p->rqueue); -} - -void -gv_create_sd(struct gv_softc *sc, struct gv_sd *s) -{ - struct gv_plex *p; - struct gv_drive *d; - - KASSERT(s != NULL, ("gv_create_sd: NULL s")); - - /* Find the drive where this subdisk should be put on. */ - d = gv_find_drive(sc, s->drive); - if (d == NULL) { - /* - * It's possible that the subdisk references a drive that - * doesn't exist yet (during the taste process), so create a - * practically empty "referenced" drive. - */ - if (s->flags & GV_SD_TASTED) { - d = g_malloc(sizeof(struct gv_drive), - M_WAITOK | M_ZERO); - d->flags |= GV_DRIVE_REFERENCED; - strncpy(d->name, s->drive, GV_MAXDRIVENAME); - gv_create_drive(sc, d); - } else { - printf("VINUM: create sd '%s': drive '%s' not found\n", - s->name, s->drive); - g_free(s); - return; - } - } - - /* Find the plex where this subdisk belongs to. */ - p = gv_find_plex(sc, s->plex); - if (p == NULL) { - printf("VINUM: create sd '%s': plex '%s' not found\n", - s->name, s->plex); - g_free(s); - return; - } - - /* - * First we give the subdisk to the drive, to handle autosized - * values ... - */ - if (gv_sd_to_drive(s, d) != 0) { - g_free(s); - return; - } - - /* - * Then, we give the subdisk to the plex; we check if the - * given values are correct and maybe adjust them. - */ - if (gv_sd_to_plex(s, p) != 0) { - printf("VINUM: couldn't give sd '%s' to plex '%s'\n", - s->name, p->name); - if (s->drive_sc) - LIST_REMOVE(s, from_drive); - gv_free_sd(s); - g_free(s); - /* - * If this subdisk can't be created, we won't create - * the attached plex either, if it is also a new one. - */ - if (!(p->flags & GV_PLEX_NEWBORN)) - return; - gv_rm_plex(sc, p); - return; - } - s->flags |= GV_SD_NEWBORN; - - s->vinumconf = sc; - LIST_INSERT_HEAD(&sc->subdisks, s, sd); -} ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_init.c#18 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004, 2007 Lukas Ertl + * Copyright (c) 2004, 2007 Lukas Ertl, 2007 Ulf Lilleengen * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -280,7 +280,7 @@ g_topology_unlock(); if (error) { printf("VINUM: unable to access provider\n"); - return (GV_ERR_ISOPEN); /*XXX: wrong errorcode */ + return (GV_ERR_ISBUSY); /*XXX: wrong errorcode */ } /* XXX: This routine with finding origsize is used two other places as ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_move.c#4 (text+ko) ==== @@ -114,7 +114,7 @@ gv_consumer_is_open(destination->consumer)) { printf("VINUM: consumers on current and destination drive " " still open\n"); - return (GV_ERR_ISOPEN); + return (GV_ERR_ISBUSY); } if (!(flags && GV_FLAG_F)) { ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_plex.c#21 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004, 2007 Lukas Ertl + * Copyright (c) 2004, 2007 Lukas Ertl, 2007 Ulf Lilleengen * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,13 +45,11 @@ struct gv_raid5_packet *); static int gv_normal_parity(struct gv_plex *, struct bio *, struct gv_raid5_packet *); -static void gv_parity_complete(struct gv_plex *, struct bio *); -static void gv_rebuild_complete(struct gv_plex *, struct bio *); -static void gv_init_complete(struct gv_plex *, struct bio *); -static struct bio * gv_plexbuffer(struct gv_plex *, struct bio *, caddr_t, - off_t, off_t, int *); static void gv_plex_flush(struct gv_plex *); - +static int gv_plex_offset(struct gv_plex *, off_t, off_t, off_t *, off_t *, + int *); +static int gv_plex_normal_request(struct gv_plex *, struct bio *, off_t, + off_t, caddr_t); void gv_plex_start(struct gv_plex *p, struct bio *bp) { @@ -60,7 +58,6 @@ struct gv_raid5_packet *wp; caddr_t addr; off_t bcount, boff, len; - int err; bcount = bp->bio_length; addr = bp->bio_data; @@ -91,25 +88,11 @@ * through. */ } else { - cbp = gv_plexbuffer(p, bp, addr, boff, bcount, &err); - - /* Building the sub-request failed. */ - if (cbp == NULL && err != 0) { - printf("VINUM: plex request failed for "); - g_print_bio(bp); - printf("\n"); - g_io_deliver(bp, err); - return; - } - - len = cbp->bio_length; - - /* - * Store the sub-requests now and send them down later. - */ - bioq_insert_tail(p->bqueue, cbp); + len = gv_plex_normal_request(p, bp, boff, bcount, addr); } - + if (len < 0) + return; + bcount -= len; addr += len; boff += len; @@ -140,98 +123,132 @@ } } -static struct bio * -gv_plexbuffer(struct gv_plex *p, struct bio *bp, caddr_t addr, off_t boff, off_t bcount, int *err) +static int +gv_plex_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off, + off_t *real_len, int *sdno) { struct gv_sd *s; - struct bio *cbp; - int i, sdcount, sdno; - off_t len_left, real_len, real_off; - off_t stripeend, stripeno, stripestart; - - *err = ENXIO; + int i, sdcount; + off_t len_left, stripeend, stripeno, stripestart; - if (p == NULL || LIST_EMPTY(&p->subdisks)) - return (NULL); - - s = NULL; - - /* - * We only handle concatenated and striped plexes here. RAID5 plexes - * are handled in build_raid5_request(). - */ switch (p->org) { case GV_PLEX_CONCAT: /* * Find the subdisk where this request starts. The subdisks in * this list must be ordered by plex_offset. */ + i = 0; LIST_FOREACH(s, &p->subdisks, in_plex) { if (s->plex_offset <= boff && - s->plex_offset + s->size > boff) + s->plex_offset + s->size > boff) { + *sdno = i; break; + } + i++; } /* Subdisk not found. */ if (s == NULL || s->drive_sc == NULL) - return (NULL); + return (GV_ERR_NOTFOUND); /* Calculate corresponding offsets on disk. */ - real_off = boff - s->plex_offset; - len_left = s->size - real_off; - real_len = (bcount > len_left) ? len_left : bcount; + *real_off = boff - s->plex_offset; + len_left = s->size - (*real_off); + KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0")); + *real_len = (bcount > len_left) ? len_left : bcount; break; case GV_PLEX_STRIPED: /* The number of the stripe where the request starts. */ stripeno = boff / p->stripesize; + KASSERT(stripeno >= 0, ("gv_plex_offset: stripeno < 0")); + + /* Take growing subdisks into account when calculating. */ sdcount = p->sdcount; if (boff >= p->synced) { LIST_FOREACH(s, &p->subdisks, in_plex) { if (s->flags & GV_SD_GROW) sdcount--; } - /*XXX: Fix. */ - } else if (boff + bcount <= p->synced); - else { - bioq_disksort(p->rqueue, bp); - *err = 0; - return (NULL); /* XXX: Not failed... */ + } else if (!(boff + bcount <= p->synced)){ + return (GV_ERR_ISBUSY); } /* The number of the subdisk where the stripe resides. */ - sdno = stripeno % sdcount; + *sdno = stripeno % sdcount; - /* Find the right subdisk. */ - i = 0; - LIST_FOREACH(s, &p->subdisks, in_plex) { - if (i == sdno) - break; - i++; - } - - /* Subdisk not found. */ - if (s == NULL || s->drive_sc == NULL) - return (NULL); + KASSERT(sdno >= 0, ("gv_plex_offset: sdno < 0")); /* The offset of the stripe from the start of the subdisk. */ stripestart = (stripeno / sdcount) * p->stripesize; + KASSERT(stripestart >= 0, ("gv_plex_offset: stripestart < 0")); /* The offset at the end of the stripe. */ stripeend = stripestart + p->stripesize; /* The offset of the request on this subdisk. */ - real_off = boff - (stripeno * p->stripesize) + + *real_off = boff - (stripeno * p->stripesize) + stripestart; /* The length left in this stripe. */ - len_left = stripeend - real_off; + len_left = stripeend - *real_off; + KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0")); - real_len = (bcount <= len_left) ? bcount : len_left; + *real_len = (bcount <= len_left) ? bcount : len_left; break; default: - *err = EINVAL; - return (NULL); + return (GV_ERR_PLEXORG); + } + return (0); +} + +/* + * Prepare a normal plex request. + */ +static int +gv_plex_normal_request(struct gv_plex *p, struct bio *bp, off_t boff, + off_t bcount, caddr_t addr) +{ + struct gv_sd *s; + struct bio *cbp; + off_t real_len, real_off; + int i, err, sdno; + + err = ENXIO; + s = NULL; + sdno = -1; + real_len = real_off = 0; + + if (p == NULL || LIST_EMPTY(&p->subdisks)) { + printf("Where's my fuckin' plex!\n"); + goto bad; + } + + err = gv_plex_offset(p, boff, bcount, &real_off, + &real_len, &sdno); + /* If the request was blocked, put it into wait. */ + if (err == GV_ERR_ISBUSY) { + printf("Delayed? no way!\n"); + bioq_disksort(p->rqueue, bp); + return (real_len); + } + if (err) { + printf("Got err after offset. \n"); + goto bad; + } + + /* Find the right subdisk. */ + i = 0; + LIST_FOREACH(s, &p->subdisks, in_plex) { + if (i == sdno) + break; + i++; + } + + /* Subdisk not found. */ + if (s == NULL || s->drive_sc == NULL) { + printf("WTF no sd?\n"); + goto bad; } /* Now check if we can handle the request on this subdisk. */ @@ -239,30 +256,30 @@ >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707292211.l6TMB9wI090007>