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