diff options
author | dillon <dillon@FreeBSD.org> | 1999-09-17 05:34:00 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 1999-09-17 05:34:00 +0000 |
commit | 77cf4cb54b547996b17474b25570116447285537 (patch) | |
tree | 3a59baafca356bd7ea5958a89aad60d93ce40361 /sys | |
parent | 124cdf53462edef3fd859a8d3c9d6bf6be840e98 (diff) | |
download | FreeBSD-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.c | 58 | ||||
-rw-r--r-- | sys/sys/mdioctl.h | 3 | ||||
-rw-r--r-- | sys/sys/vnioctl.h | 3 |
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_*/ |