xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 39590)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)vfs_vnops.c	7.12 (Berkeley) 11/22/89
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "user.h"
23 #include "kernel.h"
24 #include "file.h"
25 #include "stat.h"
26 #include "buf.h"
27 #include "proc.h"
28 #include "uio.h"
29 #include "socket.h"
30 #include "socketvar.h"
31 #include "mount.h"
32 #include "vnode.h"
33 #include "../ufs/fs.h"
34 #include "../ufs/quota.h"
35 #include "ioctl.h"
36 #include "tty.h"
37 
38 int	vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close();
39 struct 	fileops vnops =
40 	{ vn_read, vn_write, vn_ioctl, vn_select, vn_close };
41 
42 /*
43  * Common code for vnode open operations.
44  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
45  */
46 vn_open(ndp, fmode, cmode)
47 	register struct nameidata *ndp;
48 	int fmode, cmode;
49 {
50 	register struct vnode *vp;
51 	struct vattr vat;
52 	struct vattr *vap = &vat;
53 	int error;
54 
55 	if (fmode & FCREAT) {
56 		ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF;
57 		if ((fmode & FEXCL) == 0)
58 			ndp->ni_nameiop |= FOLLOW;
59 		if (error = namei(ndp))
60 			return (error);
61 		if (ndp->ni_vp == NULL) {
62 			vattr_null(vap);
63 			vap->va_type = VREG;
64 			vap->va_mode = cmode;
65 			if (error = VOP_CREATE(ndp, vap))
66 				return (error);
67 			fmode &= ~FTRUNC;
68 			vp = ndp->ni_vp;
69 		} else {
70 			vp = ndp->ni_vp;
71 			ndp->ni_vp = 0;
72 			VOP_ABORTOP(ndp);
73 			ndp->ni_vp = vp;
74 			if (fmode & FEXCL) {
75 				error = EEXIST;
76 				goto bad;
77 			}
78 			fmode &= ~FCREAT;
79 		}
80 	} else {
81 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
82 		if (error = namei(ndp))
83 			return (error);
84 		vp = ndp->ni_vp;
85 	}
86 	if (vp->v_type == VSOCK) {
87 		error = EOPNOTSUPP;
88 		goto bad;
89 	}
90 	if ((fmode & FCREAT) == 0) {
91 		if (fmode & FREAD) {
92 			if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred))
93 				goto bad;
94 		}
95 		if (fmode & (FWRITE|FTRUNC)) {
96 			if (vp->v_type == VDIR) {
97 				error = EISDIR;
98 				goto bad;
99 			}
100 			if ((error = vn_writechk(vp)) ||
101 			    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
102 				goto bad;
103 		}
104 	}
105 	if (fmode & FTRUNC) {
106 		vattr_null(vap);
107 		vap->va_size = 0;
108 		if (error = VOP_SETATTR(vp, vap, ndp->ni_cred))
109 			goto bad;
110 	}
111 	VOP_UNLOCK(vp);
112 	if (setjmp(&u.u_qsave)) {
113 		if (error == 0)
114 			error = EINTR;
115 		return (error);
116 	}
117 	error = VOP_OPEN(vp, fmode, ndp->ni_cred);
118 	if (error)
119 		vrele(vp);
120 	return (error);
121 
122 bad:
123 	vput(vp);
124 	return(error);
125 }
126 
127 /*
128  * Check for write permissions on the specified vnode.
129  * The read-only status of the file system is checked.
130  * Also, prototype text segments cannot be written.
131  */
132 vn_writechk(vp)
133 	register struct vnode *vp;
134 {
135 
136 	/*
137 	 * Disallow write attempts on read-only file systems;
138 	 * unless the file is a socket or a block or character
139 	 * device resident on the file system.
140 	 */
141 	if ((vp->v_mount->m_flag & M_RDONLY) && vp->v_type != VCHR &&
142 	    vp->v_type != VBLK && vp->v_type != VSOCK)
143 		return (EROFS);
144 	/*
145 	 * If there's shared text associated with
146 	 * the vnode, try to free it up once.  If
147 	 * we fail, we can't allow writing.
148 	 */
149 	if (vp->v_flag & VTEXT)
150 		xrele(vp);
151 	if (vp->v_flag & VTEXT)
152 		return (ETXTBSY);
153 	return (0);
154 }
155 
156 /*
157  * Vnode version of rdwri() for calls on file systems.
158  */
159 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid)
160 	enum uio_rw rw;
161 	struct vnode *vp;
162 	caddr_t base;
163 	int len;
164 	off_t offset;
165 	enum uio_seg segflg;
166 	int ioflg;
167 	struct ucred *cred;
168 	int *aresid;
169 {
170 	struct uio auio;
171 	struct iovec aiov;
172 	int error;
173 
174 	if ((ioflg & IO_NODELOCKED) == 0)
175 		VOP_LOCK(vp);
176 	auio.uio_iov = &aiov;
177 	auio.uio_iovcnt = 1;
178 	aiov.iov_base = base;
179 	aiov.iov_len = len;
180 	auio.uio_resid = len;
181 	auio.uio_offset = offset;
182 	auio.uio_segflg = segflg;
183 	auio.uio_rw = rw;
184 	if (rw == UIO_READ)
185 		error = VOP_READ(vp, &auio, ioflg, cred);
186 	else
187 		error = VOP_WRITE(vp, &auio, ioflg, cred);
188 	if (aresid)
189 		*aresid = auio.uio_resid;
190 	else
191 		if (auio.uio_resid && error == 0)
192 			error = EIO;
193 	if ((ioflg & IO_NODELOCKED) == 0)
194 		VOP_UNLOCK(vp);
195 	return (error);
196 }
197 
198 vn_read(fp, uio, cred)
199 	struct file *fp;
200 	struct uio *uio;
201 	struct ucred *cred;
202 {
203 	register struct vnode *vp = (struct vnode *)fp->f_data;
204 	int count, error;
205 
206 	VOP_LOCK(vp);
207 	uio->uio_offset = fp->f_offset;
208 	count = uio->uio_resid;
209 	error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred);
210 	fp->f_offset += count - uio->uio_resid;
211 	VOP_UNLOCK(vp);
212 	return (error);
213 }
214 
215 vn_write(fp, uio, cred)
216 	struct file *fp;
217 	struct uio *uio;
218 	struct ucred *cred;
219 {
220 	register struct vnode *vp = (struct vnode *)fp->f_data;
221 	int count, error, ioflag = 0;
222 
223 	if (vp->v_type == VREG && (fp->f_flag & FAPPEND))
224 		ioflag |= IO_APPEND;
225 	if (fp->f_flag & FNDELAY)
226 		ioflag |= IO_NDELAY;
227 	VOP_LOCK(vp);
228 	uio->uio_offset = fp->f_offset;
229 	count = uio->uio_resid;
230 	error = VOP_WRITE(vp, uio, ioflag, cred);
231 	if (ioflag & IO_APPEND)
232 		fp->f_offset = uio->uio_offset;
233 	else
234 		fp->f_offset += count - uio->uio_resid;
235 	VOP_UNLOCK(vp);
236 	return (error);
237 }
238 
239 /*
240  * Get stat info for a vnode.
241  */
242 vn_stat(vp, sb)
243 	struct vnode *vp;
244 	register struct stat *sb;
245 {
246 	struct vattr vattr;
247 	register struct vattr *vap;
248 	int error;
249 	u_short mode;
250 
251 	vap = &vattr;
252 	error = VOP_GETATTR(vp, vap, u.u_cred);
253 	if (error)
254 		return (error);
255 	/*
256 	 * Copy from vattr table
257 	 */
258 	sb->st_dev = vap->va_fsid;
259 	sb->st_ino = vap->va_fileid;
260 	mode = vap->va_mode;
261 	switch (vp->v_type) {
262 	case VREG:
263 		mode |= S_IFREG;
264 		break;
265 	case VDIR:
266 		mode |= S_IFDIR;
267 		break;
268 	case VBLK:
269 		mode |= S_IFBLK;
270 		break;
271 	case VCHR:
272 		mode |= S_IFCHR;
273 		break;
274 	case VLNK:
275 		mode |= S_IFLNK;
276 		break;
277 	case VSOCK:
278 		mode |= S_IFSOCK;
279 		break;
280 	default:
281 		return (EBADF);
282 	};
283 	sb->st_mode = mode;
284 	sb->st_nlink = vap->va_nlink;
285 	sb->st_uid = vap->va_uid;
286 	sb->st_gid = vap->va_gid;
287 	sb->st_rdev = vap->va_rdev;
288 	sb->st_size = vap->va_size;
289 	sb->st_atime = vap->va_atime.tv_sec;
290 	sb->st_spare1 = 0;
291 	sb->st_mtime = vap->va_mtime.tv_sec;
292 	sb->st_spare2 = 0;
293 	sb->st_ctime = vap->va_ctime.tv_sec;
294 	sb->st_spare3 = 0;
295 	sb->st_blksize = vap->va_blocksize;
296 	sb->st_flags = vap->va_flags;
297 	sb->st_gen = vap->va_gen;
298 	sb->st_blocks = vap->va_bytes / S_BLKSIZE;
299 	return (0);
300 }
301 
302 /*
303  * Vnode ioctl call
304  */
305 vn_ioctl(fp, com, data)
306 	struct file *fp;
307 	int com;
308 	caddr_t data;
309 {
310 	register struct vnode *vp = ((struct vnode *)fp->f_data);
311 	struct vattr vattr;
312 	int error;
313 
314 	switch (vp->v_type) {
315 
316 	case VREG:
317 	case VDIR:
318 		if (com == FIONREAD) {
319 			if (error = VOP_GETATTR(vp, &vattr, u.u_cred))
320 				return (error);
321 			*(off_t *)data = vattr.va_size - fp->f_offset;
322 			return (0);
323 		}
324 		if (com == FIONBIO || com == FIOASYNC)	/* XXX */
325 			return (0);			/* XXX */
326 		/* fall into ... */
327 
328 	default:
329 		return (ENOTTY);
330 
331 	case VCHR:
332 	case VBLK:
333 		u.u_r.r_val1 = 0;
334 		if (setjmp(&u.u_qsave)) {
335 			if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
336 				return(EINTR);
337 			u.u_eosys = RESTARTSYS;
338 			return (0);
339 		}
340 		error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred);
341 		if (error == 0 && com == TIOCSCTTY) {
342 			u.u_procp->p_session->s_ttyvp = vp;
343 			VREF(vp);
344 		}
345 		return (error);
346 	}
347 }
348 
349 /*
350  * Vnode select call
351  */
352 vn_select(fp, which)
353 	struct file *fp;
354 	int which;
355 {
356 	return(VOP_SELECT(((struct vnode *)fp->f_data), which, u.u_cred));
357 }
358 
359 /*
360  * Vnode close call
361  */
362 vn_close(fp)
363 	register struct file *fp;
364 {
365 	struct vnode *vp = ((struct vnode *)fp->f_data);
366 	int error;
367 
368 	if (fp->f_flag & (FSHLOCK|FEXLOCK))
369 		vn_unlock(fp, FSHLOCK|FEXLOCK);
370 	/*
371 	 * Must delete vnode reference from this file entry
372 	 * before VOP_CLOSE, so that only other references
373 	 * will prevent close.
374 	 */
375 	fp->f_data = (caddr_t) 0;
376 	error = VOP_CLOSE(vp, fp->f_flag, u.u_cred);
377 	vrele(vp);
378 	return (error);
379 }
380 
381 /*
382  * Place an advisory lock on a vnode.
383  * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries
384  */
385 vn_lock(fp, cmd)
386 	register struct file *fp;
387 	int cmd;
388 {
389 	register int priority = PLOCK;
390 	register struct vnode *vp = (struct vnode *)fp->f_data;
391 
392 	if ((cmd & LOCK_EX) == 0)
393 		priority += 4;
394 	if (setjmp(&u.u_qsave)) {
395 		if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
396 			return(EINTR);
397 		u.u_eosys = RESTARTSYS;
398 		return (0);
399 	}
400 	/*
401 	 * If there's a exclusive lock currently applied
402 	 * to the file, then we've gotta wait for the
403 	 * lock with everyone else.
404 	 */
405 again:
406 	while (vp->v_flag & VEXLOCK) {
407 		/*
408 		 * If we're holding an exclusive
409 		 * lock, then release it.
410 		 */
411 		if (fp->f_flag & FEXLOCK) {
412 			vn_unlock(fp, FEXLOCK);
413 			continue;
414 		}
415 		if (cmd & LOCK_NB)
416 			return (EWOULDBLOCK);
417 		vp->v_flag |= VLWAIT;
418 		sleep((caddr_t)&vp->v_exlockc, priority);
419 	}
420 	if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) {
421 		/*
422 		 * Must wait for any shared locks to finish
423 		 * before we try to apply a exclusive lock.
424 		 *
425 		 * If we're holding a shared
426 		 * lock, then release it.
427 		 */
428 		if (fp->f_flag & FSHLOCK) {
429 			vn_unlock(fp, FSHLOCK);
430 			goto again;
431 		}
432 		if (cmd & LOCK_NB)
433 			return (EWOULDBLOCK);
434 		vp->v_flag |= VLWAIT;
435 		sleep((caddr_t)&vp->v_shlockc, PLOCK);
436 		goto again;
437 	}
438 	if (fp->f_flag & FEXLOCK)
439 		panic("vn_lock");
440 	if (cmd & LOCK_EX) {
441 		cmd &= ~LOCK_SH;
442 		vp->v_exlockc++;
443 		vp->v_flag |= VEXLOCK;
444 		fp->f_flag |= FEXLOCK;
445 	}
446 	if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
447 		vp->v_shlockc++;
448 		vp->v_flag |= VSHLOCK;
449 		fp->f_flag |= FSHLOCK;
450 	}
451 	return (0);
452 }
453 
454 /*
455  * Unlock a file.
456  */
457 vn_unlock(fp, kind)
458 	register struct file *fp;
459 	int kind;
460 {
461 	register struct vnode *vp = (struct vnode *)fp->f_data;
462 	int flags;
463 
464 	kind &= fp->f_flag;
465 	if (vp == NULL || kind == 0)
466 		return;
467 	flags = vp->v_flag;
468 	if (kind & FSHLOCK) {
469 		if ((flags & VSHLOCK) == 0)
470 			panic("vn_unlock: SHLOCK");
471 		if (--vp->v_shlockc == 0) {
472 			vp->v_flag &= ~VSHLOCK;
473 			if (flags & VLWAIT)
474 				wakeup((caddr_t)&vp->v_shlockc);
475 		}
476 		fp->f_flag &= ~FSHLOCK;
477 	}
478 	if (kind & FEXLOCK) {
479 		if ((flags & VEXLOCK) == 0)
480 			panic("vn_unlock: EXLOCK");
481 		if (--vp->v_exlockc == 0) {
482 			vp->v_flag &= ~(VEXLOCK|VLWAIT);
483 			if (flags & VLWAIT)
484 				wakeup((caddr_t)&vp->v_exlockc);
485 		}
486 		fp->f_flag &= ~FEXLOCK;
487 	}
488 }
489 
490 /*
491  * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
492  * 	- look up fsid in mount list (if not found ret error)
493  *	- get vp by calling VFS_FHTOVP() macro
494  *	- if lockflag lock it with VOP_LOCK()
495  */
496 vn_fhtovp(fhp, lockflag, vpp)
497 	fhandle_t *fhp;
498 	int lockflag;
499 	struct vnode **vpp;
500 {
501 	register struct mount *mp;
502 
503 	if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
504 		return (ESTALE);
505 	if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
506 		return (ESTALE);
507 	if (!lockflag)
508 		VOP_UNLOCK(*vpp);
509 	return (0);
510 }
511 
512 /*
513  * Noop
514  */
515 vfs_noop()
516 {
517 
518 	return (ENXIO);
519 }
520 
521 /*
522  * Null op
523  */
524 vfs_nullop()
525 {
526 
527 	return (0);
528 }
529