Date: Tue, 24 Aug 1999 20:16:03 -0700 (PDT) From: Matthew Dillon <dillon@apollo.backplane.com> To: Luigi Rizzo <luigi@labinfo.iet.unipi.it> Cc: julian@whistle.com (Julian Elischer), phk@critter.freebsd.dk, bde@zeta.org.au, jb@cimlogic.com.au, atrens@nortelnetworks.com, current@FreeBSD.ORG Subject: VN fixed Message-ID: <199908250316.UAA23429@apollo.backplane.com> References: <199908221115.NAA05282@labinfo.iet.unipi.it>
next in thread | previous in thread | raw e-mail | index | archive | help
I have submitted a patch to DG that fixes VN for CURRENT. Since VN is currently broken on CURRENT, the patch is on a fast-track for commit. I've include the patch below, but beware that it may be committed quickly. This also fixes swap-backed VN. The -S option can be applied to files now and two new options -T (truncate/create file) and -Z (write zero's to file to pre-allocate the file blocks) have been added. Example usage: vnconfig -e -s labels -T -Z -S 64m /dev/vn0 /usr/obj/test disklabel -w -r vn0 auto newfs /dev/rvn0c mount /dev/vn0c ....some_mount_point.... ... umount ....the_mount_point... vnconfig -u /dev/vn0 The VN device can also be used with direct-swap backing store by not specifying a backing file. Note that the sector size is the system page size (4K on intel). vnconfig -e -s labels -S 256m /dev/vn0 disklabel -w -r vn0 auto newfs /dev/rvn0c mount /dev/vn0c ....some_mount_point.... ... umount ....the_mount_point... vnconfig -u /dev/vn0 Performance: The VN device operates as a raw disk device. This means that 'disk I/O' operations are written to the underlying storage whereas with MFS 'disk I/O' operations are written to memory. VN should be reasonably efficient memory-wise at the cost of some performance (e.g. the I/O performed). MFS is less memory efficient (each cached block exists in main memory twice instead of once) but if you have lots of memory MFS will not perform any I/O. Note that VN does take advantage of the VM cache, of course, because the filesystem running on top of it caches things in the VM cache. What does this mean? For small filesystems use MFS. For large filesystems use VN. Use of file-backed vs swap-backed VN. It's your choice. A swap-backed VN device has lower I/O overhead but is not persistant and you must be sure to have sufficient swap to hold the entire size of the VN device to avoid running the system out of swap if someone fills up the VN partition. file-backed storage can be made persistant (you can even run fsck on the file prior to mounting it). -Matt Index: sys/vm/vm_pager.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_pager.c,v retrieving revision 1.51 diff -u -r1.51 vm_pager.c --- vm_pager.c 1999/07/05 12:50:54 1.51 +++ vm_pager.c 1999/08/25 02:20:02 @@ -566,6 +566,7 @@ nbp->b_bufsize = nbp->b_bcount; if ((nbp->b_flags & B_READ) == 0) nbp->b_dirtyend = nbp->b_bcount; + BUF_KERNPROC(nbp); VOP_STRATEGY(nbp->b_vp, nbp); } else { biodone(nbp); Index: sys/vm/swap_pager.c =================================================================== RCS file: /home/ncvs/src/sys/vm/swap_pager.c,v retrieving revision 1.124 diff -u -r1.124 swap_pager.c --- swap_pager.c 1999/08/23 23:55:03 1.124 +++ swap_pager.c 1999/08/25 02:20:42 @@ -857,6 +857,7 @@ if (nbp == NULL) { nbp = getchainbuf(bp, swapdev_vp, B_READ|B_ASYNC); nbp->b_blkno = blk; + nbp->b_bcount = 0; nbp->b_data = data; } nbp->b_bcount += PAGE_SIZE; Index: sys/dev/vn/vn.c =================================================================== RCS file: /home/ncvs/src/sys/dev/vn/vn.c,v retrieving revision 1.86 diff -u -r1.86 vn.c --- vn.c 1999/08/23 20:35:16 1.86 +++ vn.c 1999/08/25 02:21:50 @@ -207,18 +207,23 @@ static int vnopen(dev_t dev, int flags, int mode, struct proc *p) { - int unit; struct vn_softc *vn; - unit = dkunit(dev); - vn = dev->si_drv1; - if (!vn) + /* + * Locate preexisting device + */ + + if ((vn = dev->si_drv1) == NULL) vn = vnfindvn(dev); IFOPT(vn, VN_FOLLOW) printf("vnopen(%s, 0x%x, 0x%x, %p)\n", devtoname(dev), flags, mode, (void *)p); + /* + * Initialize label + */ + IFOPT(vn, VN_LABELS) { if (vn->sc_flags & VNF_INITED) { struct disklabel label; @@ -238,8 +243,9 @@ } if (dkslice(dev) != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART || - mode != S_IFCHR) + mode != S_IFCHR) { return (ENXIO); + } } return(0); } @@ -500,7 +506,15 @@ VOP_UNLOCK(nd.ni_vp, 0, p); vn->sc_secsize = DEV_BSIZE; vn->sc_vp = nd.ni_vp; - vn->sc_size = vattr.va_size / vn->sc_secsize; /* note truncation */ + + /* + * If the size is specified, override the file attributes. Note that + * the vn_size argument is in PAGE_SIZE sized blocks. + */ + if (vio->vn_size) + vn->sc_size = (quad_t)vio->vn_size * PAGE_SIZE / vn->sc_secsize; + else + vn->sc_size = vattr.va_size / vn->sc_secsize; error = vnsetcred(vn, p->p_ucred); if (error) { (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p); Index: usr.sbin/vnconfig/vnconfig.8 =================================================================== RCS file: /home/ncvs/src/usr.sbin/vnconfig/vnconfig.8,v retrieving revision 1.8 diff -u -r1.8 vnconfig.8 --- vnconfig.8 1999/07/12 20:12:29 1.8 +++ vnconfig.8 1999/08/25 02:52:49 @@ -133,7 +133,18 @@ 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 Index: usr.sbin/vnconfig/vnconfig.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/vnconfig/vnconfig.c,v retrieving revision 1.10 diff -u -r1.10 vnconfig.c --- vnconfig.c 1999/05/16 08:09:23 1.10 +++ vnconfig.c 1999/08/25 02:51:51 @@ -50,6 +50,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <fcntl.h> #include <string.h> #include <unistd.h> #include <sys/param.h> @@ -62,6 +63,7 @@ #define MAXVNDISK 16 #define LINESIZE 1024 +#define ZBUFSIZE 32768 struct vndisk { char *dev; @@ -82,6 +84,8 @@ #define VN_IGNORE 0x80 #define VN_SET 0x100 #define VN_RESET 0x200 +#define VN_TRUNCATE 0x400 +#define VN_ZERO 0x800 int nvndisks; @@ -111,7 +115,7 @@ char *autolabel = NULL; 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 */ @@ -176,6 +180,14 @@ size = getsize(optarg); break; + case 'T': + flags |= VN_TRUNCATE; + break; + + case 'Z': + flags |= VN_ZERO; + break; + case 'L': autolabel = optarg; break; @@ -190,13 +202,13 @@ 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; @@ -235,6 +247,7 @@ char *rdev; FILE *f; u_long l; + int pgsize = getpagesize(); dev = vnp->dev; file = vnp->file; @@ -243,6 +256,47 @@ 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"); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199908250316.UAA23429>