xref: /csrg-svn/sys/dev/vn.c (revision 69448)
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  *
1266614Shibler  * from: Utah $Hdr: vn.c 1.13 94/04/02$
1341480Smckusick  *
14*69448Smckusick  *	@(#)vn.c	8.9 (Berkeley) 05/14/95
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
5766613Shibler 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
vnattach(num)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
vnopen(dev,flags,mode,p)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  */
13668158Scgd void
vnstrategy(bp)13749299Shibler vnstrategy(bp)
13841480Smckusick 	register struct buf *bp;
13941480Smckusick {
14049299Shibler 	int unit = vnunit(bp->b_dev);
14149299Shibler 	register struct vn_softc *vn = &vn_softc[unit];
14241480Smckusick 	register struct buf *nbp;
14341480Smckusick 	register int bn, bsize, resid;
14441480Smckusick 	register caddr_t addr;
14566613Shibler 	int sz, flags, error;
14653921Shibler 	extern void vniodone();
14741480Smckusick 
14841480Smckusick #ifdef DEBUG
14949299Shibler 	if (vndebug & VDB_FOLLOW)
15049299Shibler 		printf("vnstrategy(%x): unit %d\n", bp, unit);
15141480Smckusick #endif
15249299Shibler 	if ((vn->sc_flags & VNF_INITED) == 0) {
15341480Smckusick 		bp->b_error = ENXIO;
15441480Smckusick 		bp->b_flags |= B_ERROR;
15549299Shibler 		biodone(bp);
15641480Smckusick 		return;
15741480Smckusick 	}
15841480Smckusick 	bn = bp->b_blkno;
15941480Smckusick 	sz = howmany(bp->b_bcount, DEV_BSIZE);
16041480Smckusick 	bp->b_resid = bp->b_bcount;
16149299Shibler 	if (bn < 0 || bn + sz > vn->sc_size) {
16249299Shibler 		if (bn != vn->sc_size) {
16341480Smckusick 			bp->b_error = EINVAL;
16441480Smckusick 			bp->b_flags |= B_ERROR;
16541480Smckusick 		}
16649299Shibler 		biodone(bp);
16741480Smckusick 		return;
16841480Smckusick 	}
16941480Smckusick 	bn = dbtob(bn);
17051945Smckusick 	bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
17164902Shibler 	addr = bp->b_data;
17241480Smckusick 	flags = bp->b_flags | B_CALL;
17341480Smckusick 	for (resid = bp->b_resid; resid; resid -= sz) {
17441480Smckusick 		struct vnode *vp;
17541480Smckusick 		daddr_t nbn;
17666613Shibler 		int off, s, nra;
17741480Smckusick 
17866613Shibler 		nra = 0;
17966613Shibler 		error = VOP_BMAP(vn->sc_vp, bn / bsize, &vp, &nbn, &nra);
18066613Shibler 		if (error == 0 && (long)nbn == -1)
18166613Shibler 			error = EIO;
18241480Smckusick #ifdef DEBUG
18366613Shibler 		if (!dovncluster)
18466613Shibler 			nra = 0;
18566613Shibler #endif
18666613Shibler 
18766613Shibler 		if (off = bn % bsize)
18866613Shibler 			sz = bsize - off;
18966613Shibler 		else
19066613Shibler 			sz = (1 + nra) * bsize;
19166613Shibler 		if (resid < sz)
19266613Shibler 			sz = resid;
19366613Shibler #ifdef DEBUG
19449299Shibler 		if (vndebug & VDB_IO)
19566613Shibler 			printf("vnstrategy: vp %x/%x bn %x/%x sz %x\n",
19666613Shibler 			       vn->sc_vp, vp, bn, nbn, sz);
19741480Smckusick #endif
19866613Shibler 
19966613Shibler 		nbp = getvnbuf();
20041480Smckusick 		nbp->b_flags = flags;
20141480Smckusick 		nbp->b_bcount = sz;
20241480Smckusick 		nbp->b_bufsize = bp->b_bufsize;
20341480Smckusick 		nbp->b_error = 0;
20449299Shibler 		if (vp->v_type == VBLK || vp->v_type == VCHR)
20549299Shibler 			nbp->b_dev = vp->v_rdev;
20649299Shibler 		else
20749299Shibler 			nbp->b_dev = NODEV;
20864902Shibler 		nbp->b_data = addr;
20941480Smckusick 		nbp->b_blkno = nbn + btodb(off);
21041480Smckusick 		nbp->b_proc = bp->b_proc;
21149299Shibler 		nbp->b_iodone = vniodone;
21241480Smckusick 		nbp->b_vp = vp;
21341480Smckusick 		nbp->b_pfcent = (int) bp;	/* XXX */
21457301Shibler 		nbp->b_rcred = vn->sc_cred;	/* XXX crdup? */
21557301Shibler 		nbp->b_wcred = vn->sc_cred;	/* XXX crdup? */
21657301Shibler 		nbp->b_dirtyoff = bp->b_dirtyoff;
21757301Shibler 		nbp->b_dirtyend = bp->b_dirtyend;
21857301Shibler 		nbp->b_validoff = bp->b_validoff;
21957301Shibler 		nbp->b_validend = bp->b_validend;
22041480Smckusick 		/*
22166613Shibler 		 * If there was an error or a hole in the file...punt.
22264661Shibler 		 * Note that we deal with this after the nbp allocation.
22364661Shibler 		 * This ensures that we properly clean up any operations
22464661Shibler 		 * that we have already fired off.
22564661Shibler 		 *
22666613Shibler 		 * XXX we could deal with holes here but it would be
22764661Shibler 		 * a hassle (in the write case).
22864661Shibler 		 */
22966613Shibler 		if (error) {
23066613Shibler 			nbp->b_error = error;
23164661Shibler 			nbp->b_flags |= B_ERROR;
23264661Shibler 			bp->b_resid -= (resid - sz);
23364661Shibler 			biodone(nbp);
23464661Shibler 			return;
23564661Shibler 		}
23664661Shibler 		/*
23741480Smckusick 		 * Just sort by block number
23841480Smckusick 		 */
23941480Smckusick 		nbp->b_cylin = nbp->b_blkno;
24041480Smckusick 		s = splbio();
24159342Shibler 		disksort(&vn->sc_tab, nbp);
24259342Shibler 		if (vn->sc_tab.b_active < vn->sc_maxactive) {
24359342Shibler 			vn->sc_tab.b_active++;
24459342Shibler 			vnstart(vn);
24541480Smckusick 		}
24641480Smckusick 		splx(s);
24741480Smckusick 		bn += sz;
24841480Smckusick 		addr += sz;
24941480Smckusick 	}
25041480Smckusick }
25141480Smckusick 
25241480Smckusick /*
25341480Smckusick  * Feed requests sequentially.
25441480Smckusick  * We do it this way to keep from flooding NFS servers if we are connected
25541480Smckusick  * to an NFS file.  This places the burden on the client rather than the
25641480Smckusick  * server.
25741480Smckusick  */
vnstart(vn)25859342Shibler vnstart(vn)
25959342Shibler 	register struct vn_softc *vn;
26041480Smckusick {
26141480Smckusick 	register struct buf *bp;
26241480Smckusick 
26341480Smckusick 	/*
26441480Smckusick 	 * Dequeue now since lower level strategy routine might
26541480Smckusick 	 * queue using same links
26641480Smckusick 	 */
26759342Shibler 	bp = vn->sc_tab.b_actf;
26859342Shibler 	vn->sc_tab.b_actf = bp->b_actf;
26941480Smckusick #ifdef DEBUG
27049299Shibler 	if (vndebug & VDB_IO)
27149299Shibler 		printf("vnstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
27264902Shibler 		       vn-vn_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
27341480Smckusick 		       bp->b_bcount);
27441480Smckusick #endif
27557301Shibler 	if ((bp->b_flags & B_READ) == 0)
27657301Shibler 		bp->b_vp->v_numoutput++;
27741480Smckusick 	VOP_STRATEGY(bp);
27841480Smckusick }
27941480Smckusick 
28053921Shibler void
vniodone(bp)28149299Shibler vniodone(bp)
28241480Smckusick 	register struct buf *bp;
28341480Smckusick {
28441480Smckusick 	register struct buf *pbp = (struct buf *)bp->b_pfcent;	/* XXX */
28559342Shibler 	register struct vn_softc *vn = &vn_softc[vnunit(pbp->b_dev)];
28641480Smckusick 	int s;
28741480Smckusick 
28841480Smckusick 	s = splbio();
28941480Smckusick #ifdef DEBUG
29049299Shibler 	if (vndebug & VDB_IO)
29149299Shibler 		printf("vniodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
29264902Shibler 		       vn-vn_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
29341480Smckusick 		       bp->b_bcount);
29441480Smckusick #endif
29541480Smckusick 	if (bp->b_error) {
29641480Smckusick #ifdef DEBUG
29749299Shibler 		if (vndebug & VDB_IO)
29849299Shibler 			printf("vniodone: bp %x error %d\n", bp, bp->b_error);
29941480Smckusick #endif
30041480Smckusick 		pbp->b_flags |= B_ERROR;
30149299Shibler 		pbp->b_error = biowait(bp);
30241480Smckusick 	}
30341480Smckusick 	pbp->b_resid -= bp->b_bcount;
30449299Shibler 	putvnbuf(bp);
30541480Smckusick 	if (pbp->b_resid == 0) {
30641480Smckusick #ifdef DEBUG
30749299Shibler 		if (vndebug & VDB_IO)
30849299Shibler 			printf("vniodone: pbp %x iodone\n", pbp);
30941480Smckusick #endif
31049299Shibler 		biodone(pbp);
31141480Smckusick 	}
31259342Shibler 	if (vn->sc_tab.b_actf)
31359342Shibler 		vnstart(vn);
31441480Smckusick 	else
31559342Shibler 		vn->sc_tab.b_active--;
31641480Smckusick 	splx(s);
31741480Smckusick }
31841480Smckusick 
vnread(dev,uio,flags,p)31949299Shibler vnread(dev, uio, flags, p)
32041480Smckusick 	dev_t dev;
32141480Smckusick 	struct uio *uio;
32249299Shibler 	int flags;
32349299Shibler 	struct proc *p;
32441480Smckusick {
32541480Smckusick 
32641480Smckusick #ifdef DEBUG
32749299Shibler 	if (vndebug & VDB_FOLLOW)
32849299Shibler 		printf("vnread(%x, %x, %x, %x)\n", dev, uio, flags, p);
32941480Smckusick #endif
33059342Shibler 	return(physio(vnstrategy, NULL, dev, B_READ, minphys, uio));
33141480Smckusick }
33241480Smckusick 
vnwrite(dev,uio,flags,p)33349299Shibler vnwrite(dev, uio, flags, p)
33441480Smckusick 	dev_t dev;
33541480Smckusick 	struct uio *uio;
33649299Shibler 	int flags;
33749299Shibler 	struct proc *p;
33841480Smckusick {
33941480Smckusick 
34041480Smckusick #ifdef DEBUG
34149299Shibler 	if (vndebug & VDB_FOLLOW)
34249299Shibler 		printf("vnwrite(%x, %x, %x, %x)\n", dev, uio, flags, p);
34341480Smckusick #endif
34459342Shibler 	return(physio(vnstrategy, NULL, dev, B_WRITE, minphys, uio));
34541480Smckusick }
34641480Smckusick 
34741480Smckusick /* ARGSUSED */
vnioctl(dev,cmd,data,flag,p)34849299Shibler vnioctl(dev, cmd, data, flag, p)
34941480Smckusick 	dev_t dev;
35041480Smckusick 	u_long cmd;
35141480Smckusick 	caddr_t data;
35241480Smckusick 	int flag;
35349299Shibler 	struct proc *p;
35441480Smckusick {
35549299Shibler 	int unit = vnunit(dev);
35649299Shibler 	register struct vn_softc *vn;
35749299Shibler 	struct vn_ioctl *vio;
35841480Smckusick 	struct vattr vattr;
35949299Shibler 	struct nameidata nd;
36041480Smckusick 	int error;
36141480Smckusick 
36241480Smckusick #ifdef DEBUG
36349299Shibler 	if (vndebug & VDB_FOLLOW)
36449299Shibler 		printf("vnioctl(%x, %x, %x, %x, %x): unit %d\n",
36549299Shibler 		       dev, cmd, data, flag, p, unit);
36641480Smckusick #endif
36749299Shibler 	error = suser(p->p_ucred, &p->p_acflag);
36841480Smckusick 	if (error)
36941480Smckusick 		return (error);
37059342Shibler 	if (unit >= numvnd)
37141480Smckusick 		return (ENXIO);
37241480Smckusick 
37349299Shibler 	vn = &vn_softc[unit];
37449299Shibler 	vio = (struct vn_ioctl *)data;
37541480Smckusick 	switch (cmd) {
37641480Smckusick 
37749299Shibler 	case VNIOCSET:
37849299Shibler 		if (vn->sc_flags & VNF_INITED)
37941480Smckusick 			return(EBUSY);
38041480Smckusick 		/*
38141480Smckusick 		 * Always open for read and write.
38241480Smckusick 		 * This is probably bogus, but it lets vn_open()
38341480Smckusick 		 * weed out directories, sockets, etc. so we don't
38441480Smckusick 		 * have to worry about them.
38541480Smckusick 		 */
38652761Shibler 		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vn_file, p);
38752761Shibler 		if (error = vn_open(&nd, FREAD|FWRITE, 0))
38841480Smckusick 			return(error);
38950115Smckusick 		if (error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p)) {
390*69448Smckusick 			VOP_UNLOCK(nd.ni_vp, 0, p);
39150115Smckusick 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
39241480Smckusick 			return(error);
39341480Smckusick 		}
394*69448Smckusick 		VOP_UNLOCK(nd.ni_vp, 0, p);
39549299Shibler 		vn->sc_vp = nd.ni_vp;
39649299Shibler 		vn->sc_size = btodb(vattr.va_size);	/* note truncation */
39750115Smckusick 		if (error = vnsetcred(vn, p->p_ucred)) {
39866613Shibler 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
39941480Smckusick 			return(error);
40041480Smckusick 		}
40149299Shibler 		vnthrottle(vn, vn->sc_vp);
40249299Shibler 		vio->vn_size = dbtob(vn->sc_size);
40349299Shibler 		vn->sc_flags |= VNF_INITED;
40441480Smckusick #ifdef DEBUG
40549299Shibler 		if (vndebug & VDB_INIT)
40649299Shibler 			printf("vnioctl: SET vp %x size %x\n",
40749299Shibler 			       vn->sc_vp, vn->sc_size);
40841480Smckusick #endif
40941480Smckusick 		break;
41041480Smckusick 
41149299Shibler 	case VNIOCCLR:
41249299Shibler 		if ((vn->sc_flags & VNF_INITED) == 0)
41341480Smckusick 			return(ENXIO);
41449299Shibler 		vnclear(vn);
41541480Smckusick #ifdef DEBUG
41649299Shibler 		if (vndebug & VDB_INIT)
41749299Shibler 			printf("vnioctl: CLRed\n");
41841480Smckusick #endif
41941480Smckusick 		break;
42041480Smckusick 
42141480Smckusick 	default:
42267741Smckusick 		return(ENOTTY);
42341480Smckusick 	}
42441480Smckusick 	return(0);
42541480Smckusick }
42641480Smckusick 
42741480Smckusick /*
42841480Smckusick  * Duplicate the current processes' credentials.  Since we are called only
42941480Smckusick  * as the result of a SET ioctl and only root can do that, any future access
43041480Smckusick  * to this "disk" is essentially as root.  Note that credentials may change
43141480Smckusick  * if some other uid can write directly to the mapped file (NFS).
43241480Smckusick  */
vnsetcred(vn,cred)43349299Shibler vnsetcred(vn, cred)
43449299Shibler 	register struct vn_softc *vn;
43565266Smckusick 	struct ucred *cred;
43641480Smckusick {
43741480Smckusick 	struct uio auio;
43841480Smckusick 	struct iovec aiov;
43966613Shibler 	char *tmpbuf;
44066613Shibler 	int error;
44141480Smckusick 
44249299Shibler 	vn->sc_cred = crdup(cred);
44366613Shibler 	tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
44466613Shibler 
44541480Smckusick 	/* XXX: Horrible kludge to establish credentials for NFS */
44641480Smckusick 	aiov.iov_base = tmpbuf;
44755159Spendry 	aiov.iov_len = min(DEV_BSIZE, dbtob(vn->sc_size));
44841480Smckusick 	auio.uio_iov = &aiov;
44941480Smckusick 	auio.uio_iovcnt = 1;
45041480Smckusick 	auio.uio_offset = 0;
45141480Smckusick 	auio.uio_rw = UIO_READ;
45241480Smckusick 	auio.uio_segflg = UIO_SYSSPACE;
45341480Smckusick 	auio.uio_resid = aiov.iov_len;
45466613Shibler 	error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
45566613Shibler 
45666613Shibler 	free(tmpbuf, M_TEMP);
45766613Shibler 	return (error);
45841480Smckusick }
45941480Smckusick 
46041480Smckusick /*
46141480Smckusick  * Set maxactive based on FS type
46241480Smckusick  */
vnthrottle(vn,vp)46349299Shibler vnthrottle(vn, vp)
46449299Shibler 	register struct vn_softc *vn;
46541480Smckusick 	struct vnode *vp;
46641480Smckusick {
46753517Sheideman 	extern int (**nfsv2_vnodeop_p)();
46841480Smckusick 
46953517Sheideman 	if (vp->v_op == nfsv2_vnodeop_p)
47049299Shibler 		vn->sc_maxactive = 2;
47141480Smckusick 	else
47249299Shibler 		vn->sc_maxactive = 8;
47341480Smckusick 
47449299Shibler 	if (vn->sc_maxactive < 1)
47549299Shibler 		vn->sc_maxactive = 1;
47641480Smckusick }
47741480Smckusick 
vnshutdown()47849299Shibler vnshutdown()
47941480Smckusick {
48049299Shibler 	register struct vn_softc *vn;
48141480Smckusick 
48259342Shibler 	for (vn = &vn_softc[0]; vn < &vn_softc[numvnd]; vn++)
48349299Shibler 		if (vn->sc_flags & VNF_INITED)
48449299Shibler 			vnclear(vn);
48541480Smckusick }
48641480Smckusick 
vnclear(vn)48749299Shibler vnclear(vn)
48849299Shibler 	register struct vn_softc *vn;
48941480Smckusick {
49049299Shibler 	register struct vnode *vp = vn->sc_vp;
49150115Smckusick 	struct proc *p = curproc;		/* XXX */
49241480Smckusick 
49341480Smckusick #ifdef DEBUG
49449299Shibler 	if (vndebug & VDB_FOLLOW)
49549299Shibler 		printf("vnclear(%x): vp %x\n", vp);
49641480Smckusick #endif
49749299Shibler 	vn->sc_flags &= ~VNF_INITED;
49841480Smckusick 	if (vp == (struct vnode *)0)
49949299Shibler 		panic("vnioctl: null vp");
50050115Smckusick 	(void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p);
50149299Shibler 	crfree(vn->sc_cred);
50249299Shibler 	vn->sc_vp = (struct vnode *)0;
50349299Shibler 	vn->sc_cred = (struct ucred *)0;
50449299Shibler 	vn->sc_size = 0;
50541480Smckusick }
50641480Smckusick 
vnsize(dev)50749299Shibler vnsize(dev)
50841480Smckusick 	dev_t dev;
50941480Smckusick {
51049299Shibler 	int unit = vnunit(dev);
51149299Shibler 	register struct vn_softc *vn = &vn_softc[unit];
51241480Smckusick 
51359342Shibler 	if (unit >= numvnd || (vn->sc_flags & VNF_INITED) == 0)
51441480Smckusick 		return(-1);
51549299Shibler 	return(vn->sc_size);
51641480Smckusick }
51741480Smckusick 
vndump(dev)51849299Shibler vndump(dev)
51941480Smckusick {
52041480Smckusick 	return(ENXIO);
52141480Smckusick }
52241480Smckusick #endif
523