Author: trasz
Date: Sat Jul  7 20:32:21 2012
New Revision: 238215
URL: http://svn.freebsd.org/changeset/base/238215

Log:
  Make it possible to resize md(4) devices.
  
  Reviewed by:  kib
  Sponsored by: FreeBSD Foundation

Modified:
  head/sbin/mdconfig/mdconfig.8
  head/sbin/mdconfig/mdconfig.c
  head/sys/dev/md/md.c
  head/sys/sys/mdioctl.h

Modified: head/sbin/mdconfig/mdconfig.8
==============================================================================
--- head/sbin/mdconfig/mdconfig.8       Sat Jul  7 20:21:05 2012        
(r238214)
+++ head/sbin/mdconfig/mdconfig.8       Sat Jul  7 20:32:21 2012        
(r238215)
@@ -64,6 +64,11 @@
 .Fl u Ar unit
 .Op Fl o Oo Cm no Oc Ns Ar force
 .Nm
+.Fl r
+.Fl u Ar unit
+.Fl s Ar size
+.Op Fl o Oo Cm no Oc Ns Ar force
+.Nm
 .Fl l
 .Op Fl n
 .Op Fl v
@@ -85,6 +90,8 @@ This will configure and attach a memory 
 parameters specified and attach it to the system.
 .It Fl d
 Detach a memory disk from the system and release all resources.
+.It Fl r
+Resize a memory disk.
 .It Fl t Ar type
 Select the type of the memory disk.
 .Bl -tag -width "malloc"

Modified: head/sbin/mdconfig/mdconfig.c
==============================================================================
--- head/sbin/mdconfig/mdconfig.c       Sat Jul  7 20:21:05 2012        
(r238214)
+++ head/sbin/mdconfig/mdconfig.c       Sat Jul  7 20:32:21 2012        
(r238215)
@@ -54,7 +54,7 @@
 #include <unistd.h>
 
 static struct md_ioctl mdio;
-static enum {UNSET, ATTACH, DETACH, LIST} action = UNSET;
+static enum {UNSET, ATTACH, DETACH, RESIZE, LIST} action = UNSET;
 static int nflag;
 
 static void usage(void);
@@ -81,6 +81,7 @@ usage(void)
 "                [-s size] [-S sectorsize] [-u unit]\n"
 "                [-x sectors/track] [-y heads/cylinder]\n"
 "       mdconfig -d -u unit [-o [no]force]\n"
+"       mdconfig -r -u unit -s size [-o [no]force]\n"
 "       mdconfig -l [-v] [-n] [-u unit]\n"
 "       mdconfig file\n");
        fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n");
