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

          Line data    Source code
       1             : /*      $OpenBSD: ext2fs_alloc.c,v 1.36 2016/06/03 18:00:10 natano Exp $        */
       2             : /*      $NetBSD: ext2fs_alloc.c,v 1.10 2001/07/05 08:38:27 toshii 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_alloc.c 8.11 (Berkeley) 10/27/94
      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             : #include <sys/mount.h>
      42             : #include <sys/syslog.h>
      43             : 
      44             : #include <ufs/ufs/quota.h>
      45             : #include <ufs/ufs/inode.h>
      46             : #include <ufs/ufs/ufsmount.h>
      47             : #include <ufs/ufs/ufs_extern.h>
      48             : 
      49             : #include <ufs/ext2fs/ext2fs.h>
      50             : #include <ufs/ext2fs/ext2fs_extern.h>
      51             : 
      52             : u_long ext2gennumber;
      53             : 
      54             : static u_int32_t        ext2fs_alloccg(struct inode *, int, u_int32_t, int);
      55             : static int              ext2fs_dirpref(struct m_ext2fs *);
      56             : static void             ext2fs_fserr(struct m_ext2fs *, uid_t, char *);
      57             : static u_int32_t        ext2fs_hashalloc(struct inode *, int, u_int32_t, int,
      58             :                             u_int32_t (*)(struct inode *, int, u_int32_t, int));
      59             : static ufsino_t         ext2fs_nodealloccg(struct inode *, int, ufsino_t, int);
      60             : static u_int32_t        ext2fs_mapsearch(struct m_ext2fs *, char *, u_int32_t);
      61             : 
      62             : /*
      63             :  * Allocate a block in the file system.
      64             :  *
      65             :  * A preference may be optionally specified. If a preference is given
      66             :  * the following hierarchy is used to allocate a block:
      67             :  *   1) allocate the requested block.
      68             :  *   2) allocate a rotationally optimal block in the same cylinder.
      69             :  *   3) allocate a block in the same cylinder group.
      70             :  *   4) quadratically rehash into other cylinder groups, until an
      71             :  *        available block is located.
      72             :  * If no block preference is given the following hierarchy is used
      73             :  * to allocate a block:
      74             :  *   1) allocate a block in the cylinder group that contains the
      75             :  *        inode for the file.
      76             :  *   2) quadratically rehash into other cylinder groups, until an
      77             :  *        available block is located.
      78             :  */
      79             : int
      80           0 : ext2fs_alloc(struct inode *ip, u_int32_t lbn, u_int32_t bpref,
      81             :     struct ucred *cred, u_int32_t *bnp)
      82             : {
      83             :         struct m_ext2fs *fs;
      84             :         u_int32_t bno;
      85             :         int cg;
      86             : 
      87           0 :         *bnp = 0;
      88           0 :         fs = ip->i_e2fs;
      89             : #ifdef DIAGNOSTIC
      90           0 :         if (cred == NOCRED)
      91           0 :                 panic("ext2fs_alloc: missing credential");
      92             : #endif /* DIAGNOSTIC */
      93           0 :         if (fs->e2fs.e2fs_fbcount == 0)
      94             :                 goto nospace;
      95           0 :         if (cred->cr_uid != 0 && freespace(fs) <= 0)
      96             :                 goto nospace;
      97           0 :         if (bpref >= fs->e2fs.e2fs_bcount)
      98           0 :                 bpref = 0;
      99           0 :         if (bpref == 0)
     100           0 :                 cg = ino_to_cg(fs, ip->i_number);
     101             :         else
     102           0 :                 cg = dtog(fs, bpref);
     103           0 :         bno = ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2fs_alloccg);
     104           0 :         if (bno > 0) {
     105           0 :                 ip->i_e2fs_nblock += btodb(fs->e2fs_bsize);
     106           0 :                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
     107           0 :                 *bnp = bno;
     108           0 :                 return (0);
     109             :         }
     110             : nospace:
     111           0 :         ext2fs_fserr(fs, cred->cr_uid, "file system full");
     112           0 :         uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt);
     113           0 :         return (ENOSPC);
     114           0 : }
     115             : 
     116             : /*
     117             :  * Allocate an inode in the file system.
     118             :  *
     119             :  * If allocating a directory, use ext2fs_dirpref to select the inode.
     120             :  * If allocating in a directory, the following hierarchy is followed:
     121             :  *   1) allocate the preferred inode.
     122             :  *   2) allocate an inode in the same cylinder group.
     123             :  *   3) quadratically rehash into other cylinder groups, until an
     124             :  *        available inode is located.
     125             :  * If no inode preference is given the following hierarchy is used
     126             :  * to allocate an inode:
     127             :  *   1) allocate an inode in cylinder group 0.
     128             :  *   2) quadratically rehash into other cylinder groups, until an
     129             :  *        available inode is located.
     130             :  */
     131             : int
     132           0 : ext2fs_inode_alloc(struct inode *pip, mode_t mode, struct ucred *cred,
     133             :     struct vnode **vpp)
     134             : {
     135             :         struct vnode *pvp;
     136             :         struct m_ext2fs *fs;
     137             :         struct inode *ip;
     138             :         ufsino_t ino, ipref;
     139             :         int cg, error;
     140             : 
     141           0 :         *vpp = NULL;
     142           0 :         pvp = ITOV(pip);
     143           0 :         fs = pip->i_e2fs;
     144           0 :         if (fs->e2fs.e2fs_ficount == 0)
     145             :                 goto noinodes;
     146             : 
     147           0 :         if ((mode & IFMT) == IFDIR)
     148           0 :                 cg = ext2fs_dirpref(fs);
     149             :         else
     150           0 :                 cg = ino_to_cg(fs, pip->i_number);
     151           0 :         ipref = cg * fs->e2fs.e2fs_ipg + 1;
     152           0 :         ino = ext2fs_hashalloc(pip, cg, ipref, mode, ext2fs_nodealloccg);
     153           0 :         if (ino == 0)
     154             :                 goto noinodes;
     155           0 :         error = VFS_VGET(pvp->v_mount, ino, vpp);
     156           0 :         if (error) {
     157           0 :                 ext2fs_inode_free(pip, ino, mode);
     158           0 :                 return (error);
     159             :         }
     160           0 :         ip = VTOI(*vpp);
     161           0 :         if (ip->i_e2fs_mode && ip->i_e2fs_nlink != 0) {
     162           0 :                 printf("mode = 0%o, nlinks %u, inum = %u, fs = %s\n",
     163           0 :                     ip->i_e2fs_mode, ip->i_e2fs_nlink, ip->i_number,
     164           0 :                     fs->e2fs_fsmnt);
     165           0 :                 panic("ext2fs_valloc: dup alloc");
     166             :         }
     167             : 
     168           0 :         memset(ip->i_e2din, 0, sizeof(struct ext2fs_dinode));
     169             : 
     170             :         /*
     171             :          * Set up a new generation number for this inode.
     172             :          */
     173           0 :         if (++ext2gennumber < (u_long)time_second)
     174           0 :                 ext2gennumber = time_second;
     175           0 :         ip->i_e2fs_gen = ext2gennumber;
     176           0 :         return (0);
     177             :  noinodes:
     178           0 :         ext2fs_fserr(fs, cred->cr_uid, "out of inodes");
     179           0 :         uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
     180           0 :         return (ENOSPC);
     181           0 : }
     182             : 
     183             : /*
     184             :  * Find a cylinder to place a directory.
     185             :  *
     186             :  * The policy implemented by this algorithm is to select from
     187             :  * among those cylinder groups with above the average number of
     188             :  * free inodes, the one with the smallest number of directories.
     189             :  */
     190             : static int
     191           0 : ext2fs_dirpref(struct m_ext2fs *fs)
     192             : {
     193             :         int cg, maxspace, mincg, avgifree;
     194             : 
     195           0 :         avgifree = fs->e2fs.e2fs_ficount / fs->e2fs_ncg;
     196             :         maxspace = 0;
     197             :         mincg = -1;
     198           0 :         for (cg = 0; cg < fs->e2fs_ncg; cg++)
     199           0 :                 if ( fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) {
     200           0 :                         if (mincg == -1 || fs->e2fs_gd[cg].ext2bgd_nbfree > maxspace) {
     201             :                                 mincg = cg;
     202           0 :                                 maxspace = fs->e2fs_gd[cg].ext2bgd_nbfree;
     203           0 :                         }
     204             :                 }
     205           0 :         return mincg;
     206             : }
     207             : 
     208             : /*
     209             :  * Select the desired position for the next block in a file.  The file is
     210             :  * logically divided into sections. The first section is composed of the
     211             :  * direct blocks. Each additional section contains fs_maxbpg blocks.
     212             :  *
     213             :  * If no blocks have been allocated in the first section, the policy is to
     214             :  * request a block in the same cylinder group as the inode that describes
     215             :  * the file. Otherwise, the policy is to try to allocate the blocks
     216             :  * contigously. The two fields of the ext2 inode extension (see
     217             :  * ufs/ufs/inode.h) help this.
     218             :  */
     219             : daddr_t
     220           0 : ext2fs_blkpref(struct inode *ip, u_int32_t lbn, int baps, u_int32_t *bap)
     221             : {
     222             :         struct m_ext2fs *fs;
     223             :         int cg, i;
     224             : 
     225           0 :         fs = ip->i_e2fs;
     226             :         /*
     227             :          * if we are doing contigous lbn allocation, try to alloc blocks
     228             :          * contigously on disk
     229             :          */
     230             : 
     231           0 :         if ( ip->i_e2fs_last_blk && lbn == ip->i_e2fs_last_lblk + 1) {
     232           0 :                 return ip->i_e2fs_last_blk + 1;
     233             :         }
     234             : 
     235             :         /*
     236             :          * bap, if provided, gives us a list of blocks to which we want to
     237             :          * stay close
     238             :          */
     239             : 
     240           0 :         if (bap) {
     241           0 :                 for (i = baps; i >= 0 ; i--) {
     242           0 :                         if (bap[i]) {
     243           0 :                                 return letoh32(bap[i]) + 1;
     244             :                         }
     245             :                 }
     246             :         }
     247             : 
     248             :         /* fall back to the first block of the cylinder containing the inode */
     249             : 
     250           0 :         cg = ino_to_cg(fs, ip->i_number);
     251           0 :         return fs->e2fs.e2fs_bpg * cg + fs->e2fs.e2fs_first_dblock + 1;
     252           0 : }
     253             : 
     254             : /*
     255             :  * Implement the cylinder overflow algorithm.
     256             :  *
     257             :  * The policy implemented by this algorithm is:
     258             :  *   1) allocate the block in its requested cylinder group.
     259             :  *   2) quadratically rehash on the cylinder group number.
     260             :  *   3) brute force search for a free block.
     261             :  */
     262             : static u_int32_t
     263           0 : ext2fs_hashalloc(struct inode *ip, int cg, u_int32_t pref, int size,
     264             :     u_int32_t (*allocator)(struct inode *, int, u_int32_t, int))
     265             : {
     266             :         struct m_ext2fs *fs;
     267             :         long result;
     268             :         int i, icg = cg;
     269             : 
     270           0 :         fs = ip->i_e2fs;
     271             :         /*
     272             :          * 1: preferred cylinder group
     273             :          */
     274           0 :         result = (*allocator)(ip, cg, pref, size);
     275           0 :         if (result)
     276           0 :                 return (result);
     277             :         /*
     278             :          * 2: quadratic rehash
     279             :          */
     280           0 :         for (i = 1; i < fs->e2fs_ncg; i *= 2) {
     281           0 :                 cg += i;
     282           0 :                 if (cg >= fs->e2fs_ncg)
     283           0 :                         cg -= fs->e2fs_ncg;
     284           0 :                 result = (*allocator)(ip, cg, 0, size);
     285           0 :                 if (result)
     286           0 :                         return (result);
     287             :         }
     288             :         /*
     289             :          * 3: brute force search
     290             :          * Note that we start at i == 2, since 0 was checked initially,
     291             :          * and 1 is always checked in the quadratic rehash.
     292             :          */
     293           0 :         cg = (icg + 2) % fs->e2fs_ncg;
     294           0 :         for (i = 2; i < fs->e2fs_ncg; i++) {
     295           0 :                 result = (*allocator)(ip, cg, 0, size);
     296           0 :                 if (result)
     297           0 :                         return (result);
     298           0 :                 cg++;
     299           0 :                 if (cg == fs->e2fs_ncg)
     300             :                         cg = 0;
     301             :         }
     302           0 :         return (0);
     303           0 : }
     304             : 
     305             : /*
     306             :  * Determine whether a block can be allocated.
     307             :  *
     308             :  * Check to see if a block of the appropriate size is available,
     309             :  * and if it is, allocate it.
     310             :  */
     311             : static u_int32_t
     312           0 : ext2fs_alloccg(struct inode *ip, int cg, u_int32_t bpref, int size)
     313             : {
     314             :         struct m_ext2fs *fs;
     315             :         char *bbp;
     316           0 :         struct buf *bp;
     317             :         u_int32_t bno;
     318             :         int error, start, end, loc;
     319             : 
     320           0 :         fs = ip->i_e2fs;
     321           0 :         if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
     322           0 :                 return (0);
     323           0 :         error = bread(ip->i_devvp, fsbtodb(fs,
     324           0 :             fs->e2fs_gd[cg].ext2bgd_b_bitmap), (int)fs->e2fs_bsize, &bp);
     325           0 :         if (error || fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
     326           0 :                 brelse(bp);
     327           0 :                 return (0);
     328             :         }
     329           0 :         bbp = (char *)bp->b_data;
     330             : 
     331           0 :         if (dtog(fs, bpref) != cg)
     332           0 :                 bpref = 0;
     333           0 :         if (bpref != 0) {
     334           0 :                 bpref = dtogd(fs, bpref);
     335             :                 /*
     336             :                  * if the requested block is available, use it
     337             :                  */
     338           0 :                 if (isclr(bbp, bpref)) {
     339             :                         bno = bpref;
     340           0 :                         goto gotit;
     341             :                 }
     342             :         }
     343             :         /*
     344             :          * no blocks in the requested cylinder, so take next
     345             :          * available one in this cylinder group.
     346             :          * first try to get 8 contigous blocks, then fall back to a single
     347             :          * block.
     348             :          */
     349           0 :         if (bpref)
     350           0 :                 start = dtogd(fs, bpref) / NBBY;
     351             :         else
     352             :                 start = 0;
     353           0 :         end = howmany(fs->e2fs.e2fs_fpg, NBBY) - start;
     354           0 :         for (loc = start; loc < end; loc++) {
     355           0 :                 if (bbp[loc] == 0) {
     356           0 :                         bno = loc * NBBY;
     357           0 :                         goto gotit;
     358             :                 }
     359             :         }
     360           0 :         for (loc = 0; loc < start; loc++) {
     361           0 :                 if (bbp[loc] == 0) {
     362           0 :                         bno = loc * NBBY;
     363           0 :                         goto gotit;
     364             :                 }
     365             :         }
     366             : 
     367           0 :         bno = ext2fs_mapsearch(fs, bbp, bpref);
     368             :  gotit:
     369             : #ifdef DIAGNOSTIC
     370           0 :         if (isset(bbp, bno)) {
     371           0 :                 panic("%s: dup alloc: cg=%d bno=%u fs=%s\n",
     372           0 :                     __func__, cg, bno, fs->e2fs_fsmnt);
     373             :         }
     374             : #endif
     375           0 :         setbit(bbp, bno);
     376           0 :         fs->e2fs.e2fs_fbcount--;
     377           0 :         fs->e2fs_gd[cg].ext2bgd_nbfree--;
     378           0 :         fs->e2fs_fmod = 1;
     379           0 :         bdwrite(bp);
     380           0 :         return (cg * fs->e2fs.e2fs_fpg + fs->e2fs.e2fs_first_dblock + bno);
     381           0 : }
     382             : 
     383             : /*
     384             :  * Determine whether an inode can be allocated.
     385             :  *
     386             :  * Check to see if an inode is available, and if it is,
     387             :  * allocate it using the following policy:
     388             :  *   1) allocate the requested inode.
     389             :  *   2) allocate the next available inode after the requested
     390             :  *        inode in the specified cylinder group.
     391             :  */
     392             : static ufsino_t
     393           0 : ext2fs_nodealloccg(struct inode *ip, int cg, ufsino_t ipref, int mode)
     394             : {
     395             :         struct m_ext2fs *fs;
     396             :         char *ibp;
     397           0 :         struct buf *bp;
     398             :         int error, start, len, loc, map, i;
     399             : 
     400           0 :         ipref--; /* to avoid a lot of (ipref -1) */
     401           0 :         fs = ip->i_e2fs;
     402           0 :         if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
     403           0 :                 return (0);
     404           0 :         error = bread(ip->i_devvp, fsbtodb(fs,
     405           0 :             fs->e2fs_gd[cg].ext2bgd_i_bitmap), (int)fs->e2fs_bsize, &bp);
     406           0 :         if (error) {
     407           0 :                 brelse(bp);
     408           0 :                 return (0);
     409             :         }
     410           0 :         ibp = (char *)bp->b_data;
     411           0 :         if (ipref) {
     412           0 :                 ipref %= fs->e2fs.e2fs_ipg;
     413           0 :                 if (isclr(ibp, ipref))
     414             :                         goto gotit;
     415             :         }
     416           0 :         start = ipref / NBBY;
     417           0 :         len = howmany(fs->e2fs.e2fs_ipg - ipref, NBBY);
     418           0 :         loc = skpc(0xff, len, &ibp[start]);
     419           0 :         if (loc == 0) {
     420           0 :                 len = start + 1;
     421             :                 start = 0;
     422           0 :                 loc = skpc(0xff, len, &ibp[0]);
     423           0 :                 if (loc == 0) {
     424           0 :                         printf("cg = %d, ipref = %u, fs = %s\n",
     425           0 :                             cg, ipref, fs->e2fs_fsmnt);
     426           0 :                         panic("ext2fs_nodealloccg: map corrupted");
     427             :                         /* NOTREACHED */
     428             :                 }
     429             :         }
     430           0 :         i = start + len - loc;
     431           0 :         map = ibp[i];
     432           0 :         ipref = i * NBBY;
     433           0 :         for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
     434           0 :                 if ((map & i) == 0) {
     435             :                         goto gotit;
     436             :                 }
     437             :         }
     438           0 :         printf("fs = %s\n", fs->e2fs_fsmnt);
     439           0 :         panic("ext2fs_nodealloccg: block not in map");
     440             :         /* NOTREACHED */
     441             :  gotit:
     442           0 :         setbit(ibp, ipref);
     443           0 :         fs->e2fs.e2fs_ficount--;
     444           0 :         fs->e2fs_gd[cg].ext2bgd_nifree--;
     445           0 :         fs->e2fs_fmod = 1;
     446           0 :         if ((mode & IFMT) == IFDIR) {
     447           0 :                 fs->e2fs_gd[cg].ext2bgd_ndirs++;
     448           0 :         }
     449           0 :         bdwrite(bp);
     450           0 :         return (cg * fs->e2fs.e2fs_ipg + ipref + 1);
     451           0 : }
     452             : 
     453             : /*
     454             :  * Free a block.
     455             :  *
     456             :  * The specified block is placed back in the
     457             :  * free map.
     458             :  */
     459             : void
     460           0 : ext2fs_blkfree(struct inode *ip, u_int32_t bno)
     461             : {
     462             :         struct m_ext2fs *fs;
     463             :         char *bbp;
     464           0 :         struct buf *bp;
     465             :         int error, cg;
     466             : 
     467           0 :         fs = ip->i_e2fs;
     468           0 :         cg = dtog(fs, bno);
     469           0 :         if (bno >= fs->e2fs.e2fs_bcount) {
     470           0 :                 printf("bad block %u, ino %u\n", bno, ip->i_number);
     471           0 :                 ext2fs_fserr(fs, ip->i_e2fs_uid, "bad block");
     472           0 :                 return;
     473             :         }
     474           0 :         error = bread(ip->i_devvp,
     475           0 :             fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
     476           0 :             (int)fs->e2fs_bsize, &bp);
     477           0 :         if (error) {
     478           0 :                 brelse(bp);
     479           0 :                 return;
     480             :         }
     481           0 :         bbp = (char *)bp->b_data;
     482           0 :         bno = dtogd(fs, bno);
     483           0 :         if (isclr(bbp, bno))
     484           0 :                 panic("%s: freeing free block: dev = 0x%x, block = %u, fs = %s\n",
     485           0 :                     __func__, ip->i_dev, bno, fs->e2fs_fsmnt);
     486             : 
     487           0 :         clrbit(bbp, bno);
     488           0 :         fs->e2fs.e2fs_fbcount++;
     489           0 :         fs->e2fs_gd[cg].ext2bgd_nbfree++;
     490             : 
     491           0 :         fs->e2fs_fmod = 1;
     492           0 :         bdwrite(bp);
     493           0 : }
     494             : 
     495             : /*
     496             :  * Free an inode.
     497             :  *
     498             :  * The specified inode is placed back in the free map.
     499             :  */
     500             : void
     501           0 : ext2fs_inode_free(struct inode *pip, ufsino_t ino, mode_t mode)
     502             : {
     503             :         struct m_ext2fs *fs;
     504             :         char *ibp;
     505           0 :         struct buf *bp;
     506             :         int error, cg;
     507             : 
     508           0 :         fs = pip->i_e2fs;
     509           0 :         if (ino > fs->e2fs.e2fs_icount || ino < EXT2_FIRSTINO)
     510           0 :                 panic("ifree: range: dev = 0x%x, ino = %u, fs = %s",
     511           0 :                     pip->i_dev, ino, fs->e2fs_fsmnt);
     512           0 :         cg = ino_to_cg(fs, ino);
     513           0 :         error = bread(pip->i_devvp,
     514           0 :             fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
     515           0 :             (int)fs->e2fs_bsize, &bp);
     516           0 :         if (error) {
     517           0 :                 brelse(bp);
     518           0 :                 return;
     519             :         }
     520           0 :         ibp = (char *)bp->b_data;
     521           0 :         ino = (ino - 1) % fs->e2fs.e2fs_ipg;
     522           0 :         if (isclr(ibp, ino)) {
     523           0 :                 printf("dev = 0x%x, ino = %d, fs = %s\n",
     524           0 :                     pip->i_dev, ino, fs->e2fs_fsmnt);
     525           0 :                 if (fs->e2fs_ronly == 0)
     526           0 :                         panic("ifree: freeing free inode");
     527             :         }
     528           0 :         clrbit(ibp, ino);
     529           0 :         fs->e2fs.e2fs_ficount++;
     530           0 :         fs->e2fs_gd[cg].ext2bgd_nifree++;
     531           0 :         if ((mode & IFMT) == IFDIR) {
     532           0 :                 fs->e2fs_gd[cg].ext2bgd_ndirs--;
     533           0 :         }
     534           0 :         fs->e2fs_fmod = 1;
     535           0 :         bdwrite(bp);
     536           0 : }
     537             : 
     538             : /*
     539             :  * Find a block in the specified cylinder group.
     540             :  *
     541             :  * It is a panic if a request is made to find a block if none are
     542             :  * available.
     543             :  */
     544             : 
     545             : static u_int32_t
     546           0 : ext2fs_mapsearch(struct m_ext2fs *fs, char *bbp, u_int32_t bpref)
     547             : {
     548             :         u_int32_t bno;
     549             :         int start, len, loc, i, map;
     550             : 
     551             :         /*
     552             :          * find the fragment by searching through the free block
     553             :          * map for an appropriate bit pattern
     554             :          */
     555           0 :         if (bpref)
     556           0 :                 start = dtogd(fs, bpref) / NBBY;
     557             :         else
     558             :                 start = 0;
     559           0 :         len = howmany(fs->e2fs.e2fs_fpg, NBBY) - start;
     560           0 :         loc = skpc(0xff, len, &bbp[start]);
     561           0 :         if (loc == 0) {
     562           0 :                 len = start + 1;
     563             :                 start = 0;
     564           0 :                 loc = skpc(0xff, len, &bbp[start]);
     565           0 :                 if (loc == 0) {
     566           0 :                         printf("start = %d, len = %d, fs = %s\n",
     567           0 :                                 start, len, fs->e2fs_fsmnt);
     568           0 :                         panic("ext2fs_alloccg: map corrupted");
     569             :                         /* NOTREACHED */
     570             :                 }
     571             :         }
     572           0 :         i = start + len - loc;
     573           0 :         map = bbp[i];
     574           0 :         bno = i * NBBY;
     575           0 :         for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
     576           0 :                 if ((map & i) == 0)
     577           0 :                         return (bno);
     578             :         }
     579           0 :         printf("fs = %s\n", fs->e2fs_fsmnt);
     580           0 :         panic("ext2fs_mapsearch: block not in map");
     581             :         /* NOTREACHED */
     582             : }
     583             : 
     584             : /*
     585             :  * Fserr prints the name of a file system with an error diagnostic.
     586             :  *
     587             :  * The form of the error message is:
     588             :  *      fs: error message
     589             :  */
     590             : static void
     591           0 : ext2fs_fserr(struct m_ext2fs *fs, uid_t uid, char *cp)
     592             : {
     593           0 :         log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp);
     594           0 : }

Generated by: LCOV version 1.13