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/ufs/ffs/ffs_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 /*      $NetBSD: ffs_vnops.c,v 1.138 2021/12/14 11:06:12 chs Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Wasabi Systems, Inc, and by Andrew Doran.
    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  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1982, 1986, 1989, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
   61  */
   62 
   63 #include <sys/cdefs.h>
   64 __KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.138 2021/12/14 11:06:12 chs Exp $");
   65 
   66 #if defined(_KERNEL_OPT)
   67 #include "opt_ffs.h"
   68 #include "opt_wapbl.h"
   69 #endif
   70 
   71 #include <sys/param.h>
   72 #include <sys/systm.h>
   73 #include <sys/resourcevar.h>
   74 #include <sys/kernel.h>
   75 #include <sys/file.h>
   76 #include <sys/stat.h>
   77 #include <sys/buf.h>
   78 #include <sys/event.h>
   79 #include <sys/proc.h>
   80 #include <sys/mount.h>
   81 #include <sys/vnode.h>
   82 #include <sys/pool.h>
   83 #include <sys/signalvar.h>
   84 #include <sys/kauth.h>
   85 #include <sys/wapbl.h>
   86 
   87 #include <miscfs/fifofs/fifo.h>
   88 #include <miscfs/genfs/genfs.h>
   89 #include <miscfs/specfs/specdev.h>
   90 
   91 #include <ufs/ufs/acl.h>
   92 #include <ufs/ufs/inode.h>
   93 #include <ufs/ufs/dir.h>
   94 #include <ufs/ufs/ufs_extern.h>
   95 #include <ufs/ufs/ufsmount.h>
   96 #include <ufs/ufs/ufs_wapbl.h>
   97 
   98 #include <ufs/ffs/fs.h>
   99 #include <ufs/ffs/ffs_extern.h>
  100 
  101 /* Global vfs data structures for ufs. */
  102 int (**ffs_vnodeop_p)(void *);
  103 const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
  104         { &vop_default_desc, vn_default_error },
  105         { &vop_parsepath_desc, genfs_parsepath },       /* parsepath */
  106         { &vop_lookup_desc, ufs_lookup },               /* lookup */
  107         { &vop_create_desc, ufs_create },               /* create */
  108         { &vop_whiteout_desc, ufs_whiteout },           /* whiteout */
  109         { &vop_mknod_desc, ufs_mknod },                 /* mknod */
  110         { &vop_open_desc, ufs_open },                   /* open */
  111         { &vop_close_desc, ufs_close },                 /* close */
  112         { &vop_access_desc, genfs_access },             /* access */
  113         { &vop_accessx_desc, ufs_accessx },             /* accessx */
  114         { &vop_getattr_desc, ufs_getattr },             /* getattr */
  115         { &vop_setattr_desc, ufs_setattr },             /* setattr */
  116         { &vop_read_desc, ffs_read },                   /* read */
  117         { &vop_write_desc, ffs_write },                 /* write */
  118         { &vop_fallocate_desc, genfs_eopnotsupp },      /* fallocate */
  119         { &vop_fdiscard_desc, genfs_eopnotsupp },       /* fdiscard */
  120         { &vop_ioctl_desc, genfs_enoioctl },            /* ioctl */
  121         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  122         { &vop_poll_desc, genfs_poll },                 /* poll */
  123         { &vop_kqfilter_desc, genfs_kqfilter },         /* kqfilter */
  124         { &vop_revoke_desc, genfs_revoke },             /* revoke */
  125         { &vop_mmap_desc, genfs_mmap },                 /* mmap */
  126         { &vop_fsync_desc, ffs_fsync },                 /* fsync */
  127         { &vop_seek_desc, genfs_seek },                 /* seek */
  128         { &vop_remove_desc, ufs_remove },               /* remove */
  129         { &vop_link_desc, ufs_link },                   /* link */
  130         { &vop_rename_desc, ufs_rename },               /* rename */
  131         { &vop_mkdir_desc, ufs_mkdir },                 /* mkdir */
  132         { &vop_rmdir_desc, ufs_rmdir },                 /* rmdir */
  133         { &vop_symlink_desc, ufs_symlink },             /* symlink */
  134         { &vop_readdir_desc, ufs_readdir },             /* readdir */
  135         { &vop_readlink_desc, ufs_readlink },           /* readlink */
  136         { &vop_abortop_desc, genfs_abortop },           /* abortop */
  137         { &vop_inactive_desc, ufs_inactive },           /* inactive */
  138         { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
  139         { &vop_lock_desc, genfs_lock },                 /* lock */
  140         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  141         { &vop_bmap_desc, ufs_bmap },                   /* bmap */
  142         { &vop_strategy_desc, ufs_strategy },           /* strategy */
  143         { &vop_print_desc, ufs_print },                 /* print */
  144         { &vop_islocked_desc, genfs_islocked },         /* islocked */
  145         { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
  146         { &vop_advlock_desc, ufs_advlock },             /* advlock */
  147         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
  148         { &vop_getpages_desc, genfs_getpages },         /* getpages */
  149         { &vop_putpages_desc, genfs_putpages },         /* putpages */
  150         { &vop_openextattr_desc, ffs_openextattr },     /* openextattr */
  151         { &vop_closeextattr_desc, ffs_closeextattr },   /* closeextattr */
  152         { &vop_getextattr_desc, ffs_getextattr },       /* getextattr */
  153         { &vop_setextattr_desc, ffs_setextattr },       /* setextattr */
  154         { &vop_listextattr_desc, ffs_listextattr },     /* listextattr */
  155         { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
  156         { &vop_getacl_desc, ufs_getacl },               /* getacl */
  157         { &vop_setacl_desc, ufs_setacl },               /* setacl */
  158         { &vop_aclcheck_desc, ufs_aclcheck },           /* aclcheck */
  159         { NULL, NULL }
  160 };
  161 const struct vnodeopv_desc ffs_vnodeop_opv_desc =
  162         { &ffs_vnodeop_p, ffs_vnodeop_entries };
  163 
  164 int (**ffs_specop_p)(void *);
  165 const struct vnodeopv_entry_desc ffs_specop_entries[] = {
  166         { &vop_default_desc, vn_default_error },
  167         GENFS_SPECOP_ENTRIES,
  168         { &vop_close_desc, ufsspec_close },             /* close */
  169         { &vop_access_desc, genfs_access },             /* access */
  170         { &vop_accessx_desc, ufs_accessx },             /* accessx */
  171         { &vop_getattr_desc, ufs_getattr },             /* getattr */
  172         { &vop_setattr_desc, ufs_setattr },             /* setattr */
  173         { &vop_read_desc, ufsspec_read },               /* read */
  174         { &vop_write_desc, ufsspec_write },             /* write */
  175         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  176         { &vop_fsync_desc, ffs_spec_fsync },            /* fsync */
  177         { &vop_inactive_desc, ufs_inactive },           /* inactive */
  178         { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
  179         { &vop_lock_desc, genfs_lock },                 /* lock */
  180         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  181         { &vop_print_desc, ufs_print },                 /* print */
  182         { &vop_islocked_desc, genfs_islocked },         /* islocked */
  183         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
  184         { &vop_openextattr_desc, ffs_openextattr },     /* openextattr */
  185         { &vop_closeextattr_desc, ffs_closeextattr },   /* closeextattr */
  186         { &vop_getextattr_desc, ffs_getextattr },       /* getextattr */
  187         { &vop_setextattr_desc, ffs_setextattr },       /* setextattr */
  188         { &vop_listextattr_desc, ffs_listextattr },     /* listextattr */
  189         { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
  190         { &vop_getacl_desc, ufs_getacl },               /* getacl */
  191         { &vop_setacl_desc, ufs_setacl },               /* setacl */
  192         { &vop_aclcheck_desc, ufs_aclcheck },           /* aclcheck */
  193         { NULL, NULL }
  194 };
  195 const struct vnodeopv_desc ffs_specop_opv_desc =
  196         { &ffs_specop_p, ffs_specop_entries };
  197 
  198 int (**ffs_fifoop_p)(void *);
  199 const struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
  200         { &vop_default_desc, vn_default_error },
  201         GENFS_FIFOOP_ENTRIES,
  202         { &vop_close_desc, ufsfifo_close },             /* close */
  203         { &vop_access_desc, genfs_access },             /* access */
  204         { &vop_accessx_desc, ufs_accessx },             /* accessx */
  205         { &vop_getattr_desc, ufs_getattr },             /* getattr */
  206         { &vop_setattr_desc, ufs_setattr },             /* setattr */
  207         { &vop_read_desc, ufsfifo_read },               /* read */
  208         { &vop_write_desc, ufsfifo_write },             /* write */
  209         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  210         { &vop_fsync_desc, ffs_fsync },                 /* fsync */
  211         { &vop_inactive_desc, ufs_inactive },           /* inactive */
  212         { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
  213         { &vop_lock_desc, genfs_lock },                 /* lock */
  214         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  215         { &vop_bmap_desc, ufs_bmap },                   /* bmap */
  216         { &vop_strategy_desc, ffsext_strategy },        /* strategy */
  217         { &vop_print_desc, ufs_print },                 /* print */
  218         { &vop_islocked_desc, genfs_islocked },         /* islocked */
  219         { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
  220         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
  221         { &vop_openextattr_desc, ffs_openextattr },     /* openextattr */
  222         { &vop_closeextattr_desc, ffs_closeextattr },   /* closeextattr */
  223         { &vop_getextattr_desc, ffs_getextattr },       /* getextattr */
  224         { &vop_setextattr_desc, ffs_setextattr },       /* setextattr */
  225         { &vop_listextattr_desc, ffs_listextattr },     /* listextattr */
  226         { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
  227         { &vop_getacl_desc, ufs_getacl },               /* getacl */
  228         { &vop_setacl_desc, ufs_setacl },               /* setacl */
  229         { &vop_aclcheck_desc, ufs_aclcheck },           /* aclcheck */
  230         { NULL, NULL }
  231 };
  232 const struct vnodeopv_desc ffs_fifoop_opv_desc =
  233         { &ffs_fifoop_p, ffs_fifoop_entries };
  234 
  235 #include <ufs/ufs/ufs_readwrite.c>
  236 
  237 int
  238 ffs_spec_fsync(void *v)
  239 {
  240         struct vop_fsync_args /* {
  241                 struct vnode *a_vp;
  242                 kauth_cred_t a_cred;
  243                 int a_flags;
  244                 off_t a_offlo;
  245                 off_t a_offhi;
  246                 struct lwp *a_l;
  247         } */ *ap = v;
  248         int error, flags, uflags;
  249         struct vnode *vp;
  250 
  251         flags = ap->a_flags;
  252         uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0);
  253         vp = ap->a_vp;
  254 
  255         error = spec_fsync(v);
  256         if (error)
  257                 goto out;
  258 
  259 #ifdef WAPBL
  260         struct mount *mp = vp->v_mount;
  261 
  262         if (mp && mp->mnt_wapbl) {
  263                 /*
  264                  * Don't bother writing out metadata if the syncer is
  265                  * making the request.  We will let the sync vnode
  266                  * write it out in a single burst through a call to
  267                  * VFS_SYNC().
  268                  */
  269                 if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0)
  270                         goto out;
  271                 if ((VTOI(vp)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE
  272                     | IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) != 0) {
  273                         error = UFS_WAPBL_BEGIN(mp);
  274                         if (error != 0)
  275                                 goto out;
  276                         error = ffs_update(vp, NULL, NULL, uflags);
  277                         UFS_WAPBL_END(mp);
  278                 }
  279                 goto out;
  280         }
  281 #endif /* WAPBL */
  282 
  283         error = ffs_update(vp, NULL, NULL, uflags);
  284 
  285 out:
  286         return error;
  287 }
  288 
  289 int
  290 ffs_fsync(void *v)
  291 {
  292         struct vop_fsync_args /* {
  293                 struct vnode *a_vp;
  294                 kauth_cred_t a_cred;
  295                 int a_flags;
  296                 off_t a_offlo;
  297                 off_t a_offhi;
  298                 struct lwp *a_l;
  299         } */ *ap = v;
  300         struct buf *bp;
  301         int num, error, i;
  302         struct indir ia[UFS_NIADDR + 1];
  303         int bsize;
  304         daddr_t blk_high;
  305         struct vnode *vp;
  306         struct mount *mp;
  307 
  308         vp = ap->a_vp;
  309         mp = vp->v_mount;
  310 
  311         if ((ap->a_offlo == 0 && ap->a_offhi == 0) || (vp->v_type != VREG)) {
  312                 error = ffs_full_fsync(vp, ap->a_flags);
  313                 goto out;
  314         }
  315 
  316         bsize = mp->mnt_stat.f_iosize;
  317         blk_high = ap->a_offhi / bsize;
  318         if (ap->a_offhi % bsize != 0)
  319                 blk_high++;
  320 
  321         /*
  322          * First, flush all pages in range.
  323          */
  324 
  325         rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
  326         error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
  327             round_page(ap->a_offhi), PGO_CLEANIT |
  328             ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0));
  329         if (error) {
  330                 goto out;
  331         }
  332 
  333 #ifdef WAPBL
  334         KASSERT(vp->v_type == VREG);
  335         if (mp->mnt_wapbl) {
  336                 /*
  337                  * Don't bother writing out metadata if the syncer is
  338                  * making the request.  We will let the sync vnode
  339                  * write it out in a single burst through a call to
  340                  * VFS_SYNC().
  341                  */
  342                 if ((ap->a_flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0) {
  343                         return 0;
  344                 }
  345                 error = 0;
  346                 if (vp->v_tag == VT_UFS && VTOI(vp)->i_flag &
  347                     (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY |
  348                                  IN_MODIFIED | IN_ACCESSED)) {
  349                         error = UFS_WAPBL_BEGIN(mp);
  350                         if (error) {
  351                                 return error;
  352                         }
  353                         error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |
  354                             ((ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0));
  355                         UFS_WAPBL_END(mp);
  356                 }
  357                 if (error || (ap->a_flags & FSYNC_NOLOG) != 0) {
  358                         return error;
  359                 }
  360                 error = wapbl_flush(mp->mnt_wapbl, 0);
  361                 return error;
  362         }
  363 #endif /* WAPBL */
  364 
  365         /*
  366          * Then, flush indirect blocks.
  367          */
  368 
  369         if (blk_high >= UFS_NDADDR) {
  370                 error = ufs_getlbns(vp, blk_high, ia, &num);
  371                 if (error)
  372                         goto out;
  373 
  374                 mutex_enter(&bufcache_lock);
  375                 for (i = 0; i < num; i++) {
  376                         if ((bp = incore(vp, ia[i].in_lbn)) == NULL)
  377                                 continue;
  378                         if ((bp->b_cflags & BC_BUSY) != 0 ||
  379                             (bp->b_oflags & BO_DELWRI) == 0)
  380                                 continue;
  381                         bp->b_cflags |= BC_BUSY | BC_VFLUSH;
  382                         mutex_exit(&bufcache_lock);
  383                         bawrite(bp);
  384                         mutex_enter(&bufcache_lock);
  385                 }
  386                 mutex_exit(&bufcache_lock);
  387         }
  388 
  389         if (ap->a_flags & FSYNC_WAIT) {
  390                 mutex_enter(vp->v_interlock);
  391                 while (vp->v_numoutput > 0)
  392                         cv_wait(&vp->v_cv, vp->v_interlock);
  393                 mutex_exit(vp->v_interlock);
  394         }
  395 
  396         error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |
  397             (((ap->a_flags & (FSYNC_WAIT | FSYNC_DATAONLY)) == FSYNC_WAIT)
  398             ? UPDATE_WAIT : 0));
  399 
  400         if (error == 0 && ap->a_flags & FSYNC_CACHE) {
  401                 int l = 0;
  402                 VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE,
  403                         curlwp->l_cred);
  404         }
  405 
  406 out:
  407         return error;
  408 }
  409 
  410 /*
  411  * Synch an open file.  Called for VOP_FSYNC().
  412  */
  413 /* ARGSUSED */
  414 int
  415 ffs_full_fsync(struct vnode *vp, int flags)
  416 {
  417         int error, i, uflags;
  418 
  419         KASSERT(vp->v_tag == VT_UFS);
  420         KASSERT(VTOI(vp) != NULL);
  421         KASSERT(vp->v_type != VCHR && vp->v_type != VBLK);
  422 
  423         uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0);
  424 
  425 #ifdef WAPBL
  426         struct mount *mp = vp->v_mount;
  427 
  428         if (mp && mp->mnt_wapbl) {
  429 
  430                 /*
  431                  * Flush all dirty data associated with the vnode.
  432                  */
  433                 if (vp->v_type == VREG) {
  434                         int pflags = PGO_ALLPAGES | PGO_CLEANIT;
  435 
  436                         if ((flags & FSYNC_LAZY))
  437                                 pflags |= PGO_LAZY;
  438                         if ((flags & FSYNC_WAIT))
  439                                 pflags |= PGO_SYNCIO;
  440                         rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
  441                         error = VOP_PUTPAGES(vp, 0, 0, pflags);
  442                         if (error)
  443                                 return error;
  444                 }
  445 
  446                 /*
  447                  * Don't bother writing out metadata if the syncer is
  448                  * making the request.  We will let the sync vnode
  449                  * write it out in a single burst through a call to
  450                  * VFS_SYNC().
  451                  */
  452                 if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0)
  453                         return 0;
  454 
  455                 if ((VTOI(vp)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE
  456                     | IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) != 0) {
  457                         error = UFS_WAPBL_BEGIN(mp);
  458                         if (error)
  459                                 return error;
  460                         error = ffs_update(vp, NULL, NULL, uflags);
  461                         UFS_WAPBL_END(mp);
  462                 } else {
  463                         error = 0;
  464                 }
  465                 if (error || (flags & FSYNC_NOLOG) != 0)
  466                         return error;
  467 
  468                 /*
  469                  * Don't flush the log if the vnode being flushed
  470                  * contains no dirty buffers that could be in the log.
  471                  */
  472                 if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
  473                         error = wapbl_flush(mp->mnt_wapbl, 0);
  474                         if (error)
  475                                 return error;
  476                 }
  477 
  478                 if ((flags & FSYNC_WAIT) != 0) {
  479                         mutex_enter(vp->v_interlock);
  480                         while (vp->v_numoutput != 0)
  481                                 cv_wait(&vp->v_cv, vp->v_interlock);
  482                         mutex_exit(vp->v_interlock);
  483                 }
  484 
  485                 return error;
  486         }
  487 #endif /* WAPBL */
  488 
  489         error = vflushbuf(vp, flags);
  490         if (error == 0)
  491                 error = ffs_update(vp, NULL, NULL, uflags);
  492         if (error == 0 && (flags & FSYNC_CACHE) != 0) {
  493                 i = 1;
  494                 (void)VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE,
  495                     kauth_cred_get());
  496         }
  497 
  498         return error;
  499 }
  500 
  501 /*
  502  * Reclaim an inode so that it can be used for other purposes.
  503  */
  504 int
  505 ffs_reclaim(void *v)
  506 {
  507         struct vop_reclaim_v2_args /* {
  508                 struct vnode *a_vp;
  509                 struct lwp *a_l;
  510         } */ *ap = v;
  511         struct vnode *vp = ap->a_vp;
  512         struct inode *ip = VTOI(vp);
  513         struct mount *mp = vp->v_mount;
  514         struct ufsmount *ump = ip->i_ump;
  515         void *data;
  516         int error;
  517 
  518         VOP_UNLOCK(vp);
  519 
  520         /*
  521          * The inode must be freed and updated before being removed
  522          * from its hash chain.  Other threads trying to gain a hold
  523          * or lock on the inode will be stalled.
  524          */
  525         error = UFS_WAPBL_BEGIN(mp);
  526         if (error) {
  527                 return error;
  528         }
  529         if (ip->i_nlink <= 0 && ip->i_omode != 0 &&
  530             (vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
  531                 ffs_vfree(vp, ip->i_number, ip->i_omode);
  532         UFS_WAPBL_END(mp);
  533         if ((error = ufs_reclaim(vp)) != 0) {
  534                 return (error);
  535         }
  536         if (ip->i_din.ffs1_din != NULL) {
  537                 if (ump->um_fstype == UFS1)
  538                         pool_cache_put(ffs_dinode1_cache, ip->i_din.ffs1_din);
  539                 else
  540                         pool_cache_put(ffs_dinode2_cache, ip->i_din.ffs2_din);
  541         }
  542         /*
  543          * To interlock with ffs_sync().
  544          */
  545         genfs_node_destroy(vp);
  546         mutex_enter(vp->v_interlock);
  547         data = vp->v_data;
  548         vp->v_data = NULL;
  549         mutex_exit(vp->v_interlock);
  550 
  551         /*
  552          * XXX MFS ends up here, too, to free an inode.  Should we create
  553          * XXX a separate pool for MFS inodes?
  554          */
  555         pool_cache_put(ffs_inode_cache, data);
  556         return (0);
  557 }
  558 
  559 /*
  560  * Return the last logical file offset that should be written for this file
  561  * if we're doing a write that ends at "size".
  562  */
  563 
  564 void
  565 ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
  566 {
  567         struct inode *ip = VTOI(vp);
  568         struct fs *fs = ip->i_fs;
  569         daddr_t olbn, nlbn;
  570 
  571         olbn = ffs_lblkno(fs, ip->i_size);
  572         nlbn = ffs_lblkno(fs, size);
  573         if (nlbn < UFS_NDADDR && olbn <= nlbn) {
  574                 *eobp = ffs_fragroundup(fs, size);
  575         } else {
  576                 *eobp = ffs_blkroundup(fs, size);
  577         }
  578 }

Cache object: a21be9b99534edffbb8a1773d1d4ffd5


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