]> git.saurik.com Git - apple/xnu.git/blame - bsd/vfs/vfs_vnops.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_vnops.c
CommitLineData
1c79356b 1/*
9bccf70c 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
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,
d7e50217
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));
1c79356b
A
96
97struct fileops vnops =
98 { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile };
99
100/*
101 * Common code for vnode open operations.
102 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
103 */
9bccf70c 104int
1c79356b
A
105vn_open(ndp, fmode, cmode)
106 register struct nameidata *ndp;
107 int fmode, cmode;
108{
109 register struct vnode *vp;
110 register struct proc *p = ndp->ni_cnd.cn_proc;
111 register struct ucred *cred = p->p_ucred;
112 struct vattr vat;
113 struct vattr *vap = &vat;
114 int error;
9bccf70c 115 int didhold = 0;
1c79356b
A
116
117 if (fmode & O_CREAT) {
118 ndp->ni_cnd.cn_nameiop = CREATE;
119 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
120 if ((fmode & O_EXCL) == 0)
121 ndp->ni_cnd.cn_flags |= FOLLOW;
9bccf70c 122 bwillwrite();
1c79356b
A
123 if (error = namei(ndp))
124 return (error);
125 if (ndp->ni_vp == NULL) {
126 VATTR_NULL(vap);
127 vap->va_type = VREG;
128 vap->va_mode = cmode;
129 if (fmode & O_EXCL)
130 vap->va_vaflags |= VA_EXCLUSIVE;
131 VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
132 if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
133 &ndp->ni_cnd, vap))
134 return (error);
135 fmode &= ~O_TRUNC;
136 vp = ndp->ni_vp;
137 } else {
138 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
139 if (ndp->ni_dvp == ndp->ni_vp)
140 vrele(ndp->ni_dvp);
141 else
142 vput(ndp->ni_dvp);
143 ndp->ni_dvp = NULL;
144 vp = ndp->ni_vp;
145 if (fmode & O_EXCL) {
146 error = EEXIST;
147 goto bad;
148 }
149 fmode &= ~O_CREAT;
150 }
151 } else {
152 ndp->ni_cnd.cn_nameiop = LOOKUP;
153 ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF;
154 if (error = namei(ndp))
155 return (error);
156 vp = ndp->ni_vp;
157 }
158 if (vp->v_type == VSOCK) {
159 error = EOPNOTSUPP;
160 goto bad;
161 }
9bccf70c
A
162
163#if DIAGNOSTIC
164 if (UBCINFOMISSING(vp))
165 panic("vn_open: ubc_info_init");
166#endif /* DIAGNOSTIC */
167
168 if (UBCINFOEXISTS(vp) && ((didhold = ubc_hold(vp)) == 0)) {
169 error = ENOENT;
170 goto bad;
171 }
172
1c79356b
A
173 if ((fmode & O_CREAT) == 0) {
174 if (fmode & FREAD && fmode & (FWRITE | O_TRUNC)) {
175 int err = 0;
176 if (vp->v_type == VDIR)
177 err = EISDIR;
178 else
179 err = vn_writechk(vp);
180 if (err && !(error = VOP_ACCESS(vp, VREAD, cred, p)))
181 error = err;
182 if (error || (error = VOP_ACCESS(vp, VREAD|VWRITE,
183 cred, p)))
184 goto bad;
185 } else if (fmode & FREAD) {
186 if ((error = VOP_ACCESS(vp, VREAD, cred, p)))
187 goto bad;
188 } else if (fmode & (FWRITE | O_TRUNC)) {
189 if (vp->v_type == VDIR) {
190 error = EISDIR;
191 goto bad;
192 }
193 if ((error = vn_writechk(vp)) ||
194 (error = VOP_ACCESS(vp, VWRITE, cred, p)))
195 goto bad;
196 }
197 }
198 if (fmode & O_TRUNC) {
199 VOP_UNLOCK(vp, 0, p); /* XXX */
200 VOP_LEASE(vp, p, cred, LEASE_WRITE);
0b4e3aa0 201 (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
1c79356b
A
202 VATTR_NULL(vap);
203 vap->va_size = 0;
204 if (error = VOP_SETATTR(vp, vap, cred, p))
205 goto bad;
206 }
0b4e3aa0 207
0b4e3aa0 208 if (error = VOP_OPEN(vp, fmode, cred, p)) {
0b4e3aa0
A
209 goto bad;
210 }
211
1c79356b
A
212 if (fmode & FWRITE)
213 if (++vp->v_writecount <= 0)
214 panic("vn_open: v_writecount");
215 return (0);
216bad:
9bccf70c
A
217 VOP_UNLOCK(vp, 0, p);
218 if (didhold)
219 ubc_rele(vp);
220 vrele(vp);
1c79356b
A
221 return (error);
222}
223
224/*
225 * Check for write permissions on the specified vnode.
226 * Prototype text segments cannot be written.
227 */
9bccf70c 228int
1c79356b
A
229vn_writechk(vp)
230 register struct vnode *vp;
231{
232
233 /*
234 * If there's shared text associated with
235 * the vnode, try to free it up once. If
236 * we fail, we can't allow writing.
237 */
238#if 0
239 /* XXXXX Not sure we need this */
240 if (vp->v_flag & VTEXT)
241 return (ETXTBSY);
242#endif /* 0 */
243 return (0);
244}
245
246/*
247 * Vnode close call
248 */
9bccf70c 249int
1c79356b
A
250vn_close(vp, flags, cred, p)
251 register struct vnode *vp;
252 int flags;
253 struct ucred *cred;
254 struct proc *p;
255{
256 int error;
1c79356b
A
257
258 if (flags & FWRITE)
259 vp->v_writecount--;
260 error = VOP_CLOSE(vp, flags, cred, p);
261 ubc_rele(vp);
262 vrele(vp);
263 return (error);
264}
265
266/*
267 * Package up an I/O request on a vnode into a uio and do it.
268 */
9bccf70c 269int
1c79356b
A
270vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
271 enum uio_rw rw;
272 struct vnode *vp;
273 caddr_t base;
274 int len;
275 off_t offset;
276 enum uio_seg segflg;
277 int ioflg;
278 struct ucred *cred;
279 int *aresid;
280 struct proc *p;
281{
282 struct uio auio;
283 struct iovec aiov;
284 int error=0;
285
286 /* FIXME XXX */
287 if ((ioflg & IO_NODELOCKED) == 0)
0b4e3aa0 288 (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1c79356b
A
289 auio.uio_iov = &aiov;
290 auio.uio_iovcnt = 1;
291 aiov.iov_base = base;
292 aiov.iov_len = len;
293 auio.uio_resid = len;
294 auio.uio_offset = offset;
295 auio.uio_segflg = segflg;
296 auio.uio_rw = rw;
297 auio.uio_procp = p;
298
299 if (rw == UIO_READ)
300 error = VOP_READ(vp, &auio, ioflg, cred);
301 else
302 error = VOP_WRITE(vp, &auio, ioflg, cred);
303
304 if (aresid)
305 *aresid = auio.uio_resid;
306 else
307 if (auio.uio_resid && error == 0)
308 error = EIO;
309 if ((ioflg & IO_NODELOCKED) == 0)
310 VOP_UNLOCK(vp, 0, p);
311 return (error);
312}
313
314/*
315 * File table vnode read routine.
316 */
9bccf70c
A
317static int
318vn_read(fp, uio, cred, flags, p)
1c79356b
A
319 struct file *fp;
320 struct uio *uio;
321 struct ucred *cred;
9bccf70c
A
322 int flags;
323 struct proc *p;
1c79356b 324{
9bccf70c
A
325 struct vnode *vp;
326 int error, ioflag;
1c79356b
A
327 off_t count;
328
9bccf70c
A
329 if (p != uio->uio_procp)
330 panic("vn_read: uio_procp does not match p");
331
332 vp = (struct vnode *)fp->f_data;
333 ioflag = 0;
334 if (fp->f_flag & FNONBLOCK)
335 ioflag |= IO_NDELAY;
1c79356b 336 VOP_LEASE(vp, p, cred, LEASE_READ);
9bccf70c
A
337 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
338 if (error)
339 return (error);
340 if ((flags & FOF_OFFSET) == 0)
341 uio->uio_offset = fp->f_offset;
1c79356b
A
342 count = uio->uio_resid;
343
9bccf70c
A
344 if(UBCINFOEXISTS(vp)) {
345 memory_object_t pager;
346 struct iovec *iov;
347 off_t file_off;
348 kern_return_t kr = KERN_SUCCESS;
349 kern_return_t ret = KERN_SUCCESS;
350 int count;
351
352 pager = (memory_object_t)ubc_getpager(vp);
353 file_off = uio->uio_offset;
354 iov = uio->uio_iov;
355 count = uio->uio_iovcnt;
356 while(count) {
357 kr = vm_conflict_check(current_map(),
358 (vm_offset_t)iov->iov_base, iov->iov_len,
359 pager, file_off);
360 if(kr == KERN_ALREADY_WAITING) {
361 if((count != uio->uio_iovcnt) &&
362 (ret != KERN_ALREADY_WAITING)) {
363 error = EINVAL;
364 goto done;
365 }
366 ret = KERN_ALREADY_WAITING;
367 } else if (kr != KERN_SUCCESS) {
368 error = EINVAL;
369 goto done;
370 }
371 if(kr != ret) {
372 error = EINVAL;
373 goto done;
374 }
375 file_off += iov->iov_len;
376 iov++;
377 count--;
378 }
379 if(ret == KERN_ALREADY_WAITING) {
380 uio->uio_resid = 0;
381 if ((flags & FOF_OFFSET) == 0)
382 fp->f_offset +=
383 count - uio->uio_resid;
384 error = 0;
385 goto done;
386 }
387 }
388 error = VOP_READ(vp, uio, ioflag, cred);
389 if ((flags & FOF_OFFSET) == 0)
390 fp->f_offset += count - uio->uio_resid;
391done:
1c79356b
A
392 VOP_UNLOCK(vp, 0, p);
393 return (error);
394}
395
396
397/*
398 * File table vnode write routine.
399 */
9bccf70c
A
400static int
401vn_write(fp, uio, cred, flags, p)
1c79356b
A
402 struct file *fp;
403 struct uio *uio;
404 struct ucred *cred;
9bccf70c
A
405 int flags;
406 struct proc *p;
1c79356b 407{
9bccf70c
A
408 struct vnode *vp;
409 int error, ioflag;
1c79356b
A
410 off_t count;
411
9bccf70c
A
412 if (p != uio->uio_procp)
413 panic("vn_write: uio_procp does not match p");
414
415 vp = (struct vnode *)fp->f_data;
416 ioflag = IO_UNIT;
417 if (vp->v_type == VREG)
418 bwillwrite();
1c79356b
A
419 if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
420 ioflag |= IO_APPEND;
421 if (fp->f_flag & FNONBLOCK)
422 ioflag |= IO_NDELAY;
423 if ((fp->f_flag & O_FSYNC) ||
424 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
425 ioflag |= IO_SYNC;
426 VOP_LEASE(vp, p, cred, LEASE_WRITE);
9bccf70c
A
427 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
428 if (error)
429 return (error);
430 if ((flags & FOF_OFFSET) == 0) {
431 uio->uio_offset = fp->f_offset;
432 count = uio->uio_resid;
433 }
1c79356b 434
9bccf70c
A
435 if(UBCINFOEXISTS(vp)) {
436 memory_object_t pager;
437 struct iovec *iov;
438 off_t file_off;
439 kern_return_t kr = KERN_SUCCESS;
440 kern_return_t ret = KERN_SUCCESS;
441 int count;
442
443 pager = (memory_object_t)ubc_getpager(vp);
444 file_off = uio->uio_offset;
445 iov = uio->uio_iov;
446 count = uio->uio_iovcnt;
447 while(count) {
448 kr = vm_conflict_check(current_map(),
449 (vm_offset_t)iov->iov_base,
450 iov->iov_len, pager, file_off);
451 if(kr == KERN_ALREADY_WAITING) {
452 if((count != uio->uio_iovcnt) &&
453 (ret != KERN_ALREADY_WAITING)) {
454 error = EINVAL;
455 goto done;
456 }
457 ret = KERN_ALREADY_WAITING;
458 } else if (kr != KERN_SUCCESS) {
459 error = EINVAL;
460 goto done;
461 }
462 if(kr != ret) {
463 error = EINVAL;
464 goto done;
465 }
466 file_off += iov->iov_len;
467 iov++;
468 count--;
469 }
470 if(ret == KERN_ALREADY_WAITING) {
471 uio->uio_resid = 0;
472 if ((flags & FOF_OFFSET) == 0)
473 fp->f_offset +=
474 count - uio->uio_resid;
475 error = 0;
476 goto done;
477 }
478 }
1c79356b
A
479 error = VOP_WRITE(vp, uio, ioflag, cred);
480
9bccf70c
A
481 if ((flags & FOF_OFFSET) == 0) {
482 if (ioflag & IO_APPEND)
483 fp->f_offset = uio->uio_offset;
484 else
485 fp->f_offset += count - uio->uio_resid;
486 }
487
1c79356b
A
488 /*
489 * Set the credentials on successful writes
490 */
491 if ((error == 0) && (vp->v_tag == VT_NFS) && (UBCINFOEXISTS(vp))) {
492 ubc_setcred(vp, p);
493 }
494
9bccf70c 495done:
1c79356b
A
496 VOP_UNLOCK(vp, 0, p);
497 return (error);
498}
499
500/*
501 * File table vnode stat routine.
502 */
9bccf70c 503int
1c79356b
A
504vn_stat(vp, sb, p)
505 struct vnode *vp;
506 register struct stat *sb;
507 struct proc *p;
508{
509 struct vattr vattr;
510 register struct vattr *vap;
511 int error;
512 u_short mode;
513
514 vap = &vattr;
515 error = VOP_GETATTR(vp, vap, p->p_ucred, p);
516 if (error)
517 return (error);
518 /*
519 * Copy from vattr table
520 */
521 sb->st_dev = vap->va_fsid;
522 sb->st_ino = vap->va_fileid;
523 mode = vap->va_mode;
524 switch (vp->v_type) {
525 case VREG:
526 mode |= S_IFREG;
527 break;
528 case VDIR:
529 mode |= S_IFDIR;
530 break;
531 case VBLK:
532 mode |= S_IFBLK;
533 break;
534 case VCHR:
535 mode |= S_IFCHR;
536 break;
537 case VLNK:
538 mode |= S_IFLNK;
539 break;
540 case VSOCK:
541 mode |= S_IFSOCK;
542 break;
543 case VFIFO:
544 mode |= S_IFIFO;
545 break;
546 default:
547 return (EBADF);
548 };
549 sb->st_mode = mode;
550 sb->st_nlink = vap->va_nlink;
551 sb->st_uid = vap->va_uid;
552 sb->st_gid = vap->va_gid;
553 sb->st_rdev = vap->va_rdev;
554 sb->st_size = vap->va_size;
555 sb->st_atimespec = vap->va_atime;
556 sb->st_mtimespec = vap->va_mtime;
557 sb->st_ctimespec = vap->va_ctime;
558 sb->st_blksize = vap->va_blocksize;
559 sb->st_flags = vap->va_flags;
560 /* Do not give the generation number out to unpriviledged users */
561 if (suser(p->p_ucred, &p->p_acflag))
562 sb->st_gen = 0;
563 else
564 sb->st_gen = vap->va_gen;
565 sb->st_blocks = vap->va_bytes / S_BLKSIZE;
566 return (0);
567}
568
569/*
570 * File table vnode ioctl routine.
571 */
9bccf70c 572static int
1c79356b
A
573vn_ioctl(fp, com, data, p)
574 struct file *fp;
575 u_long com;
576 caddr_t data;
577 struct proc *p;
578{
579 register struct vnode *vp = ((struct vnode *)fp->f_data);
580 struct vattr vattr;
581 int error;
fa4905b1 582 struct vnode *ttyvp;
9bccf70c 583
1c79356b
A
584 switch (vp->v_type) {
585
586 case VREG:
587 case VDIR:
588 if (com == FIONREAD) {
589 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
590 return (error);
591 *(int *)data = vattr.va_size - fp->f_offset;
592 return (0);
593 }
594 if (com == FIONBIO || com == FIOASYNC) /* XXX */
595 return (0); /* XXX */
596 /* fall into ... */
597
598 default:
599 return (ENOTTY);
600
601 case VFIFO:
602 case VCHR:
603 case VBLK:
9bccf70c
A
604
605 /* Should not be able to set block size from user space */
606 if(com == DKIOCSETBLOCKSIZE)
607 return (EPERM);
608
609 if (com == FIODTYPE) {
610 if (vp->v_type == VBLK) {
611 if (major(vp->v_rdev) >= nblkdev)
612 return (ENXIO);
613 *(int *)data = bdevsw[major(vp->v_rdev)].d_type;
614 } else if (vp->v_type == VCHR) {
615 if (major(vp->v_rdev) >= nchrdev)
616 return (ENXIO);
617 *(int *)data = cdevsw[major(vp->v_rdev)].d_type;
618 } else {
619 return (ENOTTY);
620 }
621 return (0);
622 }
623 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
624 if (error == 0 && com == TIOCSCTTY) {
625 VREF(vp);
626 ttyvp = p->p_session->s_ttyvp;
627 p->p_session->s_ttyvp = vp;
628 if (ttyvp)
629 vrele(ttyvp);
630 }
631 return (error);
1c79356b
A
632 }
633}
634
635/*
636 * File table vnode select routine.
637 */
9bccf70c 638static int
0b4e3aa0 639vn_select(fp, which, wql, p)
1c79356b
A
640 struct file *fp;
641 int which;
0b4e3aa0 642 void * wql;
1c79356b
A
643 struct proc *p;
644{
645
0b4e3aa0
A
646 return(VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
647 fp->f_cred, wql, p));
1c79356b
A
648}
649
650/*
651 * Check that the vnode is still valid, and if so
652 * acquire requested lock.
653 */
654int
655vn_lock(vp, flags, p)
656 struct vnode *vp;
657 int flags;
658 struct proc *p;
659{
660 int error;
661
662 do {
663 if ((flags & LK_INTERLOCK) == 0)
664 simple_lock(&vp->v_interlock);
665 if (vp->v_flag & VXLOCK) {
666 while (vp->v_flag & VXLOCK) {
667 vp->v_flag |= VXWANT;
668 simple_unlock(&vp->v_interlock);
0b4e3aa0 669 (void)tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
1c79356b
A
670 }
671 error = ENOENT;
672 } else {
673 error = VOP_LOCK(vp, flags | LK_INTERLOCK, p);
674 if (error == 0)
675 return (error);
676 }
677 flags &= ~LK_INTERLOCK;
678 } while (flags & LK_RETRY);
679 return (error);
680}
681
682/*
683 * File table vnode close routine.
684 */
9bccf70c 685static int
1c79356b
A
686vn_closefile(fp, p)
687 struct file *fp;
688 struct proc *p;
689{
690
691 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
692 fp->f_cred, p));
693}