123396Smckusick /* 237736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 5*44537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*44537Sbostic * @(#)lfs_balloc.c 7.10 (Berkeley) 06/28/90 823396Smckusick */ 97443Sroot 1017099Sbloom #include "param.h" 1117099Sbloom #include "systm.h" 1217099Sbloom #include "user.h" 1317099Sbloom #include "buf.h" 1417099Sbloom #include "proc.h" 1537736Smckusick #include "file.h" 1637736Smckusick #include "vnode.h" 1741310Smckusick #include "../ufs/quota.h" 1837736Smckusick #include "../ufs/inode.h" 1937736Smckusick #include "../ufs/fs.h" 207443Sroot 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; 1357443Sroot ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); 1367443Sroot ip->i_flag |= IUPD|ICHG; 13739679Smckusick if (flags & B_SYNC) 13839679Smckusick bwrite(bp); 13939679Smckusick else 14039679Smckusick bawrite(bp); 1417443Sroot } 1427443Sroot } 1437443Sroot /* 1447443Sroot * The first NDADDR blocks are direct blocks 1457443Sroot */ 1467443Sroot if (bn < NDADDR) { 1478258Smckusick nb = ip->i_db[bn]; 14839679Smckusick if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { 14939679Smckusick error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); 15039679Smckusick if (error) { 15139679Smckusick brelse(bp); 15239679Smckusick return (error); 15339679Smckusick } 15439679Smckusick *bpp = bp; 15539679Smckusick return (0); 15639679Smckusick } 15739679Smckusick if (nb != 0) { 15839679Smckusick /* 15939679Smckusick * Consider need to reallocate a fragment. 16039679Smckusick */ 16139679Smckusick osize = fragroundup(fs, blkoff(fs, ip->i_size)); 16239679Smckusick nsize = fragroundup(fs, size); 16339679Smckusick if (nsize <= osize) { 16439679Smckusick error = bread(vp, bn, osize, NOCRED, &bp); 16539679Smckusick if (error) { 16639679Smckusick brelse(bp); 16739679Smckusick return (error); 16839679Smckusick } 16939679Smckusick } else { 17039679Smckusick error = realloccg(ip, bn, 1719165Ssam blkpref(ip, bn, (int)bn, &ip->i_db[0]), 17237736Smckusick osize, nsize, &bp); 17339679Smckusick if (error) 17439679Smckusick return (error); 1757443Sroot } 17639679Smckusick } else { 17739679Smckusick if (ip->i_size < (bn + 1) * fs->fs_bsize) 17839679Smckusick nsize = fragroundup(fs, size); 17939679Smckusick else 18039679Smckusick nsize = fs->fs_bsize; 18139679Smckusick error = alloc(ip, bn, 18239679Smckusick blkpref(ip, bn, (int)bn, &ip->i_db[0]), 18339679Smckusick nsize, &newb); 18439679Smckusick if (error) 18537736Smckusick return (error); 18639679Smckusick bp = getblk(vp, bn, nsize); 18739679Smckusick bp->b_blkno = fsbtodb(fs, newb); 18839679Smckusick if (flags & B_CLRBUF) 18939679Smckusick clrbuf(bp); 1907443Sroot } 19139679Smckusick ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); 19239679Smckusick ip->i_flag |= IUPD|ICHG; 19339679Smckusick *bpp = bp; 19437736Smckusick return (0); 1957443Sroot } 1967443Sroot /* 19739679Smckusick * Determine the number of levels of indirection. 1987443Sroot */ 1998258Smckusick pref = 0; 2007443Sroot sh = 1; 2018258Smckusick lbn = bn; 2027443Sroot bn -= NDADDR; 20337736Smckusick for (j = NIADDR; j > 0; j--) { 2047443Sroot sh *= NINDIR(fs); 2057443Sroot if (bn < sh) 2067443Sroot break; 2077443Sroot bn -= sh; 2087443Sroot } 20937736Smckusick if (j == 0) 21037736Smckusick return (EFBIG); 2117443Sroot /* 21239679Smckusick * Fetch the first indirect block allocating if necessary. 2137443Sroot */ 2147443Sroot nb = ip->i_ib[NIADDR - j]; 2157443Sroot if (nb == 0) { 2169165Ssam pref = blkpref(ip, lbn, 0, (daddr_t *)0); 21739679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) 21837736Smckusick return (error); 21939679Smckusick nb = newb; 22039679Smckusick bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 22139679Smckusick clrbuf(bp); 2227443Sroot /* 2237443Sroot * Write synchronously so that indirect blocks 2247443Sroot * never point at garbage. 2257443Sroot */ 22639679Smckusick if (error = bwrite(bp)) { 22739679Smckusick blkfree(ip, nb, fs->fs_bsize); 22839679Smckusick return (error); 22939679Smckusick } 2307443Sroot ip->i_ib[NIADDR - j] = nb; 2317443Sroot ip->i_flag |= IUPD|ICHG; 2327443Sroot } 2337443Sroot /* 23439679Smckusick * Fetch through the indirect blocks, allocating as necessary. 2357443Sroot */ 23639679Smckusick for (; ; j++) { 23739679Smckusick error = bread(ip->i_devvp, fsbtodb(fs, nb), 23839679Smckusick (int)fs->fs_bsize, NOCRED, &bp); 23939679Smckusick if (error) { 2407443Sroot brelse(bp); 24137736Smckusick return (error); 2427443Sroot } 2437443Sroot bap = bp->b_un.b_daddr; 2447443Sroot sh /= NINDIR(fs); 2457443Sroot i = (bn / sh) % NINDIR(fs); 2467443Sroot nb = bap[i]; 24739679Smckusick if (j == NIADDR) 24839679Smckusick break; 24939679Smckusick if (nb != 0) { 25039679Smckusick brelse(bp); 25139679Smckusick continue; 25239679Smckusick } 25339679Smckusick if (pref == 0) 25439679Smckusick pref = blkpref(ip, lbn, 0, (daddr_t *)0); 25539679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 25639679Smckusick brelse(bp); 25739679Smckusick return (error); 25839679Smckusick } 25939679Smckusick nb = newb; 26039679Smckusick nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 26139679Smckusick clrbuf(nbp); 26239679Smckusick /* 26339679Smckusick * Write synchronously so that indirect blocks 26439679Smckusick * never point at garbage. 26539679Smckusick */ 26639679Smckusick if (error = bwrite(nbp)) { 26739679Smckusick blkfree(ip, nb, fs->fs_bsize); 26839679Smckusick brelse(bp); 26939679Smckusick return (error); 27039679Smckusick } 27139679Smckusick bap[i] = nb; 27239878Smckusick /* 27339878Smckusick * If required, write synchronously, otherwise use 27439878Smckusick * delayed write. If this is the first instance of 27539878Smckusick * the delayed write, reassociate the buffer with the 27639878Smckusick * file so it will be written if the file is sync'ed. 27739878Smckusick */ 27839878Smckusick if (flags & B_SYNC) { 27939679Smckusick bwrite(bp); 28039878Smckusick } else if (bp->b_flags & B_DELWRI) { 2817443Sroot bdwrite(bp); 28239878Smckusick } else { 28339878Smckusick bdwrite(bp); 28439878Smckusick reassignbuf(bp, vp); 28539878Smckusick } 28639679Smckusick } 28739679Smckusick /* 28839679Smckusick * Get the data block, allocating if necessary. 28939679Smckusick */ 29039679Smckusick if (nb == 0) { 29139679Smckusick pref = blkpref(ip, lbn, i, &bap[0]); 29239679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 2937443Sroot brelse(bp); 29439679Smckusick return (error); 29539679Smckusick } 29639679Smckusick nb = newb; 29739679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 29839679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 29939679Smckusick if (flags & B_CLRBUF) 30039679Smckusick clrbuf(nbp); 30139679Smckusick bap[i] = nb; 30239878Smckusick /* 30339878Smckusick * If required, write synchronously, otherwise use 30439878Smckusick * delayed write. If this is the first instance of 30539878Smckusick * the delayed write, reassociate the buffer with the 30639878Smckusick * file so it will be written if the file is sync'ed. 30739878Smckusick */ 30839878Smckusick if (flags & B_SYNC) { 30939679Smckusick bwrite(bp); 31039878Smckusick } else if (bp->b_flags & B_DELWRI) { 31139679Smckusick bdwrite(bp); 31239878Smckusick } else { 31339878Smckusick bdwrite(bp); 31439878Smckusick reassignbuf(bp, vp); 31539878Smckusick } 31639679Smckusick *bpp = nbp; 31739679Smckusick return (0); 3187443Sroot } 31939679Smckusick brelse(bp); 32041333Smckusick if (flags & B_CLRBUF) { 32139679Smckusick error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); 32239679Smckusick if (error) { 32339679Smckusick brelse(nbp); 32439679Smckusick return (error); 32539679Smckusick } 32641333Smckusick } else { 32741333Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 32841333Smckusick nbp->b_blkno = fsbtodb(fs, nb); 32939679Smckusick } 33039679Smckusick *bpp = nbp; 33137736Smckusick return (0); 3327443Sroot } 333