LCOV - code coverage report
Current view: top level - ufs/ext2fs - ext2fs_balloc.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 146 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ext2fs_balloc.c,v 1.26 2016/06/03 18:00:10 natano Exp $       */
       2             : /*      $NetBSD: ext2fs_balloc.c,v 1.10 2001/07/04 21:16:01 chs Exp $   */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1997 Manuel Bouyer.
       6             :  * Copyright (c) 1982, 1986, 1989, 1993
       7             :  *      The Regents of the University of California.  All rights reserved.
       8             :  *
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  * 2. Redistributions in binary form must reproduce the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer in the
      16             :  *    documentation and/or other materials provided with the distribution.
      17             :  * 3. 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             :  * Modified for ext2fs by Manuel Bouyer.
      35             :  */
      36             : 
      37             : #include <sys/param.h>
      38             : #include <sys/systm.h>
      39             : #include <sys/buf.h>
      40             : #include <sys/vnode.h>
      41             : 
      42             : #include <ufs/ufs/quota.h>
      43             : #include <ufs/ufs/inode.h>
      44             : #include <ufs/ufs/ufs_extern.h>
      45             : 
      46             : #include <ufs/ext2fs/ext2fs.h>
      47             : #include <ufs/ext2fs/ext2fs_extern.h>
      48             : 
      49             : /*
      50             :  * Balloc defines the structure of file system storage
      51             :  * by allocating the physical blocks on a device given
      52             :  * the inode and the logical block number in a file.
      53             :  */
      54             : int
      55           0 : ext2fs_buf_alloc(struct inode *ip, u_int32_t bn, int size, struct ucred *cred,
      56             :     struct buf **bpp, int flags)
      57             : {
      58             :         struct m_ext2fs *fs;
      59           0 :         struct buf *bp, *nbp;
      60           0 :         struct vnode *vp = ITOV(ip);
      61           0 :         struct indir indirs[NIADDR + 2];
      62           0 :         u_int32_t nb, newb, *bap;
      63           0 :         int num, i, error;
      64             :         u_int deallocated;
      65           0 :         u_int32_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
      66             :         int unwindidx = -1;
      67             :         daddr_t lbn, pref;
      68             : 
      69           0 :         *bpp = NULL;
      70           0 :         fs = ip->i_e2fs;
      71           0 :         lbn = bn;
      72             : 
      73             :         /*
      74             :          * The first NDADDR blocks are direct blocks
      75             :          */
      76           0 :         if (bn < NDADDR) {
      77           0 :                 nb = letoh32(ip->i_e2fs_blocks[bn]);
      78           0 :                 if (nb != 0) {
      79           0 :                         error = bread(vp, bn, fs->e2fs_bsize, &bp);
      80           0 :                         if (error) {
      81           0 :                                 brelse(bp);
      82           0 :                                 return (error);
      83             :                         }
      84           0 :                         *bpp = bp;
      85           0 :                         return (0);
      86             :                 }
      87             : 
      88             :                 /*
      89             :                  * allocate a new direct block.
      90             :                  */
      91           0 :                 error = ext2fs_alloc(ip, bn,
      92           0 :                     ext2fs_blkpref(ip, bn, (int)bn, &ip->i_e2fs_blocks[0]),
      93             :                     cred, &newb);
      94           0 :                 if (error)
      95           0 :                         return (error);
      96           0 :                 ip->i_e2fs_last_lblk = lbn;
      97           0 :                 ip->i_e2fs_last_blk = newb;
      98           0 :                 ip->i_e2fs_blocks[bn] = htole32(newb);
      99           0 :                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
     100           0 :                 bp = getblk(vp, bn, fs->e2fs_bsize, 0, 0);
     101           0 :                 bp->b_blkno = fsbtodb(fs, newb);
     102           0 :                 if (flags & B_CLRBUF)
     103           0 :                         clrbuf(bp);
     104           0 :                 *bpp = bp;
     105           0 :                 return (0);
     106             :         }
     107             :         /*
     108             :          * Determine the number of levels of indirection.
     109             :          */
     110             :         pref = 0;
     111           0 :         if ((error = ufs_getlbns(vp, bn, indirs, &num)) != 0)
     112           0 :                 return(error);
     113             : #ifdef DIAGNOSTIC
     114           0 :         if (num < 1)
     115           0 :                 panic ("ext2fs_balloc: ufs_getlbns returned indirect block");
     116             : #endif
     117             :         /*
     118             :          * Fetch the first indirect block allocating if necessary.
     119             :          */
     120           0 :         --num;
     121           0 :         nb = letoh32(ip->i_e2fs_blocks[NDADDR + indirs[0].in_off]);
     122             :         allocib = NULL;
     123           0 :         allocblk = allociblk;
     124           0 :         if (nb == 0) {
     125           0 :                 pref = ext2fs_blkpref(ip, lbn, 0, NULL);
     126           0 :                 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
     127           0 :                 if (error)
     128           0 :                         return (error);
     129           0 :                 nb = newb;
     130           0 :                 *allocblk++ = nb;
     131           0 :                 ip->i_e2fs_last_blk = newb;
     132           0 :                 bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0);
     133           0 :                 bp->b_blkno = fsbtodb(fs, newb);
     134           0 :                 clrbuf(bp);
     135             :                 /*
     136             :                  * Write synchronously so that indirect blocks
     137             :                  * never point at garbage.
     138             :                  */
     139           0 :                 if ((error = bwrite(bp)) != 0)
     140             :                         goto fail;
     141             :                 unwindidx = 0;
     142           0 :                 allocib = &ip->i_e2fs_blocks[NDADDR + indirs[0].in_off];
     143           0 :                 *allocib = htole32(newb);
     144           0 :                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
     145           0 :         }
     146             :         /*
     147             :          * Fetch through the indirect blocks, allocating as necessary.
     148             :          */
     149           0 :         for (i = 1;;) {
     150           0 :                 error = bread(vp, indirs[i].in_lbn, (int)fs->e2fs_bsize, &bp);
     151           0 :                 if (error) {
     152           0 :                         brelse(bp);
     153           0 :                         goto fail;
     154             :                 }
     155           0 :                 bap = (u_int32_t *)bp->b_data;
     156           0 :                 nb = letoh32(bap[indirs[i].in_off]);
     157           0 :                 if (i == num)
     158             :                         break;
     159           0 :                 i++;
     160           0 :                 if (nb != 0) {
     161           0 :                         brelse(bp);
     162           0 :                         continue;
     163             :                 }
     164           0 :                 pref = ext2fs_blkpref(ip, lbn, 0, NULL);
     165           0 :                 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
     166           0 :                 if (error) {
     167           0 :                         brelse(bp);
     168           0 :                         goto fail;
     169             :                 }
     170           0 :                 nb = newb;
     171           0 :                 *allocblk++ = nb;
     172           0 :                 ip->i_e2fs_last_blk = newb;
     173           0 :                 nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0);
     174           0 :                 nbp->b_blkno = fsbtodb(fs, nb);
     175           0 :                 clrbuf(nbp);
     176             :                 /*
     177             :                  * Write synchronously so that indirect blocks
     178             :                  * never point at garbage.
     179             :                  */
     180           0 :                 if ((error = bwrite(nbp)) != 0) {
     181           0 :                         brelse(bp);
     182           0 :                         goto fail;
     183             :                 }
     184           0 :                 if (unwindidx < 0)
     185           0 :                         unwindidx = i - 1;
     186           0 :                 bap[indirs[i - 1].in_off] = htole32(nb);
     187             :                 /*
     188             :                  * If required, write synchronously, otherwise use
     189             :                  * delayed write.
     190             :                  */
     191           0 :                 if (flags & B_SYNC) {
     192           0 :                         bwrite(bp);
     193           0 :                 } else {
     194           0 :                         bdwrite(bp);
     195             :                 }
     196             :         }
     197             :         /*
     198             :          * Get the data block, allocating if necessary.
     199             :          */
     200           0 :         if (nb == 0) {
     201           0 :                 pref = ext2fs_blkpref(ip, lbn, indirs[num].in_off, bap);
     202           0 :                 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
     203           0 :                 if (error) {
     204           0 :                         brelse(bp);
     205           0 :                         goto fail;
     206             :                 }
     207           0 :                 nb = newb;
     208           0 :                 *allocblk++ = nb;
     209           0 :                 ip->i_e2fs_last_lblk = lbn;
     210           0 :                 ip->i_e2fs_last_blk = newb;
     211           0 :                 bap[indirs[num].in_off] = htole32(nb);
     212             :                 /*
     213             :                  * If required, write synchronously, otherwise use
     214             :                  * delayed write.
     215             :                  */
     216           0 :                 if (flags & B_SYNC) {
     217           0 :                         bwrite(bp);
     218           0 :                 } else {
     219           0 :                         bdwrite(bp);
     220             :                 }
     221           0 :                 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
     222           0 :                 nbp->b_blkno = fsbtodb(fs, nb);
     223           0 :                 if (flags & B_CLRBUF)
     224           0 :                         clrbuf(nbp);
     225           0 :                 *bpp = nbp;
     226           0 :                 return (0);
     227             :         }
     228           0 :         brelse(bp);
     229           0 :         if (flags & B_CLRBUF) {
     230           0 :                 error = bread(vp, lbn, (int)fs->e2fs_bsize, &nbp);
     231           0 :                 if (error) {
     232           0 :                         brelse(nbp);
     233           0 :                         goto fail;
     234             :                 }
     235             :         } else {
     236           0 :                 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
     237           0 :                 nbp->b_blkno = fsbtodb(fs, nb);
     238             :         }
     239             : 
     240           0 :         *bpp = nbp;
     241           0 :         return (0);
     242             : fail:
     243             :         /*
     244             :          * If we have failed part way through block allocation, we
     245             :          * have to deallocate any indirect blocks that we have allocated.
     246             :          */
     247           0 :         for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
     248           0 :                 ext2fs_blkfree(ip, *blkp);
     249           0 :                 deallocated += fs->e2fs_bsize;
     250             :         }
     251           0 :         if (unwindidx >= 0) {
     252           0 :                 if (unwindidx == 0) {
     253           0 :                         *allocib = 0;
     254           0 :                 } else {
     255             :                         int r;
     256             : 
     257           0 :                         r = bread(vp, indirs[unwindidx].in_lbn,
     258           0 :                             (int)fs->e2fs_bsize, &bp);
     259           0 :                         if (r) {
     260           0 :                                 panic("Could not unwind indirect block, error %d", r);
     261             :                         } else {
     262           0 :                                 bap = (u_int32_t *)bp->b_data;
     263           0 :                                 bap[indirs[unwindidx].in_off] = 0;
     264           0 :                                 if (flags & B_SYNC)
     265           0 :                                         bwrite(bp);
     266             :                                 else
     267           0 :                                         bdwrite(bp);
     268             :                         }
     269             :                 }
     270           0 :                 for (i = unwindidx + 1; i <= num; i++) {
     271           0 :                         bp = getblk(vp, indirs[i].in_lbn, (int)fs->e2fs_bsize,
     272             :                             0, 0);
     273           0 :                         bp->b_flags |= B_INVAL;
     274           0 :                         brelse(bp);
     275             :                 }
     276             :         }
     277           0 :         if (deallocated) {
     278           0 :                 ip->i_e2fs_nblock -= btodb(deallocated);
     279           0 :                 ip->i_e2fs_flags |= IN_CHANGE | IN_UPDATE;
     280           0 :         }
     281           0 :         return error;
     282           0 : }

Generated by: LCOV version 1.13