Skip site navigation (1)Skip section navigation (2)
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>