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_balloc.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_balloc.c        8.4 (Berkeley) 9/23/93
   34  * $FreeBSD: src/sys/ufs/ffs/ffs_balloc.c,v 1.10.4.1 1999/09/05 08:23:32 peter Exp $
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/buf.h>
   40 #include <sys/proc.h>
   41 #include <sys/file.h>
   42 #include <sys/vnode.h>
   43 
   44 #include <vm/vm.h>
   45 
   46 #include <ufs/ufs/quota.h>
   47 #include <ufs/ufs/inode.h>
   48 #include <ufs/ufs/ufs_extern.h>
   49 
   50 #include <ufs/ffs/fs.h>
   51 #include <ufs/ffs/ffs_extern.h>
   52 
   53 /*
   54  * Balloc defines the structure of file system storage
   55  * by allocating the physical blocks on a device given
   56  * the inode and the logical block number in a file.
   57  */
   58 int
   59 ffs_balloc(ip, bn, size, cred, bpp, flags)
   60         register struct inode *ip;
   61         register daddr_t bn;
   62         int size;
   63         struct ucred *cred;
   64         struct buf **bpp;
   65         int flags;
   66 {
   67         register struct fs *fs;
   68         register daddr_t nb;
   69         struct buf *bp, *nbp;
   70         struct vnode *vp = ITOV(ip);
   71         struct indir indirs[NIADDR + 2];
   72         daddr_t newb, lbn, *bap, pref;
   73         int osize, nsize, num, i, error;
   74 
   75         *bpp = NULL;
   76         if (bn < 0)
   77                 return (EFBIG);
   78         fs = ip->i_fs;
   79         lbn = bn;
   80 
   81         /*
   82          * If the next write will extend the file into a new block,
   83          * and the file is currently composed of a fragment
   84          * this fragment has to be extended to be a full block.
   85          */
   86         nb = lblkno(fs, ip->i_size);
   87         if (nb < NDADDR && nb < bn) {
   88                 osize = blksize(fs, ip, nb);
   89                 if (osize < fs->fs_bsize && osize > 0) {
   90                         error = ffs_realloccg(ip, nb,
   91                                 ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]),
   92                                 osize, (int)fs->fs_bsize, cred, &bp);
   93                         if (error)
   94                                 return (error);
   95                         ip->i_size = (nb + 1) * fs->fs_bsize;
   96                         ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
   97                         ip->i_flag |= IN_CHANGE | IN_UPDATE;
   98                         if (flags & B_SYNC)
   99                                 bwrite(bp);
  100                         else
  101                                 bawrite(bp);
  102                 }
  103         }
  104         /*
  105          * The first NDADDR blocks are direct blocks
  106          */
  107         if (bn < NDADDR) {
  108                 nb = ip->i_db[bn];
  109                 if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
  110                         error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
  111                         if (error) {
  112                                 brelse(bp);
  113                                 return (error);
  114                         }
  115                         bp->b_blkno = fsbtodb(fs, nb);
  116                         *bpp = bp;
  117                         return (0);
  118                 }
  119                 if (nb != 0) {
  120                         /*
  121                          * Consider need to reallocate a fragment.
  122                          */
  123                         osize = fragroundup(fs, blkoff(fs, ip->i_size));
  124                         nsize = fragroundup(fs, size);
  125                         if (nsize <= osize) {
  126                                 error = bread(vp, bn, osize, NOCRED, &bp);
  127                                 if (error) {
  128                                         brelse(bp);
  129                                         return (error);
  130                                 }
  131                                 bp->b_blkno = fsbtodb(fs, nb);
  132                         } else {
  133                                 error = ffs_realloccg(ip, bn,
  134                                     ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
  135                                     osize, nsize, cred, &bp);
  136                                 if (error)
  137                                         return (error);
  138                         }
  139                 } else {
  140                         if (ip->i_size < (bn + 1) * fs->fs_bsize)
  141                                 nsize = fragroundup(fs, size);
  142                         else
  143                                 nsize = fs->fs_bsize;
  144                         error = ffs_alloc(ip, bn,
  145                             ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
  146                             nsize, cred, &newb);
  147                         if (error)
  148                                 return (error);
  149                         bp = getblk(vp, bn, nsize, 0, 0);
  150                         bp->b_blkno = fsbtodb(fs, newb);
  151                         if (flags & B_CLRBUF)
  152                                 vfs_bio_clrbuf(bp);
  153                 }
  154                 ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
  155                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  156                 *bpp = bp;
  157                 return (0);
  158         }
  159         /*
  160          * Determine the number of levels of indirection.
  161          */
  162         pref = 0;
  163         error = ufs_getlbns(vp, bn, indirs, &num);
  164         if (error)
  165                 return(error);
  166 #ifdef DIAGNOSTIC
  167         if (num < 1)
  168                 panic ("ffs_balloc: ufs_bmaparray returned indirect block");
  169 #endif
  170         /*
  171          * Fetch the first indirect block allocating if necessary.
  172          */
  173         --num;
  174         nb = ip->i_ib[indirs[0].in_off];
  175         if (nb == 0) {
  176                 pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
  177                 error = ffs_alloc(ip, lbn, pref,
  178                         (int)fs->fs_bsize, cred, &newb);
  179                 if (error)
  180                         return (error);
  181                 nb = newb;
  182                 bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
  183                 bp->b_blkno = fsbtodb(fs, newb);
  184                 vfs_bio_clrbuf(bp);
  185                 /*
  186                  * Write synchronously so that indirect blocks
  187                  * never point at garbage.
  188                  */
  189                 error = bwrite(bp);
  190                 if (error) {
  191                         ffs_blkfree(ip, nb, fs->fs_bsize);
  192                         return (error);
  193                 }
  194                 ip->i_ib[indirs[0].in_off] = newb;
  195                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  196         }
  197         /*
  198          * Fetch through the indirect blocks, allocating as necessary.
  199          */
  200         for (i = 1;;) {
  201                 error = bread(vp,
  202                     indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
  203                 if (error) {
  204                         brelse(bp);
  205                         return (error);
  206                 }
  207                 bap = (daddr_t *)bp->b_data;
  208                 nb = bap[indirs[i].in_off];
  209                 if (i == num)
  210                         break;
  211                 i += 1;
  212                 if (nb != 0) {
  213                         bqrelse(bp);
  214                         continue;
  215                 }
  216                 if (pref == 0)
  217                         pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
  218                 error =
  219                     ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb);
  220                 if (error) {
  221                         brelse(bp);
  222                         return (error);
  223                 }
  224                 nb = newb;
  225                 nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
  226                 nbp->b_blkno = fsbtodb(fs, nb);
  227                 vfs_bio_clrbuf(nbp);
  228                 /*
  229                  * Write synchronously so that indirect blocks
  230                  * never point at garbage.
  231                  */
  232                 error = bwrite(nbp);
  233                 if (error) {
  234                         ffs_blkfree(ip, nb, fs->fs_bsize);
  235                         brelse(bp);
  236                         return (error);
  237                 }
  238                 bap[indirs[i - 1].in_off] = nb;
  239                 /*
  240                  * If required, write synchronously, otherwise use
  241                  * delayed write.
  242                  */
  243                 if (flags & B_SYNC) {
  244                         bwrite(bp);
  245                 } else {
  246                         bdwrite(bp);
  247                 }
  248         }
  249         /*
  250          * Get the data block, allocating if necessary.
  251          */
  252         if (nb == 0) {
  253                 pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
  254                 error = ffs_alloc(ip,
  255                     lbn, pref, (int)fs->fs_bsize, cred, &newb);
  256                 if (error) {
  257                         brelse(bp);
  258                         return (error);
  259                 }
  260                 nb = newb;
  261                 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
  262                 nbp->b_blkno = fsbtodb(fs, nb);
  263                 if (flags & B_CLRBUF)
  264                         vfs_bio_clrbuf(nbp);
  265                 bap[indirs[i].in_off] = nb;
  266                 /*
  267                  * If required, write synchronously, otherwise use
  268                  * delayed write.
  269                  */
  270                 if (flags & B_SYNC) {
  271                         bwrite(bp);
  272                 } else {
  273                         bdwrite(bp);
  274                 }
  275                 *bpp = nbp;
  276                 return (0);
  277         }
  278         brelse(bp);
  279         if (flags & B_CLRBUF) {
  280                 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
  281                 if (error) {
  282                         brelse(nbp);
  283                         return (error);
  284                 }
  285         } else {
  286                 nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
  287                 nbp->b_blkno = fsbtodb(fs, nb);
  288         }
  289         *bpp = nbp;
  290         return (0);
  291 }

Cache object: 8ba2cb864bd83899f0d607cf20e47222


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