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

Cache object: b93e0eb481d3679440b789f8c49bb566


[ 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.