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*39878Smckusick * @(#)lfs_balloc.c 7.7 (Berkeley) 01/04/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" 2737736Smckusick #include "../ufs/inode.h" 2837736Smckusick #include "../ufs/fs.h" 297443Sroot 307443Sroot /* 317443Sroot * Bmap defines the structure of file system storage 3239679Smckusick * by returning the physical block number on a device 3339679Smckusick * given the inode and the logical block number in a file. 347443Sroot */ 3539679Smckusick 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 /* 6439679Smckusick * 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 /* 7739679Smckusick * 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 } 9037736Smckusick bap = bp->b_un.b_daddr; 9137736Smckusick sh /= NINDIR(fs); 9237736Smckusick i = (bn / sh) % NINDIR(fs); 9337736Smckusick nb = bap[i]; 9437736Smckusick if (nb == 0) { 9537736Smckusick *bnp = (daddr_t)-1; 9637736Smckusick brelse(bp); 9737736Smckusick return (0); 9837736Smckusick } 9939679Smckusick brelse(bp); 10037736Smckusick } 10137736Smckusick *bnp = fsbtodb(fs, nb); 10237736Smckusick return (0); 10337736Smckusick } 10437736Smckusick 10537736Smckusick /* 10637736Smckusick * Balloc defines the structure of file system storage 10739679Smckusick * by allocating the physical blocks on a device given 10839679Smckusick * the inode and the logical block number in a file. 10937736Smckusick */ 11039679Smckusick balloc(ip, bn, size, bpp, flags) 11137736Smckusick register struct inode *ip; 11237736Smckusick register daddr_t bn; 11337736Smckusick int size; 11439679Smckusick struct buf **bpp; 11537736Smckusick int flags; 11637736Smckusick { 11737736Smckusick register struct fs *fs; 11837736Smckusick register daddr_t nb; 1197443Sroot struct buf *bp, *nbp; 12039679Smckusick struct vnode *vp = ITOV(ip); 12137736Smckusick int osize, nsize, i, j, sh, error; 12239679Smckusick daddr_t newb, lbn, *bap, pref, blkpref(); 1237443Sroot 12439679Smckusick *bpp = (struct buf *)0; 12537736Smckusick if (bn < 0) 12637736Smckusick return (EFBIG); 1277443Sroot fs = ip->i_fs; 1287443Sroot 1297443Sroot /* 1307443Sroot * If the next write will extend the file into a new block, 1317443Sroot * and the file is currently composed of a fragment 1327443Sroot * this fragment has to be extended to be a full block. 1337443Sroot */ 1347443Sroot nb = lblkno(fs, ip->i_size); 13537736Smckusick if (nb < NDADDR && nb < bn) { 1367443Sroot osize = blksize(fs, ip, nb); 1377443Sroot if (osize < fs->fs_bsize && osize > 0) { 13839679Smckusick error = realloccg(ip, nb, 1399165Ssam blkpref(ip, nb, (int)nb, &ip->i_db[0]), 14037736Smckusick osize, (int)fs->fs_bsize, &bp); 14139679Smckusick if (error) 14237736Smckusick return (error); 1437443Sroot ip->i_size = (nb + 1) * fs->fs_bsize; 1447443Sroot ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); 1457443Sroot ip->i_flag |= IUPD|ICHG; 14639679Smckusick if (flags & B_SYNC) 14739679Smckusick bwrite(bp); 14839679Smckusick else 14939679Smckusick bawrite(bp); 1507443Sroot } 1517443Sroot } 1527443Sroot /* 1537443Sroot * The first NDADDR blocks are direct blocks 1547443Sroot */ 1557443Sroot if (bn < NDADDR) { 1568258Smckusick nb = ip->i_db[bn]; 15739679Smckusick if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { 15839679Smckusick error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); 15939679Smckusick if (error) { 16039679Smckusick brelse(bp); 16139679Smckusick return (error); 16239679Smckusick } 16339679Smckusick *bpp = bp; 16439679Smckusick return (0); 16539679Smckusick } 16639679Smckusick if (nb != 0) { 16739679Smckusick /* 16839679Smckusick * Consider need to reallocate a fragment. 16939679Smckusick */ 17039679Smckusick osize = fragroundup(fs, blkoff(fs, ip->i_size)); 17139679Smckusick nsize = fragroundup(fs, size); 17239679Smckusick if (nsize <= osize) { 17339679Smckusick error = bread(vp, bn, osize, NOCRED, &bp); 17439679Smckusick if (error) { 17539679Smckusick brelse(bp); 17639679Smckusick return (error); 17739679Smckusick } 17839679Smckusick } else { 17939679Smckusick error = realloccg(ip, bn, 1809165Ssam blkpref(ip, bn, (int)bn, &ip->i_db[0]), 18137736Smckusick osize, nsize, &bp); 18239679Smckusick if (error) 18339679Smckusick return (error); 1847443Sroot } 18539679Smckusick } else { 18639679Smckusick if (ip->i_size < (bn + 1) * fs->fs_bsize) 18739679Smckusick nsize = fragroundup(fs, size); 18839679Smckusick else 18939679Smckusick nsize = fs->fs_bsize; 19039679Smckusick error = alloc(ip, bn, 19139679Smckusick blkpref(ip, bn, (int)bn, &ip->i_db[0]), 19239679Smckusick nsize, &newb); 19339679Smckusick if (error) 19437736Smckusick return (error); 19539679Smckusick bp = getblk(vp, bn, nsize); 19639679Smckusick bp->b_blkno = fsbtodb(fs, newb); 19739679Smckusick if (flags & B_CLRBUF) 19839679Smckusick clrbuf(bp); 1997443Sroot } 20039679Smckusick ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); 20139679Smckusick ip->i_flag |= IUPD|ICHG; 20239679Smckusick *bpp = bp; 20337736Smckusick return (0); 2047443Sroot } 2057443Sroot /* 20639679Smckusick * Determine the number of levels of indirection. 2077443Sroot */ 2088258Smckusick pref = 0; 2097443Sroot sh = 1; 2108258Smckusick lbn = bn; 2117443Sroot bn -= NDADDR; 21237736Smckusick for (j = NIADDR; j > 0; j--) { 2137443Sroot sh *= NINDIR(fs); 2147443Sroot if (bn < sh) 2157443Sroot break; 2167443Sroot bn -= sh; 2177443Sroot } 21837736Smckusick if (j == 0) 21937736Smckusick return (EFBIG); 2207443Sroot /* 22139679Smckusick * Fetch the first indirect block allocating if necessary. 2227443Sroot */ 2237443Sroot nb = ip->i_ib[NIADDR - j]; 2247443Sroot if (nb == 0) { 2259165Ssam pref = blkpref(ip, lbn, 0, (daddr_t *)0); 22639679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) 22737736Smckusick return (error); 22839679Smckusick nb = newb; 22939679Smckusick bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 23039679Smckusick clrbuf(bp); 2317443Sroot /* 2327443Sroot * Write synchronously so that indirect blocks 2337443Sroot * never point at garbage. 2347443Sroot */ 23539679Smckusick if (error = bwrite(bp)) { 23639679Smckusick blkfree(ip, nb, fs->fs_bsize); 23739679Smckusick return (error); 23839679Smckusick } 2397443Sroot ip->i_ib[NIADDR - j] = nb; 2407443Sroot ip->i_flag |= IUPD|ICHG; 2417443Sroot } 2427443Sroot /* 24339679Smckusick * Fetch through the indirect blocks, allocating as necessary. 2447443Sroot */ 24539679Smckusick for (; ; j++) { 24639679Smckusick error = bread(ip->i_devvp, fsbtodb(fs, nb), 24739679Smckusick (int)fs->fs_bsize, NOCRED, &bp); 24839679Smckusick if (error) { 2497443Sroot brelse(bp); 25037736Smckusick return (error); 2517443Sroot } 2527443Sroot bap = bp->b_un.b_daddr; 2537443Sroot sh /= NINDIR(fs); 2547443Sroot i = (bn / sh) % NINDIR(fs); 2557443Sroot nb = bap[i]; 25639679Smckusick if (j == NIADDR) 25739679Smckusick break; 25839679Smckusick if (nb != 0) { 25939679Smckusick brelse(bp); 26039679Smckusick continue; 26139679Smckusick } 26239679Smckusick if (pref == 0) 26339679Smckusick pref = blkpref(ip, lbn, 0, (daddr_t *)0); 26439679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 26539679Smckusick brelse(bp); 26639679Smckusick return (error); 26739679Smckusick } 26839679Smckusick nb = newb; 26939679Smckusick nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 27039679Smckusick clrbuf(nbp); 27139679Smckusick /* 27239679Smckusick * Write synchronously so that indirect blocks 27339679Smckusick * never point at garbage. 27439679Smckusick */ 27539679Smckusick if (error = bwrite(nbp)) { 27639679Smckusick blkfree(ip, nb, fs->fs_bsize); 27739679Smckusick brelse(bp); 27839679Smckusick return (error); 27939679Smckusick } 28039679Smckusick bap[i] = nb; 281*39878Smckusick /* 282*39878Smckusick * If required, write synchronously, otherwise use 283*39878Smckusick * delayed write. If this is the first instance of 284*39878Smckusick * the delayed write, reassociate the buffer with the 285*39878Smckusick * file so it will be written if the file is sync'ed. 286*39878Smckusick */ 287*39878Smckusick if (flags & B_SYNC) { 28839679Smckusick bwrite(bp); 289*39878Smckusick } else if (bp->b_flags & B_DELWRI) { 2907443Sroot bdwrite(bp); 291*39878Smckusick } else { 292*39878Smckusick bdwrite(bp); 293*39878Smckusick reassignbuf(bp, vp); 294*39878Smckusick } 29539679Smckusick } 29639679Smckusick /* 29739679Smckusick * Get the data block, allocating if necessary. 29839679Smckusick */ 29939679Smckusick if (nb == 0) { 30039679Smckusick pref = blkpref(ip, lbn, i, &bap[0]); 30139679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 3027443Sroot brelse(bp); 30339679Smckusick return (error); 30439679Smckusick } 30539679Smckusick nb = newb; 30639679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 30739679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 30839679Smckusick if (flags & B_CLRBUF) 30939679Smckusick clrbuf(nbp); 31039679Smckusick bap[i] = nb; 311*39878Smckusick /* 312*39878Smckusick * If required, write synchronously, otherwise use 313*39878Smckusick * delayed write. If this is the first instance of 314*39878Smckusick * the delayed write, reassociate the buffer with the 315*39878Smckusick * file so it will be written if the file is sync'ed. 316*39878Smckusick */ 317*39878Smckusick if (flags & B_SYNC) { 31839679Smckusick bwrite(bp); 319*39878Smckusick } else if (bp->b_flags & B_DELWRI) { 32039679Smckusick bdwrite(bp); 321*39878Smckusick } else { 322*39878Smckusick bdwrite(bp); 323*39878Smckusick reassignbuf(bp, vp); 324*39878Smckusick } 32539679Smckusick *bpp = nbp; 32639679Smckusick return (0); 3277443Sroot } 32839679Smckusick brelse(bp); 32939679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 33039679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 33139679Smckusick if ((flags & B_CLRBUF) && (nbp->b_flags & (B_DONE|B_DELWRI)) == 0) { 33239679Smckusick brelse(nbp); 33339679Smckusick error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); 33439679Smckusick if (error) { 33539679Smckusick brelse(nbp); 33639679Smckusick return (error); 33739679Smckusick } 33839679Smckusick } 33939679Smckusick *bpp = nbp; 34037736Smckusick return (0); 3417443Sroot } 342