|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. 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: * @(#)ufs_bmap.c 7.13 (Berkeley) 5/8/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "buf.h" ! 39: #include "proc.h" ! 40: #include "file.h" ! 41: #include "vnode.h" ! 42: ! 43: #include "quota.h" ! 44: #include "inode.h" ! 45: #include "fs.h" ! 46: ! 47: /* ! 48: * Bmap converts a the logical block number of a file ! 49: * to its physical block number on the disk. The conversion ! 50: * is done by using the logical block number to index into ! 51: * the array of block pointers described by the dinode. ! 52: */ ! 53: bmap(ip, bn, bnp) ! 54: register struct inode *ip; ! 55: register daddr_t bn; ! 56: daddr_t *bnp; ! 57: { ! 58: register struct fs *fs; ! 59: register daddr_t nb; ! 60: struct buf *bp; ! 61: daddr_t *bap; ! 62: int i, j, sh; ! 63: int error; ! 64: ! 65: if (bn < 0) ! 66: return (EFBIG); ! 67: fs = ip->i_fs; ! 68: ! 69: /* ! 70: * The first NDADDR blocks are direct blocks ! 71: */ ! 72: if (bn < NDADDR) { ! 73: nb = ip->i_db[bn]; ! 74: if (nb == 0) { ! 75: *bnp = (daddr_t)-1; ! 76: return (0); ! 77: } ! 78: *bnp = fsbtodb(fs, nb); ! 79: return (0); ! 80: } ! 81: /* ! 82: * Determine the number of levels of indirection. ! 83: */ ! 84: sh = 1; ! 85: bn -= NDADDR; ! 86: for (j = NIADDR; j > 0; j--) { ! 87: sh *= NINDIR(fs); ! 88: if (bn < sh) ! 89: break; ! 90: bn -= sh; ! 91: } ! 92: if (j == 0) ! 93: return (EFBIG); ! 94: /* ! 95: * Fetch through the indirect blocks. ! 96: */ ! 97: nb = ip->i_ib[NIADDR - j]; ! 98: if (nb == 0) { ! 99: *bnp = (daddr_t)-1; ! 100: return (0); ! 101: } ! 102: for (; j <= NIADDR; j++) { ! 103: if (error = bread(ip->i_devvp, fsbtodb(fs, nb), ! 104: (int)fs->fs_bsize, NOCRED, &bp)) { ! 105: brelse(bp); ! 106: return (error); ! 107: } ! 108: bap = bp->b_un.b_daddr; ! 109: sh /= NINDIR(fs); ! 110: i = (bn / sh) % NINDIR(fs); ! 111: nb = bap[i]; ! 112: if (nb == 0) { ! 113: *bnp = (daddr_t)-1; ! 114: brelse(bp); ! 115: return (0); ! 116: } ! 117: brelse(bp); ! 118: } ! 119: *bnp = fsbtodb(fs, nb); ! 120: return (0); ! 121: } ! 122: ! 123: /* ! 124: * Balloc defines the structure of file system storage ! 125: * by allocating the physical blocks on a device given ! 126: * the inode and the logical block number in a file. ! 127: */ ! 128: balloc(ip, bn, size, bpp, flags) ! 129: register struct inode *ip; ! 130: register daddr_t bn; ! 131: int size; ! 132: struct buf **bpp; ! 133: int flags; ! 134: { ! 135: register struct fs *fs; ! 136: register daddr_t nb; ! 137: struct buf *bp, *nbp; ! 138: struct vnode *vp = ITOV(ip); ! 139: int osize, nsize, i, j, sh, error; ! 140: daddr_t newb, lbn, *bap, pref, blkpref(); ! 141: ! 142: *bpp = (struct buf *)0; ! 143: if (bn < 0) ! 144: return (EFBIG); ! 145: fs = ip->i_fs; ! 146: ! 147: /* ! 148: * If the next write will extend the file into a new block, ! 149: * and the file is currently composed of a fragment ! 150: * this fragment has to be extended to be a full block. ! 151: */ ! 152: nb = lblkno(fs, ip->i_size); ! 153: if (nb < NDADDR && nb < bn) { ! 154: osize = blksize(fs, ip, nb); ! 155: if (osize < fs->fs_bsize && osize > 0) { ! 156: error = realloccg(ip, nb, ! 157: blkpref(ip, nb, (int)nb, &ip->i_db[0]), ! 158: osize, (int)fs->fs_bsize, &bp); ! 159: if (error) ! 160: return (error); ! 161: ip->i_size = (nb + 1) * fs->fs_bsize; ! 162: vnode_pager_setsize(ITOV(ip), (u_long)ip->i_size); ! 163: ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); ! 164: ip->i_flag |= IUPD|ICHG; ! 165: if (flags & B_SYNC) ! 166: bwrite(bp); ! 167: else ! 168: bawrite(bp); ! 169: } ! 170: } ! 171: /* ! 172: * The first NDADDR blocks are direct blocks ! 173: */ ! 174: if (bn < NDADDR) { ! 175: nb = ip->i_db[bn]; ! 176: if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { ! 177: error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); ! 178: if (error) { ! 179: brelse(bp); ! 180: return (error); ! 181: } ! 182: *bpp = bp; ! 183: return (0); ! 184: } ! 185: if (nb != 0) { ! 186: /* ! 187: * Consider need to reallocate a fragment. ! 188: */ ! 189: osize = fragroundup(fs, blkoff(fs, ip->i_size)); ! 190: nsize = fragroundup(fs, size); ! 191: if (nsize <= osize) { ! 192: error = bread(vp, bn, osize, NOCRED, &bp); ! 193: if (error) { ! 194: brelse(bp); ! 195: return (error); ! 196: } ! 197: } else { ! 198: error = realloccg(ip, bn, ! 199: blkpref(ip, bn, (int)bn, &ip->i_db[0]), ! 200: osize, nsize, &bp); ! 201: if (error) ! 202: return (error); ! 203: } ! 204: } else { ! 205: if (ip->i_size < (bn + 1) * fs->fs_bsize) ! 206: nsize = fragroundup(fs, size); ! 207: else ! 208: nsize = fs->fs_bsize; ! 209: error = alloc(ip, bn, ! 210: blkpref(ip, bn, (int)bn, &ip->i_db[0]), ! 211: nsize, &newb); ! 212: if (error) ! 213: return (error); ! 214: bp = getblk(vp, bn, nsize); ! 215: bp->b_blkno = fsbtodb(fs, newb); ! 216: if (flags & B_CLRBUF) ! 217: clrbuf(bp); ! 218: } ! 219: ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); ! 220: ip->i_flag |= IUPD|ICHG; ! 221: *bpp = bp; ! 222: return (0); ! 223: } ! 224: /* ! 225: * Determine the number of levels of indirection. ! 226: */ ! 227: pref = 0; ! 228: sh = 1; ! 229: lbn = bn; ! 230: bn -= NDADDR; ! 231: for (j = NIADDR; j > 0; j--) { ! 232: sh *= NINDIR(fs); ! 233: if (bn < sh) ! 234: break; ! 235: bn -= sh; ! 236: } ! 237: if (j == 0) ! 238: return (EFBIG); ! 239: /* ! 240: * Fetch the first indirect block allocating if necessary. ! 241: */ ! 242: nb = ip->i_ib[NIADDR - j]; ! 243: if (nb == 0) { ! 244: pref = blkpref(ip, lbn, 0, (daddr_t *)0); ! 245: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) ! 246: return (error); ! 247: nb = newb; ! 248: bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); ! 249: clrbuf(bp); ! 250: /* ! 251: * Write synchronously so that indirect blocks ! 252: * never point at garbage. ! 253: */ ! 254: if (error = bwrite(bp)) { ! 255: blkfree(ip, nb, fs->fs_bsize); ! 256: return (error); ! 257: } ! 258: ip->i_ib[NIADDR - j] = nb; ! 259: ip->i_flag |= IUPD|ICHG; ! 260: } ! 261: /* ! 262: * Fetch through the indirect blocks, allocating as necessary. ! 263: */ ! 264: for (; ; j++) { ! 265: error = bread(ip->i_devvp, fsbtodb(fs, nb), ! 266: (int)fs->fs_bsize, NOCRED, &bp); ! 267: if (error) { ! 268: brelse(bp); ! 269: return (error); ! 270: } ! 271: bap = bp->b_un.b_daddr; ! 272: sh /= NINDIR(fs); ! 273: i = (bn / sh) % NINDIR(fs); ! 274: nb = bap[i]; ! 275: if (j == NIADDR) ! 276: break; ! 277: if (nb != 0) { ! 278: brelse(bp); ! 279: continue; ! 280: } ! 281: if (pref == 0) ! 282: pref = blkpref(ip, lbn, 0, (daddr_t *)0); ! 283: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { ! 284: brelse(bp); ! 285: return (error); ! 286: } ! 287: nb = newb; ! 288: nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); ! 289: clrbuf(nbp); ! 290: /* ! 291: * Write synchronously so that indirect blocks ! 292: * never point at garbage. ! 293: */ ! 294: if (error = bwrite(nbp)) { ! 295: blkfree(ip, nb, fs->fs_bsize); ! 296: brelse(bp); ! 297: return (error); ! 298: } ! 299: bap[i] = nb; ! 300: /* ! 301: * If required, write synchronously, otherwise use ! 302: * delayed write. If this is the first instance of ! 303: * the delayed write, reassociate the buffer with the ! 304: * file so it will be written if the file is sync'ed. ! 305: */ ! 306: if (flags & B_SYNC) { ! 307: bwrite(bp); ! 308: } else if (bp->b_flags & B_DELWRI) { ! 309: bdwrite(bp); ! 310: } else { ! 311: bdwrite(bp); ! 312: reassignbuf(bp, vp); ! 313: } ! 314: } ! 315: /* ! 316: * Get the data block, allocating if necessary. ! 317: */ ! 318: if (nb == 0) { ! 319: pref = blkpref(ip, lbn, i, &bap[0]); ! 320: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { ! 321: brelse(bp); ! 322: return (error); ! 323: } ! 324: nb = newb; ! 325: nbp = getblk(vp, lbn, fs->fs_bsize); ! 326: nbp->b_blkno = fsbtodb(fs, nb); ! 327: if (flags & B_CLRBUF) ! 328: clrbuf(nbp); ! 329: bap[i] = nb; ! 330: /* ! 331: * If required, write synchronously, otherwise use ! 332: * delayed write. If this is the first instance of ! 333: * the delayed write, reassociate the buffer with the ! 334: * file so it will be written if the file is sync'ed. ! 335: */ ! 336: if (flags & B_SYNC) { ! 337: bwrite(bp); ! 338: } else if (bp->b_flags & B_DELWRI) { ! 339: bdwrite(bp); ! 340: } else { ! 341: bdwrite(bp); ! 342: reassignbuf(bp, vp); ! 343: } ! 344: *bpp = nbp; ! 345: return (0); ! 346: } ! 347: brelse(bp); ! 348: if (flags & B_CLRBUF) { ! 349: error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); ! 350: if (error) { ! 351: brelse(nbp); ! 352: return (error); ! 353: } ! 354: } else { ! 355: nbp = getblk(vp, lbn, fs->fs_bsize); ! 356: nbp->b_blkno = fsbtodb(fs, nb); ! 357: } ! 358: *bpp = nbp; ! 359: return (0); ! 360: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.