xref: /original-bsd/sys/kern/vfs_vnops.c (revision 4ec9d53d)
1b5970980Smckusick /*
2309aa356Sbostic  * Copyright (c) 1982, 1986, 1989, 1993
3309aa356Sbostic  *	The Regents of the University of California.  All rights reserved.
4342da129Sbostic  * (c) UNIX System Laboratories, Inc.
5342da129Sbostic  * All or some portions of this file are derived from material licensed
6342da129Sbostic  * to the University of California by American Telephone and Telegraph
7342da129Sbostic  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8342da129Sbostic  * the permission of UNIX System Laboratories, Inc.
9b5970980Smckusick  *
1073a8e095Sbostic  * %sccs.include.redist.c%
11760e73c7Smckusick  *
12*4ec9d53dSmckusick  *	@(#)vfs_vnops.c	8.14 (Berkeley) 06/15/95
13b5970980Smckusick  */
1482e77ef7Ssam 
156e23d7a0Sbostic #include <sys/param.h>
166e23d7a0Sbostic #include <sys/systm.h>
176e23d7a0Sbostic #include <sys/kernel.h>
186e23d7a0Sbostic #include <sys/file.h>
196e23d7a0Sbostic #include <sys/stat.h>
206e23d7a0Sbostic #include <sys/buf.h>
216e23d7a0Sbostic #include <sys/proc.h>
226e23d7a0Sbostic #include <sys/mount.h>
236e23d7a0Sbostic #include <sys/namei.h>
246e23d7a0Sbostic #include <sys/vnode.h>
256e23d7a0Sbostic #include <sys/ioctl.h>
266e23d7a0Sbostic #include <sys/tty.h>
276e23d7a0Sbostic 
282a80cc9eSmckusick #include <vm/vm.h>
291d37f34bSbill 
30760e73c7Smckusick struct 	fileops vnops =
311a59b964Smckusick 	{ vn_read, vn_write, vn_ioctl, vn_select, vn_closefile };
32ae1aeb7bSmckusick 
331d37f34bSbill /*
34760e73c7Smckusick  * Common code for vnode open operations.
35760e73c7Smckusick  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
361d37f34bSbill  */
vn_open(ndp,fmode,cmode)37b1e88a53Smckusick vn_open(ndp, fmode, cmode)
38760e73c7Smckusick 	register struct nameidata *ndp;
39760e73c7Smckusick 	int fmode, cmode;
401d37f34bSbill {
41760e73c7Smckusick 	register struct vnode *vp;
42b1e88a53Smckusick 	register struct proc *p = ndp->ni_cnd.cn_proc;
436bd82dc0Smckusick 	register struct ucred *cred = p->p_ucred;
44760e73c7Smckusick 	struct vattr vat;
45760e73c7Smckusick 	struct vattr *vap = &vat;
46760e73c7Smckusick 	int error;
471d37f34bSbill 
48552d28cbSmckusick 	if (fmode & O_CREAT) {
49b1e88a53Smckusick 		ndp->ni_cnd.cn_nameiop = CREATE;
50b1e88a53Smckusick 		ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
51552d28cbSmckusick 		if ((fmode & O_EXCL) == 0)
52b1e88a53Smckusick 			ndp->ni_cnd.cn_flags |= FOLLOW;
53b1e88a53Smckusick 		if (error = namei(ndp))
54760e73c7Smckusick 			return (error);
55760e73c7Smckusick 		if (ndp->ni_vp == NULL) {
569a8d5e2aSmckusick 			VATTR_NULL(vap);
57760e73c7Smckusick 			vap->va_type = VREG;
58760e73c7Smckusick 			vap->va_mode = cmode;
599879b7b8Smckusick 			if (fmode & O_EXCL)
609879b7b8Smckusick 				vap->va_vaflags |= VA_EXCLUSIVE;
615274606dSmckusick 			VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
62b1e88a53Smckusick 			if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
63b1e88a53Smckusick 			    &ndp->ni_cnd, vap))
64760e73c7Smckusick 				return (error);
65552d28cbSmckusick 			fmode &= ~O_TRUNC;
66760e73c7Smckusick 			vp = ndp->ni_vp;
67760e73c7Smckusick 		} else {
68b1c104dbSheideman 			VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
6983225eaeSmckusick 			if (ndp->ni_dvp == ndp->ni_vp)
7083225eaeSmckusick 				vrele(ndp->ni_dvp);
71e8a20c25Smckusick 			else
7283225eaeSmckusick 				vput(ndp->ni_dvp);
7383225eaeSmckusick 			ndp->ni_dvp = NULL;
74760e73c7Smckusick 			vp = ndp->ni_vp;
75552d28cbSmckusick 			if (fmode & O_EXCL) {
76760e73c7Smckusick 				error = EEXIST;
77760e73c7Smckusick 				goto bad;
78760e73c7Smckusick 			}
79552d28cbSmckusick 			fmode &= ~O_CREAT;
80760e73c7Smckusick 		}
81760e73c7Smckusick 	} else {
82b1e88a53Smckusick 		ndp->ni_cnd.cn_nameiop = LOOKUP;
83b1e88a53Smckusick 		ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF;
84b1e88a53Smckusick 		if (error = namei(ndp))
85760e73c7Smckusick 			return (error);
86760e73c7Smckusick 		vp = ndp->ni_vp;
87760e73c7Smckusick 	}
88760e73c7Smckusick 	if (vp->v_type == VSOCK) {
89760e73c7Smckusick 		error = EOPNOTSUPP;
90760e73c7Smckusick 		goto bad;
91760e73c7Smckusick 	}
92552d28cbSmckusick 	if ((fmode & O_CREAT) == 0) {
93760e73c7Smckusick 		if (fmode & FREAD) {
942d8de7e9Smckusick 			if (error = VOP_ACCESS(vp, VREAD, cred, p))
95760e73c7Smckusick 				goto bad;
96760e73c7Smckusick 		}
97552d28cbSmckusick 		if (fmode & (FWRITE | O_TRUNC)) {
98760e73c7Smckusick 			if (vp->v_type == VDIR) {
99760e73c7Smckusick 				error = EISDIR;
100760e73c7Smckusick 				goto bad;
101760e73c7Smckusick 			}
102a597f5e9Smckusick 			if ((error = vn_writechk(vp)) ||
1032d8de7e9Smckusick 			    (error = VOP_ACCESS(vp, VWRITE, cred, p)))
104a597f5e9Smckusick 				goto bad;
105760e73c7Smckusick 		}
106760e73c7Smckusick 	}
107552d28cbSmckusick 	if (fmode & O_TRUNC) {
10888c3d290Smckusick 		VOP_UNLOCK(vp, 0, p);				/* XXX */
1095274606dSmckusick 		VOP_LEASE(vp, p, cred, LEASE_WRITE);
11088c3d290Smckusick 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);	/* XXX */
1119a8d5e2aSmckusick 		VATTR_NULL(vap);
112760e73c7Smckusick 		vap->va_size = 0;
1132d8de7e9Smckusick 		if (error = VOP_SETATTR(vp, vap, cred, p))
114760e73c7Smckusick 			goto bad;
115760e73c7Smckusick 	}
116c121a858Smckusick 	if (error = VOP_OPEN(vp, fmode, cred, p))
117c121a858Smckusick 		goto bad;
118c121a858Smckusick 	if (fmode & FWRITE)
119c121a858Smckusick 		vp->v_writecount++;
120552d28cbSmckusick 	return (0);
121760e73c7Smckusick bad:
122760e73c7Smckusick 	vput(vp);
123760e73c7Smckusick 	return (error);
124760e73c7Smckusick }
125760e73c7Smckusick 
12645db6fc1Ssam /*
127a597f5e9Smckusick  * Check for write permissions on the specified vnode.
1282892e00fSmckusick  * Prototype text segments cannot be written.
12945db6fc1Ssam  */
vn_writechk(vp)130a597f5e9Smckusick vn_writechk(vp)
131760e73c7Smckusick 	register struct vnode *vp;
132760e73c7Smckusick {
133760e73c7Smckusick 
134760e73c7Smckusick 	/*
13545db6fc1Ssam 	 * If there's shared text associated with
136a597f5e9Smckusick 	 * the vnode, try to free it up once.  If
13745db6fc1Ssam 	 * we fail, we can't allow writing.
13845db6fc1Ssam 	 */
1393065037bSmckusick 	if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
140760e73c7Smckusick 		return (ETXTBSY);
141a597f5e9Smckusick 	return (0);
1421d37f34bSbill }
1431d37f34bSbill 
1441d37f34bSbill /*
1451a59b964Smckusick  * Vnode close call
1461a59b964Smckusick  */
vn_close(vp,flags,cred,p)1471a59b964Smckusick vn_close(vp, flags, cred, p)
1481a59b964Smckusick 	register struct vnode *vp;
1491a59b964Smckusick 	int flags;
1501a59b964Smckusick 	struct ucred *cred;
1511a59b964Smckusick 	struct proc *p;
1521a59b964Smckusick {
1531a59b964Smckusick 	int error;
1541a59b964Smckusick 
1551a59b964Smckusick 	if (flags & FWRITE)
1561a59b964Smckusick 		vp->v_writecount--;
1571a59b964Smckusick 	error = VOP_CLOSE(vp, flags, cred, p);
1581a59b964Smckusick 	vrele(vp);
1591a59b964Smckusick 	return (error);
1601a59b964Smckusick }
1611a59b964Smckusick 
1621a59b964Smckusick /*
1631a59b964Smckusick  * Package up an I/O request on a vnode into a uio and do it.
1641d37f34bSbill  */
1652d8de7e9Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
166760e73c7Smckusick 	enum uio_rw rw;
167760e73c7Smckusick 	struct vnode *vp;
168760e73c7Smckusick 	caddr_t base;
169760e73c7Smckusick 	int len;
170760e73c7Smckusick 	off_t offset;
171760e73c7Smckusick 	enum uio_seg segflg;
172760e73c7Smckusick 	int ioflg;
173760e73c7Smckusick 	struct ucred *cred;
174760e73c7Smckusick 	int *aresid;
1752d8de7e9Smckusick 	struct proc *p;
1761d37f34bSbill {
177760e73c7Smckusick 	struct uio auio;
178760e73c7Smckusick 	struct iovec aiov;
179760e73c7Smckusick 	int error;
1801d37f34bSbill 
1812a601dc3Smckusick 	if ((ioflg & IO_NODELOCKED) == 0)
18288c3d290Smckusick 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
183760e73c7Smckusick 	auio.uio_iov = &aiov;
184760e73c7Smckusick 	auio.uio_iovcnt = 1;
185760e73c7Smckusick 	aiov.iov_base = base;
186760e73c7Smckusick 	aiov.iov_len = len;
187760e73c7Smckusick 	auio.uio_resid = len;
188760e73c7Smckusick 	auio.uio_offset = offset;
189760e73c7Smckusick 	auio.uio_segflg = segflg;
190760e73c7Smckusick 	auio.uio_rw = rw;
1912d8de7e9Smckusick 	auio.uio_procp = p;
192fdc68a99Smckusick 	if (rw == UIO_READ) {
1932a601dc3Smckusick 		error = VOP_READ(vp, &auio, ioflg, cred);
194fdc68a99Smckusick 	} else {
1952a601dc3Smckusick 		error = VOP_WRITE(vp, &auio, ioflg, cred);
196fdc68a99Smckusick 	}
197760e73c7Smckusick 	if (aresid)
198760e73c7Smckusick 		*aresid = auio.uio_resid;
199760e73c7Smckusick 	else
200760e73c7Smckusick 		if (auio.uio_resid && error == 0)
201760e73c7Smckusick 			error = EIO;
2022a601dc3Smckusick 	if ((ioflg & IO_NODELOCKED) == 0)
20388c3d290Smckusick 		VOP_UNLOCK(vp, 0, p);
204760e73c7Smckusick 	return (error);
2052510f0cdSmckusick }
2061d37f34bSbill 
2071a59b964Smckusick /*
2081a59b964Smckusick  * File table vnode read routine.
2091a59b964Smckusick  */
210760e73c7Smckusick vn_read(fp, uio, cred)
211760e73c7Smckusick 	struct file *fp;
212760e73c7Smckusick 	struct uio *uio;
213760e73c7Smckusick 	struct ucred *cred;
2141d37f34bSbill {
21588c3d290Smckusick 	struct vnode *vp = (struct vnode *)fp->f_data;
21688c3d290Smckusick 	struct proc *p = uio->uio_procp;
2172a601dc3Smckusick 	int count, error;
2181d37f34bSbill 
21988c3d290Smckusick 	VOP_LEASE(vp, p, cred, LEASE_READ);
22088c3d290Smckusick 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2212a601dc3Smckusick 	uio->uio_offset = fp->f_offset;
2222a601dc3Smckusick 	count = uio->uio_resid;
223552d28cbSmckusick 	error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
224552d28cbSmckusick 		cred);
2252a601dc3Smckusick 	fp->f_offset += count - uio->uio_resid;
22688c3d290Smckusick 	VOP_UNLOCK(vp, 0, p);
2272a601dc3Smckusick 	return (error);
228760e73c7Smckusick }
229760e73c7Smckusick 
2301a59b964Smckusick /*
2311a59b964Smckusick  * File table vnode write routine.
2321a59b964Smckusick  */
233760e73c7Smckusick vn_write(fp, uio, cred)
234760e73c7Smckusick 	struct file *fp;
235760e73c7Smckusick 	struct uio *uio;
236760e73c7Smckusick 	struct ucred *cred;
237760e73c7Smckusick {
23888c3d290Smckusick 	struct vnode *vp = (struct vnode *)fp->f_data;
23988c3d290Smckusick 	struct proc *p = uio->uio_procp;
24019849eecSmckusick 	int count, error, ioflag = IO_UNIT;
241760e73c7Smckusick 
242552d28cbSmckusick 	if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
243760e73c7Smckusick 		ioflag |= IO_APPEND;
244552d28cbSmckusick 	if (fp->f_flag & FNONBLOCK)
245760e73c7Smckusick 		ioflag |= IO_NDELAY;
246*4ec9d53dSmckusick 	if ((fp->f_flag & O_FSYNC) ||
247*4ec9d53dSmckusick 	    (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
2481821a922Smckusick 		ioflag |= IO_SYNC;
24988c3d290Smckusick 	VOP_LEASE(vp, p, cred, LEASE_WRITE);
25088c3d290Smckusick 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2512a601dc3Smckusick 	uio->uio_offset = fp->f_offset;
2522a601dc3Smckusick 	count = uio->uio_resid;
2532a601dc3Smckusick 	error = VOP_WRITE(vp, uio, ioflag, cred);
2542a601dc3Smckusick 	if (ioflag & IO_APPEND)
2552a601dc3Smckusick 		fp->f_offset = uio->uio_offset;
2562a601dc3Smckusick 	else
2572a601dc3Smckusick 		fp->f_offset += count - uio->uio_resid;
25888c3d290Smckusick 	VOP_UNLOCK(vp, 0, p);
2592a601dc3Smckusick 	return (error);
260760e73c7Smckusick }
261760e73c7Smckusick 
262760e73c7Smckusick /*
2631a59b964Smckusick  * File table vnode stat routine.
264760e73c7Smckusick  */
2652d8de7e9Smckusick vn_stat(vp, sb, p)
266760e73c7Smckusick 	struct vnode *vp;
267760e73c7Smckusick 	register struct stat *sb;
2682d8de7e9Smckusick 	struct proc *p;
269760e73c7Smckusick {
270760e73c7Smckusick 	struct vattr vattr;
271760e73c7Smckusick 	register struct vattr *vap;
272760e73c7Smckusick 	int error;
273760e73c7Smckusick 	u_short mode;
274760e73c7Smckusick 
275760e73c7Smckusick 	vap = &vattr;
2762d8de7e9Smckusick 	error = VOP_GETATTR(vp, vap, p->p_ucred, p);
277760e73c7Smckusick 	if (error)
278760e73c7Smckusick 		return (error);
279760e73c7Smckusick 	/*
280760e73c7Smckusick 	 * Copy from vattr table
281760e73c7Smckusick 	 */
282760e73c7Smckusick 	sb->st_dev = vap->va_fsid;
283760e73c7Smckusick 	sb->st_ino = vap->va_fileid;
284760e73c7Smckusick 	mode = vap->va_mode;
285760e73c7Smckusick 	switch (vp->v_type) {
286760e73c7Smckusick 	case VREG:
2876357f7baSmckusick 		mode |= S_IFREG;
288760e73c7Smckusick 		break;
289760e73c7Smckusick 	case VDIR:
2906357f7baSmckusick 		mode |= S_IFDIR;
291760e73c7Smckusick 		break;
292760e73c7Smckusick 	case VBLK:
2936357f7baSmckusick 		mode |= S_IFBLK;
294760e73c7Smckusick 		break;
295760e73c7Smckusick 	case VCHR:
2966357f7baSmckusick 		mode |= S_IFCHR;
297760e73c7Smckusick 		break;
298760e73c7Smckusick 	case VLNK:
2996357f7baSmckusick 		mode |= S_IFLNK;
300760e73c7Smckusick 		break;
301760e73c7Smckusick 	case VSOCK:
3026357f7baSmckusick 		mode |= S_IFSOCK;
303760e73c7Smckusick 		break;
304920ab10fSmckusick 	case VFIFO:
305920ab10fSmckusick 		mode |= S_IFIFO;
306920ab10fSmckusick 		break;
307760e73c7Smckusick 	default:
308760e73c7Smckusick 		return (EBADF);
309760e73c7Smckusick 	};
310760e73c7Smckusick 	sb->st_mode = mode;
311760e73c7Smckusick 	sb->st_nlink = vap->va_nlink;
312760e73c7Smckusick 	sb->st_uid = vap->va_uid;
313760e73c7Smckusick 	sb->st_gid = vap->va_gid;
314760e73c7Smckusick 	sb->st_rdev = vap->va_rdev;
315760e73c7Smckusick 	sb->st_size = vap->va_size;
3161c5a6ce1Smckusick 	sb->st_atimespec = vap->va_atime;
3171c5a6ce1Smckusick 	sb->st_mtimespec = vap->va_mtime;
3181c5a6ce1Smckusick 	sb->st_ctimespec = vap->va_ctime;
319760e73c7Smckusick 	sb->st_blksize = vap->va_blocksize;
32018b27549Smckusick 	sb->st_flags = vap->va_flags;
32118b27549Smckusick 	sb->st_gen = vap->va_gen;
322aa6f7503Smckusick 	sb->st_blocks = vap->va_bytes / S_BLKSIZE;
3231d37f34bSbill 	return (0);
3241d37f34bSbill }
325760e73c7Smckusick 
326760e73c7Smckusick /*
3271a59b964Smckusick  * File table vnode ioctl routine.
328760e73c7Smckusick  */
3292d8de7e9Smckusick vn_ioctl(fp, com, data, p)
330760e73c7Smckusick 	struct file *fp;
331d1a6a392Scgd 	u_long com;
332760e73c7Smckusick 	caddr_t data;
3332d8de7e9Smckusick 	struct proc *p;
334760e73c7Smckusick {
335760e73c7Smckusick 	register struct vnode *vp = ((struct vnode *)fp->f_data);
336760e73c7Smckusick 	struct vattr vattr;
337760e73c7Smckusick 	int error;
338760e73c7Smckusick 
339760e73c7Smckusick 	switch (vp->v_type) {
340760e73c7Smckusick 
341760e73c7Smckusick 	case VREG:
342760e73c7Smckusick 	case VDIR:
343760e73c7Smckusick 		if (com == FIONREAD) {
3442d8de7e9Smckusick 			if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
345760e73c7Smckusick 				return (error);
346f0ba414aStorek 			*(int *)data = vattr.va_size - fp->f_offset;
347760e73c7Smckusick 			return (0);
348760e73c7Smckusick 		}
349760e73c7Smckusick 		if (com == FIONBIO || com == FIOASYNC)	/* XXX */
350760e73c7Smckusick 			return (0);			/* XXX */
351760e73c7Smckusick 		/* fall into ... */
352760e73c7Smckusick 
353760e73c7Smckusick 	default:
354760e73c7Smckusick 		return (ENOTTY);
355760e73c7Smckusick 
356920ab10fSmckusick 	case VFIFO:
357760e73c7Smckusick 	case VCHR:
358760e73c7Smckusick 	case VBLK:
3592d8de7e9Smckusick 		error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
360e79e4887Smarc 		if (error == 0 && com == TIOCSCTTY) {
3613dc20f1fSmckusick 			if (p->p_session->s_ttyvp)
3623dc20f1fSmckusick 				vrele(p->p_session->s_ttyvp);
3630b0833e3Skarels 			p->p_session->s_ttyvp = vp;
364e79e4887Smarc 			VREF(vp);
365e79e4887Smarc 		}
366e79e4887Smarc 		return (error);
367760e73c7Smckusick 	}
368760e73c7Smckusick }
369760e73c7Smckusick 
370760e73c7Smckusick /*
3711a59b964Smckusick  * File table vnode select routine.
372760e73c7Smckusick  */
3732d8de7e9Smckusick vn_select(fp, which, p)
374760e73c7Smckusick 	struct file *fp;
375760e73c7Smckusick 	int which;
3762d8de7e9Smckusick 	struct proc *p;
377760e73c7Smckusick {
3780b0833e3Skarels 
379920ab10fSmckusick 	return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
3801a59b964Smckusick 		fp->f_cred, p));
381760e73c7Smckusick }
382760e73c7Smckusick 
383760e73c7Smckusick /*
38488c3d290Smckusick  * Check that the vnode is still valid, and if so
38588c3d290Smckusick  * acquire requested lock.
38688c3d290Smckusick  */
38788c3d290Smckusick int
vn_lock(vp,flags,p)38888c3d290Smckusick vn_lock(vp, flags, p)
38988c3d290Smckusick 	struct vnode *vp;
39088c3d290Smckusick 	int flags;
39188c3d290Smckusick 	struct proc *p;
39288c3d290Smckusick {
39388c3d290Smckusick 	int error;
39488c3d290Smckusick 
39588c3d290Smckusick 	do {
39688c3d290Smckusick 		if ((flags & LK_INTERLOCK) == 0)
39788c3d290Smckusick 			simple_lock(&vp->v_interlock);
39888c3d290Smckusick 		if (vp->v_flag & VXLOCK) {
39988c3d290Smckusick 			vp->v_flag |= VXWANT;
40088c3d290Smckusick 			simple_unlock(&vp->v_interlock);
40188c3d290Smckusick 			tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
40288c3d290Smckusick 			error = ENOENT;
40388c3d290Smckusick 		} else {
40488c3d290Smckusick 			error = VOP_LOCK(vp, flags | LK_INTERLOCK, p);
40588c3d290Smckusick 			if (error == 0)
40688c3d290Smckusick 				return (error);
40788c3d290Smckusick 		}
40888c3d290Smckusick 		flags &= ~LK_INTERLOCK;
40988c3d290Smckusick 	} while (flags & LK_RETRY);
41088c3d290Smckusick 	return (error);
41188c3d290Smckusick }
41288c3d290Smckusick 
41388c3d290Smckusick /*
4141a59b964Smckusick  * File table vnode close routine.
415760e73c7Smckusick  */
4161a59b964Smckusick vn_closefile(fp, p)
4171a59b964Smckusick 	struct file *fp;
4182d8de7e9Smckusick 	struct proc *p;
419760e73c7Smckusick {
420760e73c7Smckusick 
4211a59b964Smckusick 	return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
4221a59b964Smckusick 		fp->f_cred, p));
423760e73c7Smckusick }
424