]> git.saurik.com Git - apple/xnu.git/blame - bsd/vfs/vfs_vnops.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_vnops.c
CommitLineData
1c79356b 1/*
55e303ae 2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26/*
27 * Copyright (c) 1982, 1986, 1989, 1993
28 * The Regents of the University of California. All rights reserved.
29 * (c) UNIX System Laboratories, Inc.
30 * All or some portions of this file are derived from material licensed
31 * to the University of California by American Telephone and Telegraph
32 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
33 * the permission of UNIX System Laboratories, Inc.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95
64 *
1c79356b
A
65 */
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/kernel.h>
70#include <sys/file.h>
71#include <sys/stat.h>
72#include <sys/buf.h>
73#include <sys/proc.h>
74#include <sys/mount.h>
75#include <sys/namei.h>
76#include <sys/vnode.h>
77#include <sys/ioctl.h>
78#include <sys/tty.h>
79#include <sys/ubc.h>
9bccf70c
A
80#include <sys/conf.h>
81#include <sys/disk.h>
82
83#include <vm/vm_kern.h>
84
85#include <miscfs/specfs/specdev.h>
86
87static int vn_closefile __P((struct file *fp, struct proc *p));
88static int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
89 struct proc *p));
90static int vn_read __P((struct file *fp, struct uio *uio,
91 struct ucred *cred, int flags, struct proc *p));
92static int vn_write __P((struct file *fp, struct uio *uio,
93 struct ucred *cred, int flags, struct proc *p));
94static int vn_select __P(( struct file *fp, int which, void * wql,
95 struct proc *p));
55e303ae
A
96static int vn_kqfilt_add __P((struct file *fp, struct knote *kn, struct proc *p));
97static int vn_kqfilt_remove __P((struct vnode *vp, uintptr_t ident, struct proc *p));
1c79356b
A
98
99struct fileops vnops =
55e303ae 100 { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile, vn_kqfilt_add };
1c79356b
A
101
102/*
103 * Common code for vnode open operations.
104 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
105 */
9bccf70c 106int
1c79356b
A
107vn_open(ndp, fmode, cmode)
108 register struct nameidata *ndp;
109 int fmode, cmode;
55e303ae
A
110{
111 return vn_open_modflags(ndp,&fmode,cmode);
112}
113
114__private_extern__ int
115vn_open_modflags(ndp, fmodep, cmode)
116 register struct nameidata *ndp;
117 int *fmodep;
118 int cmode;
1c79356b
A
119{
120 register struct vnode *vp;
121 register struct proc *p = ndp->ni_cnd.cn_proc;
122 register struct ucred *cred = p->p_ucred;
123 struct vattr vat;
124 struct vattr *vap = &vat;
125 int error;
9bccf70c 126 int didhold = 0;
55e303ae
A
127 char *nameptr;
128 int fmode = *fmodep;
1c79356b
A
129
130 if (fmode & O_CREAT) {
131 ndp->ni_cnd.cn_nameiop = CREATE;
55e303ae 132 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | AUDITVNPATH1;
1c79356b
A
133 if ((fmode & O_EXCL) == 0)
134 ndp->ni_cnd.cn_flags |= FOLLOW;
9bccf70c 135 bwillwrite();
1c79356b
A
136 if (error = namei(ndp))
137 return (error);
138 if (ndp->ni_vp == NULL) {
55e303ae
A
139 nameptr = add_name(ndp->ni_cnd.cn_nameptr,
140 ndp->ni_cnd.cn_namelen,
141 ndp->ni_cnd.cn_hash, 0);
142
1c79356b
A
143 VATTR_NULL(vap);
144 vap->va_type = VREG;
145 vap->va_mode = cmode;
146 if (fmode & O_EXCL)
147 vap->va_vaflags |= VA_EXCLUSIVE;
148 VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
149 if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
55e303ae
A
150 &ndp->ni_cnd, vap)) {
151 remove_name(nameptr);
1c79356b 152 return (error);
55e303ae 153 }
1c79356b
A
154 fmode &= ~O_TRUNC;
155 vp = ndp->ni_vp;
55e303ae
A
156
157 VNAME(vp) = nameptr;
158 if (vget(ndp->ni_dvp, 0, p) == 0) {
159 VPARENT(vp) = ndp->ni_dvp;
160 }
1c79356b
A
161 } else {
162 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
163 if (ndp->ni_dvp == ndp->ni_vp)
164 vrele(ndp->ni_dvp);
165 else
166 vput(ndp->ni_dvp);
167 ndp->ni_dvp = NULL;
168 vp = ndp->ni_vp;
169 if (fmode & O_EXCL) {
170 error = EEXIST;
171 goto bad;
172 }
173 fmode &= ~O_CREAT;
174 }
175 } else {
176 ndp->ni_cnd.cn_nameiop = LOOKUP;
55e303ae 177 ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | AUDITVNPATH1;
1c79356b
A
178 if (error = namei(ndp))
179 return (error);
180 vp = ndp->ni_vp;
181 }
182 if (vp->v_type == VSOCK) {
183 error = EOPNOTSUPP;
184 goto bad;
185 }
9bccf70c
A
186
187#if DIAGNOSTIC
188 if (UBCINFOMISSING(vp))
189 panic("vn_open: ubc_info_init");
190#endif /* DIAGNOSTIC */
191
192 if (UBCINFOEXISTS(vp) && ((didhold = ubc_hold(vp)) == 0)) {
193 error = ENOENT;
194 goto bad;
195 }
196
1c79356b
A
197 if ((fmode & O_CREAT) == 0) {
198 if (fmode & FREAD && fmode & (FWRITE | O_TRUNC)) {
199 int err = 0;
200 if (vp->v_type == VDIR)
201 err = EISDIR;
202 else
203 err = vn_writechk(vp);
204 if (err && !(error = VOP_ACCESS(vp, VREAD, cred, p)))
205 error = err;
206 if (error || (error = VOP_ACCESS(vp, VREAD|VWRITE,
207 cred, p)))
208 goto bad;
209 } else if (fmode & FREAD) {
210 if ((error = VOP_ACCESS(vp, VREAD, cred, p)))
211 goto bad;
212 } else if (fmode & (FWRITE | O_TRUNC)) {
213 if (vp->v_type == VDIR) {
214 error = EISDIR;
215 goto bad;
216 }
217 if ((error = vn_writechk(vp)) ||
218 (error = VOP_ACCESS(vp, VWRITE, cred, p)))
219 goto bad;
220 }
221 }
0b4e3aa0 222
0b4e3aa0 223 if (error = VOP_OPEN(vp, fmode, cred, p)) {
0b4e3aa0
A
224 goto bad;
225 }
226
1c79356b
A
227 if (fmode & FWRITE)
228 if (++vp->v_writecount <= 0)
229 panic("vn_open: v_writecount");
55e303ae 230 *fmodep = fmode;
1c79356b
A
231 return (0);
232bad:
9bccf70c
A
233 VOP_UNLOCK(vp, 0, p);
234 if (didhold)
235 ubc_rele(vp);
236 vrele(vp);
55e303ae 237 ndp->ni_vp = NULL;
1c79356b
A
238 return (error);
239}
240
241/*
242 * Check for write permissions on the specified vnode.
243 * Prototype text segments cannot be written.
244 */
9bccf70c 245int
1c79356b
A
246vn_writechk(vp)
247 register struct vnode *vp;
248{
249
250 /*
251 * If there's shared text associated with
252 * the vnode, try to free it up once. If
253 * we fail, we can't allow writing.
254 */
255#if 0
256 /* XXXXX Not sure we need this */
257 if (vp->v_flag & VTEXT)
258 return (ETXTBSY);
259#endif /* 0 */
260 return (0);
261}
262
263/*
264 * Vnode close call
265 */
9bccf70c 266int
1c79356b
A
267vn_close(vp, flags, cred, p)
268 register struct vnode *vp;
269 int flags;
270 struct ucred *cred;
271 struct proc *p;
272{
273 int error;
1c79356b 274
55e303ae
A
275 if (flags & FWRITE) {
276
1c79356b 277 vp->v_writecount--;
55e303ae
A
278
279 {
280 extern void notify_filemod_watchers(struct vnode *vp, struct proc *p);
281
282 notify_filemod_watchers(vp, p);
283 }
284 }
285
1c79356b
A
286 error = VOP_CLOSE(vp, flags, cred, p);
287 ubc_rele(vp);
288 vrele(vp);
289 return (error);
290}
291
292/*
293 * Package up an I/O request on a vnode into a uio and do it.
294 */
9bccf70c 295int
1c79356b
A
296vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
297 enum uio_rw rw;
298 struct vnode *vp;
299 caddr_t base;
300 int len;
301 off_t offset;
302 enum uio_seg segflg;
303 int ioflg;
304 struct ucred *cred;
305 int *aresid;
306 struct proc *p;
307{
308 struct uio auio;
309 struct iovec aiov;
310 int error=0;
311
312 /* FIXME XXX */
313 if ((ioflg & IO_NODELOCKED) == 0)
0b4e3aa0 314 (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1c79356b
A
315 auio.uio_iov = &aiov;
316 auio.uio_iovcnt = 1;
317 aiov.iov_base = base;
318 aiov.iov_len = len;
319 auio.uio_resid = len;
320 auio.uio_offset = offset;
321 auio.uio_segflg = segflg;
322 auio.uio_rw = rw;
323 auio.uio_procp = p;
324
325 if (rw == UIO_READ)
326 error = VOP_READ(vp, &auio, ioflg, cred);
327 else
328 error = VOP_WRITE(vp, &auio, ioflg, cred);
329
330 if (aresid)
331 *aresid = auio.uio_resid;
332 else
333 if (auio.uio_resid && error == 0)
334 error = EIO;
335 if ((ioflg & IO_NODELOCKED) == 0)
336 VOP_UNLOCK(vp, 0, p);
337 return (error);
338}
339
340/*
341 * File table vnode read routine.
342 */
9bccf70c
A
343static int
344vn_read(fp, uio, cred, flags, p)
1c79356b
A
345 struct file *fp;
346 struct uio *uio;
347 struct ucred *cred;
9bccf70c
A
348 int flags;
349 struct proc *p;
1c79356b 350{
9bccf70c
A
351 struct vnode *vp;
352 int error, ioflag;
1c79356b
A
353 off_t count;
354
9bccf70c
A
355 if (p != uio->uio_procp)
356 panic("vn_read: uio_procp does not match p");
357
358 vp = (struct vnode *)fp->f_data;
359 ioflag = 0;
360 if (fp->f_flag & FNONBLOCK)
361 ioflag |= IO_NDELAY;
1c79356b 362 VOP_LEASE(vp, p, cred, LEASE_READ);
9bccf70c
A
363 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
364 if (error)
365 return (error);
366 if ((flags & FOF_OFFSET) == 0)
367 uio->uio_offset = fp->f_offset;
1c79356b
A
368 count = uio->uio_resid;
369
9bccf70c
A
370 if(UBCINFOEXISTS(vp)) {
371 memory_object_t pager;
372 struct iovec *iov;
373 off_t file_off;
374 kern_return_t kr = KERN_SUCCESS;
375 kern_return_t ret = KERN_SUCCESS;
376 int count;
377
378 pager = (memory_object_t)ubc_getpager(vp);
379 file_off = uio->uio_offset;
380 iov = uio->uio_iov;
381 count = uio->uio_iovcnt;
382 while(count) {
383 kr = vm_conflict_check(current_map(),
384 (vm_offset_t)iov->iov_base, iov->iov_len,
385 pager, file_off);
386 if(kr == KERN_ALREADY_WAITING) {
387 if((count != uio->uio_iovcnt) &&
388 (ret != KERN_ALREADY_WAITING)) {
389 error = EINVAL;
390 goto done;
391 }
392 ret = KERN_ALREADY_WAITING;
393 } else if (kr != KERN_SUCCESS) {
394 error = EINVAL;
395 goto done;
396 }
397 if(kr != ret) {
398 error = EINVAL;
399 goto done;
400 }
401 file_off += iov->iov_len;
402 iov++;
403 count--;
404 }
405 if(ret == KERN_ALREADY_WAITING) {
406 uio->uio_resid = 0;
407 if ((flags & FOF_OFFSET) == 0)
408 fp->f_offset +=
409 count - uio->uio_resid;
410 error = 0;
411 goto done;
412 }
413 }
414 error = VOP_READ(vp, uio, ioflag, cred);
415 if ((flags & FOF_OFFSET) == 0)
416 fp->f_offset += count - uio->uio_resid;
417done:
1c79356b
A
418 VOP_UNLOCK(vp, 0, p);
419 return (error);
420}
421
422
423/*
424 * File table vnode write routine.
425 */
9bccf70c
A
426static int
427vn_write(fp, uio, cred, flags, p)
1c79356b
A
428 struct file *fp;
429 struct uio *uio;
430 struct ucred *cred;
9bccf70c
A
431 int flags;
432 struct proc *p;
1c79356b 433{
9bccf70c
A
434 struct vnode *vp;
435 int error, ioflag;
1c79356b
A
436 off_t count;
437
9bccf70c
A
438 if (p != uio->uio_procp)
439 panic("vn_write: uio_procp does not match p");
440
441 vp = (struct vnode *)fp->f_data;
442 ioflag = IO_UNIT;
443 if (vp->v_type == VREG)
444 bwillwrite();
1c79356b
A
445 if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
446 ioflag |= IO_APPEND;
447 if (fp->f_flag & FNONBLOCK)
448 ioflag |= IO_NDELAY;
449 if ((fp->f_flag & O_FSYNC) ||
450 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
451 ioflag |= IO_SYNC;
452 VOP_LEASE(vp, p, cred, LEASE_WRITE);
9bccf70c
A
453 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
454 if (error)
455 return (error);
456 if ((flags & FOF_OFFSET) == 0) {
457 uio->uio_offset = fp->f_offset;
458 count = uio->uio_resid;
459 }
1c79356b 460
9bccf70c
A
461 if(UBCINFOEXISTS(vp)) {
462 memory_object_t pager;
463 struct iovec *iov;
464 off_t file_off;
465 kern_return_t kr = KERN_SUCCESS;
466 kern_return_t ret = KERN_SUCCESS;
467 int count;
468
469 pager = (memory_object_t)ubc_getpager(vp);
470 file_off = uio->uio_offset;
471 iov = uio->uio_iov;
472 count = uio->uio_iovcnt;
473 while(count) {
474 kr = vm_conflict_check(current_map(),
475 (vm_offset_t)iov->iov_base,
476 iov->iov_len, pager, file_off);
477 if(kr == KERN_ALREADY_WAITING) {
478 if((count != uio->uio_iovcnt) &&
479 (ret != KERN_ALREADY_WAITING)) {
480 error = EINVAL;
481 goto done;
482 }
483 ret = KERN_ALREADY_WAITING;
484 } else if (kr != KERN_SUCCESS) {
485 error = EINVAL;
486 goto done;
487 }
488 if(kr != ret) {
489 error = EINVAL;
490 goto done;
491 }
492 file_off += iov->iov_len;
493 iov++;
494 count--;
495 }
496 if(ret == KERN_ALREADY_WAITING) {
497 uio->uio_resid = 0;
498 if ((flags & FOF_OFFSET) == 0)
499 fp->f_offset +=
500 count - uio->uio_resid;
501 error = 0;
502 goto done;
503 }
504 }
1c79356b
A
505 error = VOP_WRITE(vp, uio, ioflag, cred);
506
9bccf70c
A
507 if ((flags & FOF_OFFSET) == 0) {
508 if (ioflag & IO_APPEND)
509 fp->f_offset = uio->uio_offset;
510 else
511 fp->f_offset += count - uio->uio_resid;
512 }
513
1c79356b
A
514 /*
515 * Set the credentials on successful writes
516 */
517 if ((error == 0) && (vp->v_tag == VT_NFS) && (UBCINFOEXISTS(vp))) {
518 ubc_setcred(vp, p);
519 }
520
9bccf70c 521done:
1c79356b
A
522 VOP_UNLOCK(vp, 0, p);
523 return (error);
524}
525
526/*
527 * File table vnode stat routine.
528 */
9bccf70c 529int
1c79356b
A
530vn_stat(vp, sb, p)
531 struct vnode *vp;
532 register struct stat *sb;
533 struct proc *p;
534{
535 struct vattr vattr;
536 register struct vattr *vap;
537 int error;
538 u_short mode;
539
540 vap = &vattr;
541 error = VOP_GETATTR(vp, vap, p->p_ucred, p);
542 if (error)
543 return (error);
544 /*
545 * Copy from vattr table
546 */
547 sb->st_dev = vap->va_fsid;
548 sb->st_ino = vap->va_fileid;
549 mode = vap->va_mode;
550 switch (vp->v_type) {
551 case VREG:
552 mode |= S_IFREG;
553 break;
554 case VDIR:
555 mode |= S_IFDIR;
556 break;
557 case VBLK:
558 mode |= S_IFBLK;
559 break;
560 case VCHR:
561 mode |= S_IFCHR;
562 break;
563 case VLNK:
564 mode |= S_IFLNK;
565 break;
566 case VSOCK:
567 mode |= S_IFSOCK;
568 break;
569 case VFIFO:
570 mode |= S_IFIFO;
571 break;
572 default:
573 return (EBADF);
574 };
575 sb->st_mode = mode;
576 sb->st_nlink = vap->va_nlink;
577 sb->st_uid = vap->va_uid;
578 sb->st_gid = vap->va_gid;
579 sb->st_rdev = vap->va_rdev;
580 sb->st_size = vap->va_size;
581 sb->st_atimespec = vap->va_atime;
582 sb->st_mtimespec = vap->va_mtime;
583 sb->st_ctimespec = vap->va_ctime;
584 sb->st_blksize = vap->va_blocksize;
585 sb->st_flags = vap->va_flags;
586 /* Do not give the generation number out to unpriviledged users */
55e303ae 587 if (vap->va_gen && suser(p->p_ucred, &p->p_acflag))
1c79356b
A
588 sb->st_gen = 0;
589 else
590 sb->st_gen = vap->va_gen;
591 sb->st_blocks = vap->va_bytes / S_BLKSIZE;
592 return (0);
593}
594
595/*
596 * File table vnode ioctl routine.
597 */
9bccf70c 598static int
1c79356b
A
599vn_ioctl(fp, com, data, p)
600 struct file *fp;
601 u_long com;
602 caddr_t data;
603 struct proc *p;
604{
605 register struct vnode *vp = ((struct vnode *)fp->f_data);
606 struct vattr vattr;
607 int error;
fa4905b1 608 struct vnode *ttyvp;
9bccf70c 609
1c79356b
A
610 switch (vp->v_type) {
611
612 case VREG:
613 case VDIR:
614 if (com == FIONREAD) {
615 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
616 return (error);
617 *(int *)data = vattr.va_size - fp->f_offset;
618 return (0);
619 }
620 if (com == FIONBIO || com == FIOASYNC) /* XXX */
621 return (0); /* XXX */
622 /* fall into ... */
623
624 default:
625 return (ENOTTY);
626
627 case VFIFO:
628 case VCHR:
629 case VBLK:
9bccf70c
A
630
631 /* Should not be able to set block size from user space */
632 if(com == DKIOCSETBLOCKSIZE)
633 return (EPERM);
634
635 if (com == FIODTYPE) {
636 if (vp->v_type == VBLK) {
637 if (major(vp->v_rdev) >= nblkdev)
638 return (ENXIO);
639 *(int *)data = bdevsw[major(vp->v_rdev)].d_type;
640 } else if (vp->v_type == VCHR) {
641 if (major(vp->v_rdev) >= nchrdev)
642 return (ENXIO);
643 *(int *)data = cdevsw[major(vp->v_rdev)].d_type;
644 } else {
645 return (ENOTTY);
646 }
647 return (0);
648 }
649 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
650 if (error == 0 && com == TIOCSCTTY) {
651 VREF(vp);
652 ttyvp = p->p_session->s_ttyvp;
653 p->p_session->s_ttyvp = vp;
654 if (ttyvp)
655 vrele(ttyvp);
656 }
657 return (error);
1c79356b
A
658 }
659}
660
661/*
662 * File table vnode select routine.
663 */
9bccf70c 664static int
0b4e3aa0 665vn_select(fp, which, wql, p)
1c79356b
A
666 struct file *fp;
667 int which;
0b4e3aa0 668 void * wql;
1c79356b
A
669 struct proc *p;
670{
671
0b4e3aa0
A
672 return(VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
673 fp->f_cred, wql, p));
1c79356b
A
674}
675
676/*
677 * Check that the vnode is still valid, and if so
678 * acquire requested lock.
679 */
680int
681vn_lock(vp, flags, p)
682 struct vnode *vp;
683 int flags;
684 struct proc *p;
685{
686 int error;
687
688 do {
689 if ((flags & LK_INTERLOCK) == 0)
690 simple_lock(&vp->v_interlock);
691 if (vp->v_flag & VXLOCK) {
692 while (vp->v_flag & VXLOCK) {
693 vp->v_flag |= VXWANT;
694 simple_unlock(&vp->v_interlock);
0b4e3aa0 695 (void)tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
1c79356b
A
696 }
697 error = ENOENT;
698 } else {
699 error = VOP_LOCK(vp, flags | LK_INTERLOCK, p);
700 if (error == 0)
701 return (error);
702 }
703 flags &= ~LK_INTERLOCK;
704 } while (flags & LK_RETRY);
705 return (error);
706}
707
708/*
709 * File table vnode close routine.
710 */
9bccf70c 711static int
1c79356b
A
712vn_closefile(fp, p)
713 struct file *fp;
714 struct proc *p;
715{
716
717 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
718 fp->f_cred, p));
719}
55e303ae
A
720
721static int
722vn_kqfilt_add(fp, kn, p)
723 struct file *fp;
724 struct knote *kn;
725 struct proc *p;
726{
727 struct vnode *vp = (struct vnode *)fp->f_data;
728 int error;
729
730 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
731 if (error) return (error);
732 error = VOP_KQFILT_ADD(vp, kn, p);
733 (void)VOP_UNLOCK(vp, 0, p);
734 return (error);
735}
736
737static int
738vn_kqfilt_remove(vp, ident, p)
739 struct vnode *vp;
740 uintptr_t ident;
741 struct proc *p;
742{
743 int error;
744
745 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
746 if (error) return (error);
747 error = VOP_KQFILT_REMOVE(vp, ident, p);
748 (void)VOP_UNLOCK(vp, 0, p);
749 return (error);
750}