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/ext2fs/ext2fs_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 /*      $NetBSD: ext2fs_balloc.c,v 1.22 2004/03/22 19:23:08 bouyer Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)ffs_balloc.c        8.4 (Berkeley) 9/23/93
   32  * Modified for ext2fs by Manuel Bouyer.
   33  */
   34 
   35 /*
   36  * Copyright (c) 1997 Manuel Bouyer.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. All advertising materials mentioning features or use of this software
   47  *    must display the following acknowledgement:
   48  *      This product includes software developed by Manuel Bouyer.
   49  * 4. The name of the author may not be used to endorse or promote products
   50  *    derived from this software without specific prior written permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   53  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   54  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   55  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   56  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   57  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   58  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   59  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   60  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   61  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   62  *
   63  *      @(#)ffs_balloc.c        8.4 (Berkeley) 9/23/93
   64  * Modified for ext2fs by Manuel Bouyer.
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: ext2fs_balloc.c,v 1.22 2004/03/22 19:23:08 bouyer Exp $");
   69 
   70 #if defined(_KERNEL_OPT)
   71 #include "opt_uvmhist.h"
   72 #endif
   73 
   74 #include <sys/param.h>
   75 #include <sys/systm.h>
   76 #include <sys/buf.h>
   77 #include <sys/proc.h>
   78 #include <sys/file.h>
   79 #include <sys/vnode.h>
   80 #include <sys/mount.h>
   81 
   82 #include <uvm/uvm.h>
   83 
   84 #include <ufs/ufs/inode.h>
   85 #include <ufs/ufs/ufs_extern.h>
   86 
   87 #include <ufs/ext2fs/ext2fs.h>
   88 #include <ufs/ext2fs/ext2fs_extern.h>
   89 
   90 /*
   91  * Balloc defines the structure of file system storage
   92  * by allocating the physical blocks on a device given
   93  * the inode and the logical block number in a file.
   94  */
   95 int
   96 ext2fs_balloc(ip, bn, size, cred, bpp, flags)
   97         struct inode *ip;
   98         daddr_t bn;
   99         int size;
  100         struct ucred *cred;
  101         struct buf **bpp;
  102         int flags;
  103 {
  104         struct m_ext2fs *fs;
  105         daddr_t nb;
  106         struct buf *bp, *nbp;
  107         struct vnode *vp = ITOV(ip);
  108         struct indir indirs[NIADDR + 2];
  109         daddr_t newb, lbn, pref;
  110         int32_t *bap;   /* XXX ondisk32 */
  111         int num, i, error;
  112         u_int deallocated;
  113         daddr_t *blkp, *allocblk, allociblk[NIADDR + 1];
  114         int32_t *allocib;       /* XXX ondisk32 */
  115         int unwindidx = -1;
  116         UVMHIST_FUNC("ext2fs_balloc"); UVMHIST_CALLED(ubchist);
  117 
  118         UVMHIST_LOG(ubchist, "bn 0x%x", bn,0,0,0);
  119 
  120         if (bpp != NULL) {
  121                 *bpp = NULL;
  122         }
  123         if (bn < 0)
  124                 return (EFBIG);
  125         fs = ip->i_e2fs;
  126         lbn = bn;
  127 
  128         /*
  129          * The first NDADDR blocks are direct blocks
  130          */
  131         if (bn < NDADDR) {
  132                 /* XXX ondisk32 */
  133                 nb = fs2h32(ip->i_e2fs_blocks[bn]);
  134                 if (nb != 0) {
  135 
  136                         /*
  137                          * the block is already allocated, just read it.
  138                          */
  139 
  140                         if (bpp != NULL) {
  141                                 error = bread(vp, bn, fs->e2fs_bsize, NOCRED,
  142                                               &bp);
  143                                 if (error) {
  144                                         brelse(bp);
  145                                         return (error);
  146                                 }
  147                                 *bpp = bp;
  148                         }
  149                         return (0);
  150                 }
  151 
  152                 /*
  153                  * allocate a new direct block.
  154                  */
  155 
  156                 error = ext2fs_alloc(ip, bn,
  157                     ext2fs_blkpref(ip, bn, bn, &ip->i_e2fs_blocks[0]),
  158                     cred, &newb);
  159                 if (error)
  160                         return (error);
  161                 ip->i_e2fs_last_lblk = lbn;
  162                 ip->i_e2fs_last_blk = newb;
  163                 /* XXX ondisk32 */
  164                 ip->i_e2fs_blocks[bn] = h2fs32((int32_t)newb);
  165                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  166                 if (bpp != NULL) {
  167                         bp = getblk(vp, bn, fs->e2fs_bsize, 0, 0);
  168                         bp->b_blkno = fsbtodb(fs, newb);
  169                         if (flags & B_CLRBUF)
  170                                 clrbuf(bp);
  171                         *bpp = bp;
  172                 }
  173                 return (0);
  174         }
  175         /*
  176          * Determine the number of levels of indirection.
  177          */
  178         pref = 0;
  179         if ((error = ufs_getlbns(vp, bn, indirs, &num)) != 0)
  180                 return(error);
  181 #ifdef DIAGNOSTIC
  182         if (num < 1)
  183                 panic ("ext2fs_balloc: ufs_getlbns returned indirect block\n");
  184 #endif
  185         /*
  186          * Fetch the first indirect block allocating if necessary.
  187          */
  188         --num;
  189         /* XXX ondisk32 */
  190         nb = fs2h32(ip->i_e2fs_blocks[NDADDR + indirs[0].in_off]);
  191         allocib = NULL;
  192         allocblk = allociblk;
  193         if (nb == 0) {
  194                 pref = ext2fs_blkpref(ip, lbn, 0, (int32_t *)0);
  195                 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
  196                 if (error)
  197                         return (error);
  198                 nb = newb;
  199                 *allocblk++ = nb;
  200                 ip->i_e2fs_last_blk = newb;
  201                 bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0);
  202                 bp->b_blkno = fsbtodb(fs, newb);
  203                 clrbuf(bp);
  204                 /*
  205                  * Write synchronously so that indirect blocks
  206                  * never point at garbage.
  207                  */
  208                 if ((error = bwrite(bp)) != 0)
  209                         goto fail;
  210                 unwindidx = 0;
  211                 allocib = &ip->i_e2fs_blocks[NDADDR + indirs[0].in_off];
  212                 /* XXX ondisk32 */
  213                 *allocib = h2fs32((int32_t)newb);
  214                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  215         }
  216         /*
  217          * Fetch through the indirect blocks, allocating as necessary.
  218          */
  219         for (i = 1;;) {
  220                 error = bread(vp,
  221                     indirs[i].in_lbn, (int)fs->e2fs_bsize, NOCRED, &bp);
  222                 if (error) {
  223                         brelse(bp);
  224                         goto fail;
  225                 }
  226                 bap = (int32_t *)bp->b_data;    /* XXX ondisk32 */
  227                 nb = fs2h32(bap[indirs[i].in_off]);
  228                 if (i == num)
  229                         break;
  230                 i++;
  231                 if (nb != 0) {
  232                         brelse(bp);
  233                         continue;
  234                 }
  235                 pref = ext2fs_blkpref(ip, lbn, 0, (int32_t *)0);
  236                 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
  237                 if (error) {
  238                         brelse(bp);
  239                         goto fail;
  240                 }
  241                 nb = newb;
  242                 *allocblk++ = nb;
  243                 ip->i_e2fs_last_blk = newb;
  244                 nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0);
  245                 nbp->b_blkno = fsbtodb(fs, nb);
  246                 clrbuf(nbp);
  247                 /*
  248                  * Write synchronously so that indirect blocks
  249                  * never point at garbage.
  250                  */
  251                 if ((error = bwrite(nbp)) != 0) {
  252                         brelse(bp);
  253                         goto fail;
  254                 }
  255                 if (unwindidx < 0)
  256                         unwindidx = i - 1;
  257                 /* XXX ondisk32 */
  258                 bap[indirs[i - 1].in_off] = h2fs32((int32_t)nb);
  259                 /*
  260                  * If required, write synchronously, otherwise use
  261                  * delayed write.
  262                  */
  263                 if (flags & B_SYNC) {
  264                         bwrite(bp);
  265                 } else {
  266                         bdwrite(bp);
  267                 }
  268         }
  269         /*
  270          * Get the data block, allocating if necessary.
  271          */
  272         if (nb == 0) {
  273                 pref = ext2fs_blkpref(ip, lbn, indirs[num].in_off, &bap[0]);
  274                 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
  275                 if (error) {
  276                         brelse(bp);
  277                         goto fail;
  278                 }
  279                 nb = newb;
  280                 *allocblk++ = nb;
  281                 ip->i_e2fs_last_lblk = lbn;
  282                 ip->i_e2fs_last_blk = newb;
  283                 /* XXX ondisk32 */
  284                 bap[indirs[num].in_off] = h2fs32((int32_t)nb);
  285                 /*
  286                  * If required, write synchronously, otherwise use
  287                  * delayed write.
  288                  */
  289                 if (flags & B_SYNC) {
  290                         bwrite(bp);
  291                 } else {
  292                         bdwrite(bp);
  293                 }
  294                 if (bpp != NULL) {
  295                         nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
  296                         nbp->b_blkno = fsbtodb(fs, nb);
  297                         if (flags & B_CLRBUF)
  298                                 clrbuf(nbp);
  299                         *bpp = nbp;
  300                 }
  301                 return (0);
  302         }
  303         brelse(bp);
  304         if (bpp != NULL) {
  305                 if (flags & B_CLRBUF) {
  306                         error = bread(vp, lbn, (int)fs->e2fs_bsize, NOCRED,
  307                                       &nbp);
  308                         if (error) {
  309                                 brelse(nbp);
  310                                 goto fail;
  311                         }
  312                 } else {
  313                         nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
  314                         nbp->b_blkno = fsbtodb(fs, nb);
  315                 }
  316                 *bpp = nbp;
  317         }
  318         return (0);
  319 fail:
  320         /*
  321          * If we have failed part way through block allocation, we
  322          * have to deallocate any indirect blocks that we have allocated.
  323          */
  324         for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
  325                 ext2fs_blkfree(ip, *blkp);
  326                 deallocated += fs->e2fs_bsize;
  327         }
  328         if (unwindidx >= 0) {
  329                 if (unwindidx == 0) {
  330                         *allocib = 0;
  331                 } else {
  332                         int r;
  333         
  334                         r = bread(vp, indirs[unwindidx].in_lbn, 
  335                             (int)fs->e2fs_bsize, NOCRED, &bp);
  336                         if (r) {
  337                                 panic("Could not unwind indirect block, error %d", r);
  338                                 brelse(bp);
  339                         } else {
  340                                 bap = (int32_t *)bp->b_data; /* XXX ondisk32 */
  341                                 bap[indirs[unwindidx].in_off] = 0;
  342                                 if (flags & B_SYNC)
  343                                         bwrite(bp);
  344                                 else
  345                                         bdwrite(bp);
  346                         }
  347                 }
  348                 for (i = unwindidx + 1; i <= num; i++) {
  349                         bp = getblk(vp, indirs[i].in_lbn, (int)fs->e2fs_bsize,
  350                             0, 0);
  351                         bp->b_flags |= B_INVAL;
  352                         brelse(bp);
  353                 }
  354         }
  355         if (deallocated) {
  356                 ip->i_e2fs_nblock -= btodb(deallocated);
  357                 ip->i_e2fs_flags |= IN_CHANGE | IN_UPDATE;
  358         }
  359         return error;
  360 }
  361 
  362 int
  363 ext2fs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
  364     struct ucred *cred)
  365 {
  366         struct inode *ip = VTOI(vp);
  367         struct m_ext2fs *fs = ip->i_e2fs;
  368         int error, delta, bshift, bsize;
  369         UVMHIST_FUNC("ext2fs_gop_alloc"); UVMHIST_CALLED(ubchist);
  370 
  371         bshift = fs->e2fs_bshift;
  372         bsize = 1 << bshift;
  373 
  374         delta = off & (bsize - 1);
  375         off -= delta;
  376         len += delta;
  377 
  378         while (len > 0) {
  379                 bsize = min(bsize, len);
  380                 UVMHIST_LOG(ubchist, "off 0x%x len 0x%x bsize 0x%x",
  381                             off, len, bsize, 0);
  382 
  383                 error = ext2fs_balloc(ip, lblkno(fs, off), bsize, cred,
  384                     NULL, flags);
  385                 if (error) {
  386                         UVMHIST_LOG(ubchist, "error %d", error, 0,0,0);
  387                         return error;
  388                 }
  389 
  390                 /*
  391                  * increase file size now, VOP_BALLOC() requires that
  392                  * EOF be up-to-date before each call.
  393                  */
  394 
  395                 if (ip->i_e2fs_size < off + bsize) {
  396                         UVMHIST_LOG(ubchist, "old 0x%x new 0x%x",
  397                                     ip->i_e2fs_size, off + bsize,0,0);
  398                         ip->i_e2fs_size = off + bsize;
  399                 }
  400 
  401                 off += bsize;
  402                 len -= bsize;
  403         }
  404         return 0;
  405 }

Cache object: 1d7f331a5a853e7ba09119dea1ba9f2e


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