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

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

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

CVSweb