mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-03 14:48:57 +00:00
Make it possible to resize md(4) devices.
Reviewed by: kib Sponsored by: FreeBSD Foundation
This commit is contained in:
parent
fcc144ad4e
commit
dc604f0cf6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=238215
@ -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 disk with the
|
||||
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"
|
||||
|
@ -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);
|
||||
|
@ -1080,6 +1080,64 @@ mddestroy(struct md_s *sc, struct thread *td)
|
||||
return (0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -1108,7 +1166,7 @@ mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
||||
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, caddr_t addr, int flags, struct thread
|
||||
!(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)
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user