summaryrefslogtreecommitdiffstats
path: root/sys
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 /sys
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 'sys')
-rw-r--r--sys/dev/vn/vn.c58
-rw-r--r--sys/sys/mdioctl.h3
-rw-r--r--sys/sys/vnioctl.h3
3 files changed, 54 insertions, 10 deletions
diff --git a/sys/dev/vn/vn.c b/sys/dev/vn/vn.c
index 199c804..54914b2 100644
--- a/sys/dev/vn/vn.c
+++ b/sys/dev/vn/vn.c
@@ -157,6 +157,7 @@ static SLIST_HEAD(, vn_softc) vn_list;
static u_long vn_options;
#define IFOPT(vn,opt) if (((vn)->sc_options|vn_options) & (opt))
+#define TESTOPT(vn,opt) (((vn)->sc_options|vn_options) & (opt))
static int vnsetcred (struct vn_softc *vn, struct ucred *cred);
static void vnclear (struct vn_softc *vn);
@@ -208,14 +209,23 @@ vnfindvn(dev_t dev)
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);
+ /*
+ * Update si_bsize fields for device. This data will be overriden by
+ * the slice/parition code for vn accesses through partitions, and
+ * used directly if you open the 'whole disk' device.
+ */
+ dev->si_bsize_phys = vn->sc_secsize;
+ dev->si_bsize_best = vn->sc_secsize;
+
if (flags & FWRITE && vn->sc_flags & VNF_READONLY)
return (EACCES);
@@ -223,6 +233,10 @@ vnopen(dev_t dev, int flags, int mode, struct proc *p)
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;
@@ -241,8 +255,9 @@ vnopen(dev_t dev, int flags, int mode, struct proc *p)
}
if (dkslice(dev) != WHOLE_DISK_SLICE ||
dkpart(dev) != RAW_PART ||
- mode != S_IFCHR)
+ mode != S_IFCHR) {
return (ENXIO);
+ }
}
return(0);
}
@@ -295,9 +310,9 @@ vnstrategy(struct buf *bp)
return;
}
} else {
- int pbn;
+ int pbn; /* in sc_secsize chunks */
- pbn = bp->b_blkno * (vn->sc_secsize / DEV_BSIZE);
+ pbn = bp->b_blkno / (vn->sc_secsize / DEV_BSIZE);
sz = howmany(bp->b_bcount, vn->sc_secsize);
if (pbn < 0 || pbn + sz > vn->sc_size) {
@@ -356,8 +371,17 @@ vnstrategy(struct buf *bp)
* OBJT_SWAP I/O
*
* ( handles read, write, freebuf )
+ *
+ * Note: if we pre-reserved swap, B_FREEBUF is disabled
*/
- vm_pager_strategy(vn->sc_object, bp);
+ KASSERT((bp->b_bufsize & (vn->sc_secsize - 1)) == 0,
+ ("vnstrategy: buffer %p to small for physio", bp));
+
+ if ((bp->b_flags & B_FREEBUF) && TESTOPT(vn, VN_RESERVE)) {
+ biodone(bp);
+ } else {
+ vm_pager_strategy(vn->sc_object, bp);
+ }
} else {
bp->b_flags |= B_ERROR;
bp->b_error = EINVAL;
@@ -504,13 +528,20 @@ vniocattach_file(vn, vio, dev, flag, p)
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, flags, p->p_ucred, p);
return(error);
}
- dev->si_bsize_phys = vn->sc_secsize;
vn->sc_flags |= VNF_INITED;
if (flags == FREAD)
vn->sc_flags |= VNF_READONLY;
@@ -571,6 +602,13 @@ vniocattach_swap(vn, vio, dev, flag, p)
vn->sc_size = vio->vn_size;
vn->sc_object =
vm_pager_allocate(OBJT_SWAP, NULL, vn->sc_secsize * (vm_ooffset_t)vio->vn_size, VM_PROT_DEFAULT, 0);
+ IFOPT(vn, VN_RESERVE) {
+ if (swap_pager_reserve(vn->sc_object, 0, vn->sc_size) < 0) {
+ vm_pager_deallocate(vn->sc_object);
+ vn->sc_object = NULL;
+ return(EDOM);
+ }
+ }
vn->sc_flags |= VNF_INITED;
error = vnsetcred(vn, p->p_ucred);
diff --git a/sys/sys/mdioctl.h b/sys/sys/mdioctl.h
index 4f2e937..b283741 100644
--- a/sys/sys/mdioctl.h
+++ b/sys/sys/mdioctl.h
@@ -38,6 +38,8 @@
* from: Utah $Hdr: fdioctl.h 1.1 90/07/09$
*
* @(#)vnioctl.h 8.1 (Berkeley) 6/10/93
+ *
+ * $FreeBSD$
*/
#ifndef _SYS_VNIOCTL_H_
@@ -72,5 +74,6 @@ struct vn_ioctl {
#define VN_DEBUG 0x4 /* Debug data in vn driver */
#define VN_IO 0x8 /* Debug I/O in vn driver */
#define VN_DONTCLUSTER 0x10 /* Don't cluster */
+#define VN_RESERVE 0x20 /* Pre-reserve swap */
#endif /* _SYS_VNIOCTL_H_*/
diff --git a/sys/sys/vnioctl.h b/sys/sys/vnioctl.h
index 4f2e937..b283741 100644
--- a/sys/sys/vnioctl.h
+++ b/sys/sys/vnioctl.h
@@ -38,6 +38,8 @@
* from: Utah $Hdr: fdioctl.h 1.1 90/07/09$
*
* @(#)vnioctl.h 8.1 (Berkeley) 6/10/93
+ *
+ * $FreeBSD$
*/
#ifndef _SYS_VNIOCTL_H_
@@ -72,5 +74,6 @@ struct vn_ioctl {
#define VN_DEBUG 0x4 /* Debug data in vn driver */
#define VN_IO 0x8 /* Debug I/O in vn driver */
#define VN_DONTCLUSTER 0x10 /* Don't cluster */
+#define VN_RESERVE 0x20 /* Pre-reserve swap */
#endif /* _SYS_VNIOCTL_H_*/
OpenPOWER on IntegriCloud