xref: /csrg-svn/sys/dev/vn.c (revision 66613)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1988 University of Utah.
363145Sbostic  * Copyright (c) 1990, 1993
463145Sbostic  *	The Regents of the University of California.  All rights reserved.
541480Smckusick  *
641480Smckusick  * This code is derived from software contributed to Berkeley by
741480Smckusick  * the Systems Programming Group of the University of Utah Computer
841480Smckusick  * Science Department.
941480Smckusick  *
1041480Smckusick  * %sccs.include.redist.c%
1141480Smckusick  *
1257301Shibler  * from: Utah $Hdr: vn.c 1.8 92/12/20$
1341480Smckusick  *
14*66613Shibler  *	@(#)vn.c	8.5 (Berkeley) 04/01/94
1541480Smckusick  */
1641480Smckusick 
1741480Smckusick /*
1849299Shibler  * Vnode disk driver.
1941480Smckusick  *
2049299Shibler  * Block/character interface to a vnode.  Allows one to treat a file
2149299Shibler  * as a disk (e.g. build a filesystem in it, mount it, etc.).
2241480Smckusick  *
2349299Shibler  * NOTE 1: This uses the VOP_BMAP/VOP_STRATEGY interface to the vnode
2449299Shibler  * instead of a simple VOP_RDWR.  We do this to avoid distorting the
2549299Shibler  * local buffer cache.
2649299Shibler  *
2749299Shibler  * NOTE 2: There is a security issue involved with this driver.
2841480Smckusick  * Once mounted all access to the contents of the "mapped" file via
2941480Smckusick  * the special file is controlled by the permissions on the special
3041480Smckusick  * file, the protection of the mapped file is ignored (effectively,
3141480Smckusick  * by using root credentials in all transactions).
3257301Shibler  *
3357301Shibler  * NOTE 3: Doesn't interact with leases, should it?
3441480Smckusick  */
3549299Shibler #include "vn.h"
3649299Shibler #if NVN > 0
3741480Smckusick 
3855159Spendry #include <sys/param.h>
3955159Spendry #include <sys/systm.h>
4055159Spendry #include <sys/namei.h>
4155159Spendry #include <sys/proc.h>
4255159Spendry #include <sys/errno.h>
4355159Spendry #include <sys/dkstat.h>
4455159Spendry #include <sys/buf.h>
4555159Spendry #include <sys/malloc.h>
4655159Spendry #include <sys/ioctl.h>
4755159Spendry #include <sys/mount.h>
4855159Spendry #include <sys/vnode.h>
4955159Spendry #include <sys/file.h>
5055159Spendry #include <sys/uio.h>
5141480Smckusick 
5255159Spendry #include <miscfs/specfs/specdev.h>
5355159Spendry 
5456503Sbostic #include <dev/vnioctl.h>
5541480Smckusick 
5641480Smckusick #ifdef DEBUG
57*66613Shibler int dovncluster = 1;
5849299Shibler int vndebug = 0x00;
5949299Shibler #define VDB_FOLLOW	0x01
6049299Shibler #define VDB_INIT	0x02
6149299Shibler #define VDB_IO		0x04
6241480Smckusick #endif
6341480Smckusick 
6441480Smckusick #define b_cylin	b_resid
6541480Smckusick 
6649299Shibler #define	vnunit(x)	((minor(x) >> 3) & 0x7)	/* for consistency */
6741480Smckusick 
6849299Shibler #define	getvnbuf()	\
6941480Smckusick 	((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
7049299Shibler #define putvnbuf(bp)	\
7141480Smckusick 	free((caddr_t)(bp), M_DEVBUF)
7241480Smckusick 
7349299Shibler struct vn_softc {
7441480Smckusick 	int		 sc_flags;	/* flags */
7549299Shibler 	size_t		 sc_size;	/* size of vn */
7641480Smckusick 	struct vnode	*sc_vp;		/* vnode */
7741480Smckusick 	struct ucred	*sc_cred;	/* credentials */
7841480Smckusick 	int		 sc_maxactive;	/* max # of active requests */
7959342Shibler 	struct buf	 sc_tab;	/* transfer queue */
8059342Shibler };
8141480Smckusick 
8241480Smckusick /* sc_flags */
8349299Shibler #define	VNF_ALIVE	0x01
8449299Shibler #define VNF_INITED	0x02
8541480Smckusick 
8659342Shibler #if 0	/* if you need static allocation */
8759342Shibler struct vn_softc vn_softc[NVN];
8859342Shibler int numvnd = NVN;
8959342Shibler #else
9059342Shibler struct vn_softc *vn_softc;
9159342Shibler int numvnd;
9259342Shibler #endif
9359342Shibler 
9459342Shibler void
9559342Shibler vnattach(num)
9659342Shibler 	int num;
9759342Shibler {
9859342Shibler 	char *mem;
9959342Shibler 	register u_long size;
10059342Shibler 
10159342Shibler 	if (num <= 0)
10259342Shibler 		return;
10359342Shibler 	size = num * sizeof(struct vn_softc);
10459342Shibler 	mem = malloc(size, M_DEVBUF, M_NOWAIT);
10559342Shibler 	if (mem == NULL) {
10659342Shibler 		printf("WARNING: no memory for vnode disks\n");
10759342Shibler 		return;
10859342Shibler 	}
10959342Shibler 	bzero(mem, size);
11059342Shibler 	vn_softc = (struct vn_softc *)mem;
11159342Shibler 	numvnd = num;
11259342Shibler }
11359342Shibler 
11449299Shibler int
11549299Shibler vnopen(dev, flags, mode, p)
11641480Smckusick 	dev_t dev;
11749299Shibler 	int flags, mode;
11849299Shibler 	struct proc *p;
11941480Smckusick {
12049299Shibler 	int unit = vnunit(dev);
12141480Smckusick 
12241480Smckusick #ifdef DEBUG
12349299Shibler 	if (vndebug & VDB_FOLLOW)
12449299Shibler 		printf("vnopen(%x, %x, %x, %x)\n", dev, flags, mode, p);
12541480Smckusick #endif
12659342Shibler 	if (unit >= numvnd)
12741480Smckusick 		return(ENXIO);
12841480Smckusick 	return(0);
12941480Smckusick }
13041480Smckusick 
13141480Smckusick /*
13241480Smckusick  * Break the request into bsize pieces and submit using VOP_BMAP/VOP_STRATEGY.
13341480Smckusick  * Note that this driver can only be used for swapping over NFS on the hp
13441480Smckusick  * since nfs_strategy on the vax cannot handle u-areas and page tables.
13541480Smckusick  */
13649299Shibler vnstrategy(bp)
13741480Smckusick 	register struct buf *bp;
13841480Smckusick {
13949299Shibler 	int unit = vnunit(bp->b_dev);
14049299Shibler 	register struct vn_softc *vn = &vn_softc[unit];
14141480Smckusick 	register struct buf *nbp;
14241480Smckusick 	register int bn, bsize, resid;
14341480Smckusick 	register caddr_t addr;
144*66613Shibler 	int sz, flags, error;
14553921Shibler 	extern void vniodone();
14641480Smckusick 
14741480Smckusick #ifdef DEBUG
14849299Shibler 	if (vndebug & VDB_FOLLOW)
14949299Shibler 		printf("vnstrategy(%x): unit %d\n", bp, unit);
15041480Smckusick #endif
15149299Shibler 	if ((vn->sc_flags & VNF_INITED) == 0) {
15241480Smckusick 		bp->b_error = ENXIO;
15341480Smckusick 		bp->b_flags |= B_ERROR;
15449299Shibler 		biodone(bp);
15541480Smckusick 		return;
15641480Smckusick 	}
15741480Smckusick 	bn = bp->b_blkno;
15841480Smckusick 	sz = howmany(bp->b_bcount, DEV_BSIZE);
15941480Smckusick 	bp->b_resid = bp->b_bcount;
16049299Shibler 	if (bn < 0 || bn + sz > vn->sc_size) {
16149299Shibler 		if (bn != vn->sc_size) {
16241480Smckusick 			bp->b_error = EINVAL;
16341480Smckusick 			bp->b_flags |= B_ERROR;
16441480Smckusick 		}
16549299Shibler 		biodone(bp);
16641480Smckusick 		return;
16741480Smckusick 	}
16841480Smckusick 	bn = dbtob(bn);
16951945Smckusick 	bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
17064902Shibler 	addr = bp->b_data;
17141480Smckusick 	flags = bp->b_flags | B_CALL;
17241480Smckusick 	for (resid = bp->b_resid; resid; resid -= sz) {
17341480Smckusick 		struct vnode *vp;
17441480Smckusick 		daddr_t nbn;
175*66613Shibler 		int off, s, nra;
17641480Smckusick 
177*66613Shibler 		nra = 0;
178*66613Shibler 		error = VOP_BMAP(vn->sc_vp, bn / bsize, &vp, &nbn, &nra);
179*66613Shibler 		if (error == 0 && (long)nbn == -1)
180*66613Shibler 			error = EIO;
18141480Smckusick #ifdef DEBUG
182*66613Shibler 		if (!dovncluster)
183*66613Shibler 			nra = 0;
184*66613Shibler #endif
185*66613Shibler 
186*66613Shibler 		if (off = bn % bsize)
187*66613Shibler 			sz = bsize - off;
188*66613Shibler 		else
189*66613Shibler 			sz = (1 + nra) * bsize;
190*66613Shibler 		if (resid < sz)
191*66613Shibler 			sz = resid;
192*66613Shibler #ifdef DEBUG
19349299Shibler 		if (vndebug & VDB_IO)
194*66613Shibler 			printf("vnstrategy: vp %x/%x bn %x/%x sz %x\n",
195*66613Shibler 			       vn->sc_vp, vp, bn, nbn, sz);
19641480Smckusick #endif
197*66613Shibler 
198*66613Shibler 		nbp = getvnbuf();
19941480Smckusick 		nbp->b_flags = flags;
20041480Smckusick 		nbp->b_bcount = sz;
20141480Smckusick 		nbp->b_bufsize = bp->b_bufsize;
20241480Smckusick 		nbp->b_error = 0;
20349299Shibler 		if (vp->v_type == VBLK || vp->v_type == VCHR)
20449299Shibler 			nbp->b_dev = vp->v_rdev;
20549299Shibler 		else
20649299Shibler 			nbp->b_dev = NODEV;
20764902Shibler 		nbp->b_data = addr;
20841480Smckusick 		nbp->b_blkno = nbn + btodb(off);
20941480Smckusick 		nbp->b_proc = bp->b_proc;
21049299Shibler 		nbp->b_iodone = vniodone;
21141480Smckusick 		nbp->b_vp = vp;
21241480Smckusick 		nbp->b_pfcent = (int) bp;	/* XXX */
21357301Shibler 		nbp->b_rcred = vn->sc_cred;	/* XXX crdup? */
21457301Shibler 		nbp->b_wcred = vn->sc_cred;	/* XXX crdup? */
21557301Shibler 		nbp->b_dirtyoff = bp->b_dirtyoff;
21657301Shibler 		nbp->b_dirtyend = bp->b_dirtyend;
21757301Shibler 		nbp->b_validoff = bp->b_validoff;
21857301Shibler 		nbp->b_validend = bp->b_validend;
21941480Smckusick 		/*
220*66613Shibler 		 * If there was an error or a hole in the file...punt.
22164661Shibler 		 * Note that we deal with this after the nbp allocation.
22264661Shibler 		 * This ensures that we properly clean up any operations
22364661Shibler 		 * that we have already fired off.
22464661Shibler 		 *
225*66613Shibler 		 * XXX we could deal with holes here but it would be
22664661Shibler 		 * a hassle (in the write case).
22764661Shibler 		 */
228*66613Shibler 		if (error) {
229*66613Shibler 			nbp->b_error = error;
23064661Shibler 			nbp->b_flags |= B_ERROR;
23164661Shibler 			bp->b_resid -= (resid - sz);
23264661Shibler 			biodone(nbp);
23364661Shibler 			return;
23464661Shibler 		}
23564661Shibler 		/*
23641480Smckusick 		 * Just sort by block number
23741480Smckusick 		 */
23841480Smckusick 		nbp->b_cylin = nbp->b_blkno;
23941480Smckusick 		s = splbio();
24059342Shibler 		disksort(&vn->sc_tab, nbp);
24159342Shibler 		if (vn->sc_tab.b_active < vn->sc_maxactive) {
24259342Shibler 			vn->sc_tab.b_active++;
24359342Shibler 			vnstart(vn);
24441480Smckusick 		}
24541480Smckusick 		splx(s);
24641480Smckusick 		bn += sz;
24741480Smckusick 		addr += sz;
24841480Smckusick 	}
24941480Smckusick }
25041480Smckusick 
25141480Smckusick /*
25241480Smckusick  * Feed requests sequentially.
25341480Smckusick  * We do it this way to keep from flooding NFS servers if we are connected
25441480Smckusick  * to an NFS file.  This places the burden on the client rather than the
25541480Smckusick  * server.
25641480Smckusick  */
25759342Shibler vnstart(vn)
25859342Shibler 	register struct vn_softc *vn;
25941480Smckusick {
26041480Smckusick 	register struct buf *bp;
26141480Smckusick 
26241480Smckusick 	/*
26341480Smckusick 	 * Dequeue now since lower level strategy routine might
26441480Smckusick 	 * queue using same links
26541480Smckusick 	 */
26659342Shibler 	bp = vn->sc_tab.b_actf;
26759342Shibler 	vn->sc_tab.b_actf = bp->b_actf;
26841480Smckusick #ifdef DEBUG
26949299Shibler 	if (vndebug & VDB_IO)
27049299Shibler 		printf("vnstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
27164902Shibler 		       vn-vn_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
27241480Smckusick 		       bp->b_bcount);
27341480Smckusick #endif
27457301Shibler 	if ((bp->b_flags & B_READ) == 0)
27557301Shibler 		bp->b_vp->v_numoutput++;
27641480Smckusick 	VOP_STRATEGY(bp);
27741480Smckusick }
27841480Smckusick 
27953921Shibler void
28049299Shibler vniodone(bp)
28141480Smckusick 	register struct buf *bp;
28241480Smckusick {
28341480Smckusick 	register struct buf *pbp = (struct buf *)bp->b_pfcent;	/* XXX */
28459342Shibler 	register struct vn_softc *vn = &vn_softc[vnunit(pbp->b_dev)];
28541480Smckusick 	int s;
28641480Smckusick 
28741480Smckusick 	s = splbio();
28841480Smckusick #ifdef DEBUG
28949299Shibler 	if (vndebug & VDB_IO)
29049299Shibler 		printf("vniodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
29164902Shibler 		       vn-vn_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
29241480Smckusick 		       bp->b_bcount);
29341480Smckusick #endif
29441480Smckusick 	if (bp->b_error) {
29541480Smckusick #ifdef DEBUG
29649299Shibler 		if (vndebug & VDB_IO)
29749299Shibler 			printf("vniodone: bp %x error %d\n", bp, bp->b_error);
29841480Smckusick #endif
29941480Smckusick 		pbp->b_flags |= B_ERROR;
30049299Shibler 		pbp->b_error = biowait(bp);
30141480Smckusick 	}
30241480Smckusick 	pbp->b_resid -= bp->b_bcount;
30349299Shibler 	putvnbuf(bp);
30441480Smckusick 	if (pbp->b_resid == 0) {
30541480Smckusick #ifdef DEBUG
30649299Shibler 		if (vndebug & VDB_IO)
30749299Shibler 			printf("vniodone: pbp %x iodone\n", pbp);
30841480Smckusick #endif
30949299Shibler 		biodone(pbp);
31041480Smckusick 	}
31159342Shibler 	if (vn->sc_tab.b_actf)
31259342Shibler 		vnstart(vn);
31341480Smckusick 	else
31459342Shibler 		vn->sc_tab.b_active--;
31541480Smckusick 	splx(s);
31641480Smckusick }
31741480Smckusick 
31849299Shibler vnread(dev, uio, flags, p)
31941480Smckusick 	dev_t dev;
32041480Smckusick 	struct uio *uio;
32149299Shibler 	int flags;
32249299Shibler 	struct proc *p;
32341480Smckusick {
32441480Smckusick 
32541480Smckusick #ifdef DEBUG
32649299Shibler 	if (vndebug & VDB_FOLLOW)
32749299Shibler 		printf("vnread(%x, %x, %x, %x)\n", dev, uio, flags, p);
32841480Smckusick #endif
32959342Shibler 	return(physio(vnstrategy, NULL, dev, B_READ, minphys, uio));
33041480Smckusick }
33141480Smckusick 
33249299Shibler vnwrite(dev, uio, flags, p)
33341480Smckusick 	dev_t dev;
33441480Smckusick 	struct uio *uio;
33549299Shibler 	int flags;
33649299Shibler 	struct proc *p;
33741480Smckusick {
33841480Smckusick 
33941480Smckusick #ifdef DEBUG
34049299Shibler 	if (vndebug & VDB_FOLLOW)
34149299Shibler 		printf("vnwrite(%x, %x, %x, %x)\n", dev, uio, flags, p);
34241480Smckusick #endif
34359342Shibler 	return(physio(vnstrategy, NULL, dev, B_WRITE, minphys, uio));
34441480Smckusick }
34541480Smckusick 
34641480Smckusick /* ARGSUSED */
34749299Shibler vnioctl(dev, cmd, data, flag, p)
34841480Smckusick 	dev_t dev;
34941480Smckusick 	u_long cmd;
35041480Smckusick 	caddr_t data;
35141480Smckusick 	int flag;
35249299Shibler 	struct proc *p;
35341480Smckusick {
35449299Shibler 	int unit = vnunit(dev);
35549299Shibler 	register struct vn_softc *vn;
35649299Shibler 	struct vn_ioctl *vio;
35741480Smckusick 	struct vattr vattr;
35849299Shibler 	struct nameidata nd;
35941480Smckusick 	int error;
36041480Smckusick 
36141480Smckusick #ifdef DEBUG
36249299Shibler 	if (vndebug & VDB_FOLLOW)
36349299Shibler 		printf("vnioctl(%x, %x, %x, %x, %x): unit %d\n",
36449299Shibler 		       dev, cmd, data, flag, p, unit);
36541480Smckusick #endif
36649299Shibler 	error = suser(p->p_ucred, &p->p_acflag);
36741480Smckusick 	if (error)
36841480Smckusick 		return (error);
36959342Shibler 	if (unit >= numvnd)
37041480Smckusick 		return (ENXIO);
37141480Smckusick 
37249299Shibler 	vn = &vn_softc[unit];
37349299Shibler 	vio = (struct vn_ioctl *)data;
37441480Smckusick 	switch (cmd) {
37541480Smckusick 
37649299Shibler 	case VNIOCSET:
37749299Shibler 		if (vn->sc_flags & VNF_INITED)
37841480Smckusick 			return(EBUSY);
37941480Smckusick 		/*
38041480Smckusick 		 * Always open for read and write.
38141480Smckusick 		 * This is probably bogus, but it lets vn_open()
38241480Smckusick 		 * weed out directories, sockets, etc. so we don't
38341480Smckusick 		 * have to worry about them.
38441480Smckusick 		 */
38552761Shibler 		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vn_file, p);
38652761Shibler 		if (error = vn_open(&nd, FREAD|FWRITE, 0))
38741480Smckusick 			return(error);
38850115Smckusick 		if (error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p)) {
38950115Smckusick 			VOP_UNLOCK(nd.ni_vp);
39050115Smckusick 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
39141480Smckusick 			return(error);
39241480Smckusick 		}
39350115Smckusick 		VOP_UNLOCK(nd.ni_vp);
39449299Shibler 		vn->sc_vp = nd.ni_vp;
39549299Shibler 		vn->sc_size = btodb(vattr.va_size);	/* note truncation */
39650115Smckusick 		if (error = vnsetcred(vn, p->p_ucred)) {
397*66613Shibler 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
39841480Smckusick 			return(error);
39941480Smckusick 		}
40049299Shibler 		vnthrottle(vn, vn->sc_vp);
40149299Shibler 		vio->vn_size = dbtob(vn->sc_size);
40249299Shibler 		vn->sc_flags |= VNF_INITED;
40341480Smckusick #ifdef DEBUG
40449299Shibler 		if (vndebug & VDB_INIT)
40549299Shibler 			printf("vnioctl: SET vp %x size %x\n",
40649299Shibler 			       vn->sc_vp, vn->sc_size);
40741480Smckusick #endif
40841480Smckusick 		break;
40941480Smckusick 
41049299Shibler 	case VNIOCCLR:
41149299Shibler 		if ((vn->sc_flags & VNF_INITED) == 0)
41241480Smckusick 			return(ENXIO);
41349299Shibler 		vnclear(vn);
41441480Smckusick #ifdef DEBUG
41549299Shibler 		if (vndebug & VDB_INIT)
41649299Shibler 			printf("vnioctl: CLRed\n");
41741480Smckusick #endif
41841480Smckusick 		break;
41941480Smckusick 
42041480Smckusick 	default:
42141480Smckusick 		return(ENXIO);
42241480Smckusick 	}
42341480Smckusick 	return(0);
42441480Smckusick }
42541480Smckusick 
42641480Smckusick /*
42741480Smckusick  * Duplicate the current processes' credentials.  Since we are called only
42841480Smckusick  * as the result of a SET ioctl and only root can do that, any future access
42941480Smckusick  * to this "disk" is essentially as root.  Note that credentials may change
43041480Smckusick  * if some other uid can write directly to the mapped file (NFS).
43141480Smckusick  */
43249299Shibler vnsetcred(vn, cred)
43349299Shibler 	register struct vn_softc *vn;
43465266Smckusick 	struct ucred *cred;
43541480Smckusick {
43641480Smckusick 	struct uio auio;
43741480Smckusick 	struct iovec aiov;
438*66613Shibler 	char *tmpbuf;
439*66613Shibler 	int error;
44041480Smckusick 
44149299Shibler 	vn->sc_cred = crdup(cred);
442*66613Shibler 	tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
443*66613Shibler 
44441480Smckusick 	/* XXX: Horrible kludge to establish credentials for NFS */
44541480Smckusick 	aiov.iov_base = tmpbuf;
44655159Spendry 	aiov.iov_len = min(DEV_BSIZE, dbtob(vn->sc_size));
44741480Smckusick 	auio.uio_iov = &aiov;
44841480Smckusick 	auio.uio_iovcnt = 1;
44941480Smckusick 	auio.uio_offset = 0;
45041480Smckusick 	auio.uio_rw = UIO_READ;
45141480Smckusick 	auio.uio_segflg = UIO_SYSSPACE;
45241480Smckusick 	auio.uio_resid = aiov.iov_len;
453*66613Shibler 	error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
454*66613Shibler 
455*66613Shibler 	free(tmpbuf, M_TEMP);
456*66613Shibler 	return (error);
45741480Smckusick }
45841480Smckusick 
45941480Smckusick /*
46041480Smckusick  * Set maxactive based on FS type
46141480Smckusick  */
46249299Shibler vnthrottle(vn, vp)
46349299Shibler 	register struct vn_softc *vn;
46441480Smckusick 	struct vnode *vp;
46541480Smckusick {
46653517Sheideman 	extern int (**nfsv2_vnodeop_p)();
46741480Smckusick 
46853517Sheideman 	if (vp->v_op == nfsv2_vnodeop_p)
46949299Shibler 		vn->sc_maxactive = 2;
47041480Smckusick 	else
47149299Shibler 		vn->sc_maxactive = 8;
47241480Smckusick 
47349299Shibler 	if (vn->sc_maxactive < 1)
47449299Shibler 		vn->sc_maxactive = 1;
47541480Smckusick }
47641480Smckusick 
47749299Shibler vnshutdown()
47841480Smckusick {
47949299Shibler 	register struct vn_softc *vn;
48041480Smckusick 
48159342Shibler 	for (vn = &vn_softc[0]; vn < &vn_softc[numvnd]; vn++)
48249299Shibler 		if (vn->sc_flags & VNF_INITED)
48349299Shibler 			vnclear(vn);
48441480Smckusick }
48541480Smckusick 
48649299Shibler vnclear(vn)
48749299Shibler 	register struct vn_softc *vn;
48841480Smckusick {
48949299Shibler 	register struct vnode *vp = vn->sc_vp;
49050115Smckusick 	struct proc *p = curproc;		/* XXX */
49141480Smckusick 
49241480Smckusick #ifdef DEBUG
49349299Shibler 	if (vndebug & VDB_FOLLOW)
49449299Shibler 		printf("vnclear(%x): vp %x\n", vp);
49541480Smckusick #endif
49649299Shibler 	vn->sc_flags &= ~VNF_INITED;
49741480Smckusick 	if (vp == (struct vnode *)0)
49849299Shibler 		panic("vnioctl: null vp");
49950115Smckusick 	(void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p);
50049299Shibler 	crfree(vn->sc_cred);
50149299Shibler 	vn->sc_vp = (struct vnode *)0;
50249299Shibler 	vn->sc_cred = (struct ucred *)0;
50349299Shibler 	vn->sc_size = 0;
50441480Smckusick }
50541480Smckusick 
50649299Shibler vnsize(dev)
50741480Smckusick 	dev_t dev;
50841480Smckusick {
50949299Shibler 	int unit = vnunit(dev);
51049299Shibler 	register struct vn_softc *vn = &vn_softc[unit];
51141480Smckusick 
51259342Shibler 	if (unit >= numvnd || (vn->sc_flags & VNF_INITED) == 0)
51341480Smckusick 		return(-1);
51449299Shibler 	return(vn->sc_size);
51541480Smckusick }
51641480Smckusick 
51749299Shibler vndump(dev)
51841480Smckusick {
51941480Smckusick 	return(ENXIO);
52041480Smckusick }
52141480Smckusick #endif
522