123396Smckusick /* 237736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 537736Smckusick * Redistribution and use in source and binary forms are permitted 637736Smckusick * provided that the above copyright notice and this paragraph are 737736Smckusick * duplicated in all such forms and that any documentation, 837736Smckusick * advertising materials, and other materials related to such 937736Smckusick * distribution and use acknowledge that the software was developed 1037736Smckusick * by the University of California, Berkeley. The name of the 1137736Smckusick * University may not be used to endorse or promote products derived 1237736Smckusick * from this software without specific prior written permission. 1337736Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437736Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537736Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637736Smckusick * 17*39679Smckusick * @(#)lfs_balloc.c 7.6 (Berkeley) 11/30/89 1823396Smckusick */ 197443Sroot 2017099Sbloom #include "param.h" 2117099Sbloom #include "systm.h" 2217099Sbloom #include "user.h" 2317099Sbloom #include "buf.h" 2417099Sbloom #include "proc.h" 2537736Smckusick #include "file.h" 2637736Smckusick #include "vnode.h" 2737736Smckusick #include "../ufs/inode.h" 2837736Smckusick #include "../ufs/fs.h" 297443Sroot 307443Sroot /* 317443Sroot * Bmap defines the structure of file system storage 32*39679Smckusick * by returning the physical block number on a device 33*39679Smckusick * given the inode and the logical block number in a file. 347443Sroot */ 35*39679Smckusick bmap(ip, bn, bnp) 367443Sroot register struct inode *ip; 3737736Smckusick register daddr_t bn; 3837736Smckusick daddr_t *bnp; 397443Sroot { 4037736Smckusick register struct fs *fs; 4137736Smckusick register daddr_t nb; 4237736Smckusick struct buf *bp; 4337736Smckusick daddr_t *bap; 4437736Smckusick int i, j, sh; 4537736Smckusick int error; 4637736Smckusick 4737736Smckusick if (bn < 0) 4837736Smckusick return (EFBIG); 4937736Smckusick fs = ip->i_fs; 5037736Smckusick 5137736Smckusick /* 5237736Smckusick * The first NDADDR blocks are direct blocks 5337736Smckusick */ 5437736Smckusick if (bn < NDADDR) { 5537736Smckusick nb = ip->i_db[bn]; 5637736Smckusick if (nb == 0) { 5737736Smckusick *bnp = (daddr_t)-1; 5837736Smckusick return (0); 5937736Smckusick } 6037736Smckusick *bnp = fsbtodb(fs, nb); 6137736Smckusick return (0); 6237736Smckusick } 6337736Smckusick /* 64*39679Smckusick * Determine the number of levels of indirection. 6537736Smckusick */ 6637736Smckusick sh = 1; 6737736Smckusick bn -= NDADDR; 6837736Smckusick for (j = NIADDR; j > 0; j--) { 6937736Smckusick sh *= NINDIR(fs); 7037736Smckusick if (bn < sh) 7137736Smckusick break; 7237736Smckusick bn -= sh; 7337736Smckusick } 7437736Smckusick if (j == 0) 7537736Smckusick return (EFBIG); 7637736Smckusick /* 77*39679Smckusick * Fetch through the indirect blocks. 7837736Smckusick */ 7937736Smckusick nb = ip->i_ib[NIADDR - j]; 8037736Smckusick if (nb == 0) { 8137736Smckusick *bnp = (daddr_t)-1; 8237736Smckusick return (0); 8337736Smckusick } 8437736Smckusick for (; j <= NIADDR; j++) { 8537736Smckusick if (error = bread(ip->i_devvp, fsbtodb(fs, nb), 8638776Smckusick (int)fs->fs_bsize, NOCRED, &bp)) { 8737736Smckusick brelse(bp); 8837736Smckusick return (error); 8937736Smckusick } 90*39679Smckusick if ((bp->b_flags & B_CACHE) == 0) 91*39679Smckusick reassignbuf(bp, ITOV(ip)); 9237736Smckusick bap = bp->b_un.b_daddr; 9337736Smckusick sh /= NINDIR(fs); 9437736Smckusick i = (bn / sh) % NINDIR(fs); 9537736Smckusick nb = bap[i]; 9637736Smckusick if (nb == 0) { 9737736Smckusick *bnp = (daddr_t)-1; 9837736Smckusick brelse(bp); 9937736Smckusick return (0); 10037736Smckusick } 101*39679Smckusick brelse(bp); 10237736Smckusick } 10337736Smckusick *bnp = fsbtodb(fs, nb); 10437736Smckusick return (0); 10537736Smckusick } 10637736Smckusick 10737736Smckusick /* 10837736Smckusick * Balloc defines the structure of file system storage 109*39679Smckusick * by allocating the physical blocks on a device given 110*39679Smckusick * the inode and the logical block number in a file. 11137736Smckusick */ 112*39679Smckusick balloc(ip, bn, size, bpp, flags) 11337736Smckusick register struct inode *ip; 11437736Smckusick register daddr_t bn; 11537736Smckusick int size; 116*39679Smckusick struct buf **bpp; 11737736Smckusick int flags; 11837736Smckusick { 11937736Smckusick register struct fs *fs; 12037736Smckusick register daddr_t nb; 1217443Sroot struct buf *bp, *nbp; 122*39679Smckusick struct vnode *vp = ITOV(ip); 12337736Smckusick int osize, nsize, i, j, sh, error; 124*39679Smckusick daddr_t newb, lbn, *bap, pref, blkpref(); 1257443Sroot 126*39679Smckusick *bpp = (struct buf *)0; 12737736Smckusick if (bn < 0) 12837736Smckusick return (EFBIG); 1297443Sroot fs = ip->i_fs; 1307443Sroot 1317443Sroot /* 1327443Sroot * If the next write will extend the file into a new block, 1337443Sroot * and the file is currently composed of a fragment 1347443Sroot * this fragment has to be extended to be a full block. 1357443Sroot */ 1367443Sroot nb = lblkno(fs, ip->i_size); 13737736Smckusick if (nb < NDADDR && nb < bn) { 1387443Sroot osize = blksize(fs, ip, nb); 1397443Sroot if (osize < fs->fs_bsize && osize > 0) { 140*39679Smckusick error = realloccg(ip, nb, 1419165Ssam blkpref(ip, nb, (int)nb, &ip->i_db[0]), 14237736Smckusick osize, (int)fs->fs_bsize, &bp); 143*39679Smckusick if (error) 14437736Smckusick return (error); 1457443Sroot ip->i_size = (nb + 1) * fs->fs_bsize; 1467443Sroot ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); 1477443Sroot ip->i_flag |= IUPD|ICHG; 148*39679Smckusick if (flags & B_SYNC) 149*39679Smckusick bwrite(bp); 150*39679Smckusick else 151*39679Smckusick bawrite(bp); 1527443Sroot } 1537443Sroot } 1547443Sroot /* 1557443Sroot * The first NDADDR blocks are direct blocks 1567443Sroot */ 1577443Sroot if (bn < NDADDR) { 1588258Smckusick nb = ip->i_db[bn]; 159*39679Smckusick if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { 160*39679Smckusick error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); 161*39679Smckusick if (error) { 162*39679Smckusick brelse(bp); 163*39679Smckusick return (error); 164*39679Smckusick } 165*39679Smckusick *bpp = bp; 166*39679Smckusick return (0); 167*39679Smckusick } 168*39679Smckusick if (nb != 0) { 169*39679Smckusick /* 170*39679Smckusick * Consider need to reallocate a fragment. 171*39679Smckusick */ 172*39679Smckusick osize = fragroundup(fs, blkoff(fs, ip->i_size)); 173*39679Smckusick nsize = fragroundup(fs, size); 174*39679Smckusick if (nsize <= osize) { 175*39679Smckusick error = bread(vp, bn, osize, NOCRED, &bp); 176*39679Smckusick if (error) { 177*39679Smckusick brelse(bp); 178*39679Smckusick return (error); 179*39679Smckusick } 180*39679Smckusick } else { 181*39679Smckusick error = realloccg(ip, bn, 1829165Ssam blkpref(ip, bn, (int)bn, &ip->i_db[0]), 18337736Smckusick osize, nsize, &bp); 184*39679Smckusick if (error) 185*39679Smckusick return (error); 1867443Sroot } 187*39679Smckusick } else { 188*39679Smckusick if (ip->i_size < (bn + 1) * fs->fs_bsize) 189*39679Smckusick nsize = fragroundup(fs, size); 190*39679Smckusick else 191*39679Smckusick nsize = fs->fs_bsize; 192*39679Smckusick error = alloc(ip, bn, 193*39679Smckusick blkpref(ip, bn, (int)bn, &ip->i_db[0]), 194*39679Smckusick nsize, &newb); 195*39679Smckusick if (error) 19637736Smckusick return (error); 197*39679Smckusick bp = getblk(vp, bn, nsize); 198*39679Smckusick bp->b_blkno = fsbtodb(fs, newb); 199*39679Smckusick if (flags & B_CLRBUF) 200*39679Smckusick clrbuf(bp); 2017443Sroot } 202*39679Smckusick ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); 203*39679Smckusick ip->i_flag |= IUPD|ICHG; 204*39679Smckusick *bpp = bp; 20537736Smckusick return (0); 2067443Sroot } 2077443Sroot /* 208*39679Smckusick * Determine the number of levels of indirection. 2097443Sroot */ 2108258Smckusick pref = 0; 2117443Sroot sh = 1; 2128258Smckusick lbn = bn; 2137443Sroot bn -= NDADDR; 21437736Smckusick for (j = NIADDR; j > 0; j--) { 2157443Sroot sh *= NINDIR(fs); 2167443Sroot if (bn < sh) 2177443Sroot break; 2187443Sroot bn -= sh; 2197443Sroot } 22037736Smckusick if (j == 0) 22137736Smckusick return (EFBIG); 2227443Sroot /* 223*39679Smckusick * Fetch the first indirect block allocating if necessary. 2247443Sroot */ 2257443Sroot nb = ip->i_ib[NIADDR - j]; 2267443Sroot if (nb == 0) { 2279165Ssam pref = blkpref(ip, lbn, 0, (daddr_t *)0); 228*39679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) 22937736Smckusick return (error); 230*39679Smckusick nb = newb; 231*39679Smckusick bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 232*39679Smckusick clrbuf(bp); 233*39679Smckusick if ((bp->b_flags & B_CACHE) == 0) 234*39679Smckusick reassignbuf(bp, vp); 2357443Sroot /* 2367443Sroot * Write synchronously so that indirect blocks 2377443Sroot * never point at garbage. 2387443Sroot */ 239*39679Smckusick if (error = bwrite(bp)) { 240*39679Smckusick blkfree(ip, nb, fs->fs_bsize); 241*39679Smckusick return (error); 242*39679Smckusick } 2437443Sroot ip->i_ib[NIADDR - j] = nb; 2447443Sroot ip->i_flag |= IUPD|ICHG; 2457443Sroot } 2467443Sroot /* 247*39679Smckusick * Fetch through the indirect blocks, allocating as necessary. 2487443Sroot */ 249*39679Smckusick for (; ; j++) { 250*39679Smckusick error = bread(ip->i_devvp, fsbtodb(fs, nb), 251*39679Smckusick (int)fs->fs_bsize, NOCRED, &bp); 252*39679Smckusick if (error) { 2537443Sroot brelse(bp); 25437736Smckusick return (error); 2557443Sroot } 256*39679Smckusick if ((bp->b_flags & B_CACHE) == 0) 257*39679Smckusick reassignbuf(bp, vp); 2587443Sroot bap = bp->b_un.b_daddr; 2597443Sroot sh /= NINDIR(fs); 2607443Sroot i = (bn / sh) % NINDIR(fs); 2617443Sroot nb = bap[i]; 262*39679Smckusick if (j == NIADDR) 263*39679Smckusick break; 264*39679Smckusick if (nb != 0) { 265*39679Smckusick brelse(bp); 266*39679Smckusick continue; 267*39679Smckusick } 268*39679Smckusick if (pref == 0) 269*39679Smckusick pref = blkpref(ip, lbn, 0, (daddr_t *)0); 270*39679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 271*39679Smckusick brelse(bp); 272*39679Smckusick return (error); 273*39679Smckusick } 274*39679Smckusick nb = newb; 275*39679Smckusick nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 276*39679Smckusick clrbuf(nbp); 277*39679Smckusick if ((nbp->b_flags & B_CACHE) == 0) 278*39679Smckusick reassignbuf(nbp, vp); 279*39679Smckusick /* 280*39679Smckusick * Write synchronously so that indirect blocks 281*39679Smckusick * never point at garbage. 282*39679Smckusick */ 283*39679Smckusick if (error = bwrite(nbp)) { 284*39679Smckusick blkfree(ip, nb, fs->fs_bsize); 285*39679Smckusick brelse(bp); 286*39679Smckusick return (error); 287*39679Smckusick } 288*39679Smckusick bap[i] = nb; 289*39679Smckusick if (flags & B_SYNC) 290*39679Smckusick bwrite(bp); 291*39679Smckusick else 2927443Sroot bdwrite(bp); 293*39679Smckusick } 294*39679Smckusick /* 295*39679Smckusick * Get the data block, allocating if necessary. 296*39679Smckusick */ 297*39679Smckusick if (nb == 0) { 298*39679Smckusick pref = blkpref(ip, lbn, i, &bap[0]); 299*39679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 3007443Sroot brelse(bp); 301*39679Smckusick return (error); 302*39679Smckusick } 303*39679Smckusick nb = newb; 304*39679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 305*39679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 306*39679Smckusick if (flags & B_CLRBUF) 307*39679Smckusick clrbuf(nbp); 308*39679Smckusick bap[i] = nb; 309*39679Smckusick if (flags & B_SYNC) 310*39679Smckusick bwrite(bp); 311*39679Smckusick else 312*39679Smckusick bdwrite(bp); 313*39679Smckusick *bpp = nbp; 314*39679Smckusick return (0); 3157443Sroot } 316*39679Smckusick brelse(bp); 317*39679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 318*39679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 319*39679Smckusick if ((flags & B_CLRBUF) && (nbp->b_flags & (B_DONE|B_DELWRI)) == 0) { 320*39679Smckusick brelse(nbp); 321*39679Smckusick error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); 322*39679Smckusick if (error) { 323*39679Smckusick brelse(nbp); 324*39679Smckusick return (error); 325*39679Smckusick } 326*39679Smckusick } 327*39679Smckusick *bpp = nbp; 32837736Smckusick return (0); 3297443Sroot } 330