123396Smckusick /* 237736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*47571Skarels * @(#)lfs_balloc.c 7.12 (Berkeley) 03/19/91 823396Smckusick */ 97443Sroot 1017099Sbloom #include "param.h" 1117099Sbloom #include "systm.h" 1217099Sbloom #include "buf.h" 1317099Sbloom #include "proc.h" 1437736Smckusick #include "file.h" 1537736Smckusick #include "vnode.h" 167443Sroot 17*47571Skarels #include "quota.h" 18*47571Skarels #include "inode.h" 19*47571Skarels #include "fs.h" 20*47571Skarels 217443Sroot /* 227443Sroot * Bmap defines the structure of file system storage 2339679Smckusick * by returning the physical block number on a device 2439679Smckusick * given the inode and the logical block number in a file. 257443Sroot */ 2639679Smckusick bmap(ip, bn, bnp) 277443Sroot register struct inode *ip; 2837736Smckusick register daddr_t bn; 2937736Smckusick daddr_t *bnp; 307443Sroot { 3137736Smckusick register struct fs *fs; 3237736Smckusick register daddr_t nb; 3337736Smckusick struct buf *bp; 3437736Smckusick daddr_t *bap; 3537736Smckusick int i, j, sh; 3637736Smckusick int error; 3737736Smckusick 3837736Smckusick if (bn < 0) 3937736Smckusick return (EFBIG); 4037736Smckusick fs = ip->i_fs; 4137736Smckusick 4237736Smckusick /* 4337736Smckusick * The first NDADDR blocks are direct blocks 4437736Smckusick */ 4537736Smckusick if (bn < NDADDR) { 4637736Smckusick nb = ip->i_db[bn]; 4737736Smckusick if (nb == 0) { 4837736Smckusick *bnp = (daddr_t)-1; 4937736Smckusick return (0); 5037736Smckusick } 5137736Smckusick *bnp = fsbtodb(fs, nb); 5237736Smckusick return (0); 5337736Smckusick } 5437736Smckusick /* 5539679Smckusick * Determine the number of levels of indirection. 5637736Smckusick */ 5737736Smckusick sh = 1; 5837736Smckusick bn -= NDADDR; 5937736Smckusick for (j = NIADDR; j > 0; j--) { 6037736Smckusick sh *= NINDIR(fs); 6137736Smckusick if (bn < sh) 6237736Smckusick break; 6337736Smckusick bn -= sh; 6437736Smckusick } 6537736Smckusick if (j == 0) 6637736Smckusick return (EFBIG); 6737736Smckusick /* 6839679Smckusick * Fetch through the indirect blocks. 6937736Smckusick */ 7037736Smckusick nb = ip->i_ib[NIADDR - j]; 7137736Smckusick if (nb == 0) { 7237736Smckusick *bnp = (daddr_t)-1; 7337736Smckusick return (0); 7437736Smckusick } 7537736Smckusick for (; j <= NIADDR; j++) { 7637736Smckusick if (error = bread(ip->i_devvp, fsbtodb(fs, nb), 7738776Smckusick (int)fs->fs_bsize, NOCRED, &bp)) { 7837736Smckusick brelse(bp); 7937736Smckusick return (error); 8037736Smckusick } 8137736Smckusick bap = bp->b_un.b_daddr; 8237736Smckusick sh /= NINDIR(fs); 8337736Smckusick i = (bn / sh) % NINDIR(fs); 8437736Smckusick nb = bap[i]; 8537736Smckusick if (nb == 0) { 8637736Smckusick *bnp = (daddr_t)-1; 8737736Smckusick brelse(bp); 8837736Smckusick return (0); 8937736Smckusick } 9039679Smckusick brelse(bp); 9137736Smckusick } 9237736Smckusick *bnp = fsbtodb(fs, nb); 9337736Smckusick return (0); 9437736Smckusick } 9537736Smckusick 9637736Smckusick /* 9737736Smckusick * Balloc defines the structure of file system storage 9839679Smckusick * by allocating the physical blocks on a device given 9939679Smckusick * the inode and the logical block number in a file. 10037736Smckusick */ 10139679Smckusick balloc(ip, bn, size, bpp, flags) 10237736Smckusick register struct inode *ip; 10337736Smckusick register daddr_t bn; 10437736Smckusick int size; 10539679Smckusick struct buf **bpp; 10637736Smckusick int flags; 10737736Smckusick { 10837736Smckusick register struct fs *fs; 10937736Smckusick register daddr_t nb; 1107443Sroot struct buf *bp, *nbp; 11139679Smckusick struct vnode *vp = ITOV(ip); 11237736Smckusick int osize, nsize, i, j, sh, error; 11339679Smckusick daddr_t newb, lbn, *bap, pref, blkpref(); 1147443Sroot 11539679Smckusick *bpp = (struct buf *)0; 11637736Smckusick if (bn < 0) 11737736Smckusick return (EFBIG); 1187443Sroot fs = ip->i_fs; 1197443Sroot 1207443Sroot /* 1217443Sroot * If the next write will extend the file into a new block, 1227443Sroot * and the file is currently composed of a fragment 1237443Sroot * this fragment has to be extended to be a full block. 1247443Sroot */ 1257443Sroot nb = lblkno(fs, ip->i_size); 12637736Smckusick if (nb < NDADDR && nb < bn) { 1277443Sroot osize = blksize(fs, ip, nb); 1287443Sroot if (osize < fs->fs_bsize && osize > 0) { 12939679Smckusick error = realloccg(ip, nb, 1309165Ssam blkpref(ip, nb, (int)nb, &ip->i_db[0]), 13137736Smckusick osize, (int)fs->fs_bsize, &bp); 13239679Smckusick if (error) 13337736Smckusick return (error); 1347443Sroot ip->i_size = (nb + 1) * fs->fs_bsize; 13545720Smckusick vnode_pager_setsize(ITOV(ip), (u_long)ip->i_size); 1367443Sroot ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); 1377443Sroot ip->i_flag |= IUPD|ICHG; 13839679Smckusick if (flags & B_SYNC) 13939679Smckusick bwrite(bp); 14039679Smckusick else 14139679Smckusick bawrite(bp); 1427443Sroot } 1437443Sroot } 1447443Sroot /* 1457443Sroot * The first NDADDR blocks are direct blocks 1467443Sroot */ 1477443Sroot if (bn < NDADDR) { 1488258Smckusick nb = ip->i_db[bn]; 14939679Smckusick if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { 15039679Smckusick error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); 15139679Smckusick if (error) { 15239679Smckusick brelse(bp); 15339679Smckusick return (error); 15439679Smckusick } 15539679Smckusick *bpp = bp; 15639679Smckusick return (0); 15739679Smckusick } 15839679Smckusick if (nb != 0) { 15939679Smckusick /* 16039679Smckusick * Consider need to reallocate a fragment. 16139679Smckusick */ 16239679Smckusick osize = fragroundup(fs, blkoff(fs, ip->i_size)); 16339679Smckusick nsize = fragroundup(fs, size); 16439679Smckusick if (nsize <= osize) { 16539679Smckusick error = bread(vp, bn, osize, NOCRED, &bp); 16639679Smckusick if (error) { 16739679Smckusick brelse(bp); 16839679Smckusick return (error); 16939679Smckusick } 17039679Smckusick } else { 17139679Smckusick error = realloccg(ip, bn, 1729165Ssam blkpref(ip, bn, (int)bn, &ip->i_db[0]), 17337736Smckusick osize, nsize, &bp); 17439679Smckusick if (error) 17539679Smckusick return (error); 1767443Sroot } 17739679Smckusick } else { 17839679Smckusick if (ip->i_size < (bn + 1) * fs->fs_bsize) 17939679Smckusick nsize = fragroundup(fs, size); 18039679Smckusick else 18139679Smckusick nsize = fs->fs_bsize; 18239679Smckusick error = alloc(ip, bn, 18339679Smckusick blkpref(ip, bn, (int)bn, &ip->i_db[0]), 18439679Smckusick nsize, &newb); 18539679Smckusick if (error) 18637736Smckusick return (error); 18739679Smckusick bp = getblk(vp, bn, nsize); 18839679Smckusick bp->b_blkno = fsbtodb(fs, newb); 18939679Smckusick if (flags & B_CLRBUF) 19039679Smckusick clrbuf(bp); 1917443Sroot } 19239679Smckusick ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); 19339679Smckusick ip->i_flag |= IUPD|ICHG; 19439679Smckusick *bpp = bp; 19537736Smckusick return (0); 1967443Sroot } 1977443Sroot /* 19839679Smckusick * Determine the number of levels of indirection. 1997443Sroot */ 2008258Smckusick pref = 0; 2017443Sroot sh = 1; 2028258Smckusick lbn = bn; 2037443Sroot bn -= NDADDR; 20437736Smckusick for (j = NIADDR; j > 0; j--) { 2057443Sroot sh *= NINDIR(fs); 2067443Sroot if (bn < sh) 2077443Sroot break; 2087443Sroot bn -= sh; 2097443Sroot } 21037736Smckusick if (j == 0) 21137736Smckusick return (EFBIG); 2127443Sroot /* 21339679Smckusick * Fetch the first indirect block allocating if necessary. 2147443Sroot */ 2157443Sroot nb = ip->i_ib[NIADDR - j]; 2167443Sroot if (nb == 0) { 2179165Ssam pref = blkpref(ip, lbn, 0, (daddr_t *)0); 21839679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) 21937736Smckusick return (error); 22039679Smckusick nb = newb; 22139679Smckusick bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 22239679Smckusick clrbuf(bp); 2237443Sroot /* 2247443Sroot * Write synchronously so that indirect blocks 2257443Sroot * never point at garbage. 2267443Sroot */ 22739679Smckusick if (error = bwrite(bp)) { 22839679Smckusick blkfree(ip, nb, fs->fs_bsize); 22939679Smckusick return (error); 23039679Smckusick } 2317443Sroot ip->i_ib[NIADDR - j] = nb; 2327443Sroot ip->i_flag |= IUPD|ICHG; 2337443Sroot } 2347443Sroot /* 23539679Smckusick * Fetch through the indirect blocks, allocating as necessary. 2367443Sroot */ 23739679Smckusick for (; ; j++) { 23839679Smckusick error = bread(ip->i_devvp, fsbtodb(fs, nb), 23939679Smckusick (int)fs->fs_bsize, NOCRED, &bp); 24039679Smckusick if (error) { 2417443Sroot brelse(bp); 24237736Smckusick return (error); 2437443Sroot } 2447443Sroot bap = bp->b_un.b_daddr; 2457443Sroot sh /= NINDIR(fs); 2467443Sroot i = (bn / sh) % NINDIR(fs); 2477443Sroot nb = bap[i]; 24839679Smckusick if (j == NIADDR) 24939679Smckusick break; 25039679Smckusick if (nb != 0) { 25139679Smckusick brelse(bp); 25239679Smckusick continue; 25339679Smckusick } 25439679Smckusick if (pref == 0) 25539679Smckusick pref = blkpref(ip, lbn, 0, (daddr_t *)0); 25639679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 25739679Smckusick brelse(bp); 25839679Smckusick return (error); 25939679Smckusick } 26039679Smckusick nb = newb; 26139679Smckusick nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 26239679Smckusick clrbuf(nbp); 26339679Smckusick /* 26439679Smckusick * Write synchronously so that indirect blocks 26539679Smckusick * never point at garbage. 26639679Smckusick */ 26739679Smckusick if (error = bwrite(nbp)) { 26839679Smckusick blkfree(ip, nb, fs->fs_bsize); 26939679Smckusick brelse(bp); 27039679Smckusick return (error); 27139679Smckusick } 27239679Smckusick bap[i] = nb; 27339878Smckusick /* 27439878Smckusick * If required, write synchronously, otherwise use 27539878Smckusick * delayed write. If this is the first instance of 27639878Smckusick * the delayed write, reassociate the buffer with the 27739878Smckusick * file so it will be written if the file is sync'ed. 27839878Smckusick */ 27939878Smckusick if (flags & B_SYNC) { 28039679Smckusick bwrite(bp); 28139878Smckusick } else if (bp->b_flags & B_DELWRI) { 2827443Sroot bdwrite(bp); 28339878Smckusick } else { 28439878Smckusick bdwrite(bp); 28539878Smckusick reassignbuf(bp, vp); 28639878Smckusick } 28739679Smckusick } 28839679Smckusick /* 28939679Smckusick * Get the data block, allocating if necessary. 29039679Smckusick */ 29139679Smckusick if (nb == 0) { 29239679Smckusick pref = blkpref(ip, lbn, i, &bap[0]); 29339679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 2947443Sroot brelse(bp); 29539679Smckusick return (error); 29639679Smckusick } 29739679Smckusick nb = newb; 29839679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 29939679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 30039679Smckusick if (flags & B_CLRBUF) 30139679Smckusick clrbuf(nbp); 30239679Smckusick bap[i] = nb; 30339878Smckusick /* 30439878Smckusick * If required, write synchronously, otherwise use 30539878Smckusick * delayed write. If this is the first instance of 30639878Smckusick * the delayed write, reassociate the buffer with the 30739878Smckusick * file so it will be written if the file is sync'ed. 30839878Smckusick */ 30939878Smckusick if (flags & B_SYNC) { 31039679Smckusick bwrite(bp); 31139878Smckusick } else if (bp->b_flags & B_DELWRI) { 31239679Smckusick bdwrite(bp); 31339878Smckusick } else { 31439878Smckusick bdwrite(bp); 31539878Smckusick reassignbuf(bp, vp); 31639878Smckusick } 31739679Smckusick *bpp = nbp; 31839679Smckusick return (0); 3197443Sroot } 32039679Smckusick brelse(bp); 32141333Smckusick if (flags & B_CLRBUF) { 32239679Smckusick error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); 32339679Smckusick if (error) { 32439679Smckusick brelse(nbp); 32539679Smckusick return (error); 32639679Smckusick } 32741333Smckusick } else { 32841333Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 32941333Smckusick nbp->b_blkno = fsbtodb(fs, nb); 33039679Smckusick } 33139679Smckusick *bpp = nbp; 33237736Smckusick return (0); 3337443Sroot } 334