diff options
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/eli/g_eli.c | 2 | ||||
-rw-r--r-- | sys/geom/geom.h | 2 | ||||
-rw-r--r-- | sys/geom/geom_dev.c | 42 | ||||
-rw-r--r-- | sys/geom/geom_disk.c | 14 | ||||
-rw-r--r-- | sys/geom/geom_disk.h | 1 | ||||
-rw-r--r-- | sys/geom/geom_io.c | 68 | ||||
-rw-r--r-- | sys/geom/geom_subr.c | 1 |
7 files changed, 129 insertions, 1 deletions
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 403d0b6..66b3c4e5 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -309,6 +309,7 @@ g_eli_start(struct bio *bp) case BIO_WRITE: case BIO_GETATTR: case BIO_FLUSH: + case BIO_ZONE: break; case BIO_DELETE: /* @@ -348,6 +349,7 @@ g_eli_start(struct bio *bp) case BIO_GETATTR: case BIO_FLUSH: case BIO_DELETE: + case BIO_ZONE: cbp->bio_done = g_std_done; cp = LIST_FIRST(&sc->sc_geom->consumer); cbp->bio_to = cp->provider; diff --git a/sys/geom/geom.h b/sys/geom/geom.h index bf70d0b..98b53dc 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -56,6 +56,7 @@ struct bio; struct sbuf; struct gctl_req; struct g_configargs; +struct disk_zone_args; typedef int g_config_t (struct g_configargs *ca); typedef void g_ctl_req_t (struct gctl_req *, struct g_class *cp, char const *verb); @@ -318,6 +319,7 @@ struct bio * g_duplicate_bio(struct bio *); void g_destroy_bio(struct bio *); void g_io_deliver(struct bio *bp, int error); int g_io_getattr(const char *attr, struct g_consumer *cp, int *len, void *ptr); +int g_io_zonecmd(struct disk_zone_args *zone_args, struct g_consumer *cp); int g_io_flush(struct g_consumer *cp); int g_register_classifier(struct g_classifier_hook *hook); void g_unregister_classifier(struct g_classifier_hook *hook); diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index 5ba9191..005cc3c 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -549,6 +549,42 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread error = g_io_getattr(arg->name, cp, &arg->len, &arg->value); break; } + case DIOCZONECMD: { + struct disk_zone_args *zone_args =(struct disk_zone_args *)data; + struct disk_zone_rep_entry *new_entries, *old_entries; + struct disk_zone_report *rep; + size_t alloc_size; + + old_entries = NULL; + new_entries = NULL; + rep = NULL; + alloc_size = 0; + + if (zone_args->zone_cmd == DISK_ZONE_REPORT_ZONES) { + + rep = &zone_args->zone_params.report; + alloc_size = rep->entries_allocated * + sizeof(struct disk_zone_rep_entry); + if (alloc_size != 0) + new_entries = g_malloc(alloc_size, + M_WAITOK| M_ZERO); + old_entries = rep->entries; + rep->entries = new_entries; + } + error = g_io_zonecmd(zone_args, cp); + if ((zone_args->zone_cmd == DISK_ZONE_REPORT_ZONES) + && (alloc_size != 0) + && (error == 0)) { + error = copyout(new_entries, old_entries, alloc_size); + } + if ((old_entries != NULL) + && (rep != NULL)) + rep->entries = old_entries; + + if (new_entries != NULL) + g_free(new_entries); + break; + } default: if (cp->provider->geom->ioctl != NULL) { error = cp->provider->geom->ioctl(cp->provider, cmd, data, fflag, td); @@ -574,6 +610,9 @@ g_dev_done(struct bio *bp2) bp->bio_error = bp2->bio_error; bp->bio_completed = bp2->bio_completed; bp->bio_resid = bp->bio_length - bp2->bio_completed; + if (bp2->bio_cmd == BIO_ZONE) + bcopy(&bp2->bio_zone, &bp->bio_zone, sizeof(bp->bio_zone)); + if (bp2->bio_error != 0) { g_trace(G_T_BIO, "g_dev_done(%p) had error %d", bp2, bp2->bio_error); @@ -608,7 +647,8 @@ g_dev_strategy(struct bio *bp) KASSERT(bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_DELETE || - bp->bio_cmd == BIO_FLUSH, + bp->bio_cmd == BIO_FLUSH || + bp->bio_cmd == BIO_ZONE, ("Wrong bio_cmd bio=%p cmd=%d", bp, bp->bio_cmd)); dev = bp->bio_dev; cp = dev->si_drv2; diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 1580030..ce4e079 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -226,7 +226,11 @@ g_disk_done(struct bio *bp) if (bp2->bio_error == 0) bp2->bio_error = bp->bio_error; bp2->bio_completed += bp->bio_completed; + switch (bp->bio_cmd) { + case BIO_ZONE: + bcopy(&bp->bio_zone, &bp2->bio_zone, sizeof(bp->bio_zone)); + /*FALLTHROUGH*/ case BIO_READ: case BIO_WRITE: case BIO_DELETE: @@ -515,6 +519,16 @@ g_disk_start(struct bio *bp) error = EOPNOTSUPP; break; } + /*FALLTHROUGH*/ + case BIO_ZONE: + if (bp->bio_cmd == BIO_ZONE) { + if (!(dp->d_flags & DISKFLAG_CANZONE)) { + error = EOPNOTSUPP; + break; + } + g_trace(G_T_BIO, "g_disk_zone(%s)", + bp->bio_to->name); + } bp2 = g_clone_bio(bp); if (bp2 == NULL) { g_io_deliver(bp, ENOMEM); diff --git a/sys/geom/geom_disk.h b/sys/geom/geom_disk.h index 4cf53c4..97faeed 100644 --- a/sys/geom/geom_disk.h +++ b/sys/geom/geom_disk.h @@ -109,6 +109,7 @@ struct disk { #define DISKFLAG_CANFLUSHCACHE 0x8 #define DISKFLAG_UNMAPPED_BIO 0x10 #define DISKFLAG_DIRECT_COMPLETION 0x20 +#define DISKFLAG_CANZONE 0x80 struct disk *disk_alloc(void); void disk_create(struct disk *disk, int version); diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index 8270274..401c20f 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -218,6 +218,9 @@ g_clone_bio(struct bio *bp) bp2->bio_ma_n = bp->bio_ma_n; bp2->bio_ma_offset = bp->bio_ma_offset; bp2->bio_attribute = bp->bio_attribute; + if (bp->bio_cmd == BIO_ZONE) + bcopy(&bp->bio_zone, &bp2->bio_zone, + sizeof(bp->bio_zone)); /* Inherit classification info from the parent */ bp2->bio_classifier1 = bp->bio_classifier1; bp2->bio_classifier2 = bp->bio_classifier2; @@ -305,6 +308,34 @@ g_io_getattr(const char *attr, struct g_consumer *cp, int *len, void *ptr) } int +g_io_zonecmd(struct disk_zone_args *zone_args, struct g_consumer *cp) +{ + struct bio *bp; + int error; + + g_trace(G_T_BIO, "bio_zone(%d)", zone_args->zone_cmd); + bp = g_alloc_bio(); + bp->bio_cmd = BIO_ZONE; + bp->bio_done = NULL; + /* + * XXX KDM need to handle report zone data. + */ + bcopy(zone_args, &bp->bio_zone, sizeof(*zone_args)); + if (zone_args->zone_cmd == DISK_ZONE_REPORT_ZONES) + bp->bio_length = + zone_args->zone_params.report.entries_allocated * + sizeof(struct disk_zone_rep_entry); + else + bp->bio_length = 0; + + g_io_request(bp, cp); + error = biowait(bp, "gzone"); + bcopy(&bp->bio_zone, zone_args, sizeof(*zone_args)); + g_destroy_bio(bp); + return (error); +} + +int g_io_flush(struct g_consumer *cp) { struct bio *bp; @@ -349,6 +380,14 @@ g_io_check(struct bio *bp) if (cp->acw == 0) return (EPERM); break; + case BIO_ZONE: + if ((bp->bio_zone.zone_cmd == DISK_ZONE_REPORT_ZONES) || + (bp->bio_zone.zone_cmd == DISK_ZONE_GET_PARAMS)) { + if (cp->acr == 0) + return (EPERM); + } else if (cp->acw == 0) + return (EPERM); + break; default: return (EPERM); } @@ -988,6 +1027,35 @@ g_print_bio(struct bio *bp) cmd = "FLUSH"; printf("%s[%s]", pname, cmd); return; + case BIO_ZONE: { + char *subcmd = NULL; + cmd = "ZONE"; + switch (bp->bio_zone.zone_cmd) { + case DISK_ZONE_OPEN: + subcmd = "OPEN"; + break; + case DISK_ZONE_CLOSE: + subcmd = "CLOSE"; + break; + case DISK_ZONE_FINISH: + subcmd = "FINISH"; + break; + case DISK_ZONE_RWP: + subcmd = "RWP"; + break; + case DISK_ZONE_REPORT_ZONES: + subcmd = "REPORT ZONES"; + break; + case DISK_ZONE_GET_PARAMS: + subcmd = "GET PARAMS"; + break; + default: + subcmd = "UNKNOWN"; + break; + } + printf("%s[%s,%s]", pname, cmd, subcmd); + return; + } case BIO_READ: cmd = "READ"; break; diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 54a99bf..ef89299 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -1471,6 +1471,7 @@ db_print_bio_cmd(struct bio *bp) case BIO_CMD0: db_printf("BIO_CMD0"); break; case BIO_CMD1: db_printf("BIO_CMD1"); break; case BIO_CMD2: db_printf("BIO_CMD2"); break; + case BIO_ZONE: db_printf("BIO_ZONE"); break; default: db_printf("UNKNOWN"); break; } db_printf("\n"); |