summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/eli/g_eli.c2
-rw-r--r--sys/geom/geom.h2
-rw-r--r--sys/geom/geom_dev.c42
-rw-r--r--sys/geom/geom_disk.c14
-rw-r--r--sys/geom/geom_disk.h1
-rw-r--r--sys/geom/geom_io.c68
-rw-r--r--sys/geom/geom_subr.c1
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");
OpenPOWER on IntegriCloud