xref: /original-bsd/sys/kern/vfs_vnops.c (revision 9fc842b5)
1b5970980Smckusick /*
2760e73c7Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3760e73c7Smckusick  * All rights reserved.
4b5970980Smckusick  *
573a8e095Sbostic  * %sccs.include.redist.c%
6760e73c7Smckusick  *
7*9fc842b5Smckusick  *	@(#)vfs_vnops.c	7.24 (Berkeley) 08/22/90
8b5970980Smckusick  */
982e77ef7Ssam 
10ecd0bebeSbloom #include "param.h"
11ecd0bebeSbloom #include "systm.h"
12ecd0bebeSbloom #include "user.h"
13760e73c7Smckusick #include "kernel.h"
14ecd0bebeSbloom #include "file.h"
15760e73c7Smckusick #include "stat.h"
16760e73c7Smckusick #include "buf.h"
17760e73c7Smckusick #include "proc.h"
18760e73c7Smckusick #include "uio.h"
19ecd0bebeSbloom #include "socket.h"
20ecd0bebeSbloom #include "socketvar.h"
21760e73c7Smckusick #include "mount.h"
22760e73c7Smckusick #include "vnode.h"
23760e73c7Smckusick #include "ioctl.h"
24760e73c7Smckusick #include "tty.h"
251d37f34bSbill 
26760e73c7Smckusick int	vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close();
27760e73c7Smckusick struct 	fileops vnops =
28760e73c7Smckusick 	{ vn_read, vn_write, vn_ioctl, vn_select, vn_close };
29ae1aeb7bSmckusick 
301d37f34bSbill /*
31760e73c7Smckusick  * Common code for vnode open operations.
32760e73c7Smckusick  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
331d37f34bSbill  */
34760e73c7Smckusick vn_open(ndp, fmode, cmode)
35760e73c7Smckusick 	register struct nameidata *ndp;
36760e73c7Smckusick 	int fmode, cmode;
371d37f34bSbill {
38760e73c7Smckusick 	register struct vnode *vp;
39760e73c7Smckusick 	struct vattr vat;
40760e73c7Smckusick 	struct vattr *vap = &vat;
41760e73c7Smckusick 	int error;
421d37f34bSbill 
43760e73c7Smckusick 	if (fmode & FCREAT) {
44760e73c7Smckusick 		ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF;
45760e73c7Smckusick 		if ((fmode & FEXCL) == 0)
46760e73c7Smckusick 			ndp->ni_nameiop |= FOLLOW;
47760e73c7Smckusick 		if (error = namei(ndp))
48760e73c7Smckusick 			return (error);
49760e73c7Smckusick 		if (ndp->ni_vp == NULL) {
509a8d5e2aSmckusick 			VATTR_NULL(vap);
51760e73c7Smckusick 			vap->va_type = VREG;
52760e73c7Smckusick 			vap->va_mode = cmode;
53760e73c7Smckusick 			if (error = VOP_CREATE(ndp, vap))
54760e73c7Smckusick 				return (error);
55760e73c7Smckusick 			fmode &= ~FTRUNC;
56760e73c7Smckusick 			vp = ndp->ni_vp;
57760e73c7Smckusick 		} else {
5883225eaeSmckusick 			if (ndp->ni_dvp == ndp->ni_vp)
5983225eaeSmckusick 				vrele(ndp->ni_dvp);
60e8a20c25Smckusick 			else
6183225eaeSmckusick 				vput(ndp->ni_dvp);
6283225eaeSmckusick 			ndp->ni_dvp = NULL;
63760e73c7Smckusick 			vp = ndp->ni_vp;
64760e73c7Smckusick 			if (fmode & FEXCL) {
65760e73c7Smckusick 				error = EEXIST;
66760e73c7Smckusick 				goto bad;
67760e73c7Smckusick 			}
68760e73c7Smckusick 			fmode &= ~FCREAT;
69760e73c7Smckusick 		}
70760e73c7Smckusick 	} else {
71760e73c7Smckusick 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
72760e73c7Smckusick 		if (error = namei(ndp))
73760e73c7Smckusick 			return (error);
74760e73c7Smckusick 		vp = ndp->ni_vp;
75760e73c7Smckusick 	}
76760e73c7Smckusick 	if (vp->v_type == VSOCK) {
77760e73c7Smckusick 		error = EOPNOTSUPP;
78760e73c7Smckusick 		goto bad;
79760e73c7Smckusick 	}
80760e73c7Smckusick 	if ((fmode & FCREAT) == 0) {
81760e73c7Smckusick 		if (fmode & FREAD) {
82a597f5e9Smckusick 			if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred))
83760e73c7Smckusick 				goto bad;
84760e73c7Smckusick 		}
85760e73c7Smckusick 		if (fmode & (FWRITE|FTRUNC)) {
86760e73c7Smckusick 			if (vp->v_type == VDIR) {
87760e73c7Smckusick 				error = EISDIR;
88760e73c7Smckusick 				goto bad;
89760e73c7Smckusick 			}
90a597f5e9Smckusick 			if ((error = vn_writechk(vp)) ||
91a597f5e9Smckusick 			    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
92a597f5e9Smckusick 				goto bad;
93760e73c7Smckusick 		}
94760e73c7Smckusick 	}
95760e73c7Smckusick 	if (fmode & FTRUNC) {
969a8d5e2aSmckusick 		VATTR_NULL(vap);
97760e73c7Smckusick 		vap->va_size = 0;
98760e73c7Smckusick 		if (error = VOP_SETATTR(vp, vap, ndp->ni_cred))
99760e73c7Smckusick 			goto bad;
100760e73c7Smckusick 	}
101760e73c7Smckusick 	VOP_UNLOCK(vp);
102a25d0e59Smckusick 	error = VOP_OPEN(vp, fmode, ndp->ni_cred);
103a25d0e59Smckusick 	if (error)
104a25d0e59Smckusick 		vrele(vp);
105a25d0e59Smckusick 	return (error);
106760e73c7Smckusick 
107760e73c7Smckusick bad:
108760e73c7Smckusick 	vput(vp);
109760e73c7Smckusick 	return (error);
110760e73c7Smckusick }
111760e73c7Smckusick 
11245db6fc1Ssam /*
113a597f5e9Smckusick  * Check for write permissions on the specified vnode.
114a597f5e9Smckusick  * The read-only status of the file system is checked.
115a597f5e9Smckusick  * Also, prototype text segments cannot be written.
11645db6fc1Ssam  */
117a597f5e9Smckusick vn_writechk(vp)
118760e73c7Smckusick 	register struct vnode *vp;
119760e73c7Smckusick {
120760e73c7Smckusick 
121760e73c7Smckusick 	/*
122760e73c7Smckusick 	 * Disallow write attempts on read-only file systems;
123760e73c7Smckusick 	 * unless the file is a socket or a block or character
124760e73c7Smckusick 	 * device resident on the file system.
125760e73c7Smckusick 	 */
126*9fc842b5Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
127*9fc842b5Smckusick 		switch (vp->v_type) {
128*9fc842b5Smckusick 		case VREG: case VDIR: case VLNK:
129760e73c7Smckusick 			return (EROFS);
130*9fc842b5Smckusick 		}
131*9fc842b5Smckusick 	}
13245db6fc1Ssam 	/*
13345db6fc1Ssam 	 * If there's shared text associated with
134a597f5e9Smckusick 	 * the vnode, try to free it up once.  If
13545db6fc1Ssam 	 * we fail, we can't allow writing.
13645db6fc1Ssam 	 */
137760e73c7Smckusick 	if (vp->v_flag & VTEXT)
138760e73c7Smckusick 		xrele(vp);
139760e73c7Smckusick 	if (vp->v_flag & VTEXT)
140760e73c7Smckusick 		return (ETXTBSY);
141a597f5e9Smckusick 	return (0);
1421d37f34bSbill }
1431d37f34bSbill 
1441d37f34bSbill /*
145760e73c7Smckusick  * Vnode version of rdwri() for calls on file systems.
1461d37f34bSbill  */
147760e73c7Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid)
148760e73c7Smckusick 	enum uio_rw rw;
149760e73c7Smckusick 	struct vnode *vp;
150760e73c7Smckusick 	caddr_t base;
151760e73c7Smckusick 	int len;
152760e73c7Smckusick 	off_t offset;
153760e73c7Smckusick 	enum uio_seg segflg;
154760e73c7Smckusick 	int ioflg;
155760e73c7Smckusick 	struct ucred *cred;
156760e73c7Smckusick 	int *aresid;
1571d37f34bSbill {
158760e73c7Smckusick 	struct uio auio;
159760e73c7Smckusick 	struct iovec aiov;
160760e73c7Smckusick 	int error;
1611d37f34bSbill 
1622a601dc3Smckusick 	if ((ioflg & IO_NODELOCKED) == 0)
1632a601dc3Smckusick 		VOP_LOCK(vp);
164760e73c7Smckusick 	auio.uio_iov = &aiov;
165760e73c7Smckusick 	auio.uio_iovcnt = 1;
166760e73c7Smckusick 	aiov.iov_base = base;
167760e73c7Smckusick 	aiov.iov_len = len;
168760e73c7Smckusick 	auio.uio_resid = len;
169760e73c7Smckusick 	auio.uio_offset = offset;
170760e73c7Smckusick 	auio.uio_segflg = segflg;
171760e73c7Smckusick 	auio.uio_rw = rw;
172760e73c7Smckusick 	if (rw == UIO_READ)
1732a601dc3Smckusick 		error = VOP_READ(vp, &auio, ioflg, cred);
174760e73c7Smckusick 	else
1752a601dc3Smckusick 		error = VOP_WRITE(vp, &auio, ioflg, cred);
176760e73c7Smckusick 	if (aresid)
177760e73c7Smckusick 		*aresid = auio.uio_resid;
178760e73c7Smckusick 	else
179760e73c7Smckusick 		if (auio.uio_resid && error == 0)
180760e73c7Smckusick 			error = EIO;
1812a601dc3Smckusick 	if ((ioflg & IO_NODELOCKED) == 0)
1822a601dc3Smckusick 		VOP_UNLOCK(vp);
183760e73c7Smckusick 	return (error);
1842510f0cdSmckusick }
1851d37f34bSbill 
186760e73c7Smckusick vn_read(fp, uio, cred)
187760e73c7Smckusick 	struct file *fp;
188760e73c7Smckusick 	struct uio *uio;
189760e73c7Smckusick 	struct ucred *cred;
1901d37f34bSbill {
1912a601dc3Smckusick 	register struct vnode *vp = (struct vnode *)fp->f_data;
1922a601dc3Smckusick 	int count, error;
1931d37f34bSbill 
1942a601dc3Smckusick 	VOP_LOCK(vp);
1952a601dc3Smckusick 	uio->uio_offset = fp->f_offset;
1962a601dc3Smckusick 	count = uio->uio_resid;
1972a601dc3Smckusick 	error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred);
1982a601dc3Smckusick 	fp->f_offset += count - uio->uio_resid;
1992a601dc3Smckusick 	VOP_UNLOCK(vp);
2002a601dc3Smckusick 	return (error);
201760e73c7Smckusick }
202760e73c7Smckusick 
203760e73c7Smckusick vn_write(fp, uio, cred)
204760e73c7Smckusick 	struct file *fp;
205760e73c7Smckusick 	struct uio *uio;
206760e73c7Smckusick 	struct ucred *cred;
207760e73c7Smckusick {
208760e73c7Smckusick 	register struct vnode *vp = (struct vnode *)fp->f_data;
2092a601dc3Smckusick 	int count, error, ioflag = 0;
210760e73c7Smckusick 
211760e73c7Smckusick 	if (vp->v_type == VREG && (fp->f_flag & FAPPEND))
212760e73c7Smckusick 		ioflag |= IO_APPEND;
213760e73c7Smckusick 	if (fp->f_flag & FNDELAY)
214760e73c7Smckusick 		ioflag |= IO_NDELAY;
2152a601dc3Smckusick 	VOP_LOCK(vp);
2162a601dc3Smckusick 	uio->uio_offset = fp->f_offset;
2172a601dc3Smckusick 	count = uio->uio_resid;
2182a601dc3Smckusick 	error = VOP_WRITE(vp, uio, ioflag, cred);
2192a601dc3Smckusick 	if (ioflag & IO_APPEND)
2202a601dc3Smckusick 		fp->f_offset = uio->uio_offset;
2212a601dc3Smckusick 	else
2222a601dc3Smckusick 		fp->f_offset += count - uio->uio_resid;
2232a601dc3Smckusick 	VOP_UNLOCK(vp);
2242a601dc3Smckusick 	return (error);
225760e73c7Smckusick }
226760e73c7Smckusick 
227760e73c7Smckusick /*
228760e73c7Smckusick  * Get stat info for a vnode.
229760e73c7Smckusick  */
230760e73c7Smckusick vn_stat(vp, sb)
231760e73c7Smckusick 	struct vnode *vp;
232760e73c7Smckusick 	register struct stat *sb;
233760e73c7Smckusick {
234760e73c7Smckusick 	struct vattr vattr;
235760e73c7Smckusick 	register struct vattr *vap;
236760e73c7Smckusick 	int error;
237760e73c7Smckusick 	u_short mode;
238760e73c7Smckusick 
239760e73c7Smckusick 	vap = &vattr;
240760e73c7Smckusick 	error = VOP_GETATTR(vp, vap, u.u_cred);
241760e73c7Smckusick 	if (error)
242760e73c7Smckusick 		return (error);
243760e73c7Smckusick 	/*
244760e73c7Smckusick 	 * Copy from vattr table
245760e73c7Smckusick 	 */
246760e73c7Smckusick 	sb->st_dev = vap->va_fsid;
247760e73c7Smckusick 	sb->st_ino = vap->va_fileid;
248760e73c7Smckusick 	mode = vap->va_mode;
249760e73c7Smckusick 	switch (vp->v_type) {
250760e73c7Smckusick 	case VREG:
2516357f7baSmckusick 		mode |= S_IFREG;
252760e73c7Smckusick 		break;
253760e73c7Smckusick 	case VDIR:
2546357f7baSmckusick 		mode |= S_IFDIR;
255760e73c7Smckusick 		break;
256760e73c7Smckusick 	case VBLK:
2576357f7baSmckusick 		mode |= S_IFBLK;
258760e73c7Smckusick 		break;
259760e73c7Smckusick 	case VCHR:
2606357f7baSmckusick 		mode |= S_IFCHR;
261760e73c7Smckusick 		break;
262760e73c7Smckusick 	case VLNK:
2636357f7baSmckusick 		mode |= S_IFLNK;
264760e73c7Smckusick 		break;
265760e73c7Smckusick 	case VSOCK:
2666357f7baSmckusick 		mode |= S_IFSOCK;
267760e73c7Smckusick 		break;
268920ab10fSmckusick 	case VFIFO:
269920ab10fSmckusick 		mode |= S_IFIFO;
270920ab10fSmckusick 		break;
271760e73c7Smckusick 	default:
272760e73c7Smckusick 		return (EBADF);
273760e73c7Smckusick 	};
274760e73c7Smckusick 	sb->st_mode = mode;
275760e73c7Smckusick 	sb->st_nlink = vap->va_nlink;
276760e73c7Smckusick 	sb->st_uid = vap->va_uid;
277760e73c7Smckusick 	sb->st_gid = vap->va_gid;
278760e73c7Smckusick 	sb->st_rdev = vap->va_rdev;
279760e73c7Smckusick 	sb->st_size = vap->va_size;
280760e73c7Smckusick 	sb->st_atime = vap->va_atime.tv_sec;
281760e73c7Smckusick 	sb->st_spare1 = 0;
282760e73c7Smckusick 	sb->st_mtime = vap->va_mtime.tv_sec;
283760e73c7Smckusick 	sb->st_spare2 = 0;
284760e73c7Smckusick 	sb->st_ctime = vap->va_ctime.tv_sec;
285760e73c7Smckusick 	sb->st_spare3 = 0;
286760e73c7Smckusick 	sb->st_blksize = vap->va_blocksize;
28718b27549Smckusick 	sb->st_flags = vap->va_flags;
28818b27549Smckusick 	sb->st_gen = vap->va_gen;
289aa6f7503Smckusick 	sb->st_blocks = vap->va_bytes / S_BLKSIZE;
2901d37f34bSbill 	return (0);
2911d37f34bSbill }
292760e73c7Smckusick 
293760e73c7Smckusick /*
294760e73c7Smckusick  * Vnode ioctl call
295760e73c7Smckusick  */
296760e73c7Smckusick vn_ioctl(fp, com, data)
297760e73c7Smckusick 	struct file *fp;
298760e73c7Smckusick 	int com;
299760e73c7Smckusick 	caddr_t data;
300760e73c7Smckusick {
301760e73c7Smckusick 	register struct vnode *vp = ((struct vnode *)fp->f_data);
302760e73c7Smckusick 	struct vattr vattr;
303760e73c7Smckusick 	int error;
304760e73c7Smckusick 
305760e73c7Smckusick 	switch (vp->v_type) {
306760e73c7Smckusick 
307760e73c7Smckusick 	case VREG:
308760e73c7Smckusick 	case VDIR:
309760e73c7Smckusick 		if (com == FIONREAD) {
310760e73c7Smckusick 			if (error = VOP_GETATTR(vp, &vattr, u.u_cred))
311760e73c7Smckusick 				return (error);
312760e73c7Smckusick 			*(off_t *)data = vattr.va_size - fp->f_offset;
313760e73c7Smckusick 			return (0);
314760e73c7Smckusick 		}
315760e73c7Smckusick 		if (com == FIONBIO || com == FIOASYNC)	/* XXX */
316760e73c7Smckusick 			return (0);			/* XXX */
317760e73c7Smckusick 		/* fall into ... */
318760e73c7Smckusick 
319760e73c7Smckusick 	default:
320760e73c7Smckusick 		return (ENOTTY);
321760e73c7Smckusick 
322920ab10fSmckusick 	case VFIFO:
323760e73c7Smckusick 	case VCHR:
324760e73c7Smckusick 	case VBLK:
325e79e4887Smarc 		error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred);
326e79e4887Smarc 		if (error == 0 && com == TIOCSCTTY) {
327e79e4887Smarc 			u.u_procp->p_session->s_ttyvp = vp;
328e79e4887Smarc 			VREF(vp);
329e79e4887Smarc 		}
330e79e4887Smarc 		return (error);
331760e73c7Smckusick 	}
332760e73c7Smckusick }
333760e73c7Smckusick 
334760e73c7Smckusick /*
335760e73c7Smckusick  * Vnode select call
336760e73c7Smckusick  */
337760e73c7Smckusick vn_select(fp, which)
338760e73c7Smckusick 	struct file *fp;
339760e73c7Smckusick 	int which;
340760e73c7Smckusick {
341920ab10fSmckusick 	return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
342920ab10fSmckusick 		u.u_cred));
343760e73c7Smckusick }
344760e73c7Smckusick 
345760e73c7Smckusick /*
346760e73c7Smckusick  * Vnode close call
347760e73c7Smckusick  */
348760e73c7Smckusick vn_close(fp)
349760e73c7Smckusick 	register struct file *fp;
350760e73c7Smckusick {
351760e73c7Smckusick 	struct vnode *vp = ((struct vnode *)fp->f_data);
352760e73c7Smckusick 	int error;
353760e73c7Smckusick 
354760e73c7Smckusick 	if (fp->f_flag & (FSHLOCK|FEXLOCK))
355760e73c7Smckusick 		vn_unlock(fp, FSHLOCK|FEXLOCK);
356760e73c7Smckusick 	/*
357760e73c7Smckusick 	 * Must delete vnode reference from this file entry
358760e73c7Smckusick 	 * before VOP_CLOSE, so that only other references
359760e73c7Smckusick 	 * will prevent close.
360760e73c7Smckusick 	 */
361760e73c7Smckusick 	fp->f_data = (caddr_t) 0;
362760e73c7Smckusick 	error = VOP_CLOSE(vp, fp->f_flag, u.u_cred);
363760e73c7Smckusick 	vrele(vp);
364760e73c7Smckusick 	return (error);
365760e73c7Smckusick }
366760e73c7Smckusick 
367760e73c7Smckusick /*
368760e73c7Smckusick  * Place an advisory lock on a vnode.
369760e73c7Smckusick  * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries
370760e73c7Smckusick  */
371760e73c7Smckusick vn_lock(fp, cmd)
372760e73c7Smckusick 	register struct file *fp;
373760e73c7Smckusick 	int cmd;
374760e73c7Smckusick {
375760e73c7Smckusick 	register int priority = PLOCK;
376760e73c7Smckusick 	register struct vnode *vp = (struct vnode *)fp->f_data;
377bad83f78Skarels 	int error = 0;
378bad83f78Skarels 	static char lockstr[] = "flock";
379760e73c7Smckusick 
380760e73c7Smckusick 	if ((cmd & LOCK_EX) == 0)
381760e73c7Smckusick 		priority += 4;
382bad83f78Skarels 	priority |= PCATCH;
383bad83f78Skarels 
384760e73c7Smckusick 	/*
385760e73c7Smckusick 	 * If there's a exclusive lock currently applied
386760e73c7Smckusick 	 * to the file, then we've gotta wait for the
387760e73c7Smckusick 	 * lock with everyone else.
388760e73c7Smckusick 	 */
389760e73c7Smckusick again:
390760e73c7Smckusick 	while (vp->v_flag & VEXLOCK) {
391760e73c7Smckusick 		/*
392760e73c7Smckusick 		 * If we're holding an exclusive
393760e73c7Smckusick 		 * lock, then release it.
394760e73c7Smckusick 		 */
395760e73c7Smckusick 		if (fp->f_flag & FEXLOCK) {
396760e73c7Smckusick 			vn_unlock(fp, FEXLOCK);
397760e73c7Smckusick 			continue;
398760e73c7Smckusick 		}
399760e73c7Smckusick 		if (cmd & LOCK_NB)
400760e73c7Smckusick 			return (EWOULDBLOCK);
401760e73c7Smckusick 		vp->v_flag |= VLWAIT;
402bad83f78Skarels 		if (error = tsleep((caddr_t)&vp->v_exlockc, priority,
403bad83f78Skarels 		    lockstr, 0))
404bad83f78Skarels 			return (error);
405760e73c7Smckusick 	}
406*9fc842b5Smckusick 	if (error == 0 && (cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) {
407760e73c7Smckusick 		/*
408760e73c7Smckusick 		 * Must wait for any shared locks to finish
409760e73c7Smckusick 		 * before we try to apply a exclusive lock.
410760e73c7Smckusick 		 *
411760e73c7Smckusick 		 * If we're holding a shared
412760e73c7Smckusick 		 * lock, then release it.
413760e73c7Smckusick 		 */
414760e73c7Smckusick 		if (fp->f_flag & FSHLOCK) {
415760e73c7Smckusick 			vn_unlock(fp, FSHLOCK);
416760e73c7Smckusick 			goto again;
417760e73c7Smckusick 		}
418760e73c7Smckusick 		if (cmd & LOCK_NB)
419760e73c7Smckusick 			return (EWOULDBLOCK);
420760e73c7Smckusick 		vp->v_flag |= VLWAIT;
421bad83f78Skarels 		if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH,
422*9fc842b5Smckusick 		    lockstr, 0))
423bad83f78Skarels 			return (error);
424760e73c7Smckusick 	}
425760e73c7Smckusick 	if (fp->f_flag & FEXLOCK)
426760e73c7Smckusick 		panic("vn_lock");
427760e73c7Smckusick 	if (cmd & LOCK_EX) {
428760e73c7Smckusick 		cmd &= ~LOCK_SH;
429760e73c7Smckusick 		vp->v_exlockc++;
430760e73c7Smckusick 		vp->v_flag |= VEXLOCK;
431760e73c7Smckusick 		fp->f_flag |= FEXLOCK;
432760e73c7Smckusick 	}
433760e73c7Smckusick 	if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
434760e73c7Smckusick 		vp->v_shlockc++;
435760e73c7Smckusick 		vp->v_flag |= VSHLOCK;
436760e73c7Smckusick 		fp->f_flag |= FSHLOCK;
437760e73c7Smckusick 	}
438760e73c7Smckusick 	return (0);
439760e73c7Smckusick }
440760e73c7Smckusick 
441760e73c7Smckusick /*
442760e73c7Smckusick  * Unlock a file.
443760e73c7Smckusick  */
444760e73c7Smckusick vn_unlock(fp, kind)
445760e73c7Smckusick 	register struct file *fp;
446760e73c7Smckusick 	int kind;
447760e73c7Smckusick {
448760e73c7Smckusick 	register struct vnode *vp = (struct vnode *)fp->f_data;
449760e73c7Smckusick 	int flags;
450760e73c7Smckusick 
451760e73c7Smckusick 	kind &= fp->f_flag;
452760e73c7Smckusick 	if (vp == NULL || kind == 0)
453760e73c7Smckusick 		return;
454760e73c7Smckusick 	flags = vp->v_flag;
455760e73c7Smckusick 	if (kind & FSHLOCK) {
456760e73c7Smckusick 		if ((flags & VSHLOCK) == 0)
457760e73c7Smckusick 			panic("vn_unlock: SHLOCK");
458760e73c7Smckusick 		if (--vp->v_shlockc == 0) {
459760e73c7Smckusick 			vp->v_flag &= ~VSHLOCK;
460760e73c7Smckusick 			if (flags & VLWAIT)
461760e73c7Smckusick 				wakeup((caddr_t)&vp->v_shlockc);
462760e73c7Smckusick 		}
463760e73c7Smckusick 		fp->f_flag &= ~FSHLOCK;
464760e73c7Smckusick 	}
465760e73c7Smckusick 	if (kind & FEXLOCK) {
466760e73c7Smckusick 		if ((flags & VEXLOCK) == 0)
467760e73c7Smckusick 			panic("vn_unlock: EXLOCK");
468760e73c7Smckusick 		if (--vp->v_exlockc == 0) {
469760e73c7Smckusick 			vp->v_flag &= ~(VEXLOCK|VLWAIT);
470760e73c7Smckusick 			if (flags & VLWAIT)
471760e73c7Smckusick 				wakeup((caddr_t)&vp->v_exlockc);
472760e73c7Smckusick 		}
473760e73c7Smckusick 		fp->f_flag &= ~FEXLOCK;
474760e73c7Smckusick 	}
475760e73c7Smckusick }
476760e73c7Smckusick 
477760e73c7Smckusick /*
478760e73c7Smckusick  * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
479760e73c7Smckusick  * 	- look up fsid in mount list (if not found ret error)
480760e73c7Smckusick  *	- get vp by calling VFS_FHTOVP() macro
481760e73c7Smckusick  *	- if lockflag lock it with VOP_LOCK()
482760e73c7Smckusick  */
483760e73c7Smckusick vn_fhtovp(fhp, lockflag, vpp)
484760e73c7Smckusick 	fhandle_t *fhp;
485760e73c7Smckusick 	int lockflag;
486760e73c7Smckusick 	struct vnode **vpp;
487760e73c7Smckusick {
488760e73c7Smckusick 	register struct mount *mp;
489760e73c7Smckusick 
490760e73c7Smckusick 	if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
491760e73c7Smckusick 		return (ESTALE);
492229daf47Smckusick 	if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
493229daf47Smckusick 		return (ESTALE);
494229daf47Smckusick 	if (!lockflag)
495229daf47Smckusick 		VOP_UNLOCK(*vpp);
496760e73c7Smckusick 	return (0);
497760e73c7Smckusick }
498760e73c7Smckusick 
499760e73c7Smckusick /*
500760e73c7Smckusick  * Noop
501760e73c7Smckusick  */
502760e73c7Smckusick vfs_noop()
503760e73c7Smckusick {
504760e73c7Smckusick 
505760e73c7Smckusick 	return (ENXIO);
506760e73c7Smckusick }
507760e73c7Smckusick 
508760e73c7Smckusick /*
509760e73c7Smckusick  * Null op
510760e73c7Smckusick  */
511760e73c7Smckusick vfs_nullop()
512760e73c7Smckusick {
513760e73c7Smckusick 
514760e73c7Smckusick 	return (0);
5152510f0cdSmckusick }
516