Annotation of sys/ufs/ext2fs/ext2fs_balloc.c, Revision 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