@@ -96,7 +97,7 @@ main(int argc, char **argv)
 {
        int ch, fd, i, vflag;
        char *p;
-       char *fflag = NULL, *tflag = NULL, *uflag = NULL;
+       char *fflag = NULL, *sflag = NULL, *tflag = NULL, *uflag = NULL;
 
        bzero(&mdio, sizeof(mdio));
        mdio.md_file = malloc(PATH_MAX);
@@ -108,25 +109,32 @@ main(int argc, char **argv)
        if (argc == 1)
                usage();
 
-       while ((ch = getopt(argc, argv, "ab:df:lno:s:S:t:u:vx:y:")) != -1) {
+       while ((ch = getopt(argc, argv, "ab:df:lno:rs:S:t:u:vx:y:")) != -1) {
                switch (ch) {
                case 'a':
                        if (action != UNSET && action != ATTACH)
-                               errx(1,
-                                   "-a is mutually exclusive with -d and -l");
+                               errx(1, "-a is mutually exclusive "
+                                   "with -d, -r, and -l");
                        action = ATTACH;
                        break;
                case 'd':
                        if (action != UNSET && action != DETACH)
-                               errx(1,
-                                   "-d is mutually exclusive with -a and -l");
+                               errx(1, "-d is mutually exclusive "
+                                   "with -a, -r, and -l");
                        action = DETACH;
                        mdio.md_options |= MD_AUTOUNIT;
                        break;
+               case 'r':
+                       if (action != UNSET && action != RESIZE)
+                               errx(1, "-r is mutually exclusive "
+                                   "with -a, -d, and -l");
+                       action = RESIZE;
+                       mdio.md_options |= MD_AUTOUNIT;
+                       break;
                case 'l':
                        if (action != UNSET && action != LIST)
-                               errx(1,
-                                   "-l is mutually exclusive with -a and -d");
+                               errx(1, "-l is mutually exclusive "
+                                   "with -a, -r, and -d");
                        action = LIST;
                        mdio.md_options |= MD_AUTOUNIT;
                        break;
@@ -188,6 +196,9 @@ main(int argc, char **argv)
                        mdio.md_sectorsize = strtoul(optarg, &p, 0);
                        break;
                case 's':
+                       if (sflag != NULL)
+                               errx(1, "-s can be passed only once");
+                       sflag = optarg;
                        mdio.md_mediasize = (off_t)strtoumax(optarg, &p, 0);
                        if (p == NULL || *p == '\0')
                                mdio.md_mediasize *= DEV_BSIZE;
@@ -242,7 +253,7 @@ main(int argc, char **argv)
                                mdio.md_type = MD_VNODE;
                                mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT |
                                    MD_COMPRESS;
-                       } else if (mdio.md_mediasize != 0) {
+                       } else if (sflag != NULL) {
                                /* Imply ``-t swap'' */
                                mdio.md_type = MD_SWAP;
                                mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT |
@@ -276,15 +287,15 @@ main(int argc, char **argv)
                }
 
                if ((mdio.md_type == MD_MALLOC || mdio.md_type == MD_SWAP) &&
-                   mdio.md_mediasize == 0)
+                   sflag == NULL)
                        errx(1, "must specify -s for -t malloc or -t swap");
                if (mdio.md_type == MD_VNODE && mdio.md_file[0] == '\0')
                        errx(1, "must specify -f for -t vnode");
        } else {
                if (mdio.md_sectorsize != 0)
                        errx(1, "-S can only be used with -a");
-               if (mdio.md_mediasize != 0)
-                       errx(1, "-s can only be used with -a");
+               if (action != RESIZE && sflag != NULL)
+                       errx(1, "-s can only be used with -a and -r");
                if (mdio.md_fwsectors != 0)
                        errx(1, "-x can only be used with -a");
                if (mdio.md_fwheads != 0)
@@ -295,13 +306,20 @@ main(int argc, char **argv)
                        errx(1, "-t can only be used with -a");
                if (argc > 0)
                        errx(1, "file can only be used with -a");
-               if (action != DETACH && (mdio.md_options & ~MD_AUTOUNIT) != 0)
-                       errx(1, "-o can only be used with -a and -d");
+               if ((action != DETACH && action != RESIZE) &&
+                   (mdio.md_options & ~MD_AUTOUNIT) != 0)
+                       errx(1, "-o can only be used with -a, -d, and -r");
                if (action == DETACH &&
                    (mdio.md_options & ~(MD_FORCE | MD_AUTOUNIT)) != 0)
                        errx(1, "only -o [no]force can be used with -d");
+               if (action == RESIZE &&
+                   (mdio.md_options & ~(MD_FORCE | MD_RESERVE | MD_AUTOUNIT)) 
!= 0)
+                       errx(1, "only -o [no]force and -o [no]reserve can be 
used with -r");
        }
 
+       if (action == RESIZE && sflag == NULL)
+               errx(1, "must specify -s for -r");
+
        if (action != LIST && vflag == OPT_VERBOSE)
                errx(1, "-v can only be used with -l");
 
@@ -333,6 +351,12 @@ main(int argc, char **argv)
                i = ioctl(fd, MDIOCDETACH, &mdio);
                if (i < 0)
                        err(1, "ioctl(/dev/%s)", MDCTL_NAME);
+       } else if (action == RESIZE) {
+               if (mdio.md_options & MD_AUTOUNIT)
+                       errx(1, "-r requires -u");
+               i = ioctl(fd, MDIOCRESIZE, &mdio);
+               if (i < 0)
+                       err(1, "ioctl(/dev/%s)", MDCTL_NAME);
        } else if (action == LIST) {
                if (mdio.md_options & MD_AUTOUNIT) {
                        /*
@@ -342,7 +366,6 @@ main(int argc, char **argv)
                        md_list(NULL, OPT_LIST | vflag);
                } else
                        return (md_query(uflag));
-
        } else
                usage();
        close(fd);

Modified: head/sys/dev/md/md.c
==============================================================================
--- head/sys/dev/md/md.c        Sat Jul  7 20:21:05 2012        (r238214)
+++ head/sys/dev/md/md.c        Sat Jul  7 20:32:21 2012        (r238215)
@@ -1081,6 +1081,64 @@ mddestroy(struct md_s *sc, struct thread
 }
 
 static int
+mdresize(struct md_s *sc, struct md_ioctl *mdio)
+{
+       int error, res;
+       vm_pindex_t oldpages, newpages;
+
+       switch (sc->type) {
+       case MD_VNODE:
+               break;
+       case MD_SWAP:
+               if (mdio->md_mediasize == 0 ||
+                   (mdio->md_mediasize % PAGE_SIZE) != 0)
+                       return (EDOM);
+               oldpages = OFF_TO_IDX(round_page(sc->mediasize));
+               newpages = OFF_TO_IDX(round_page(mdio->md_mediasize));
+               if (newpages < oldpages) {
+                       VM_OBJECT_LOCK(sc->object);
+                       vm_object_page_remove(sc->object, newpages, 0, 0);
+                       swap_pager_freespace(sc->object, newpages,
+                           oldpages - newpages);
+                       swap_release_by_cred(IDX_TO_OFF(oldpages -
+                           newpages), sc->cred);
+                       sc->object->charge = IDX_TO_OFF(newpages);
+                       sc->object->size = newpages;
+                       VM_OBJECT_UNLOCK(sc->object);
+               } else if (newpages > oldpages) {
+                       res = swap_reserve_by_cred(IDX_TO_OFF(newpages -
+                           oldpages), sc->cred);
+                       if (!res)
+                               return (ENOMEM);
+                       if ((mdio->md_options & MD_RESERVE) ||
+                           (sc->flags & MD_RESERVE)) {
+                               error = swap_pager_reserve(sc->object,
+                                   oldpages, newpages - oldpages);
+                               if (error < 0) {
+                                       swap_release_by_cred(
+                                           IDX_TO_OFF(newpages - oldpages),
+                                           sc->cred);
+                                       return (EDOM);
+                               }
+                       }
+                       VM_OBJECT_LOCK(sc->object);
+                       sc->object->charge = IDX_TO_OFF(newpages);
+                       sc->object->size = newpages;
+                       VM_OBJECT_UNLOCK(sc->object);
+               }
+               break;
+       default:
+               return (EOPNOTSUPP);
+       }
+
+       sc->mediasize = mdio->md_mediasize;
+       g_topology_lock();
+       g_resize_provider(sc->pp, sc->mediasize);
+       g_topology_unlock();
+       return (0);
+}
+
+static int
 mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
 {
        vm_ooffset_t npage;
@@ -1108,7 +1166,7 @@ mdcreate_swap(struct md_s *sc, struct md
            VM_PROT_DEFAULT, 0, td->td_ucred);
        if (sc->object == NULL)
                return (ENOMEM);
-       sc->flags = mdio->md_options & MD_FORCE;
+       sc->flags = mdio->md_options & (MD_FORCE | MD_RESERVE);
        if (mdio->md_options & MD_RESERVE) {
                if (swap_pager_reserve(sc->object, 0, npage) < 0) {
                        error = EDOM;
@@ -1217,6 +1275,18 @@ xmdctlioctl(struct cdev *dev, u_long cmd
                    !(mdio->md_options & MD_FORCE))
                        return (EBUSY);
                return (mddestroy(sc, td));
+       case MDIOCRESIZE:
+               if ((mdio->md_options & ~(MD_FORCE | MD_RESERVE)) != 0)
+                       return (EINVAL);
+
+               sc = mdfind(mdio->md_unit);
+               if (sc == NULL)
+                       return (ENOENT);
+               if (mdio->md_mediasize < sc->mediasize &&
+                   !(sc->flags & MD_FORCE) &&
+                   !(mdio->md_options & MD_FORCE))
+                       return (EBUSY);
+               return (mdresize(sc, mdio));
        case MDIOCQUERY:
                sc = mdfind(mdio->md_unit);
                if (sc == NULL)

Modified: head/sys/sys/mdioctl.h
==============================================================================
--- head/sys/sys/mdioctl.h      Sat Jul  7 20:21:05 2012        (r238214)
+++ head/sys/sys/mdioctl.h      Sat Jul  7 20:32:21 2012        (r238215)
@@ -79,6 +79,7 @@ struct md_ioctl {
 #define MDIOCDETACH    _IOWR('m', 1, struct md_ioctl)  /* detach disk */
 #define MDIOCQUERY     _IOWR('m', 2, struct md_ioctl)  /* query status */
 #define MDIOCLIST      _IOWR('m', 3, struct md_ioctl)  /* query status */
+#define MDIOCRESIZE    _IOWR('m', 4, struct md_ioctl)  /* resize disk */
 
 #define MD_CLUSTER     0x01    /* Don't cluster */
 #define MD_RESERVE     0x02    /* Pre-reserve swap */
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to