FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_vnops.c
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 * $FreeBSD$
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/fcntl.h>
45 #include <sys/file.h>
46 #include <sys/stat.h>
47 #include <sys/proc.h>
48 #include <sys/mount.h>
49 #include <sys/namei.h>
50 #include <sys/vnode.h>
51 #include <sys/filio.h>
52 #include <sys/ttycom.h>
53
54 static int vn_closefile __P((struct file *fp, struct proc *p));
55 static int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
56 struct proc *p));
57 static int vn_read __P((struct file *fp, struct uio *uio,
58 struct ucred *cred, int flags));
59 static int vn_poll __P((struct file *fp, int events, struct ucred *cred,
60 struct proc *p));
61 static int vn_write __P((struct file *fp, struct uio *uio,
62 struct ucred *cred, int flags));
63
64 struct fileops vnops =
65 { vn_read, vn_write, vn_ioctl, vn_poll, vn_closefile };
66
67 /*
68 * Common code for vnode open operations.
69 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
70 */
71 int
72 vn_open(ndp, fmode, cmode)
73 register struct nameidata *ndp;
74 int fmode, cmode;
75 {
76 register struct vnode *vp;
77 register struct proc *p = ndp->ni_cnd.cn_proc;
78 register struct ucred *cred = p->p_ucred;
79 struct vattr vat;
80 struct vattr *vap = &vat;
81 int mode, error;
82
83 if (fmode & O_CREAT) {
84 ndp->ni_cnd.cn_nameiop = CREATE;
85 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
86 if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
87 ndp->ni_cnd.cn_flags |= FOLLOW;
88 error = namei(ndp);
89 if (error)
90 return (error);
91 if (ndp->ni_vp == NULL) {
92 VATTR_NULL(vap);
93 vap->va_type = VREG;
94 vap->va_mode = cmode;
95 if (fmode & O_EXCL)
96 vap->va_vaflags |= VA_EXCLUSIVE;
97 VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
98 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
99 &ndp->ni_cnd, vap);
100 vput(ndp->ni_dvp);
101 if (error)
102 return (error);
103 ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "create");
104 ASSERT_VOP_LOCKED(ndp->ni_vp, "create");
105 fmode &= ~O_TRUNC;
106 vp = ndp->ni_vp;
107 } else {
108 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
109 if (ndp->ni_dvp == ndp->ni_vp)
110 vrele(ndp->ni_dvp);
111 else
112 vput(ndp->ni_dvp);
113 ndp->ni_dvp = NULL;
114 vp = ndp->ni_vp;
115 if (fmode & O_EXCL) {
116 error = EEXIST;
117 goto bad;
118 }
119 fmode &= ~O_CREAT;
120 }
121 } else {
122 ndp->ni_cnd.cn_nameiop = LOOKUP;
123 ndp->ni_cnd.cn_flags =
124 ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF;
125 error = namei(ndp);
126 if (error)
127 return (error);
128 vp = ndp->ni_vp;
129 }
130 if (vp->v_type == VLNK) {
131 error = EMLINK;
132 goto bad;
133 }
134 if (vp->v_type == VSOCK) {
135 error = EOPNOTSUPP;
136 goto bad;
137 }
138 if ((fmode & O_CREAT) == 0) {
139 mode = 0;
140 if (fmode & (FWRITE | O_TRUNC)) {
141 if (vp->v_type == VDIR) {
142 error = EISDIR;
143 goto bad;
144 }
145 error = vn_writechk(vp);
146 if (error)
147 goto bad;
148 mode |= VWRITE;
149 }
150 if (fmode & FREAD)
151 mode |= VREAD;
152 if (mode) {
153 error = VOP_ACCESS(vp, mode, cred, p);
154 if (error)
155 goto bad;
156 }
157 }
158 if (fmode & O_TRUNC) {
159 VOP_UNLOCK(vp, 0, p); /* XXX */
160 VOP_LEASE(vp, p, cred, LEASE_WRITE);
161 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
162 VATTR_NULL(vap);
163 vap->va_size = 0;
164 error = VOP_SETATTR(vp, vap, cred, p);
165 if (error)
166 goto bad;
167 }
168 error = VOP_OPEN(vp, fmode, cred, p);
169 if (error)
170 goto bad;
171 /*
172 * Make sure that a VM object is created for VMIO support.
173 */
174 if (vp->v_type == VREG) {
175 if ((error = vfs_object_create(vp, p, cred)) != 0)
176 goto bad;
177 }
178
179 if (fmode & FWRITE)
180 vp->v_writecount++;
181 return (0);
182 bad:
183 vput(vp);
184 return (error);
185 }
186
187 /*
188 * Check for write permissions on the specified vnode.
189 * Prototype text segments cannot be written.
190 */
191 int
192 vn_writechk(vp)
193 register struct vnode *vp;
194 {
195
196 /*
197 * If there's shared text associated with
198 * the vnode, try to free it up once. If
199 * we fail, we can't allow writing.
200 */
201 if (vp->v_flag & VTEXT)
202 return (ETXTBSY);
203 return (0);
204 }
205
206 /*
207 * Vnode close call
208 */
209 int
210 vn_close(vp, flags, cred, p)
211 register struct vnode *vp;
212 int flags;
213 struct ucred *cred;
214 struct proc *p;
215 {
216 int error;
217
218 if (flags & FWRITE)
219 vp->v_writecount--;
220 error = VOP_CLOSE(vp, flags, cred, p);
221 vrele(vp);
222 return (error);
223 }
224
225 /*
226 * Package up an I/O request on a vnode into a uio and do it.
227 */
228 int
229 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
230 enum uio_rw rw;
231 struct vnode *vp;
232 caddr_t base;
233 int len;
234 off_t offset;
235 enum uio_seg segflg;
236 int ioflg;
237 struct ucred *cred;
238 int *aresid;
239 struct proc *p;
240 {
241 struct uio auio;
242 struct iovec aiov;
243 int error;
244
245 if ((ioflg & IO_NODELOCKED) == 0)
246 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
247 auio.uio_iov = &aiov;
248 auio.uio_iovcnt = 1;
249 aiov.iov_base = base;
250 aiov.iov_len = len;
251 auio.uio_resid = len;
252 auio.uio_offset = offset;
253 auio.uio_segflg = segflg;
254 auio.uio_rw = rw;
255 auio.uio_procp = p;
256 if (rw == UIO_READ) {
257 error = VOP_READ(vp, &auio, ioflg, cred);
258 } else {
259 error = VOP_WRITE(vp, &auio, ioflg, cred);
260 }
261 if (aresid)
262 *aresid = auio.uio_resid;
263 else
264 if (auio.uio_resid && error == 0)
265 error = EIO;
266 if ((ioflg & IO_NODELOCKED) == 0)
267 VOP_UNLOCK(vp, 0, p);
268 return (error);
269 }
270
271 /*
272 * File table vnode read routine.
273 */
274 static int
275 vn_read(fp, uio, cred, flags)
276 struct file *fp;
277 struct uio *uio;
278 struct ucred *cred;
279 int flags;
280 {
281 struct vnode *vp = (struct vnode *)fp->f_data;
282 struct proc *p = uio->uio_procp;
283 int error, ioflag;
284
285 ioflag = 0;
286 if (fp->f_flag & FNONBLOCK)
287 ioflag |= IO_NDELAY;
288 VOP_LEASE(vp, p, cred, LEASE_READ);
289 vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, p);
290 if ((flags & FOF_OFFSET) == 0)
291 uio->uio_offset = fp->f_offset;
292
293 /*
294 * Sequential read heuristic.
295 * If we have been doing sequential input,
296 * a rewind operation doesn't turn off
297 * sequential input mode.
298 */
299 if ((uio->uio_offset == 0 && fp->f_seqcount > 0) ||
300 uio->uio_offset == fp->f_nextread) {
301 int tmpseq = fp->f_seqcount;
302 /*
303 * XXX we assume that the filesystem block size is
304 * the default. Not true, but still gives us a pretty
305 * good indicator of how sequential the read operations
306 * are.
307 */
308 tmpseq += (uio->uio_resid + BKVASIZE - 1) / BKVASIZE;
309 if (tmpseq >= 127)
310 tmpseq = 127;
311 fp->f_seqcount = tmpseq;
312 ioflag |= fp->f_seqcount << 16;
313 } else {
314 if (fp->f_seqcount > 1)
315 fp->f_seqcount = 1;
316 else
317 fp->f_seqcount = 0;
318 }
319 error = VOP_READ(vp, uio, ioflag, cred);
320 if ((flags & FOF_OFFSET) == 0)
321 fp->f_offset = uio->uio_offset;
322 fp->f_nextread = uio->uio_offset;
323 VOP_UNLOCK(vp, 0, p);
324 return (error);
325 }
326
327 /*
328 * File table vnode write routine.
329 */
330 static int
331 vn_write(fp, uio, cred, flags)
332 struct file *fp;
333 struct uio *uio;
334 struct ucred *cred;
335 int flags;
336 {
337 struct vnode *vp = (struct vnode *)fp->f_data;
338 struct proc *p = uio->uio_procp;
339 int error, ioflag;
340
341 ioflag = IO_UNIT;
342 if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
343 ioflag |= IO_APPEND;
344 if (fp->f_flag & FNONBLOCK)
345 ioflag |= IO_NDELAY;
346 if ((fp->f_flag & O_FSYNC) ||
347 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
348 ioflag |= IO_SYNC;
349 VOP_LEASE(vp, p, cred, LEASE_WRITE);
350 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
351 if ((flags & FOF_OFFSET) == 0)
352 uio->uio_offset = fp->f_offset;
353 error = VOP_WRITE(vp, uio, ioflag, cred);
354 if ((flags & FOF_OFFSET) == 0)
355 fp->f_offset = uio->uio_offset;
356 VOP_UNLOCK(vp, 0, p);
357 return (error);
358 }
359
360 /*
361 * File table vnode stat routine.
362 */
363 int
364 vn_stat(vp, sb, p)
365 struct vnode *vp;
366 register struct stat *sb;
367 struct proc *p;
368 {
369 struct vattr vattr;
370 register struct vattr *vap;
371 int error;
372 u_short mode;
373
374 vap = &vattr;
375 error = VOP_GETATTR(vp, vap, p->p_ucred, p);
376 if (error)
377 return (error);
378
379 /*
380 * Zero the spare stat fields
381 */
382 sb->st_lspare = 0;
383 sb->st_qspare[0] = 0;
384 sb->st_qspare[1] = 0;
385
386 /*
387 * Copy from vattr table
388 */
389 sb->st_dev = vap->va_fsid;
390 sb->st_ino = vap->va_fileid;
391 mode = vap->va_mode;
392 switch (vap->va_type) {
393 case VREG:
394 mode |= S_IFREG;
395 break;
396 case VDIR:
397 mode |= S_IFDIR;
398 break;
399 case VBLK:
400 mode |= S_IFBLK;
401 break;
402 case VCHR:
403 mode |= S_IFCHR;
404 break;
405 case VLNK:
406 mode |= S_IFLNK;
407 /* This is a cosmetic change, symlinks do not have a mode. */
408 if (vp->v_mount->mnt_flag & MNT_NOSYMFOLLOW)
409 sb->st_mode &= ~ACCESSPERMS; /* 0000 */
410 else
411 sb->st_mode |= ACCESSPERMS; /* 0777 */
412 break;
413 case VSOCK:
414 mode |= S_IFSOCK;
415 break;
416 case VFIFO:
417 mode |= S_IFIFO;
418 break;
419 default:
420 return (EBADF);
421 };
422 sb->st_mode = mode;
423 sb->st_nlink = vap->va_nlink;
424 sb->st_uid = vap->va_uid;
425 sb->st_gid = vap->va_gid;
426 sb->st_rdev = vap->va_rdev;
427 sb->st_size = vap->va_size;
428 sb->st_atimespec = vap->va_atime;
429 sb->st_mtimespec = vap->va_mtime;
430 sb->st_ctimespec = vap->va_ctime;
431 sb->st_blksize = vap->va_blocksize;
432 sb->st_flags = vap->va_flags;
433 if (p->p_ucred->cr_uid != 0)
434 sb->st_gen = 0;
435 else
436 sb->st_gen = vap->va_gen;
437
438 #if (S_BLKSIZE == 512)
439 /* Optimize this case */
440 sb->st_blocks = vap->va_bytes >> 9;
441 #else
442 sb->st_blocks = vap->va_bytes / S_BLKSIZE;
443 #endif
444 return (0);
445 }
446
447 /*
448 * File table vnode ioctl routine.
449 */
450 static int
451 vn_ioctl(fp, com, data, p)
452 struct file *fp;
453 u_long com;
454 caddr_t data;
455 struct proc *p;
456 {
457 register struct vnode *vp = ((struct vnode *)fp->f_data);
458 struct vattr vattr;
459 int error;
460
461 switch (vp->v_type) {
462
463 case VREG:
464 case VDIR:
465 if (com == FIONREAD) {
466 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
467 if (error)
468 return (error);
469 *(int *)data = vattr.va_size - fp->f_offset;
470 return (0);
471 }
472 if (com == FIONBIO || com == FIOASYNC) /* XXX */
473 return (0); /* XXX */
474 /* fall into ... */
475
476 default:
477 #if 0
478 return (ENOTTY);
479 #endif
480 case VFIFO:
481 case VCHR:
482 case VBLK:
483 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
484 if (error == 0 && com == TIOCSCTTY) {
485
486 /* Do nothing if reassigning same control tty */
487 if (p->p_session->s_ttyvp == vp)
488 return (0);
489
490 /* Get rid of reference to old control tty */
491 if (p->p_session->s_ttyvp)
492 vrele(p->p_session->s_ttyvp);
493
494 p->p_session->s_ttyvp = vp;
495 VREF(vp);
496 }
497 return (error);
498 }
499 }
500
501 /*
502 * File table vnode poll routine.
503 */
504 static int
505 vn_poll(fp, events, cred, p)
506 struct file *fp;
507 int events;
508 struct ucred *cred;
509 struct proc *p;
510 {
511
512 return (VOP_POLL(((struct vnode *)fp->f_data), events, cred, p));
513 }
514
515 /*
516 * Check that the vnode is still valid, and if so
517 * acquire requested lock.
518 */
519 int
520 #ifndef DEBUG_LOCKS
521 vn_lock(vp, flags, p)
522 #else
523 debug_vn_lock(vp, flags, p, filename, line)
524 #endif
525 struct vnode *vp;
526 int flags;
527 struct proc *p;
528 #ifdef DEBUG_LOCKS
529 const char *filename;
530 int line;
531 #endif
532 {
533 int error;
534
535 do {
536 if ((flags & LK_INTERLOCK) == 0)
537 simple_lock(&vp->v_interlock);
538 if (vp->v_flag & VXLOCK) {
539 vp->v_flag |= VXWANT;
540 simple_unlock(&vp->v_interlock);
541 tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
542 error = ENOENT;
543 } else {
544 #ifdef DEBUG_LOCKS
545 vp->filename = filename;
546 vp->line = line;
547 #endif
548 error = VOP_LOCK(vp,
549 flags | LK_NOPAUSE | LK_INTERLOCK, p);
550 if (error == 0)
551 return (error);
552 }
553 flags &= ~LK_INTERLOCK;
554 } while (flags & LK_RETRY);
555 return (error);
556 }
557
558 /*
559 * File table vnode close routine.
560 */
561 static int
562 vn_closefile(fp, p)
563 struct file *fp;
564 struct proc *p;
565 {
566
567 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
568 fp->f_cred, p));
569 }
Cache object: a3d8b95e73903ec9f0db89b663716c33
|