[BACK]Return to ext2fs_alloc.c CVS log [TXT][DIR] Up to [local] / sys / ufs / ext2fs

Annotation of sys/ufs/ext2fs/ext2fs_alloc.c, Revision 1.1.1.1

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

CVSweb