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*41310Smckusick * @(#)lfs_balloc.c 7.8 (Berkeley) 05/02/90 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" 27*41310Smckusick #include "../ufs/quota.h" 2837736Smckusick #include "../ufs/inode.h" 2937736Smckusick #include "../ufs/fs.h" 307443Sroot 317443Sroot /* 327443Sroot * Bmap defines the structure of file system storage 3339679Smckusick * by returning the physical block number on a device 3439679Smckusick * given the inode and the logical block number in a file. 357443Sroot */ 3639679Smckusick bmap(ip, bn, bnp) 377443Sroot register struct inode *ip; 3837736Smckusick register daddr_t bn; 3937736Smckusick daddr_t *bnp; 407443Sroot { 4137736Smckusick register struct fs *fs; 4237736Smckusick register daddr_t nb; 4337736Smckusick struct buf *bp; 4437736Smckusick daddr_t *bap; 4537736Smckusick int i, j, sh; 4637736Smckusick int error; 4737736Smckusick 4837736Smckusick if (bn < 0) 4937736Smckusick return (EFBIG); 5037736Smckusick fs = ip->i_fs; 5137736Smckusick 5237736Smckusick /* 5337736Smckusick * The first NDADDR blocks are direct blocks 5437736Smckusick */ 5537736Smckusick if (bn < NDADDR) { 5637736Smckusick nb = ip->i_db[bn]; 5737736Smckusick if (nb == 0) { 5837736Smckusick *bnp = (daddr_t)-1; 5937736Smckusick return (0); 6037736Smckusick } 6137736Smckusick *bnp = fsbtodb(fs, nb); 6237736Smckusick return (0); 6337736Smckusick } 6437736Smckusick /* 6539679Smckusick * Determine the number of levels of indirection. 6637736Smckusick */ 6737736Smckusick sh = 1; 6837736Smckusick bn -= NDADDR; 6937736Smckusick for (j = NIADDR; j > 0; j--) { 7037736Smckusick sh *= NINDIR(fs); 7137736Smckusick if (bn < sh) 7237736Smckusick break; 7337736Smckusick bn -= sh; 7437736Smckusick } 7537736Smckusick if (j == 0) 7637736Smckusick return (EFBIG); 7737736Smckusick /* 7839679Smckusick * Fetch through the indirect blocks. 7937736Smckusick */ 8037736Smckusick nb = ip->i_ib[NIADDR - j]; 8137736Smckusick if (nb == 0) { 8237736Smckusick *bnp = (daddr_t)-1; 8337736Smckusick return (0); 8437736Smckusick } 8537736Smckusick for (; j <= NIADDR; j++) { 8637736Smckusick if (error = bread(ip->i_devvp, fsbtodb(fs, nb), 8738776Smckusick (int)fs->fs_bsize, NOCRED, &bp)) { 8837736Smckusick brelse(bp); 8937736Smckusick return (error); 9037736Smckusick } 9137736Smckusick bap = bp->b_un.b_daddr; 9237736Smckusick sh /= NINDIR(fs); 9337736Smckusick i = (bn / sh) % NINDIR(fs); 9437736Smckusick nb = bap[i]; 9537736Smckusick if (nb == 0) { 9637736Smckusick *bnp = (daddr_t)-1; 9737736Smckusick brelse(bp); 9837736Smckusick return (0); 9937736Smckusick } 10039679Smckusick brelse(bp); 10137736Smckusick } 10237736Smckusick *bnp = fsbtodb(fs, nb); 10337736Smckusick return (0); 10437736Smckusick } 10537736Smckusick 10637736Smckusick /* 10737736Smckusick * Balloc defines the structure of file system storage 10839679Smckusick * by allocating the physical blocks on a device given 10939679Smckusick * the inode and the logical block number in a file. 11037736Smckusick */ 11139679Smckusick balloc(ip, bn, size, bpp, flags) 11237736Smckusick register struct inode *ip; 11337736Smckusick register daddr_t bn; 11437736Smckusick int size; 11539679Smckusick struct buf **bpp; 11637736Smckusick int flags; 11737736Smckusick { 11837736Smckusick register struct fs *fs; 11937736Smckusick register daddr_t nb; 1207443Sroot struct buf *bp, *nbp; 12139679Smckusick struct vnode *vp = ITOV(ip); 12237736Smckusick int osize, nsize, i, j, sh, error; 12339679Smckusick daddr_t newb, lbn, *bap, pref, blkpref(); 1247443Sroot 12539679Smckusick *bpp = (struct buf *)0; 12637736Smckusick if (bn < 0) 12737736Smckusick return (EFBIG); 1287443Sroot fs = ip->i_fs; 1297443Sroot 1307443Sroot /* 1317443Sroot * If the next write will extend the file into a new block, 1327443Sroot * and the file is currently composed of a fragment 1337443Sroot * this fragment has to be extended to be a full block. 1347443Sroot */ 1357443Sroot nb = lblkno(fs, ip->i_size); 13637736Smckusick if (nb < NDADDR && nb < bn) { 1377443Sroot osize = blksize(fs, ip, nb); 1387443Sroot if (osize < fs->fs_bsize && osize > 0) { 13939679Smckusick error = realloccg(ip, nb, 1409165Ssam blkpref(ip, nb, (int)nb, &ip->i_db[0]), 14137736Smckusick osize, (int)fs->fs_bsize, &bp); 14239679Smckusick if (error) 14337736Smckusick return (error); 1447443Sroot ip->i_size = (nb + 1) * fs->fs_bsize; 1457443Sroot ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); 1467443Sroot ip->i_flag |= IUPD|ICHG; 14739679Smckusick if (flags & B_SYNC) 14839679Smckusick bwrite(bp); 14939679Smckusick else 15039679Smckusick bawrite(bp); 1517443Sroot } 1527443Sroot } 1537443Sroot /* 1547443Sroot * The first NDADDR blocks are direct blocks 1557443Sroot */ 1567443Sroot if (bn < NDADDR) { 1578258Smckusick nb = ip->i_db[bn]; 15839679Smckusick if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { 15939679Smckusick error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); 16039679Smckusick if (error) { 16139679Smckusick brelse(bp); 16239679Smckusick return (error); 16339679Smckusick } 16439679Smckusick *bpp = bp; 16539679Smckusick return (0); 16639679Smckusick } 16739679Smckusick if (nb != 0) { 16839679Smckusick /* 16939679Smckusick * Consider need to reallocate a fragment. 17039679Smckusick */ 17139679Smckusick osize = fragroundup(fs, blkoff(fs, ip->i_size)); 17239679Smckusick nsize = fragroundup(fs, size); 17339679Smckusick if (nsize <= osize) { 17439679Smckusick error = bread(vp, bn, osize, NOCRED, &bp); 17539679Smckusick if (error) { 17639679Smckusick brelse(bp); 17739679Smckusick return (error); 17839679Smckusick } 17939679Smckusick } else { 18039679Smckusick error = realloccg(ip, bn, 1819165Ssam blkpref(ip, bn, (int)bn, &ip->i_db[0]), 18237736Smckusick osize, nsize, &bp); 18339679Smckusick if (error) 18439679Smckusick return (error); 1857443Sroot } 18639679Smckusick } else { 18739679Smckusick if (ip->i_size < (bn + 1) * fs->fs_bsize) 18839679Smckusick nsize = fragroundup(fs, size); 18939679Smckusick else 19039679Smckusick nsize = fs->fs_bsize; 19139679Smckusick error = alloc(ip, bn, 19239679Smckusick blkpref(ip, bn, (int)bn, &ip->i_db[0]), 19339679Smckusick nsize, &newb); 19439679Smckusick if (error) 19537736Smckusick return (error); 19639679Smckusick bp = getblk(vp, bn, nsize); 19739679Smckusick bp->b_blkno = fsbtodb(fs, newb); 19839679Smckusick if (flags & B_CLRBUF) 19939679Smckusick clrbuf(bp); 2007443Sroot } 20139679Smckusick ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); 20239679Smckusick ip->i_flag |= IUPD|ICHG; 20339679Smckusick *bpp = bp; 20437736Smckusick return (0); 2057443Sroot } 2067443Sroot /* 20739679Smckusick * Determine the number of levels of indirection. 2087443Sroot */ 2098258Smckusick pref = 0; 2107443Sroot sh = 1; 2118258Smckusick lbn = bn; 2127443Sroot bn -= NDADDR; 21337736Smckusick for (j = NIADDR; j > 0; j--) { 2147443Sroot sh *= NINDIR(fs); 2157443Sroot if (bn < sh) 2167443Sroot break; 2177443Sroot bn -= sh; 2187443Sroot } 21937736Smckusick if (j == 0) 22037736Smckusick return (EFBIG); 2217443Sroot /* 22239679Smckusick * Fetch the first indirect block allocating if necessary. 2237443Sroot */ 2247443Sroot nb = ip->i_ib[NIADDR - j]; 2257443Sroot if (nb == 0) { 2269165Ssam pref = blkpref(ip, lbn, 0, (daddr_t *)0); 22739679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) 22837736Smckusick return (error); 22939679Smckusick nb = newb; 23039679Smckusick bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 23139679Smckusick clrbuf(bp); 2327443Sroot /* 2337443Sroot * Write synchronously so that indirect blocks 2347443Sroot * never point at garbage. 2357443Sroot */ 23639679Smckusick if (error = bwrite(bp)) { 23739679Smckusick blkfree(ip, nb, fs->fs_bsize); 23839679Smckusick return (error); 23939679Smckusick } 2407443Sroot ip->i_ib[NIADDR - j] = nb; 2417443Sroot ip->i_flag |= IUPD|ICHG; 2427443Sroot } 2437443Sroot /* 24439679Smckusick * Fetch through the indirect blocks, allocating as necessary. 2457443Sroot */ 24639679Smckusick for (; ; j++) { 24739679Smckusick error = bread(ip->i_devvp, fsbtodb(fs, nb), 24839679Smckusick (int)fs->fs_bsize, NOCRED, &bp); 24939679Smckusick if (error) { 2507443Sroot brelse(bp); 25137736Smckusick return (error); 2527443Sroot } 2537443Sroot bap = bp->b_un.b_daddr; 2547443Sroot sh /= NINDIR(fs); 2557443Sroot i = (bn / sh) % NINDIR(fs); 2567443Sroot nb = bap[i]; 25739679Smckusick if (j == NIADDR) 25839679Smckusick break; 25939679Smckusick if (nb != 0) { 26039679Smckusick brelse(bp); 26139679Smckusick continue; 26239679Smckusick } 26339679Smckusick if (pref == 0) 26439679Smckusick pref = blkpref(ip, lbn, 0, (daddr_t *)0); 26539679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 26639679Smckusick brelse(bp); 26739679Smckusick return (error); 26839679Smckusick } 26939679Smckusick nb = newb; 27039679Smckusick nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 27139679Smckusick clrbuf(nbp); 27239679Smckusick /* 27339679Smckusick * Write synchronously so that indirect blocks 27439679Smckusick * never point at garbage. 27539679Smckusick */ 27639679Smckusick if (error = bwrite(nbp)) { 27739679Smckusick blkfree(ip, nb, fs->fs_bsize); 27839679Smckusick brelse(bp); 27939679Smckusick return (error); 28039679Smckusick } 28139679Smckusick bap[i] = nb; 28239878Smckusick /* 28339878Smckusick * If required, write synchronously, otherwise use 28439878Smckusick * delayed write. If this is the first instance of 28539878Smckusick * the delayed write, reassociate the buffer with the 28639878Smckusick * file so it will be written if the file is sync'ed. 28739878Smckusick */ 28839878Smckusick if (flags & B_SYNC) { 28939679Smckusick bwrite(bp); 29039878Smckusick } else if (bp->b_flags & B_DELWRI) { 2917443Sroot bdwrite(bp); 29239878Smckusick } else { 29339878Smckusick bdwrite(bp); 29439878Smckusick reassignbuf(bp, vp); 29539878Smckusick } 29639679Smckusick } 29739679Smckusick /* 29839679Smckusick * Get the data block, allocating if necessary. 29939679Smckusick */ 30039679Smckusick if (nb == 0) { 30139679Smckusick pref = blkpref(ip, lbn, i, &bap[0]); 30239679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 3037443Sroot brelse(bp); 30439679Smckusick return (error); 30539679Smckusick } 30639679Smckusick nb = newb; 30739679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 30839679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 30939679Smckusick if (flags & B_CLRBUF) 31039679Smckusick clrbuf(nbp); 31139679Smckusick bap[i] = nb; 31239878Smckusick /* 31339878Smckusick * If required, write synchronously, otherwise use 31439878Smckusick * delayed write. If this is the first instance of 31539878Smckusick * the delayed write, reassociate the buffer with the 31639878Smckusick * file so it will be written if the file is sync'ed. 31739878Smckusick */ 31839878Smckusick if (flags & B_SYNC) { 31939679Smckusick bwrite(bp); 32039878Smckusick } else if (bp->b_flags & B_DELWRI) { 32139679Smckusick bdwrite(bp); 32239878Smckusick } else { 32339878Smckusick bdwrite(bp); 32439878Smckusick reassignbuf(bp, vp); 32539878Smckusick } 32639679Smckusick *bpp = nbp; 32739679Smckusick return (0); 3287443Sroot } 32939679Smckusick brelse(bp); 33039679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 33139679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 33239679Smckusick if ((flags & B_CLRBUF) && (nbp->b_flags & (B_DONE|B_DELWRI)) == 0) { 33339679Smckusick brelse(nbp); 33439679Smckusick error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); 33539679Smckusick if (error) { 33639679Smckusick brelse(nbp); 33739679Smckusick return (error); 33839679Smckusick } 33939679Smckusick } 34039679Smckusick *bpp = nbp; 34137736Smckusick return (0); 3427443Sroot } 343