vfs_vnops.c revision 1.75 1 /* $NetBSD: vfs_vnops.c,v 1.75 2003/10/15 11:29:01 hannken Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.75 2003/10/15 11:29:01 hannken Exp $");
41
42 #include "fs_union.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/file.h>
48 #include <sys/stat.h>
49 #include <sys/buf.h>
50 #include <sys/proc.h>
51 #include <sys/mount.h>
52 #include <sys/namei.h>
53 #include <sys/vnode.h>
54 #include <sys/ioctl.h>
55 #include <sys/tty.h>
56 #include <sys/poll.h>
57
58 #include <uvm/uvm_extern.h>
59
60 #ifdef UNION
61 #include <fs/union/union.h>
62 #endif
63
64 #if defined(LKM) || defined(UNION)
65 int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct proc *);
66 #endif
67
68 #ifdef VERIFIED_EXEC
69 #include <sys/verified_exec.h>
70
71 extern LIST_HEAD(veriexec_devhead, veriexec_dev_list) veriexec_dev_head;
72 extern struct veriexec_devhead veriexec_file_dev_head;
73 #endif
74
75 static int vn_read(struct file *fp, off_t *offset, struct uio *uio,
76 struct ucred *cred, int flags);
77 static int vn_write(struct file *fp, off_t *offset, struct uio *uio,
78 struct ucred *cred, int flags);
79 static int vn_closefile(struct file *fp, struct proc *p);
80 static int vn_poll(struct file *fp, int events, struct proc *p);
81 static int vn_fcntl(struct file *fp, u_int com, void *data, struct proc *p);
82 static int vn_statfile(struct file *fp, struct stat *sb, struct proc *p);
83 static int vn_ioctl(struct file *fp, u_long com, void *data, struct proc *p);
84
85 struct fileops vnops = {
86 vn_read, vn_write, vn_ioctl, vn_fcntl, vn_poll,
87 vn_statfile, vn_closefile, vn_kqfilter
88 };
89
90 /*
91 * Common code for vnode open operations.
92 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
93 */
94 int
95 vn_open(ndp, fmode, cmode)
96 struct nameidata *ndp;
97 int fmode, cmode;
98 {
99 struct vnode *vp;
100 struct mount *mp;
101 struct proc *p = ndp->ni_cnd.cn_proc;
102 struct ucred *cred = p->p_ucred;
103 struct vattr va;
104 int error;
105 #ifdef VERIFIED_EXEC
106 char got_dev;
107 struct veriexec_inode_list *veriexec_node;
108 char fingerprint[MAXFINGERPRINTLEN];
109 #endif
110
111 restart:
112 if (fmode & O_CREAT) {
113 ndp->ni_cnd.cn_nameiop = CREATE;
114 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
115 if ((fmode & O_EXCL) == 0 &&
116 ((fmode & O_NOFOLLOW) == 0))
117 ndp->ni_cnd.cn_flags |= FOLLOW;
118 if ((error = namei(ndp)) != 0)
119 return (error);
120 if (ndp->ni_vp == NULL) {
121 VATTR_NULL(&va);
122 va.va_type = VREG;
123 va.va_mode = cmode;
124 if (fmode & O_EXCL)
125 va.va_vaflags |= VA_EXCLUSIVE;
126 if (vn_start_write(ndp->ni_dvp, &mp, V_NOWAIT) != 0) {
127 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
128 vput(ndp->ni_dvp);
129 if ((error = vn_start_write(NULL, &mp,
130 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0)
131 return (error);
132 goto restart;
133 }
134 VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
135 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
136 &ndp->ni_cnd, &va);
137 vn_finished_write(mp, 0);
138 if (error)
139 return (error);
140 fmode &= ~O_TRUNC;
141 vp = ndp->ni_vp;
142 } else {
143 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
144 if (ndp->ni_dvp == ndp->ni_vp)
145 vrele(ndp->ni_dvp);
146 else
147 vput(ndp->ni_dvp);
148 ndp->ni_dvp = NULL;
149 vp = ndp->ni_vp;
150 if (fmode & O_EXCL) {
151 error = EEXIST;
152 goto bad;
153 }
154 fmode &= ~O_CREAT;
155 }
156 } else {
157 ndp->ni_cnd.cn_nameiop = LOOKUP;
158 ndp->ni_cnd.cn_flags = LOCKLEAF;
159 if ((fmode & O_NOFOLLOW) == 0)
160 ndp->ni_cnd.cn_flags |= FOLLOW;
161 if ((error = namei(ndp)) != 0)
162 return (error);
163 vp = ndp->ni_vp;
164 }
165 if (vp->v_type == VSOCK) {
166 error = EOPNOTSUPP;
167 goto bad;
168 }
169 if (ndp->ni_vp->v_type == VLNK) {
170 error = EFTYPE;
171 goto bad;
172 }
173
174 #ifdef VERIFIED_EXEC
175 veriexec_node = NULL;
176
177 if ((error = VOP_GETATTR(vp, &va, cred, p)) != 0)
178 goto bad;
179 #endif
180
181 if ((fmode & O_CREAT) == 0) {
182 #ifdef VERIFIED_EXEC
183 /*
184 * Look for the file on the fingerprint lists iff
185 * it has not been seen before.
186 */
187 if ((vp->fp_status == FINGERPRINT_INVALID) ||
188 (vp->fp_status == FINGERPRINT_NODEV)) {
189 /* check the file list for the finger print */
190 veriexec_node = get_veriexec_inode(&veriexec_file_dev_head,
191 va.va_fsid,
192 va.va_fileid,
193 &got_dev);
194 if (veriexec_node == NULL) {
195 /* failing that, check the exec list */
196 veriexec_node = get_veriexec_inode(
197 &veriexec_dev_head, va.va_fsid,
198 va.va_fileid, &got_dev);
199 }
200
201 if ((veriexec_node == NULL) && (got_dev == 1))
202 vp->fp_status = FINGERPRINT_NOENTRY;
203
204 if (veriexec_node != NULL) {
205 if ((error = evaluate_fingerprint(vp,
206 veriexec_node, p, va.va_size,
207 fingerprint)) != 0)
208 goto bad;
209
210 if (fingerprintcmp(veriexec_node,
211 fingerprint) == 0) {
212 /* fingerprint ok */
213 vp->fp_status = FINGERPRINT_VALID;
214 #ifdef VERIFIED_EXEC_DEBUG
215 printf(
216 "file fingerprint matches for dev %lu, file %lu\n",
217 va.va_fsid, va.va_fileid);
218 #endif
219 } else {
220 vp->fp_status = FINGERPRINT_NOMATCH;
221 }
222 }
223 }
224 #endif
225
226 if (fmode & FREAD) {
227 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
228 goto bad;
229
230 #ifdef VERIFIED_EXEC
231 /* file is on finger print list */
232 if (vp->fp_status == FINGERPRINT_NOMATCH) {
233 /* fingerprint bad */
234 printf(
235 "file fingerprint does not match on dev %lu, file %lu\n",
236 va.va_fsid, va.va_fileid);
237 if (securelevel > 2) {
238 error = EPERM;
239 goto bad;
240 }
241 }
242 #endif
243 }
244 if (fmode & (FWRITE | O_TRUNC)) {
245 if (vp->v_type == VDIR) {
246 error = EISDIR;
247 goto bad;
248 }
249 if ((error = vn_writechk(vp)) != 0 ||
250 (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
251 goto bad;
252 #ifdef VERIFIED_EXEC
253 /*
254 * If file has a fingerprint then
255 * deny the write request, otherwise
256 * invalidate the status so we don't
257 * keep checking for the file having
258 * a fingerprint.
259 */
260 if (vp->fp_status == FINGERPRINT_VALID) {
261 printf(
262 "writing to fingerprinted file for dev %lu, file %lu\n",
263 va.va_fsid, va.va_fileid);
264 if (securelevel > 2) {
265 error = EPERM;
266 goto bad;
267 } else {
268 vp->fp_status = FINGERPRINT_INVALID;
269 }
270 }
271 #endif
272 }
273 }
274 if (fmode & O_TRUNC) {
275 VOP_UNLOCK(vp, 0); /* XXX */
276 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) {
277 vput(vp);
278 return (error);
279 }
280 VOP_LEASE(vp, p, cred, LEASE_WRITE);
281 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
282 VATTR_NULL(&va);
283 va.va_size = 0;
284 error = VOP_SETATTR(vp, &va, cred, p);
285 vn_finished_write(mp, 0);
286 if (error != 0)
287 goto bad;
288 }
289 if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0)
290 goto bad;
291 if (vp->v_type == VREG &&
292 uvn_attach(vp, fmode & FWRITE ? VM_PROT_WRITE : 0) == NULL) {
293 error = EIO;
294 goto bad;
295 }
296 if (fmode & FWRITE)
297 vp->v_writecount++;
298
299 return (0);
300 bad:
301 vput(vp);
302 return (error);
303 }
304
305 /*
306 * Check for write permissions on the specified vnode.
307 * Prototype text segments cannot be written.
308 */
309 int
310 vn_writechk(vp)
311 struct vnode *vp;
312 {
313
314 /*
315 * If the vnode is in use as a process's text,
316 * we can't allow writing.
317 */
318 if (vp->v_flag & VTEXT)
319 return (ETXTBSY);
320 return (0);
321 }
322
323 /*
324 * Mark a vnode as having executable mappings.
325 */
326 void
327 vn_markexec(vp)
328 struct vnode *vp;
329 {
330 if ((vp->v_flag & VEXECMAP) == 0) {
331 uvmexp.filepages -= vp->v_uobj.uo_npages;
332 uvmexp.execpages += vp->v_uobj.uo_npages;
333 }
334 vp->v_flag |= VEXECMAP;
335 }
336
337 /*
338 * Mark a vnode as being the text of a process.
339 * Fail if the vnode is currently writable.
340 */
341 int
342 vn_marktext(vp)
343 struct vnode *vp;
344 {
345
346 if (vp->v_writecount != 0) {
347 KASSERT((vp->v_flag & VTEXT) == 0);
348 return (ETXTBSY);
349 }
350 vp->v_flag |= VTEXT;
351 vn_markexec(vp);
352 return (0);
353 }
354
355 /*
356 * Vnode close call
357 *
358 * Note: takes an unlocked vnode, while VOP_CLOSE takes a locked node.
359 */
360 int
361 vn_close(vp, flags, cred, p)
362 struct vnode *vp;
363 int flags;
364 struct ucred *cred;
365 struct proc *p;
366 {
367 int error;
368
369 if (flags & FWRITE)
370 vp->v_writecount--;
371 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
372 error = VOP_CLOSE(vp, flags, cred, p);
373 vput(vp);
374 return (error);
375 }
376
377 /*
378 * Package up an I/O request on a vnode into a uio and do it.
379 */
380 int
381 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
382 enum uio_rw rw;
383 struct vnode *vp;
384 caddr_t base;
385 int len;
386 off_t offset;
387 enum uio_seg segflg;
388 int ioflg;
389 struct ucred *cred;
390 size_t *aresid;
391 struct proc *p;
392 {
393 struct uio auio;
394 struct iovec aiov;
395 struct mount *mp;
396 int error;
397
398 if ((ioflg & IO_NODELOCKED) == 0) {
399 if (rw == UIO_READ) {
400 vn_lock(vp, LK_SHARED | LK_RETRY);
401 } else /* UIO_WRITE */ {
402 if (vp->v_type != VCHR &&
403 (error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH))
404 != 0)
405 return (error);
406 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
407 }
408 }
409 auio.uio_iov = &aiov;
410 auio.uio_iovcnt = 1;
411 aiov.iov_base = base;
412 aiov.iov_len = len;
413 auio.uio_resid = len;
414 auio.uio_offset = offset;
415 auio.uio_segflg = segflg;
416 auio.uio_rw = rw;
417 auio.uio_procp = p;
418 if (rw == UIO_READ) {
419 error = VOP_READ(vp, &auio, ioflg, cred);
420 } else {
421 error = VOP_WRITE(vp, &auio, ioflg, cred);
422 }
423 if (aresid)
424 *aresid = auio.uio_resid;
425 else
426 if (auio.uio_resid && error == 0)
427 error = EIO;
428 if ((ioflg & IO_NODELOCKED) == 0) {
429 if (rw == UIO_WRITE)
430 vn_finished_write(mp, 0);
431 VOP_UNLOCK(vp, 0);
432 }
433 return (error);
434 }
435
436 int
437 vn_readdir(fp, buf, segflg, count, done, p, cookies, ncookies)
438 struct file *fp;
439 char *buf;
440 int segflg, *done, *ncookies;
441 u_int count;
442 struct proc *p;
443 off_t **cookies;
444 {
445 struct vnode *vp = (struct vnode *)fp->f_data;
446 struct iovec aiov;
447 struct uio auio;
448 int error, eofflag;
449
450 unionread:
451 if (vp->v_type != VDIR)
452 return (EINVAL);
453 aiov.iov_base = buf;
454 aiov.iov_len = count;
455 auio.uio_iov = &aiov;
456 auio.uio_iovcnt = 1;
457 auio.uio_rw = UIO_READ;
458 auio.uio_segflg = segflg;
459 auio.uio_procp = p;
460 auio.uio_resid = count;
461 vn_lock(vp, LK_SHARED | LK_RETRY);
462 auio.uio_offset = fp->f_offset;
463 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies,
464 ncookies);
465 fp->f_offset = auio.uio_offset;
466 VOP_UNLOCK(vp, 0);
467 if (error)
468 return (error);
469
470 #if defined(UNION) || defined(LKM)
471 if (count == auio.uio_resid && vn_union_readdir_hook) {
472 struct vnode *ovp = vp;
473
474 error = (*vn_union_readdir_hook)(&vp, fp, p);
475 if (error)
476 return (error);
477 if (vp != ovp)
478 goto unionread;
479 }
480 #endif /* UNION || LKM */
481
482 if (count == auio.uio_resid && (vp->v_flag & VROOT) &&
483 (vp->v_mount->mnt_flag & MNT_UNION)) {
484 struct vnode *tvp = vp;
485 vp = vp->v_mount->mnt_vnodecovered;
486 VREF(vp);
487 fp->f_data = vp;
488 fp->f_offset = 0;
489 vrele(tvp);
490 goto unionread;
491 }
492 *done = count - auio.uio_resid;
493 return error;
494 }
495
496 /*
497 * File table vnode read routine.
498 */
499 static int
500 vn_read(fp, offset, uio, cred, flags)
501 struct file *fp;
502 off_t *offset;
503 struct uio *uio;
504 struct ucred *cred;
505 int flags;
506 {
507 struct vnode *vp = (struct vnode *)fp->f_data;
508 int count, error, ioflag = 0;
509
510 VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ);
511 if (fp->f_flag & FNONBLOCK)
512 ioflag |= IO_NDELAY;
513 if ((fp->f_flag & (FFSYNC | FRSYNC)) == (FFSYNC | FRSYNC))
514 ioflag |= IO_SYNC;
515 if (fp->f_flag & FALTIO)
516 ioflag |= IO_ALTSEMANTICS;
517 vn_lock(vp, LK_SHARED | LK_RETRY);
518 uio->uio_offset = *offset;
519 count = uio->uio_resid;
520 error = VOP_READ(vp, uio, ioflag, cred);
521 if (flags & FOF_UPDATE_OFFSET)
522 *offset += count - uio->uio_resid;
523 VOP_UNLOCK(vp, 0);
524 return (error);
525 }
526
527 /*
528 * File table vnode write routine.
529 */
530 static int
531 vn_write(fp, offset, uio, cred, flags)
532 struct file *fp;
533 off_t *offset;
534 struct uio *uio;
535 struct ucred *cred;
536 int flags;
537 {
538 struct vnode *vp = (struct vnode *)fp->f_data;
539 struct mount *mp;
540 int count, error, ioflag = IO_UNIT;
541
542 if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
543 ioflag |= IO_APPEND;
544 if (fp->f_flag & FNONBLOCK)
545 ioflag |= IO_NDELAY;
546 if (fp->f_flag & FFSYNC ||
547 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
548 ioflag |= IO_SYNC;
549 else if (fp->f_flag & FDSYNC)
550 ioflag |= IO_DSYNC;
551 if (fp->f_flag & FALTIO)
552 ioflag |= IO_ALTSEMANTICS;
553 mp = NULL;
554 if (vp->v_type != VCHR &&
555 (error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0)
556 return (error);
557 VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE);
558 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
559 uio->uio_offset = *offset;
560 count = uio->uio_resid;
561 error = VOP_WRITE(vp, uio, ioflag, cred);
562 if (flags & FOF_UPDATE_OFFSET) {
563 if (ioflag & IO_APPEND)
564 *offset = uio->uio_offset;
565 else
566 *offset += count - uio->uio_resid;
567 }
568 VOP_UNLOCK(vp, 0);
569 vn_finished_write(mp, 0);
570 return (error);
571 }
572
573 /*
574 * File table vnode stat routine.
575 */
576 static int
577 vn_statfile(fp, sb, p)
578 struct file *fp;
579 struct stat *sb;
580 struct proc *p;
581 {
582 struct vnode *vp = (struct vnode *)fp->f_data;
583
584 return vn_stat(vp, sb, p);
585 }
586
587 int
588 vn_stat(vp, sb, p)
589 struct vnode *vp;
590 struct stat *sb;
591 struct proc *p;
592 {
593 struct vattr va;
594 int error;
595 mode_t mode;
596
597 error = VOP_GETATTR(vp, &va, p->p_ucred, p);
598 if (error)
599 return (error);
600 /*
601 * Copy from vattr table
602 */
603 sb->st_dev = va.va_fsid;
604 sb->st_ino = va.va_fileid;
605 mode = va.va_mode;
606 switch (vp->v_type) {
607 case VREG:
608 mode |= S_IFREG;
609 break;
610 case VDIR:
611 mode |= S_IFDIR;
612 break;
613 case VBLK:
614 mode |= S_IFBLK;
615 break;
616 case VCHR:
617 mode |= S_IFCHR;
618 break;
619 case VLNK:
620 mode |= S_IFLNK;
621 break;
622 case VSOCK:
623 mode |= S_IFSOCK;
624 break;
625 case VFIFO:
626 mode |= S_IFIFO;
627 break;
628 default:
629 return (EBADF);
630 };
631 sb->st_mode = mode;
632 sb->st_nlink = va.va_nlink;
633 sb->st_uid = va.va_uid;
634 sb->st_gid = va.va_gid;
635 sb->st_rdev = va.va_rdev;
636 sb->st_size = va.va_size;
637 sb->st_atimespec = va.va_atime;
638 sb->st_mtimespec = va.va_mtime;
639 sb->st_ctimespec = va.va_ctime;
640 sb->st_birthtimespec = va.va_birthtime;
641 sb->st_blksize = va.va_blocksize;
642 sb->st_flags = va.va_flags;
643 sb->st_gen = 0;
644 sb->st_blocks = va.va_bytes / S_BLKSIZE;
645 return (0);
646 }
647
648 /*
649 * File table vnode fcntl routine.
650 */
651 static int
652 vn_fcntl(fp, com, data, p)
653 struct file *fp;
654 u_int com;
655 void *data;
656 struct proc *p;
657 {
658 struct vnode *vp = ((struct vnode *)fp->f_data);
659 int error;
660
661 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
662 error = VOP_FCNTL(vp, com, data, fp->f_flag, p->p_ucred, p);
663 VOP_UNLOCK(vp, 0);
664 return (error);
665 }
666
667 /*
668 * File table vnode ioctl routine.
669 */
670 static int
671 vn_ioctl(fp, com, data, p)
672 struct file *fp;
673 u_long com;
674 void *data;
675 struct proc *p;
676 {
677 struct vnode *vp = ((struct vnode *)fp->f_data);
678 struct vattr vattr;
679 int error;
680
681 switch (vp->v_type) {
682
683 case VREG:
684 case VDIR:
685 if (com == FIONREAD) {
686 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
687 if (error)
688 return (error);
689 *(int *)data = vattr.va_size - fp->f_offset;
690 return (0);
691 }
692 if (com == FIOGETBMAP) {
693 daddr_t *block;
694
695 if (*(daddr_t *)data < 0)
696 return (EINVAL);
697 block = (daddr_t *)data;
698 return (VOP_BMAP(vp, *block, NULL, block, NULL));
699 }
700 if (com == OFIOGETBMAP) {
701 daddr_t ibn, obn;
702
703 if (*(int32_t *)data < 0)
704 return (EINVAL);
705 ibn = (daddr_t)*(int32_t *)data;
706 error = VOP_BMAP(vp, ibn, NULL, &obn, NULL);
707 *(int32_t *)data = (int32_t)obn;
708 return error;
709 }
710 if (com == FIONBIO || com == FIOASYNC) /* XXX */
711 return (0); /* XXX */
712 /* fall into ... */
713 case VFIFO:
714 case VCHR:
715 case VBLK:
716 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
717 if (error == 0 && com == TIOCSCTTY) {
718 if (p->p_session->s_ttyvp)
719 vrele(p->p_session->s_ttyvp);
720 p->p_session->s_ttyvp = vp;
721 VREF(vp);
722 }
723 return (error);
724
725 default:
726 return (EPASSTHROUGH);
727 }
728 }
729
730 /*
731 * File table vnode poll routine.
732 */
733 static int
734 vn_poll(fp, events, p)
735 struct file *fp;
736 int events;
737 struct proc *p;
738 {
739
740 return (VOP_POLL(((struct vnode *)fp->f_data), events, p));
741 }
742
743 /*
744 * File table vnode kqfilter routine.
745 */
746 int
747 vn_kqfilter(fp, kn)
748 struct file *fp;
749 struct knote *kn;
750 {
751
752 return (VOP_KQFILTER((struct vnode *)fp->f_data, kn));
753 }
754
755 /*
756 * Check that the vnode is still valid, and if so
757 * acquire requested lock.
758 */
759 int
760 vn_lock(vp, flags)
761 struct vnode *vp;
762 int flags;
763 {
764 int error;
765
766 do {
767 if ((flags & LK_INTERLOCK) == 0)
768 simple_lock(&vp->v_interlock);
769 if (vp->v_flag & VXLOCK) {
770 if (flags & LK_NOWAIT) {
771 simple_unlock(&vp->v_interlock);
772 return EBUSY;
773 }
774 vp->v_flag |= VXWANT;
775 ltsleep(vp, PINOD | PNORELOCK,
776 "vn_lock", 0, &vp->v_interlock);
777 error = ENOENT;
778 } else {
779 error = VOP_LOCK(vp, flags | LK_INTERLOCK);
780 if (error == 0 || error == EDEADLK || error == EBUSY)
781 return (error);
782 }
783 flags &= ~LK_INTERLOCK;
784 } while (flags & LK_RETRY);
785 return (error);
786 }
787
788 /*
789 * File table vnode close routine.
790 */
791 static int
792 vn_closefile(fp, p)
793 struct file *fp;
794 struct proc *p;
795 {
796
797 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
798 fp->f_cred, p));
799 }
800
801 /*
802 * Enable LK_CANRECURSE on lock. Return prior status.
803 */
804 u_int
805 vn_setrecurse(vp)
806 struct vnode *vp;
807 {
808 struct lock *lkp = &vp->v_lock;
809 u_int retval = lkp->lk_flags & LK_CANRECURSE;
810
811 lkp->lk_flags |= LK_CANRECURSE;
812 return retval;
813 }
814
815 /*
816 * Called when done with locksetrecurse.
817 */
818 void
819 vn_restorerecurse(vp, flags)
820 struct vnode *vp;
821 u_int flags;
822 {
823 struct lock *lkp = &vp->v_lock;
824
825 lkp->lk_flags &= ~LK_CANRECURSE;
826 lkp->lk_flags |= flags;
827 }
828
829 /*
830 * Request a filesystem to suspend write operations.
831 */
832 int
833 vfs_write_suspend(struct mount *mp)
834 {
835 struct proc *p = curproc; /* XXX */
836 int error;
837
838 if (mp->mnt_iflag & IMNT_SUSPEND)
839 return (0);
840 mp->mnt_iflag |= IMNT_SUSPEND;
841 if (mp->mnt_writeopcountupper > 0)
842 tsleep(&mp->mnt_writeopcountupper, PUSER - 1, "suspwt", 0);
843 if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) != 0) {
844 vfs_write_resume(mp);
845 return (error);
846 }
847 mp->mnt_iflag |= IMNT_SUSPENDLOW;
848 if (mp->mnt_writeopcountlower > 0)
849 tsleep(&mp->mnt_writeopcountlower, PUSER - 1, "suspwt", 0);
850 mp->mnt_iflag |= IMNT_SUSPENDED;
851 return (0);
852 }
853
854 /*
855 * Request a filesystem to resume write operations.
856 */
857 void
858 vfs_write_resume(struct mount *mp)
859 {
860
861 if ((mp->mnt_iflag & IMNT_SUSPEND) == 0)
862 return;
863 mp->mnt_iflag &= ~(IMNT_SUSPEND | IMNT_SUSPENDLOW | IMNT_SUSPENDED);
864 wakeup(&mp->mnt_flag);
865 }
866