The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 #include "opt_mac.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/fcntl.h>
   45 #include <sys/file.h>
   46 #include <sys/kdb.h>
   47 #include <sys/stat.h>
   48 #include <sys/priv.h>
   49 #include <sys/proc.h>
   50 #include <sys/limits.h>
   51 #include <sys/lock.h>
   52 #include <sys/mount.h>
   53 #include <sys/mutex.h>
   54 #include <sys/namei.h>
   55 #include <sys/vnode.h>
   56 #include <sys/bio.h>
   57 #include <sys/buf.h>
   58 #include <sys/filio.h>
   59 #include <sys/sx.h>
   60 #include <sys/ttycom.h>
   61 #include <sys/conf.h>
   62 #include <sys/syslog.h>
   63 #include <sys/unistd.h>
   64 
   65 #include <security/mac/mac_framework.h>
   66 
   67 static fo_rdwr_t        vn_read;
   68 static fo_rdwr_t        vn_write;
   69 static fo_ioctl_t       vn_ioctl;
   70 static fo_poll_t        vn_poll;
   71 static fo_kqfilter_t    vn_kqfilter;
   72 static fo_stat_t        vn_statfile;
   73 static fo_close_t       vn_closefile;
   74 
   75 struct  fileops vnops = {
   76         .fo_read = vn_read,
   77         .fo_write = vn_write,
   78         .fo_ioctl = vn_ioctl,
   79         .fo_poll = vn_poll,
   80         .fo_kqfilter = vn_kqfilter,
   81         .fo_stat = vn_statfile,
   82         .fo_close = vn_closefile,
   83         .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
   84 };
   85 
   86 int
   87 vn_open(ndp, flagp, cmode, fp)
   88         struct nameidata *ndp;
   89         int *flagp, cmode;
   90         struct file *fp;
   91 {
   92         struct thread *td = ndp->ni_cnd.cn_thread;
   93 
   94         return (vn_open_cred(ndp, flagp, cmode, td->td_ucred, fp));
   95 }
   96 
   97 /*
   98  * Common code for vnode open operations.
   99  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
  100  * 
  101  * Note that this does NOT free nameidata for the successful case,
  102  * due to the NDINIT being done elsewhere.
  103  */
  104 int
  105 vn_open_cred(ndp, flagp, cmode, cred, fp)
  106         struct nameidata *ndp;
  107         int *flagp, cmode;
  108         struct ucred *cred;
  109         struct file *fp;
  110 {
  111         struct vnode *vp;
  112         struct mount *mp;
  113         struct thread *td = ndp->ni_cnd.cn_thread;
  114         struct vattr vat;
  115         struct vattr *vap = &vat;
  116         int mode, fmode, error;
  117         int vfslocked, mpsafe;
  118 
  119         mpsafe = ndp->ni_cnd.cn_flags & MPSAFE;
  120 restart:
  121         vfslocked = 0;
  122         fmode = *flagp;
  123         if (fmode & O_CREAT) {
  124                 ndp->ni_cnd.cn_nameiop = CREATE;
  125                 ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF |
  126                     MPSAFE | AUDITVNODE1;
  127                 if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
  128                         ndp->ni_cnd.cn_flags |= FOLLOW;
  129                 bwillwrite();
  130                 if ((error = namei(ndp)) != 0)
  131                         return (error);
  132                 vfslocked = NDHASGIANT(ndp);
  133                 if (!mpsafe)
  134                         ndp->ni_cnd.cn_flags &= ~MPSAFE;
  135                 if (ndp->ni_vp == NULL) {
  136                         VATTR_NULL(vap);
  137                         vap->va_type = VREG;
  138                         vap->va_mode = cmode;
  139                         if (fmode & O_EXCL)
  140                                 vap->va_vaflags |= VA_EXCLUSIVE;
  141                         if (vn_start_write(ndp->ni_dvp, &mp, V_NOWAIT) != 0) {
  142                                 NDFREE(ndp, NDF_ONLY_PNBUF);
  143                                 vput(ndp->ni_dvp);
  144                                 VFS_UNLOCK_GIANT(vfslocked);
  145                                 if ((error = vn_start_write(NULL, &mp,
  146                                     V_XSLEEP | PCATCH)) != 0)
  147                                         return (error);
  148                                 goto restart;
  149                         }
  150 #ifdef MAC
  151                         error = mac_check_vnode_create(cred, ndp->ni_dvp,
  152                             &ndp->ni_cnd, vap);
  153                         if (error == 0) {
  154 #endif
  155                                 VOP_LEASE(ndp->ni_dvp, td, cred, LEASE_WRITE);
  156                                 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
  157                                                    &ndp->ni_cnd, vap);
  158 #ifdef MAC
  159                         }
  160 #endif
  161                         vput(ndp->ni_dvp);
  162                         vn_finished_write(mp);
  163                         if (error) {
  164                                 VFS_UNLOCK_GIANT(vfslocked);
  165                                 NDFREE(ndp, NDF_ONLY_PNBUF);
  166                                 return (error);
  167                         }
  168                         fmode &= ~O_TRUNC;
  169                         vp = ndp->ni_vp;
  170                 } else {
  171                         if (ndp->ni_dvp == ndp->ni_vp)
  172                                 vrele(ndp->ni_dvp);
  173                         else
  174                                 vput(ndp->ni_dvp);
  175                         ndp->ni_dvp = NULL;
  176                         vp = ndp->ni_vp;
  177                         if (fmode & O_EXCL) {
  178                                 error = EEXIST;
  179                                 goto bad;
  180                         }
  181                         fmode &= ~O_CREAT;
  182                 }
  183         } else {
  184                 ndp->ni_cnd.cn_nameiop = LOOKUP;
  185                 ndp->ni_cnd.cn_flags = ISOPEN |
  186                     ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) |
  187                     LOCKLEAF | MPSAFE | AUDITVNODE1;
  188                 if ((error = namei(ndp)) != 0)
  189                         return (error);
  190                 if (!mpsafe)
  191                         ndp->ni_cnd.cn_flags &= ~MPSAFE;
  192                 vfslocked = NDHASGIANT(ndp);
  193                 vp = ndp->ni_vp;
  194         }
  195         if (vp->v_type == VLNK) {
  196                 error = EMLINK;
  197                 goto bad;
  198         }
  199         if (vp->v_type == VSOCK) {
  200                 error = EOPNOTSUPP;
  201                 goto bad;
  202         }
  203         mode = 0;
  204         if (fmode & (FWRITE | O_TRUNC)) {
  205                 if (vp->v_type == VDIR) {
  206                         error = EISDIR;
  207                         goto bad;
  208                 }
  209                 mode |= VWRITE;
  210         }
  211         if (fmode & FREAD)
  212                 mode |= VREAD;
  213         if (fmode & O_APPEND)
  214                 mode |= VAPPEND;
  215 #ifdef MAC
  216         error = mac_check_vnode_open(cred, vp, mode);
  217         if (error)
  218                 goto bad;
  219 #endif
  220         if ((fmode & O_CREAT) == 0) {
  221                 if (mode & VWRITE) {
  222                         error = vn_writechk(vp);
  223                         if (error)
  224                                 goto bad;
  225                 }
  226                 if (mode) {
  227                         error = VOP_ACCESS(vp, mode, cred, td);
  228                         if (error)
  229                                 goto bad;
  230                 }
  231         }
  232         if ((error = VOP_OPEN(vp, fmode, cred, td, fp)) != 0)
  233                 goto bad;
  234 
  235         if (fmode & FWRITE)
  236                 vp->v_writecount++;
  237         *flagp = fmode;
  238         ASSERT_VOP_ELOCKED(vp, "vn_open_cred");
  239         if (!mpsafe)
  240                 VFS_UNLOCK_GIANT(vfslocked);
  241         return (0);
  242 bad:
  243         NDFREE(ndp, NDF_ONLY_PNBUF);
  244         vput(vp);
  245         VFS_UNLOCK_GIANT(vfslocked);
  246         *flagp = fmode;
  247         ndp->ni_vp = NULL;
  248         return (error);
  249 }
  250 
  251 /*
  252  * Check for write permissions on the specified vnode.
  253  * Prototype text segments cannot be written.
  254  */
  255 int
  256 vn_writechk(vp)
  257         register struct vnode *vp;
  258 {
  259 
  260         ASSERT_VOP_LOCKED(vp, "vn_writechk");
  261         /*
  262          * If there's shared text associated with
  263          * the vnode, try to free it up once.  If
  264          * we fail, we can't allow writing.
  265          */
  266         if (vp->v_vflag & VV_TEXT)
  267                 return (ETXTBSY);
  268 
  269         return (0);
  270 }
  271 
  272 /*
  273  * Vnode close call
  274  */
  275 int
  276 vn_close(vp, flags, file_cred, td)
  277         register struct vnode *vp;
  278         int flags;
  279         struct ucred *file_cred;
  280         struct thread *td;
  281 {
  282         struct mount *mp;
  283         int error;
  284 
  285         VFS_ASSERT_GIANT(vp->v_mount);
  286 
  287         vn_start_write(vp, &mp, V_WAIT);
  288         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  289         if (flags & FWRITE) {
  290                 VNASSERT(vp->v_writecount > 0, vp, 
  291                     ("vn_close: negative writecount"));
  292                 vp->v_writecount--;
  293         }
  294         error = VOP_CLOSE(vp, flags, file_cred, td);
  295         vput(vp);
  296         vn_finished_write(mp);
  297         return (error);
  298 }
  299 
  300 /*
  301  * Sequential heuristic - detect sequential operation
  302  */
  303 static __inline
  304 int
  305 sequential_heuristic(struct uio *uio, struct file *fp)
  306 {
  307 
  308         if ((uio->uio_offset == 0 && fp->f_seqcount > 0) ||
  309             uio->uio_offset == fp->f_nextoff) {
  310                 /*
  311                  * XXX we assume that the filesystem block size is
  312                  * the default.  Not true, but still gives us a pretty
  313                  * good indicator of how sequential the read operations
  314                  * are.
  315                  */
  316                 fp->f_seqcount += (uio->uio_resid + BKVASIZE - 1) / BKVASIZE;
  317                 if (fp->f_seqcount > IO_SEQMAX)
  318                         fp->f_seqcount = IO_SEQMAX;
  319                 return(fp->f_seqcount << IO_SEQSHIFT);
  320         }
  321 
  322         /*
  323          * Not sequential, quick draw-down of seqcount
  324          */
  325         if (fp->f_seqcount > 1)
  326                 fp->f_seqcount = 1;
  327         else
  328                 fp->f_seqcount = 0;
  329         return(0);
  330 }
  331 
  332 /*
  333  * Package up an I/O request on a vnode into a uio and do it.
  334  */
  335 int
  336 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, active_cred, file_cred,
  337     aresid, td)
  338         enum uio_rw rw;
  339         struct vnode *vp;
  340         void *base;
  341         int len;
  342         off_t offset;
  343         enum uio_seg segflg;
  344         int ioflg;
  345         struct ucred *active_cred;
  346         struct ucred *file_cred;
  347         int *aresid;
  348         struct thread *td;
  349 {
  350         struct uio auio;
  351         struct iovec aiov;
  352         struct mount *mp;
  353         struct ucred *cred;
  354         int error;
  355 
  356         VFS_ASSERT_GIANT(vp->v_mount);
  357 
  358         if ((ioflg & IO_NODELOCKED) == 0) {
  359                 mp = NULL;
  360                 if (rw == UIO_WRITE) { 
  361                         if (vp->v_type != VCHR &&
  362                             (error = vn_start_write(vp, &mp, V_WAIT | PCATCH))
  363                             != 0)
  364                                 return (error);
  365                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  366                 } else {
  367                         /*
  368                          * XXX This should be LK_SHARED but I don't trust VFS
  369                          * enough to leave it like that until it has been
  370                          * reviewed further.
  371                          */
  372                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  373                 }
  374 
  375         }
  376         ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
  377         auio.uio_iov = &aiov;
  378         auio.uio_iovcnt = 1;
  379         aiov.iov_base = base;
  380         aiov.iov_len = len;
  381         auio.uio_resid = len;
  382         auio.uio_offset = offset;
  383         auio.uio_segflg = segflg;
  384         auio.uio_rw = rw;
  385         auio.uio_td = td;
  386         error = 0;
  387 #ifdef MAC
  388         if ((ioflg & IO_NOMACCHECK) == 0) {
  389                 if (rw == UIO_READ)
  390                         error = mac_check_vnode_read(active_cred, file_cred,
  391                             vp);
  392                 else
  393                         error = mac_check_vnode_write(active_cred, file_cred,
  394                             vp);
  395         }
  396 #endif
  397         if (error == 0) {
  398                 if (file_cred)
  399                         cred = file_cred;
  400                 else
  401                         cred = active_cred;
  402                 if (rw == UIO_READ)
  403                         error = VOP_READ(vp, &auio, ioflg, cred);
  404                 else
  405                         error = VOP_WRITE(vp, &auio, ioflg, cred);
  406         }
  407         if (aresid)
  408                 *aresid = auio.uio_resid;
  409         else
  410                 if (auio.uio_resid && error == 0)
  411                         error = EIO;
  412         if ((ioflg & IO_NODELOCKED) == 0) {
  413                 if (rw == UIO_WRITE && vp->v_type != VCHR)
  414                         vn_finished_write(mp);
  415                 VOP_UNLOCK(vp, 0, td);
  416         }
  417         return (error);
  418 }
  419 
  420 /*
  421  * Package up an I/O request on a vnode into a uio and do it.  The I/O
  422  * request is split up into smaller chunks and we try to avoid saturating
  423  * the buffer cache while potentially holding a vnode locked, so we 
  424  * check bwillwrite() before calling vn_rdwr().  We also call uio_yield()
  425  * to give other processes a chance to lock the vnode (either other processes
  426  * core'ing the same binary, or unrelated processes scanning the directory).
  427  */
  428 int
  429 vn_rdwr_inchunks(rw, vp, base, len, offset, segflg, ioflg, active_cred,
  430     file_cred, aresid, td)
  431         enum uio_rw rw;
  432         struct vnode *vp;
  433         void *base;
  434         size_t len;
  435         off_t offset;
  436         enum uio_seg segflg;
  437         int ioflg;
  438         struct ucred *active_cred;
  439         struct ucred *file_cred;
  440         size_t *aresid;
  441         struct thread *td;
  442 {
  443         int error = 0;
  444         int iaresid;
  445 
  446         VFS_ASSERT_GIANT(vp->v_mount);
  447 
  448         do {
  449                 int chunk;
  450 
  451                 /*
  452                  * Force `offset' to a multiple of MAXBSIZE except possibly
  453                  * for the first chunk, so that filesystems only need to
  454                  * write full blocks except possibly for the first and last
  455                  * chunks.
  456                  */
  457                 chunk = MAXBSIZE - (uoff_t)offset % MAXBSIZE;
  458 
  459                 if (chunk > len)
  460                         chunk = len;
  461                 if (rw != UIO_READ && vp->v_type == VREG)
  462                         bwillwrite();
  463                 iaresid = 0;
  464                 error = vn_rdwr(rw, vp, base, chunk, offset, segflg,
  465                     ioflg, active_cred, file_cred, &iaresid, td);
  466                 len -= chunk;   /* aresid calc already includes length */
  467                 if (error)
  468                         break;
  469                 offset += chunk;
  470                 base = (char *)base + chunk;
  471                 uio_yield();
  472         } while (len);
  473         if (aresid)
  474                 *aresid = len + iaresid;
  475         return (error);
  476 }
  477 
  478 /*
  479  * File table vnode read routine.
  480  */
  481 static int
  482 vn_read(fp, uio, active_cred, flags, td)
  483         struct file *fp;
  484         struct uio *uio;
  485         struct ucred *active_cred;
  486         struct thread *td;
  487         int flags;
  488 {
  489         struct vnode *vp;
  490         int error, ioflag;
  491         int vfslocked;
  492 
  493         KASSERT(uio->uio_td == td, ("uio_td %p is not td %p",
  494             uio->uio_td, td));
  495         vp = fp->f_vnode;
  496         ioflag = 0;
  497         if (fp->f_flag & FNONBLOCK)
  498                 ioflag |= IO_NDELAY;
  499         if (fp->f_flag & O_DIRECT)
  500                 ioflag |= IO_DIRECT;
  501         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  502         VOP_LEASE(vp, td, fp->f_cred, LEASE_READ);
  503         /*
  504          * According to McKusick the vn lock was protecting f_offset here.
  505          * It is now protected by the FOFFSET_LOCKED flag.
  506          */
  507         if ((flags & FOF_OFFSET) == 0) {
  508                 FILE_LOCK(fp);
  509                 while(fp->f_vnread_flags & FOFFSET_LOCKED) {
  510                         fp->f_vnread_flags |= FOFFSET_LOCK_WAITING;
  511                         msleep(&fp->f_vnread_flags,fp->f_mtxp,PUSER -1,"vnread offlock",0);
  512                 }
  513                 fp->f_vnread_flags |= FOFFSET_LOCKED;
  514                 FILE_UNLOCK(fp);
  515                 vn_lock(vp, LK_SHARED | LK_RETRY, td);
  516                 uio->uio_offset = fp->f_offset;
  517         } else
  518                 vn_lock(vp, LK_SHARED | LK_RETRY, td);
  519 
  520         ioflag |= sequential_heuristic(uio, fp);
  521 
  522 #ifdef MAC
  523         error = mac_check_vnode_read(active_cred, fp->f_cred, vp);
  524         if (error == 0)
  525 #endif
  526                 error = VOP_READ(vp, uio, ioflag, fp->f_cred);
  527         if ((flags & FOF_OFFSET) == 0) {
  528                 fp->f_offset = uio->uio_offset;
  529                 FILE_LOCK(fp);
  530                 if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING)
  531                         wakeup(&fp->f_vnread_flags);
  532                 fp->f_vnread_flags = 0;
  533                 FILE_UNLOCK(fp);
  534         }
  535         fp->f_nextoff = uio->uio_offset;
  536         VOP_UNLOCK(vp, 0, td);
  537         VFS_UNLOCK_GIANT(vfslocked);
  538         return (error);
  539 }
  540 
  541 /*
  542  * File table vnode write routine.
  543  */
  544 static int
  545 vn_write(fp, uio, active_cred, flags, td)
  546         struct file *fp;
  547         struct uio *uio;
  548         struct ucred *active_cred;
  549         struct thread *td;
  550         int flags;
  551 {
  552         struct vnode *vp;
  553         struct mount *mp;
  554         int error, ioflag;
  555         int vfslocked;
  556 
  557         KASSERT(uio->uio_td == td, ("uio_td %p is not td %p",
  558             uio->uio_td, td));
  559         vp = fp->f_vnode;
  560         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  561         if (vp->v_type == VREG)
  562                 bwillwrite();
  563         ioflag = IO_UNIT;
  564         if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
  565                 ioflag |= IO_APPEND;
  566         if (fp->f_flag & FNONBLOCK)
  567                 ioflag |= IO_NDELAY;
  568         if (fp->f_flag & O_DIRECT)
  569                 ioflag |= IO_DIRECT;
  570         if ((fp->f_flag & O_FSYNC) ||
  571             (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
  572                 ioflag |= IO_SYNC;
  573         mp = NULL;
  574         if (vp->v_type != VCHR &&
  575             (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
  576                 goto unlock;
  577         VOP_LEASE(vp, td, fp->f_cred, LEASE_WRITE);
  578         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  579         if ((flags & FOF_OFFSET) == 0)
  580                 uio->uio_offset = fp->f_offset;
  581         ioflag |= sequential_heuristic(uio, fp);
  582 #ifdef MAC
  583         error = mac_check_vnode_write(active_cred, fp->f_cred, vp);
  584         if (error == 0)
  585 #endif
  586                 error = VOP_WRITE(vp, uio, ioflag, fp->f_cred);
  587         if ((flags & FOF_OFFSET) == 0)
  588                 fp->f_offset = uio->uio_offset;
  589         fp->f_nextoff = uio->uio_offset;
  590         VOP_UNLOCK(vp, 0, td);
  591         if (vp->v_type != VCHR)
  592                 vn_finished_write(mp);
  593 unlock:
  594         VFS_UNLOCK_GIANT(vfslocked);
  595         return (error);
  596 }
  597 
  598 /*
  599  * File table vnode stat routine.
  600  */
  601 static int
  602 vn_statfile(fp, sb, active_cred, td)
  603         struct file *fp;
  604         struct stat *sb;
  605         struct ucred *active_cred;
  606         struct thread *td;
  607 {
  608         struct vnode *vp = fp->f_vnode;
  609         int vfslocked;
  610         int error;
  611 
  612         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  613         vn_lock(vp, LK_SHARED | LK_RETRY, td);
  614         error = vn_stat(vp, sb, active_cred, fp->f_cred, td);
  615         VOP_UNLOCK(vp, 0, td);
  616         VFS_UNLOCK_GIANT(vfslocked);
  617 
  618         return (error);
  619 }
  620 
  621 /*
  622  * Stat a vnode; implementation for the stat syscall
  623  */
  624 int
  625 vn_stat(vp, sb, active_cred, file_cred, td)
  626         struct vnode *vp;
  627         register struct stat *sb;
  628         struct ucred *active_cred;
  629         struct ucred *file_cred;
  630         struct thread *td;
  631 {
  632         struct vattr vattr;
  633         register struct vattr *vap;
  634         int error;
  635         u_short mode;
  636 
  637 #ifdef MAC
  638         error = mac_check_vnode_stat(active_cred, file_cred, vp);
  639         if (error)
  640                 return (error);
  641 #endif
  642 
  643         vap = &vattr;
  644 
  645         /*
  646          * Initialize defaults for new and unusual fields, so that file
  647          * systems which don't support these fields don't need to know
  648          * about them.
  649          */
  650         vap->va_birthtime.tv_sec = -1;
  651         vap->va_birthtime.tv_nsec = 0;
  652         vap->va_fsid = VNOVAL;
  653         vap->va_rdev = NODEV;
  654 
  655         error = VOP_GETATTR(vp, vap, active_cred, td);
  656         if (error)
  657                 return (error);
  658 
  659         /*
  660          * Zero the spare stat fields
  661          */
  662         bzero(sb, sizeof *sb);
  663 
  664         /*
  665          * Copy from vattr table
  666          */
  667         if (vap->va_fsid != VNOVAL)
  668                 sb->st_dev = vap->va_fsid;
  669         else
  670                 sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0];
  671         sb->st_ino = vap->va_fileid;
  672         mode = vap->va_mode;
  673         switch (vap->va_type) {
  674         case VREG:
  675                 mode |= S_IFREG;
  676                 break;
  677         case VDIR:
  678                 mode |= S_IFDIR;
  679                 break;
  680         case VBLK:
  681                 mode |= S_IFBLK;
  682                 break;
  683         case VCHR:
  684                 mode |= S_IFCHR;
  685                 break;
  686         case VLNK:
  687                 mode |= S_IFLNK;
  688                 break;
  689         case VSOCK:
  690                 mode |= S_IFSOCK;
  691                 break;
  692         case VFIFO:
  693                 mode |= S_IFIFO;
  694                 break;
  695         default:
  696                 return (EBADF);
  697         };
  698         sb->st_mode = mode;
  699         sb->st_nlink = vap->va_nlink;
  700         sb->st_uid = vap->va_uid;
  701         sb->st_gid = vap->va_gid;
  702         sb->st_rdev = vap->va_rdev;
  703         if (vap->va_size > OFF_MAX)
  704                 return (EOVERFLOW);
  705         sb->st_size = vap->va_size;
  706         sb->st_atimespec = vap->va_atime;
  707         sb->st_mtimespec = vap->va_mtime;
  708         sb->st_ctimespec = vap->va_ctime;
  709         sb->st_birthtimespec = vap->va_birthtime;
  710 
  711         /*
  712          * According to www.opengroup.org, the meaning of st_blksize is 
  713          *   "a filesystem-specific preferred I/O block size for this 
  714          *    object.  In some filesystem types, this may vary from file
  715          *    to file"
  716          * Default to PAGE_SIZE after much discussion.
  717          * XXX: min(PAGE_SIZE, vp->v_bufobj.bo_bsize) may be more correct.
  718          */
  719 
  720         sb->st_blksize = PAGE_SIZE;
  721         
  722         sb->st_flags = vap->va_flags;
  723         if (priv_check(td, PRIV_VFS_GENERATION))
  724                 sb->st_gen = 0;
  725         else
  726                 sb->st_gen = vap->va_gen;
  727 
  728         sb->st_blocks = vap->va_bytes / S_BLKSIZE;
  729         return (0);
  730 }
  731 
  732 /*
  733  * File table vnode ioctl routine.
  734  */
  735 static int
  736 vn_ioctl(fp, com, data, active_cred, td)
  737         struct file *fp;
  738         u_long com;
  739         void *data;
  740         struct ucred *active_cred;
  741         struct thread *td;
  742 {
  743         struct vnode *vp = fp->f_vnode;
  744         struct vattr vattr;
  745         int vfslocked;
  746         int error;
  747 
  748         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  749         error = ENOTTY;
  750         switch (vp->v_type) {
  751         case VREG:
  752         case VDIR:
  753                 if (com == FIONREAD) {
  754                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  755                         error = VOP_GETATTR(vp, &vattr, active_cred, td);
  756                         VOP_UNLOCK(vp, 0, td);
  757                         if (!error)
  758                                 *(int *)data = vattr.va_size - fp->f_offset;
  759                 }
  760                 if (com == FIONBIO || com == FIOASYNC)  /* XXX */
  761                         error = 0;
  762                 else
  763                         error = VOP_IOCTL(vp, com, data, fp->f_flag,
  764                             active_cred, td);
  765                 break;
  766 
  767         default:
  768                 break;
  769         }
  770         VFS_UNLOCK_GIANT(vfslocked);
  771         return (error);
  772 }
  773 
  774 /*
  775  * File table vnode poll routine.
  776  */
  777 static int
  778 vn_poll(fp, events, active_cred, td)
  779         struct file *fp;
  780         int events;
  781         struct ucred *active_cred;
  782         struct thread *td;
  783 {
  784         struct vnode *vp;
  785         int vfslocked;
  786         int error;
  787 
  788         vp = fp->f_vnode;
  789         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  790 #ifdef MAC
  791         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  792         error = mac_check_vnode_poll(active_cred, fp->f_cred, vp);
  793         VOP_UNLOCK(vp, 0, td);
  794         if (!error)
  795 #endif
  796 
  797         error = VOP_POLL(vp, events, fp->f_cred, td);
  798         VFS_UNLOCK_GIANT(vfslocked);
  799         return (error);
  800 }
  801 
  802 /*
  803  * Check that the vnode is still valid, and if so
  804  * acquire requested lock.
  805  */
  806 int
  807 _vn_lock(struct vnode *vp, int flags, struct thread *td, char *file, int line)
  808 {
  809         int error;
  810 
  811         do {
  812                 if ((flags & LK_INTERLOCK) == 0)
  813                         VI_LOCK(vp);
  814 #ifdef DEBUG_VFS_LOCKS
  815                 KASSERT(vp->v_holdcnt != 0,
  816                     ("vn_lock %p: zero hold count", vp));
  817 #endif
  818                 if ((flags & LK_NOWAIT || (flags & LK_TYPE_MASK) == 0) &&
  819                     vp->v_iflag & VI_DOOMED) {
  820                         VI_UNLOCK(vp);
  821                         return (ENOENT);
  822                 }
  823                 /*
  824                  * Just polling to check validity.
  825                  */
  826                 if ((flags & LK_TYPE_MASK) == 0) {
  827                         VI_UNLOCK(vp);
  828                         return (0);
  829                 }
  830                 /*
  831                  * lockmgr drops interlock before it will return for
  832                  * any reason.  So force the code above to relock it.
  833                  */
  834                 error = VOP_LOCK1(vp, flags | LK_INTERLOCK, td, file, line);
  835                 flags &= ~LK_INTERLOCK;
  836                 KASSERT((flags & LK_RETRY) == 0 || error == 0,
  837                     ("LK_RETRY set with incompatible flags %d\n", flags));
  838                 /*
  839                  * Callers specify LK_RETRY if they wish to get dead vnodes.
  840                  * If RETRY is not set, we return ENOENT instead.
  841                  */
  842                 if (error == 0 && vp->v_iflag & VI_DOOMED &&
  843                     (flags & LK_RETRY) == 0) {
  844                         VOP_UNLOCK(vp, 0, td);
  845                         error = ENOENT;
  846                         break;
  847                 }
  848         } while (flags & LK_RETRY && error != 0);
  849         return (error);
  850 }
  851 
  852 /*
  853  * File table vnode close routine.
  854  */
  855 static int
  856 vn_closefile(fp, td)
  857         struct file *fp;
  858         struct thread *td;
  859 {
  860         struct vnode *vp;
  861         struct flock lf;
  862         int vfslocked;
  863         int error;
  864 
  865         vp = fp->f_vnode;
  866 
  867         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  868         if (fp->f_type == DTYPE_VNODE && fp->f_flag & FHASLOCK) {
  869                 lf.l_whence = SEEK_SET;
  870                 lf.l_start = 0;
  871                 lf.l_len = 0;
  872                 lf.l_type = F_UNLCK;
  873                 (void) VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
  874         }
  875 
  876         fp->f_ops = &badfileops;
  877 
  878         error = vn_close(vp, fp->f_flag, fp->f_cred, td);
  879         VFS_UNLOCK_GIANT(vfslocked);
  880         return (error);
  881 }
  882 
  883 /*
  884  * Preparing to start a filesystem write operation. If the operation is
  885  * permitted, then we bump the count of operations in progress and
  886  * proceed. If a suspend request is in progress, we wait until the
  887  * suspension is over, and then proceed.
  888  */
  889 int
  890 vn_start_write(vp, mpp, flags)
  891         struct vnode *vp;
  892         struct mount **mpp;
  893         int flags;
  894 {
  895         struct mount *mp;
  896         int error;
  897 
  898         error = 0;
  899         /*
  900          * If a vnode is provided, get and return the mount point that
  901          * to which it will write.
  902          */
  903         if (vp != NULL) {
  904                 if ((error = VOP_GETWRITEMOUNT(vp, mpp)) != 0) {
  905                         *mpp = NULL;
  906                         if (error != EOPNOTSUPP)
  907                                 return (error);
  908                         return (0);
  909                 }
  910         }
  911         if ((mp = *mpp) == NULL)
  912                 return (0);
  913         MNT_ILOCK(mp);
  914         if (vp == NULL)
  915                 MNT_REF(mp);
  916         /*
  917          * Check on status of suspension.
  918          */
  919         if ((curthread->td_pflags & TDP_IGNSUSP) == 0 ||
  920             mp->mnt_susp_owner != curthread) {
  921                 while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
  922                         if (flags & V_NOWAIT) {
  923                                 error = EWOULDBLOCK;
  924                                 goto unlock;
  925                         }
  926                         error = msleep(&mp->mnt_flag, MNT_MTX(mp),
  927                             (PUSER - 1) | (flags & PCATCH), "suspfs", 0);
  928                         if (error)
  929                                 goto unlock;
  930                 }
  931         }
  932         if (flags & V_XSLEEP)
  933                 goto unlock;
  934         mp->mnt_writeopcount++;
  935 unlock:
  936         MNT_REL(mp);
  937         MNT_IUNLOCK(mp);
  938         return (error);
  939 }
  940 
  941 /*
  942  * Secondary suspension. Used by operations such as vop_inactive
  943  * routines that are needed by the higher level functions. These
  944  * are allowed to proceed until all the higher level functions have
  945  * completed (indicated by mnt_writeopcount dropping to zero). At that
  946  * time, these operations are halted until the suspension is over.
  947  */
  948 int
  949 vn_start_secondary_write(vp, mpp, flags)
  950         struct vnode *vp;
  951         struct mount **mpp;
  952         int flags;
  953 {
  954         struct mount *mp;
  955         int error;
  956 
  957  retry:
  958         if (vp != NULL) {
  959                 if ((error = VOP_GETWRITEMOUNT(vp, mpp)) != 0) {
  960                         *mpp = NULL;
  961                         if (error != EOPNOTSUPP)
  962                                 return (error);
  963                         return (0);
  964                 }
  965         }
  966         /*
  967          * If we are not suspended or have not yet reached suspended
  968          * mode, then let the operation proceed.
  969          */
  970         if ((mp = *mpp) == NULL)
  971                 return (0);
  972         MNT_ILOCK(mp);
  973         if (vp == NULL)
  974                 MNT_REF(mp);
  975         if ((mp->mnt_kern_flag & (MNTK_SUSPENDED | MNTK_SUSPEND2)) == 0) {
  976                 mp->mnt_secondary_writes++;
  977                 mp->mnt_secondary_accwrites++;
  978                 MNT_REL(mp);
  979                 MNT_IUNLOCK(mp);
  980                 return (0);
  981         }
  982         if (flags & V_NOWAIT) {
  983                 MNT_REL(mp);
  984                 MNT_IUNLOCK(mp);
  985                 return (EWOULDBLOCK);
  986         }
  987         /*
  988          * Wait for the suspension to finish.
  989          */
  990         error = msleep(&mp->mnt_flag, MNT_MTX(mp),
  991                        (PUSER - 1) | (flags & PCATCH) | PDROP, "suspfs", 0);
  992         vfs_rel(mp);
  993         if (error == 0)
  994                 goto retry;
  995         return (error);
  996 }
  997 
  998 /*
  999  * Filesystem write operation has completed. If we are suspending and this
 1000  * operation is the last one, notify the suspender that the suspension is
 1001  * now in effect.
 1002  */
 1003 void
 1004 vn_finished_write(mp)
 1005         struct mount *mp;
 1006 {
 1007         if (mp == NULL)
 1008                 return;
 1009         MNT_ILOCK(mp);
 1010         mp->mnt_writeopcount--;
 1011         if (mp->mnt_writeopcount < 0)
 1012                 panic("vn_finished_write: neg cnt");
 1013         if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0 &&
 1014             mp->mnt_writeopcount <= 0)
 1015                 wakeup(&mp->mnt_writeopcount);
 1016         MNT_IUNLOCK(mp);
 1017 }
 1018 
 1019 
 1020 /*
 1021  * Filesystem secondary write operation has completed. If we are
 1022  * suspending and this operation is the last one, notify the suspender
 1023  * that the suspension is now in effect.
 1024  */
 1025 void
 1026 vn_finished_secondary_write(mp)
 1027         struct mount *mp;
 1028 {
 1029         if (mp == NULL)
 1030                 return;
 1031         MNT_ILOCK(mp);
 1032         mp->mnt_secondary_writes--;
 1033         if (mp->mnt_secondary_writes < 0)
 1034                 panic("vn_finished_secondary_write: neg cnt");
 1035         if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0 &&
 1036             mp->mnt_secondary_writes <= 0)
 1037                 wakeup(&mp->mnt_secondary_writes);
 1038         MNT_IUNLOCK(mp);
 1039 }
 1040 
 1041 
 1042 
 1043 /*
 1044  * Request a filesystem to suspend write operations.
 1045  */
 1046 int
 1047 vfs_write_suspend(mp)
 1048         struct mount *mp;
 1049 {
 1050         struct thread *td = curthread;
 1051         int error;
 1052 
 1053         MNT_ILOCK(mp);
 1054         if (mp->mnt_susp_owner == curthread) {
 1055                 MNT_IUNLOCK(mp);
 1056                 return (EALREADY);
 1057         }
 1058         while (mp->mnt_kern_flag & MNTK_SUSPEND)
 1059                 msleep(&mp->mnt_flag, MNT_MTX(mp), PUSER - 1, "wsuspfs", 0);
 1060         mp->mnt_kern_flag |= MNTK_SUSPEND;
 1061         mp->mnt_susp_owner = curthread;
 1062         if (mp->mnt_writeopcount > 0)
 1063                 (void) msleep(&mp->mnt_writeopcount, 
 1064                     MNT_MTX(mp), (PUSER - 1)|PDROP, "suspwt", 0);
 1065         else
 1066                 MNT_IUNLOCK(mp);
 1067         if ((error = VFS_SYNC(mp, MNT_SUSPEND, td)) != 0)
 1068                 vfs_write_resume(mp);
 1069         return (error);
 1070 }
 1071 
 1072 /*
 1073  * Request a filesystem to resume write operations.
 1074  */
 1075 void
 1076 vfs_write_resume(mp)
 1077         struct mount *mp;
 1078 {
 1079 
 1080         MNT_ILOCK(mp);
 1081         if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
 1082                 KASSERT(mp->mnt_susp_owner == curthread, ("mnt_susp_owner"));
 1083                 mp->mnt_kern_flag &= ~(MNTK_SUSPEND | MNTK_SUSPEND2 |
 1084                                        MNTK_SUSPENDED);
 1085                 mp->mnt_susp_owner = NULL;
 1086                 wakeup(&mp->mnt_writeopcount);
 1087                 wakeup(&mp->mnt_flag);
 1088                 curthread->td_pflags &= ~TDP_IGNSUSP;
 1089                 MNT_IUNLOCK(mp);
 1090                 VFS_SUSP_CLEAN(mp);
 1091         } else
 1092                 MNT_IUNLOCK(mp);
 1093 }
 1094 
 1095 /*
 1096  * Implement kqueues for files by translating it to vnode operation.
 1097  */
 1098 static int
 1099 vn_kqfilter(struct file *fp, struct knote *kn)
 1100 {
 1101         int vfslocked;
 1102         int error;
 1103 
 1104         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
 1105         error = VOP_KQFILTER(fp->f_vnode, kn);
 1106         VFS_UNLOCK_GIANT(vfslocked);
 1107 
 1108         return error;
 1109 }
 1110 
 1111 /*
 1112  * Simplified in-kernel wrapper calls for extended attribute access.
 1113  * Both calls pass in a NULL credential, authorizing as "kernel" access.
 1114  * Set IO_NODELOCKED in ioflg if the vnode is already locked.
 1115  */
 1116 int
 1117 vn_extattr_get(struct vnode *vp, int ioflg, int attrnamespace,
 1118     const char *attrname, int *buflen, char *buf, struct thread *td)
 1119 {
 1120         struct uio      auio;
 1121         struct iovec    iov;
 1122         int     error;
 1123 
 1124         iov.iov_len = *buflen;
 1125         iov.iov_base = buf;
 1126 
 1127         auio.uio_iov = &iov;
 1128         auio.uio_iovcnt = 1;
 1129         auio.uio_rw = UIO_READ;
 1130         auio.uio_segflg = UIO_SYSSPACE;
 1131         auio.uio_td = td;
 1132         auio.uio_offset = 0;
 1133         auio.uio_resid = *buflen;
 1134 
 1135         if ((ioflg & IO_NODELOCKED) == 0)
 1136                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1137 
 1138         ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
 1139 
 1140         /* authorize attribute retrieval as kernel */
 1141         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, NULL,
 1142             td);
 1143 
 1144         if ((ioflg & IO_NODELOCKED) == 0)
 1145                 VOP_UNLOCK(vp, 0, td);
 1146 
 1147         if (error == 0) {
 1148                 *buflen = *buflen - auio.uio_resid;
 1149         }
 1150 
 1151         return (error);
 1152 }
 1153 
 1154 /*
 1155  * XXX failure mode if partially written?
 1156  */
 1157 int
 1158 vn_extattr_set(struct vnode *vp, int ioflg, int attrnamespace,
 1159     const char *attrname, int buflen, char *buf, struct thread *td)
 1160 {
 1161         struct uio      auio;
 1162         struct iovec    iov;
 1163         struct mount    *mp;
 1164         int     error;
 1165 
 1166         iov.iov_len = buflen;
 1167         iov.iov_base = buf;
 1168 
 1169         auio.uio_iov = &iov;
 1170         auio.uio_iovcnt = 1;
 1171         auio.uio_rw = UIO_WRITE;
 1172         auio.uio_segflg = UIO_SYSSPACE;
 1173         auio.uio_td = td;
 1174         auio.uio_offset = 0;
 1175         auio.uio_resid = buflen;
 1176 
 1177         if ((ioflg & IO_NODELOCKED) == 0) {
 1178                 if ((error = vn_start_write(vp, &mp, V_WAIT)) != 0)
 1179                         return (error);
 1180                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1181         }
 1182 
 1183         ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
 1184 
 1185         /* authorize attribute setting as kernel */
 1186         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, td);
 1187 
 1188         if ((ioflg & IO_NODELOCKED) == 0) {
 1189                 vn_finished_write(mp);
 1190                 VOP_UNLOCK(vp, 0, td);
 1191         }
 1192 
 1193         return (error);
 1194 }
 1195 
 1196 int
 1197 vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace,
 1198     const char *attrname, struct thread *td)
 1199 {
 1200         struct mount    *mp;
 1201         int     error;
 1202 
 1203         if ((ioflg & IO_NODELOCKED) == 0) {
 1204                 if ((error = vn_start_write(vp, &mp, V_WAIT)) != 0)
 1205                         return (error);
 1206                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1207         }
 1208 
 1209         ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
 1210 
 1211         /* authorize attribute removal as kernel */
 1212         error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, NULL, td);
 1213         if (error == EOPNOTSUPP)
 1214                 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
 1215                     NULL, td);
 1216 
 1217         if ((ioflg & IO_NODELOCKED) == 0) {
 1218                 vn_finished_write(mp);
 1219                 VOP_UNLOCK(vp, 0, td);
 1220         }
 1221 
 1222         return (error);
 1223 }
 1224 
 1225 int
 1226 vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp)
 1227 {
 1228         struct mount *mp;
 1229         int ltype, error;
 1230 
 1231         mp = vp->v_mount;
 1232         ltype = VOP_ISLOCKED(vp, curthread);
 1233         KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED,
 1234             ("vn_vget_ino: vp not locked"));
 1235         for (;;) {
 1236                 error = vfs_busy(mp, LK_NOWAIT, NULL, curthread);
 1237                 if (error == 0)
 1238                         break;
 1239                 VOP_UNLOCK(vp, 0, curthread);
 1240                 pause("vn_vget", 1);
 1241                 vn_lock(vp, ltype | LK_RETRY, curthread);
 1242                 if (vp->v_iflag & VI_DOOMED)
 1243                         return (ENOENT);
 1244         }
 1245         VOP_UNLOCK(vp, 0, curthread);
 1246         error = VFS_VGET(mp, ino, lkflags, rvp);
 1247         vfs_unbusy(mp, curthread);
 1248         vn_lock(vp, ltype | LK_RETRY, curthread);
 1249         if (vp->v_iflag & VI_DOOMED) {
 1250                 if (error == 0)
 1251                         vput(*rvp);
 1252                 error = ENOENT;
 1253         }
 1254         return (error);
 1255 }

Cache object: 40fbb9ca042b32023902fc0d3644be00


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.