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 /*
    2  * Copyright (c) 1982, 1986, 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
   34  * $FreeBSD$
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/resourcevar.h>
   40 #include <sys/signalvar.h>
   41 #include <sys/kernel.h>
   42 #include <sys/stat.h>
   43 #include <sys/buf.h>
   44 #include <sys/proc.h>
   45 #include <sys/mount.h>
   46 #include <sys/vnode.h>
   47 
   48 #include <machine/limits.h>
   49 
   50 #include <vm/vm.h>
   51 #include <vm/vm_prot.h>
   52 #include <vm/vm_page.h>
   53 #include <vm/vm_object.h>
   54 #include <vm/vm_extern.h>
   55 
   56 #include <ufs/ufs/quota.h>
   57 #include <ufs/ufs/inode.h>
   58 #include <ufs/ufs/ufsmount.h>
   59 #include <ufs/ufs/ufs_extern.h>
   60 
   61 #include <ufs/ffs/fs.h>
   62 #include <ufs/ffs/ffs_extern.h>
   63 
   64 static int      ffs_fsync __P((struct vop_fsync_args *));
   65 static int      ffs_getpages __P((struct vop_getpages_args *));
   66 static int      ffs_putpages __P((struct vop_putpages_args *));
   67 static int      ffs_read __P((struct vop_read_args *));
   68 static int      ffs_write __P((struct vop_write_args *));
   69 
   70 /* Global vfs data structures for ufs. */
   71 vop_t **ffs_vnodeop_p;
   72 static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
   73         { &vop_default_desc,            (vop_t *) ufs_vnoperate },
   74         { &vop_fsync_desc,              (vop_t *) ffs_fsync },
   75         { &vop_getpages_desc,           (vop_t *) ffs_getpages },
   76         { &vop_putpages_desc,           (vop_t *) ffs_putpages },
   77         { &vop_read_desc,               (vop_t *) ffs_read },
   78         { &vop_balloc_desc,             (vop_t *) ffs_balloc },
   79         { &vop_reallocblks_desc,        (vop_t *) ffs_reallocblks },
   80         { &vop_write_desc,              (vop_t *) ffs_write },
   81         { NULL, NULL }
   82 };
   83 static struct vnodeopv_desc ffs_vnodeop_opv_desc =
   84         { &ffs_vnodeop_p, ffs_vnodeop_entries };
   85 
   86 vop_t **ffs_specop_p;
   87 static struct vnodeopv_entry_desc ffs_specop_entries[] = {
   88         { &vop_default_desc,            (vop_t *) ufs_vnoperatespec },
   89         { &vop_fsync_desc,              (vop_t *) ffs_fsync },
   90         { NULL, NULL }
   91 };
   92 static struct vnodeopv_desc ffs_specop_opv_desc =
   93         { &ffs_specop_p, ffs_specop_entries };
   94 
   95 vop_t **ffs_fifoop_p;
   96 static struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
   97         { &vop_default_desc,            (vop_t *) ufs_vnoperatefifo },
   98         { &vop_fsync_desc,              (vop_t *) ffs_fsync },
   99         { NULL, NULL }
  100 };
  101 static struct vnodeopv_desc ffs_fifoop_opv_desc =
  102         { &ffs_fifoop_p, ffs_fifoop_entries };
  103 
  104 VNODEOP_SET(ffs_vnodeop_opv_desc);
  105 VNODEOP_SET(ffs_specop_opv_desc);
  106 VNODEOP_SET(ffs_fifoop_opv_desc);
  107 
  108 #include <ufs/ufs/ufs_readwrite.c>
  109 
  110 /*
  111  * Synch an open file.
  112  */
  113 /* ARGSUSED */
  114 static int
  115 ffs_fsync(ap)
  116         struct vop_fsync_args /* {
  117                 struct vnode *a_vp;
  118                 struct ucred *a_cred;
  119                 int a_waitfor;
  120                 struct proc *a_p;
  121         } */ *ap;
  122 {
  123         struct vnode *vp = ap->a_vp;
  124         struct buf *bp;
  125         struct buf *nbp;
  126         int s, error, passes, skipmeta;
  127         daddr_t lbn;
  128 
  129 
  130         if (vp->v_type == VBLK) {
  131                 lbn = INT_MAX;
  132         } else {
  133                 struct inode *ip;
  134                 ip = VTOI(vp);
  135                 lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1));
  136         }
  137 
  138         /*
  139          * Flush all dirty buffers associated with a vnode.
  140          */
  141         passes = NIADDR;
  142         skipmeta = 0;
  143         if (ap->a_waitfor == MNT_WAIT)
  144                 skipmeta = 1;
  145         s = splbio();
  146 loop:
  147         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp;
  148              bp = TAILQ_NEXT(bp, b_vnbufs))
  149                 bp->b_flags &= ~B_SCANNED;
  150         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
  151                 nbp = TAILQ_NEXT(bp, b_vnbufs);
  152                 /* 
  153                  * First time through on a synchronous call,
  154                  * or if it's already scheduled, skip to the next 
  155                  * buffer
  156                  */
  157                 if ((bp->b_flags & (B_BUSY | B_SCANNED)) ||
  158                     ((skipmeta == 1) && (bp->b_lblkno < 0)))
  159                         continue;
  160                 if ((bp->b_flags & B_DELWRI) == 0)
  161                         panic("ffs_fsync: not dirty");
  162                 /*
  163                  * If data is outstanding to another vnode, or we were
  164                  * asked to wait for everything, or it's not a file or BDEV,
  165                  * start the IO on this buffer immediatly.
  166                  */
  167                 bp->b_flags |= B_SCANNED;
  168                 if (((bp->b_vp != vp) || (ap->a_waitfor == MNT_WAIT)) ||
  169                     ((vp->v_type != VREG) && (vp->v_type != VBLK))) {
  170 
  171                         /*
  172                          * Wait for I/O associated with indirect blocks to
  173                          * complete, since there is no way to quickly wait
  174                          * for them below.
  175                          */
  176                         if ((bp->b_vp == vp) || (ap->a_waitfor != MNT_WAIT)) {
  177                                 if ((bp->b_flags & B_CLUSTEROK) &&
  178                                     ap->a_waitfor != MNT_WAIT) {
  179                                         (void) vfs_bio_awrite(bp);
  180                                 } else {
  181                                         bremfree(bp);
  182                                         bp->b_flags |= B_BUSY;
  183                                         splx(s);
  184                                         (void) bawrite(bp);
  185                                         s = splbio();
  186                                 }
  187                         } else {
  188                                 bremfree(bp);
  189                                 bp->b_flags |= B_BUSY;
  190                                 splx(s);
  191                                 (void) bwrite(bp);
  192                                 s = splbio();
  193                         }
  194                 } else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) {
  195                         /* 
  196                          * If the buffer is for data that has been truncated
  197                          * off the file, then throw it away.
  198                          */
  199                         bremfree(bp);
  200                         bp->b_flags |= B_BUSY | B_INVAL | B_NOCACHE;
  201                         splx(s);
  202                         brelse(bp);
  203                         s = splbio();
  204                 } else {
  205                         vfs_bio_awrite(bp);
  206                 }
  207                 /*
  208                  * Since we may have slept during the I/O, we need 
  209                  * to start from a known point.
  210                  */
  211                 nbp = TAILQ_FIRST(&vp->v_dirtyblkhd);
  212         }
  213         /*
  214          * If we were asked to do this synchronously, then go back for
  215          * another pass, this time doing the metadata.
  216          */
  217         if (skipmeta) {
  218                 skipmeta = 0;
  219                 goto loop;
  220         }
  221 
  222         if (ap->a_waitfor == MNT_WAIT) {
  223                 while (vp->v_numoutput) {
  224                         vp->v_flag |= VBWAIT;
  225                         (void) tsleep((caddr_t)&vp->v_numoutput,
  226                                         PRIBIO + 4, "ffsfsn", 0);
  227                 }
  228 
  229                 /* 
  230                  * Ensure that any filesystem metatdata associated
  231                  * with the vnode has been written.
  232                  */
  233                 splx(s);
  234                 if ((error = softdep_sync_metadata(ap)) != 0)
  235                         return (error);
  236                 s = splbio();
  237 
  238                 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
  239                         /*
  240                          * Block devices associated with filesystems may
  241                          * have new I/O requests posted for them even if
  242                          * the vnode is locked, so no amount of trying will
  243                          * get them clean. Thus we give block devices a
  244                          * good effort, then just give up. For all other file
  245                          * types, go around and try again until it is clean.
  246                          */
  247                         if (passes > 0) {
  248                                 passes -= 1;
  249                                 goto loop;
  250                         }
  251 #ifdef DIAGNOSTIC
  252                         if (vp->v_type != VBLK)
  253                                 vprint("ffs_fsync: dirty", vp);
  254 #endif
  255                 }
  256         }
  257         splx(s);
  258         return (UFS_UPDATE(vp, ap->a_waitfor == MNT_WAIT));
  259 }

Cache object: 2ef57efc4cdbdcd769eaf7bb40595513


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