diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8 index 3df260390f2d..09fbf44b6f3f 100644 --- a/sbin/mdconfig/mdconfig.8 +++ b/sbin/mdconfig/mdconfig.8 @@ -61,6 +61,9 @@ .Nm .Fl d .Fl u Ar unit +.Nm +.Fl l +.Op Fl u Ar unit .Sh DESCRIPTION The .Nm @@ -92,6 +95,13 @@ swapspace is used to back this memory disk. .El .It Fl f Ar file Filename to use for the vnode type memory disk. +.It Fl l +List information about configured +.Xr md 4 +devices. If the +.Fl u +option is used in conjuction with this, the output is limited to +information on the specified device. .It Fl s Ar size Size of the memory disk. .Ar Size diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index 079be71d8670..3bcd7b259489 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -21,10 +21,16 @@ #include #include #include +#include +#include + +int intcmp(const void *, const void *); +int list(const int); +int query(const int, const int); struct md_ioctl mdio; -enum {UNSET, ATTACH, DETACH} action = UNSET; +enum {UNSET, ATTACH, DETACH, LIST} action = UNSET; void mdmaybeload(void); @@ -34,6 +40,7 @@ usage() fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tmdconfig -a -t type [-o [no]option]... [ -f file] [-s size] [-u unit]\n"); fprintf(stderr, "\tmdconfig -d -u unit\n"); + fprintf(stderr, "\tmdconfig -l [-u unit]\n"); fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n"); fprintf(stderr, "\t\toption = {cluster, compress, reserve, autounit}\n"); fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%dk (kB), %%dm (MB) or %%dg (GB)\n"); @@ -48,7 +55,7 @@ main(int argc, char **argv) int cmdline = 0; for (;;) { - ch = getopt(argc, argv, "ab:df:o:s:t:u:"); + ch = getopt(argc, argv, "ab:df:lo:s:t:u:"); if (ch == -1) break; switch (ch) { @@ -65,6 +72,13 @@ main(int argc, char **argv) mdio.md_options = MD_AUTOUNIT; cmdline = 3; break; + case 'l': + if (cmdline != 0) + usage(); + action = LIST; + mdio.md_options = MD_AUTOUNIT; + cmdline = 3; + break; case 't': if (cmdline != 1) usage(); @@ -132,10 +146,9 @@ main(int argc, char **argv) usage(); if (!strncmp(optarg, "/dev/", 5)) optarg += 5; - if (!strncmp(optarg, "md", 2)) + if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1)) optarg += 2; mdio.md_unit = strtoul(optarg, NULL, 0); - mdio.md_unit = strtoul(optarg, NULL, 0); mdio.md_options &= ~MD_AUTOUNIT; break; default: @@ -144,20 +157,121 @@ main(int argc, char **argv) } mdmaybeload(); - fd = open("/dev/mdctl", O_RDWR, 0); + fd = open("/dev/" MDCTL_NAME, O_RDWR, 0); if (fd < 0) - err(1, "open(/dev/mdctl)"); - if (action == ATTACH) { + err(1, "open(/dev/%s)", MDCTL_NAME); + if (action == LIST) { + if (mdio.md_options & MD_AUTOUNIT) + list(fd); + else + query(fd, mdio.md_unit); + } else if (action == ATTACH) { i = ioctl(fd, MDIOCATTACH, &mdio); + if (i < 0) + err(1, "ioctl(/dev/%s)", MDCTL_NAME); } else { if (mdio.md_options & MD_AUTOUNIT) usage(); i = ioctl(fd, MDIOCDETACH, &mdio); + if (i < 0) + err(1, "ioctl(/dev/%s)", MDCTL_NAME); } - if (i < 0) - err(1, "ioctl(/dev/mdctl)"); if (mdio.md_options & MD_AUTOUNIT) - printf("md%d\n", mdio.md_unit); + printf("%s%d\n", MD_NAME, mdio.md_unit); + close (fd); + return (0); +} + +int +intcmp(const void *a, const void *b) +{ + + return (*(int *)a - *(int *)b); +} + +struct dl { + int unit; + SLIST_ENTRY(dl) slist; +}; + +SLIST_HEAD(, dl) dlist = SLIST_HEAD_INITIALIZER(&dlist); + +int +list(const int fd) +{ + char *disklist, *p, *p2, *p3; + int unit, dll; + struct dl *dp, *di, *dn; + + if (sysctlbyname("kern.disks", NULL, &dll, NULL, NULL) == -1) + err(1, "sysctlbyname: kern.disks"); + if ( (disklist = malloc(dll)) == NULL) + err(1, "malloc"); + if (sysctlbyname("kern.disks", disklist, &dll, NULL, NULL) == -1) + err(1, "sysctlbyname: kern.disks"); + + for (p = disklist; + (p2 = strsep(&p, " ")) != NULL;) { + if (strncmp(p2, MD_NAME, sizeof(MD_NAME) - 1) != 0) + continue; + p2 += 2; + unit = strtoul(p2, &p3, 10); + if (p2 == p3) + continue; + dp = calloc(sizeof *dp, 1); + dp->unit = unit; + dn = SLIST_FIRST(&dlist); + if (dn == NULL || dn->unit > unit) { + SLIST_INSERT_HEAD(&dlist, dp, slist); + } else { + SLIST_FOREACH(di, &dlist, slist) { + dn = SLIST_NEXT(di, slist); + if (dn == NULL || dn->unit > unit) { + SLIST_INSERT_AFTER(di, dp, slist); + break; + } + } + } + } + SLIST_FOREACH(di, &dlist, slist) + query(fd, di->unit); + while (!SLIST_EMPTY(&dlist)) { + di = SLIST_FIRST(&dlist); + SLIST_REMOVE_HEAD(&dlist, slist); + free(di); + } + free(disklist); + return (0); +} + +int +query(const int fd, const int unit) +{ + + mdio.md_unit = unit; + + if (ioctl(fd, MDIOCQUERY, &mdio) < 0) + err(1, "ioctl(/dev/%s)", MDCTL_NAME); + + switch (mdio.md_type) { + case MD_MALLOC: + (void)printf("%s%d\tmalloc\t%d KBytes\n", MD_NAME, + mdio.md_unit, mdio.md_size / 2); + break; + case MD_PRELOAD: + (void)printf("%s%d\tpreload\t%d KBytes\n", MD_NAME, + mdio.md_unit, mdio.md_size / 2); + break; + case MD_SWAP: + (void)printf("%s%d\tswap\t%d KBytes\n", MD_NAME, + mdio.md_unit, mdio.md_size / 2); + break; + case MD_VNODE: + (void)printf("%s%d\tvnode\t%d KBytes\n", MD_NAME, + mdio.md_unit, mdio.md_size / 2); + break; + } + return (0); } diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 48ff0b35f57c..dc53517a2591 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -133,7 +133,7 @@ static struct cdevsw md_cdevsw = { /* poll */ nopoll, /* mmap */ nommap, /* strategy */ mdstrategy, - /* name */ "md", + /* name */ MD_NAME, /* maj */ CDEV_MAJOR, /* dump */ nodump, /* psize */ nopsize, @@ -149,7 +149,7 @@ static struct cdevsw mdctl_cdevsw = { /* poll */ nopoll, /* mmap */ nommap, /* strategy */ nostrategy, - /* name */ "md", + /* name */ MD_NAME, /* maj */ CDEV_MAJOR }; @@ -533,7 +533,7 @@ mdinit(struct md_s *sc) { bioq_init(&sc->bio_queue); - devstat_add_entry(&sc->stats, "md", sc->unit, sc->secsize, + devstat_add_entry(&sc->stats, MD_NAME, sc->unit, sc->secsize, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER, DEVSTAT_PRIORITY_OTHER); @@ -608,7 +608,7 @@ mdcreate_malloc(struct md_ioctl *mdio) for (u = 0; u < sc->nsect; u++) MALLOC(sc->secp[u], u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK | M_ZERO); } - printf("md%d: Malloc disk\n", sc->unit); + printf("%s%d: Malloc disk\n", MD_NAME, sc->unit); mdinit(sc); return (0); } @@ -833,6 +833,30 @@ mdctlioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) default: return (EOPNOTSUPP); } + case MDIOCQUERY: + sc = mdfind(mdio->md_unit); + if (sc == NULL) + return (ENOENT); + mdio->md_type = sc->type; + mdio->md_options = sc->flags; + switch (sc->type) { + case MD_MALLOC: + mdio->md_size = sc->nsect; + break; + case MD_PRELOAD: + mdio->md_size = sc->nsect; + (u_char *)(uintptr_t)mdio->md_base = sc->pl_ptr; + break; + case MD_SWAP: + mdio->md_size = sc->nsect * (PAGE_SIZE / DEV_BSIZE); + break; + case MD_VNODE: + mdio->md_size = sc->nsect; + /* XXX fill this in */ + mdio->md_file = NULL; + break; + } + return (0); default: return (ENOIOCTL); }; diff --git a/sys/sys/mdioctl.h b/sys/sys/mdioctl.h index 1507e6f2d714..6ebda6b8dfaf 100644 --- a/sys/sys/mdioctl.h +++ b/sys/sys/mdioctl.h @@ -64,6 +64,8 @@ struct md_ioctl { int pad[100]; /* padding for future ideas */ }; +#define MD_NAME "md" +#define MDCTL_NAME "mdctl" #define MDIOVERSION 1 /* @@ -75,6 +77,7 @@ struct md_ioctl { #define MDIOCATTACH _IOWR('m', 0, struct md_ioctl) /* attach disk */ #define MDIOCDETACH _IOWR('m', 1, struct md_ioctl) /* detach disk */ +#define MDIOCQUERY _IOWR('m', 2, struct md_ioctl) /* query status */ #define MD_CLUSTER 0x01 /* Don't cluster */ #define MD_RESERVE 0x02 /* Pre-reserve swap */