svn commit: r238215 - in head: sbin/mdconfig sys/dev/md sys/sys

Edward Tomasz Napierala trasz at FreeBSD.org
Sat Jul 7 20:32:21 UTC 2012


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 */


More information about the svn-src-all mailing list