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