From 77cf4cb54b547996b17474b25570116447285537 Mon Sep 17 00:00:00 2001 From: dillon Date: Fri, 17 Sep 1999 05:34:00 +0000 Subject: Fix a bug in the block number calculation for VN disks with a sector size != 512 that are configured without a label. The bug should only have effected swap-backed VN mounts without a label. Add several major features to VN. In the kernel we add a swap pre-reservation capability, which can be used to guarentee seek consistency for swap-backed VN nodes. This also incidently allows a swap-backed VN filesystem to be recovered after a crash in some cases (if the same swap blocks happen to be reserved). We also add a number of new options to vnconfig which do the work of pre-zeroing or creating/truncating/extending a file which greatly simplifies using VN in a file-backed configuration. Add FreeBSD CVS label to sys/sys/vnioctl.h, as well as a new ioctl flag for the swap pre-reservation feature. Reviewed by: Alan Cox , David Greenman --- usr.sbin/vnconfig/vnconfig.8 | 26 +++++++++-- usr.sbin/vnconfig/vnconfig.c | 104 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 119 insertions(+), 11 deletions(-) (limited to 'usr.sbin/vnconfig') diff --git a/usr.sbin/vnconfig/vnconfig.8 b/usr.sbin/vnconfig/vnconfig.8 index 85ced18..7cfe5170 100644 --- a/usr.sbin/vnconfig/vnconfig.8 +++ b/usr.sbin/vnconfig/vnconfig.8 @@ -46,8 +46,8 @@ .Sh SYNOPSIS .Nm vnconfig .Op Fl cdeguv -.Op Fl s Ar option -.Op Fl r Ar option +.Op Fl s Ar option[,option...] +.Op Fl r Ar option[,option...] .Op Fl S Ar value .Ar special_file Ar [regular_file] .Op Ar feature @@ -106,6 +106,15 @@ The list of allowed flags and their meanings are: .Bl -tag -width "follow" .It Ar labels use disk/slice labels. +.It Ar reserve +Pre-reserve the blocks underlying the file or swap backing store. Currently only +works for swap backing store. This option also disables on-the-fly freeing of +the underlying backing store (for example, when you remove a large file). +Use this option if you wish to avoid long-term fragmentation of the backing +store. Also note that when this option is used, the initial contents of the +backing store may contain garbage rather then zeros. It may even be possible to +recover the prior contents of a swap-backed VN across a reboot if the VN device +is configured before any swap is allocated by the system. .It Ar follow debug flow in the .Xr vn 4 @@ -133,7 +142,18 @@ option. If no regular file is specified, VN will use swap for backing store. This option specifies the size of the device. For example, '23m' for 23 megabytes. The VN device will round the size up to a machine page boundry. -Filesystems up to 7.9 terrabytes are supported. +Filesystems up to 7.9 terrabytes are supported. When specified along with +a regular file, this option overrides the regular file's size insofar as +VN is concerned. +.It Fl T +When a regular file is specified, VN will ftruncate() the file to 0 first. +Normally you should also specify the -S option to set the size of the file. +This option also creates the file if it did not previously exist. +This option is only meaningful if the -S option has been specified. +.It Fl Z +When a regular file is specified, VN will zero the contents of the file to +ensure that all blocks have been allocated by the filesystem. This option is +only meaningful if the -S option has been specified. .It Fl u Disable and ``unconfigure'' the device. .It Fl v diff --git a/usr.sbin/vnconfig/vnconfig.c b/usr.sbin/vnconfig/vnconfig.c index ce1f7ea..c9f6e5e 100644 --- a/usr.sbin/vnconfig/vnconfig.c +++ b/usr.sbin/vnconfig/vnconfig.c @@ -51,6 +51,7 @@ static const char rcsid[] = #include #include #include +#include #include #include #include @@ -64,6 +65,7 @@ static const char rcsid[] = #define MAXVNDISK 16 #define LINESIZE 1024 +#define ZBUFSIZE 32768 struct vndisk { char *dev; @@ -84,6 +86,8 @@ struct vndisk { #define VN_IGNORE 0x80 #define VN_SET 0x100 #define VN_RESET 0x200 +#define VN_TRUNCATE 0x400 +#define VN_ZERO 0x800 int nvndisks; @@ -111,9 +115,10 @@ main(argc, argv) int flags = 0; int size = 0; char *autolabel = NULL; + char *s; configfile = _PATH_VNTAB; - while ((i = getopt(argc, argv, "acdef:gr:s:S:L:uv")) != -1) + while ((i = getopt(argc, argv, "acdef:gr:s:S:TZL:uv")) != -1) switch (i) { /* all -- use config file */ @@ -151,15 +156,19 @@ main(argc, argv) /* reset options */ case 'r': - if (what_opt(optarg,&resetopt)) - errx(1, "invalid options '%s'", optarg); + for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) { + if (what_opt(s, &resetopt)) + errx(1, "invalid options '%s'", s); + } flags |= VN_RESET; break; /* set options */ case 's': - if (what_opt(optarg,&setopt)) - errx(1, "invalid options '%s'", optarg); + for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) { + if (what_opt(s, &setopt)) + errx(1, "invalid options '%s'", s); + } flags |= VN_SET; break; @@ -178,6 +187,14 @@ main(argc, argv) size = getsize(optarg); break; + case 'T': + flags |= VN_TRUNCATE; + break; + + case 'Z': + flags |= VN_ZERO; + break; + case 'L': autolabel = optarg; break; @@ -192,13 +209,13 @@ main(argc, argv) if (flags == 0) flags = VN_CONFIG; - if (all) + if (all) { readconfig(flags); - else { + } else { if (argc < optind + 1) usage(); vndisks[0].dev = argv[optind++]; - vndisks[0].file = argv[optind++]; + vndisks[0].file = argv[optind++]; /* may be NULL */ vndisks[0].flags = flags; vndisks[0].size = size; vndisks[0].autolabel = autolabel; @@ -217,6 +234,7 @@ what_opt(str,p) char *str; u_long *p; { + if (!strcmp(str,"reserve")) { *p |= VN_RESERVE; return 0; } if (!strcmp(str,"labels")) { *p |= VN_LABELS; return 0; } if (!strcmp(str,"follow")) { *p |= VN_FOLLOW; return 0; } if (!strcmp(str,"debug")) { *p |= VN_DEBUG; return 0; } @@ -237,6 +255,7 @@ config(vnp) char *rdev; FILE *f; u_long l; + int pgsize = getpagesize(); rv = 0; @@ -254,6 +273,47 @@ config(vnp) if (flags & VN_IGNORE) return(0); + /* + * When a regular file has been specified, do any requested setup + * of the file. Truncation (also creates the file if necessary), + * sizing, and zeroing. + */ + + if (file && vnp->size != 0 && (flags & VN_CONFIG)) { + int fd; + struct stat st; + + if (flags & VN_TRUNCATE) + fd = open(file, O_RDWR|O_CREAT|O_TRUNC); + else + fd = open(file, O_RDWR); + if (fd >= 0 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { + if (st.st_size < (off_t)vnp->size * pgsize) + ftruncate(fd, (off_t)vnp->size * pgsize); + if (vnp->size != 0) + st.st_size = (off_t)vnp->size * pgsize; + + if (flags & VN_ZERO) { + char *buf = malloc(ZBUFSIZE); + bzero(buf, ZBUFSIZE); + while (st.st_size > 0) { + int n = (st.st_size > ZBUFSIZE) ? + ZBUFSIZE : (int)st.st_size; + if (write(fd, buf, n) != n) { + ftruncate(fd, 0); + printf("Unable to ZERO file %s\n", file); + return(0); + } + st.st_size -= (off_t)n; + } + } + close(fd); + } else { + printf("Unable to open file %s\n", file); + return(0); + } + } + rdev = rawdevice(dev); f = fopen(rdev, "rw"); if (f == NULL) { @@ -294,6 +354,34 @@ config(vnp) printf("%s: cleared\n", dev); } /* + * Set specified options + */ + if (flags & VN_SET) { + l = setopt; + if (global) + rv = ioctl(fileno(f), VNIOCGSET, &l); + else + rv = ioctl(fileno(f), VNIOCUSET, &l); + if (rv) { + warn("VNIO[GU]SET"); + } else if (verbose) + printf("%s: flags now=%08x\n",dev,l); + } + /* + * Reset specified options + */ + if (flags & VN_RESET) { + l = resetopt; + if (global) + rv = ioctl(fileno(f), VNIOCGCLEAR, &l); + else + rv = ioctl(fileno(f), VNIOCUCLEAR, &l); + if (rv) { + warn("VNIO[GU]CLEAR"); + } else if (verbose) + printf("%s: flags now=%08x\n",dev,l); + } + /* * Configure the device */ if (flags & VN_CONFIG) { -- cgit v1.1