summaryrefslogtreecommitdiffstats
path: root/usr.sbin/vnconfig
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-09-17 05:34:00 +0000
committerdillon <dillon@FreeBSD.org>1999-09-17 05:34:00 +0000
commit77cf4cb54b547996b17474b25570116447285537 (patch)
tree3a59baafca356bd7ea5958a89aad60d93ce40361 /usr.sbin/vnconfig
parent124cdf53462edef3fd859a8d3c9d6bf6be840e98 (diff)
downloadFreeBSD-src-77cf4cb54b547996b17474b25570116447285537.zip
FreeBSD-src-77cf4cb54b547996b17474b25570116447285537.tar.gz
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 <alc@cs.rice.edu>, David Greenman <dg@root.com>
Diffstat (limited to 'usr.sbin/vnconfig')
-rw-r--r--usr.sbin/vnconfig/vnconfig.826
-rw-r--r--usr.sbin/vnconfig/vnconfig.c104
2 files changed, 119 insertions, 11 deletions
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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
@@ -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) {
OpenPOWER on IntegriCloud