xref: /freebsd/sys/kern/vfs_vnops.c (revision 05c7a37afb48ddd5ee1bd921a5d46fe59cc70b15)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)vfs_vnops.c	8.2 (Berkeley) 1/21/94
39  * $Id: vfs_vnops.c,v 1.24 1996/03/02 03:45:05 dyson Exp $
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/file.h>
46 #include <sys/stat.h>
47 #include <sys/buf.h>
48 #include <sys/proc.h>
49 #include <sys/mount.h>
50 #include <sys/namei.h>
51 #include <sys/vnode.h>
52 #include <sys/ioctl.h>
53 
54 #include <vm/vm.h>
55 #include <vm/vm_param.h>
56 #include <vm/vm_object.h>
57 #include <vm/vnode_pager.h>
58 
59 static int vn_closefile __P((struct file *fp, struct proc *p));
60 static int vn_ioctl __P((struct file *fp, int com, caddr_t data,
61 		struct proc *p));
62 static int vn_read __P((struct file *fp, struct uio *uio,
63 		struct ucred *cred));
64 static int vn_select __P((struct file *fp, int which, struct proc *p));
65 static int vn_write __P((struct file *fp, struct uio *uio,
66 		struct ucred *cred));
67 
68 struct 	fileops vnops =
69 	{ vn_read, vn_write, vn_ioctl, vn_select, vn_closefile };
70 
71 /*
72  * Common code for vnode open operations.
73  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
74  */
75 int
76 vn_open(ndp, fmode, cmode)
77 	register struct nameidata *ndp;
78 	int fmode, cmode;
79 {
80 	register struct vnode *vp;
81 	register struct proc *p = ndp->ni_cnd.cn_proc;
82 	register struct ucred *cred = p->p_ucred;
83 	struct vattr vat;
84 	struct vattr *vap = &vat;
85 	int error;
86 
87 	if (fmode & O_CREAT) {
88 		ndp->ni_cnd.cn_nameiop = CREATE;
89 		ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
90 		if ((fmode & O_EXCL) == 0)
91 			ndp->ni_cnd.cn_flags |= FOLLOW;
92 		error = namei(ndp);
93 		if (error)
94 			return (error);
95 		if (ndp->ni_vp == NULL) {
96 			VATTR_NULL(vap);
97 			vap->va_type = VREG;
98 			vap->va_mode = cmode;
99 			LEASE_CHECK(ndp->ni_dvp, p, cred, LEASE_WRITE);
100 			error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
101 			    &ndp->ni_cnd, vap);
102 			if (error)
103 				return (error);
104 			fmode &= ~O_TRUNC;
105 			vp = ndp->ni_vp;
106 		} else {
107 			VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
108 			if (ndp->ni_dvp == ndp->ni_vp)
109 				vrele(ndp->ni_dvp);
110 			else
111 				vput(ndp->ni_dvp);
112 			ndp->ni_dvp = NULL;
113 			vp = ndp->ni_vp;
114 			if (fmode & O_EXCL) {
115 				error = EEXIST;
116 				goto bad;
117 			}
118 			fmode &= ~O_CREAT;
119 		}
120 	} else {
121 		ndp->ni_cnd.cn_nameiop = LOOKUP;
122 		ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF;
123 		error = namei(ndp);
124 		if (error)
125 			return (error);
126 		vp = ndp->ni_vp;
127 	}
128 	if (vp->v_type == VSOCK) {
129 		error = EOPNOTSUPP;
130 		goto bad;
131 	}
132 	if ((fmode & O_CREAT) == 0) {
133 		if (fmode & FREAD) {
134 			error = VOP_ACCESS(vp, VREAD, cred, p);
135 			if (error)
136 				goto bad;
137 		}
138 		if (fmode & (FWRITE | O_TRUNC)) {
139 			if (vp->v_type == VDIR) {
140 				error = EISDIR;
141 				goto bad;
142 			}
143 			error = vn_writechk(vp);
144 			if (error)
145 				goto bad;
146 		        error = VOP_ACCESS(vp, VWRITE, cred, p);
147 			if (error)
148 				goto bad;
149 		}
150 	}
151 	if (fmode & O_TRUNC) {
152 		VOP_UNLOCK(vp);				/* XXX */
153 		LEASE_CHECK(vp, p, cred, LEASE_WRITE);
154 		VOP_LOCK(vp);				/* XXX */
155 		VATTR_NULL(vap);
156 		vap->va_size = 0;
157 		error = VOP_SETATTR(vp, vap, cred, p);
158 		if (error)
159 			goto bad;
160 	}
161 	error = VOP_OPEN(vp, fmode, cred, p);
162 	if (error)
163 		goto bad;
164 	/*
165 	 * this is here for VMIO support
166 	 */
167 	if (vp->v_type == VREG) {
168 		if ((error = vn_vmio_open(vp, p, cred)) != 0)
169 			goto bad;
170 	}
171 	if (fmode & FWRITE)
172 		vp->v_writecount++;
173 	return (0);
174 bad:
175 	vput(vp);
176 	return (error);
177 }
178 
179 /*
180  * Check for write permissions on the specified vnode.
181  * The read-only status of the file system is checked.
182  * Also, prototype text segments cannot be written.
183  */
184 int
185 vn_writechk(vp)
186 	register struct vnode *vp;
187 {
188 
189 	/*
190 	 * If there's shared text associated with
191 	 * the vnode, try to free it up once.  If
192 	 * we fail, we can't allow writing.
193 	 */
194 	if (vp->v_flag & VTEXT)
195 		return (ETXTBSY);
196 	return (0);
197 }
198 
199 /*
200  * Vnode close call
201  */
202 int
203 vn_close(vp, flags, cred, p)
204 	register struct vnode *vp;
205 	int flags;
206 	struct ucred *cred;
207 	struct proc *p;
208 {
209 	int error;
210 
211 	if (flags & FWRITE)
212 		vp->v_writecount--;
213 	error = VOP_CLOSE(vp, flags, cred, p);
214 	vn_vmio_close(vp);
215 	return (error);
216 }
217 
218 /*
219  * Package up an I/O request on a vnode into a uio and do it.
220  */
221 int
222 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
223 	enum uio_rw rw;
224 	struct vnode *vp;
225 	caddr_t base;
226 	int len;
227 	off_t offset;
228 	enum uio_seg segflg;
229 	int ioflg;
230 	struct ucred *cred;
231 	int *aresid;
232 	struct proc *p;
233 {
234 	struct uio auio;
235 	struct iovec aiov;
236 	int error;
237 
238 	if ((ioflg & IO_NODELOCKED) == 0)
239 		VOP_LOCK(vp);
240 	auio.uio_iov = &aiov;
241 	auio.uio_iovcnt = 1;
242 	aiov.iov_base = base;
243 	aiov.iov_len = len;
244 	auio.uio_resid = len;
245 	auio.uio_offset = offset;
246 	auio.uio_segflg = segflg;
247 	auio.uio_rw = rw;
248 	auio.uio_procp = p;
249 	if (rw == UIO_READ) {
250 		error = VOP_READ(vp, &auio, ioflg, cred);
251 	} else {
252 		error = VOP_WRITE(vp, &auio, ioflg, cred);
253 	}
254 	if (aresid)
255 		*aresid = auio.uio_resid;
256 	else
257 		if (auio.uio_resid && error == 0)
258 			error = EIO;
259 	if ((ioflg & IO_NODELOCKED) == 0)
260 		VOP_UNLOCK(vp);
261 	return (error);
262 }
263 
264 /*
265  * File table vnode read routine.
266  */
267 static int
268 vn_read(fp, uio, cred)
269 	struct file *fp;
270 	struct uio *uio;
271 	struct ucred *cred;
272 {
273 	register struct vnode *vp = (struct vnode *)fp->f_data;
274 	int count, error;
275 
276 	LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_READ);
277 	VOP_LOCK(vp);
278 	uio->uio_offset = fp->f_offset;
279 	count = uio->uio_resid;
280 	error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
281 		cred);
282 	fp->f_offset += count - uio->uio_resid;
283 	VOP_UNLOCK(vp);
284 	return (error);
285 }
286 
287 /*
288  * File table vnode write routine.
289  */
290 static int
291 vn_write(fp, uio, cred)
292 	struct file *fp;
293 	struct uio *uio;
294 	struct ucred *cred;
295 {
296 	register struct vnode *vp = (struct vnode *)fp->f_data;
297 	int count, error, ioflag = 0;
298 
299 	if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
300 		ioflag |= IO_APPEND;
301 	if (fp->f_flag & FNONBLOCK)
302 		ioflag |= IO_NDELAY;
303 	LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_WRITE);
304 	VOP_LOCK(vp);
305 	uio->uio_offset = fp->f_offset;
306 	count = uio->uio_resid;
307 	error = VOP_WRITE(vp, uio, ioflag, cred);
308 	if (ioflag & IO_APPEND)
309 		fp->f_offset = uio->uio_offset;
310 	else
311 		fp->f_offset += count - uio->uio_resid;
312 	VOP_UNLOCK(vp);
313 	return (error);
314 }
315 
316 /*
317  * File table vnode stat routine.
318  */
319 int
320 vn_stat(vp, sb, p)
321 	struct vnode *vp;
322 	register struct stat *sb;
323 	struct proc *p;
324 {
325 	struct vattr vattr;
326 	register struct vattr *vap;
327 	int error;
328 	u_short mode;
329 
330 	vap = &vattr;
331 	error = VOP_GETATTR(vp, vap, p->p_ucred, p);
332 	if (error)
333 		return (error);
334 	/*
335 	 * Copy from vattr table
336 	 */
337 	sb->st_dev = vap->va_fsid;
338 	sb->st_ino = vap->va_fileid;
339 	mode = vap->va_mode;
340 	switch (vp->v_type) {
341 	case VREG:
342 		mode |= S_IFREG;
343 		break;
344 	case VDIR:
345 		mode |= S_IFDIR;
346 		break;
347 	case VBLK:
348 		mode |= S_IFBLK;
349 		break;
350 	case VCHR:
351 		mode |= S_IFCHR;
352 		break;
353 	case VLNK:
354 		mode |= S_IFLNK;
355 		break;
356 	case VSOCK:
357 		mode |= S_IFSOCK;
358 		break;
359 	case VFIFO:
360 		mode |= S_IFIFO;
361 		break;
362 	default:
363 		return (EBADF);
364 	};
365 	sb->st_mode = mode;
366 	sb->st_nlink = vap->va_nlink;
367 	sb->st_uid = vap->va_uid;
368 	sb->st_gid = vap->va_gid;
369 	sb->st_rdev = vap->va_rdev;
370 	sb->st_size = vap->va_size;
371 	sb->st_atimespec = vap->va_atime;
372 	sb->st_mtimespec= vap->va_mtime;
373 	sb->st_ctimespec = vap->va_ctime;
374 	sb->st_blksize = vap->va_blocksize;
375 	sb->st_flags = vap->va_flags;
376 	sb->st_gen = vap->va_gen;
377 #if (S_BLKSIZE == 512)
378 	/* Optimize this case */
379 	sb->st_blocks = vap->va_bytes >> 9;
380 #else
381 	sb->st_blocks = vap->va_bytes / S_BLKSIZE;
382 #endif
383 	return (0);
384 }
385 
386 /*
387  * File table vnode ioctl routine.
388  */
389 static int
390 vn_ioctl(fp, com, data, p)
391 	struct file *fp;
392 	int com;
393 	caddr_t data;
394 	struct proc *p;
395 {
396 	register struct vnode *vp = ((struct vnode *)fp->f_data);
397 	struct vattr vattr;
398 	int error;
399 
400 	switch (vp->v_type) {
401 
402 	case VREG:
403 	case VDIR:
404 		if (com == FIONREAD) {
405 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
406 			if (error)
407 				return (error);
408 			*(int *)data = vattr.va_size - fp->f_offset;
409 			return (0);
410 		}
411 		if (com == FIONBIO || com == FIOASYNC)	/* XXX */
412 			return (0);			/* XXX */
413 		/* fall into ... */
414 
415 	default:
416 		return (ENOTTY);
417 
418 	case VFIFO:
419 	case VCHR:
420 	case VBLK:
421 		error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
422 		if (error == 0 && com == TIOCSCTTY) {
423 
424 			/* Do nothing if reassigning same control tty */
425 			if (p->p_session->s_ttyvp == vp)
426 				return (0);
427 
428 			/* Get rid of reference to old control tty */
429 			if (p->p_session->s_ttyvp)
430 				vrele(p->p_session->s_ttyvp);
431 
432 			p->p_session->s_ttyvp = vp;
433 			VREF(vp);
434 		}
435 		return (error);
436 	}
437 }
438 
439 /*
440  * File table vnode select routine.
441  */
442 static int
443 vn_select(fp, which, p)
444 	struct file *fp;
445 	int which;
446 	struct proc *p;
447 {
448 
449 	return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
450 		fp->f_cred, p));
451 }
452 
453 /*
454  * File table vnode close routine.
455  */
456 static int
457 vn_closefile(fp, p)
458 	struct file *fp;
459 	struct proc *p;
460 {
461 
462 	return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
463 		fp->f_cred, p));
464 }
465 
466 int
467 vn_vmio_open(vp, p, cred)
468 	struct vnode *vp;
469 	struct proc *p;
470 	struct ucred *cred;
471 {
472 	struct vattr vat;
473 	int error;
474 	/*
475 	 * this is here for VMIO support
476 	 */
477 	if (vp->v_type == VREG || vp->v_type == VBLK) {
478 retry:
479 		if ((vp->v_flag & VVMIO) == 0) {
480 			if ((error = VOP_GETATTR(vp, &vat, cred, p)) != 0)
481 				return error;
482 			(void) vnode_pager_alloc(vp, OFF_TO_IDX(round_page(vat.va_size)), 0, 0);
483 			vp->v_flag |= VVMIO;
484 		} else {
485 			vm_object_t object;
486 			if ((object = vp->v_object) &&
487 				(object->flags & OBJ_DEAD)) {
488 				VOP_UNLOCK(vp);
489 				tsleep(object, PVM, "vodead", 0);
490 				VOP_LOCK(vp);
491 				goto retry;
492 			}
493 			if (!object)
494 				panic("vn_open: VMIO object missing");
495 			vm_object_reference(object);
496 		}
497 	}
498 	return 0;
499 }
500 
501 void
502 vn_vmio_close(vp)
503 	struct vnode *vp;
504 {
505 	/*
506 	 * this code is here for VMIO support, will eventually
507 	 * be in vfs code.
508 	 */
509 	if (vp->v_flag & VVMIO) {
510 		vrele(vp);
511 		if (vp->v_object == NULL)
512 			panic("vn_close: VMIO object missing");
513 		vm_object_deallocate(vp->v_object);
514 	} else
515 		vrele(vp);
516 }
517