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*49450Smckusick * @(#)lfs_balloc.c 7.13 (Berkeley) 05/08/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 1747571Skarels #include "quota.h" 1847571Skarels #include "inode.h" 1947571Skarels #include "fs.h" 2047571Skarels 217443Sroot /* 22*49450Smckusick * Bmap converts a the logical block number of a file 23*49450Smckusick * to its physical block number on the disk. The conversion 24*49450Smckusick * is done by using the logical block number to index into 25*49450Smckusick * the array of block pointers described by the dinode. 267443Sroot */ 2739679Smckusick bmap(ip, bn, bnp) 287443Sroot register struct inode *ip; 2937736Smckusick register daddr_t bn; 3037736Smckusick daddr_t *bnp; 317443Sroot { 3237736Smckusick register struct fs *fs; 3337736Smckusick register daddr_t nb; 3437736Smckusick struct buf *bp; 3537736Smckusick daddr_t *bap; 3637736Smckusick int i, j, sh; 3737736Smckusick int error; 3837736Smckusick 3937736Smckusick if (bn < 0) 4037736Smckusick return (EFBIG); 4137736Smckusick fs = ip->i_fs; 4237736Smckusick 4337736Smckusick /* 4437736Smckusick * The first NDADDR blocks are direct blocks 4537736Smckusick */ 4637736Smckusick if (bn < NDADDR) { 4737736Smckusick nb = ip->i_db[bn]; 4837736Smckusick if (nb == 0) { 4937736Smckusick *bnp = (daddr_t)-1; 5037736Smckusick return (0); 5137736Smckusick } 5237736Smckusick *bnp = fsbtodb(fs, nb); 5337736Smckusick return (0); 5437736Smckusick } 5537736Smckusick /* 5639679Smckusick * Determine the number of levels of indirection. 5737736Smckusick */ 5837736Smckusick sh = 1; 5937736Smckusick bn -= NDADDR; 6037736Smckusick for (j = NIADDR; j > 0; j--) { 6137736Smckusick sh *= NINDIR(fs); 6237736Smckusick if (bn < sh) 6337736Smckusick break; 6437736Smckusick bn -= sh; 6537736Smckusick } 6637736Smckusick if (j == 0) 6737736Smckusick return (EFBIG); 6837736Smckusick /* 6939679Smckusick * Fetch through the indirect blocks. 7037736Smckusick */ 7137736Smckusick nb = ip->i_ib[NIADDR - j]; 7237736Smckusick if (nb == 0) { 7337736Smckusick *bnp = (daddr_t)-1; 7437736Smckusick return (0); 7537736Smckusick } 7637736Smckusick for (; j <= NIADDR; j++) { 7737736Smckusick if (error = bread(ip->i_devvp, fsbtodb(fs, nb), 7838776Smckusick (int)fs->fs_bsize, NOCRED, &bp)) { 7937736Smckusick brelse(bp); 8037736Smckusick return (error); 8137736Smckusick } 8237736Smckusick bap = bp->b_un.b_daddr; 8337736Smckusick sh /= NINDIR(fs); 8437736Smckusick i = (bn / sh) % NINDIR(fs); 8537736Smckusick nb = bap[i]; 8637736Smckusick if (nb == 0) { 8737736Smckusick *bnp = (daddr_t)-1; 8837736Smckusick brelse(bp); 8937736Smckusick return (0); 9037736Smckusick } 9139679Smckusick brelse(bp); 9237736Smckusick } 9337736Smckusick *bnp = fsbtodb(fs, nb); 9437736Smckusick return (0); 9537736Smckusick } 9637736Smckusick 9737736Smckusick /* 9837736Smckusick * Balloc defines the structure of file system storage 9939679Smckusick * by allocating the physical blocks on a device given 10039679Smckusick * the inode and the logical block number in a file. 10137736Smckusick */ 10239679Smckusick balloc(ip, bn, size, bpp, flags) 10337736Smckusick register struct inode *ip; 10437736Smckusick register daddr_t bn; 10537736Smckusick int size; 10639679Smckusick struct buf **bpp; 10737736Smckusick int flags; 10837736Smckusick { 10937736Smckusick register struct fs *fs; 11037736Smckusick register daddr_t nb; 1117443Sroot struct buf *bp, *nbp; 11239679Smckusick struct vnode *vp = ITOV(ip); 11337736Smckusick int osize, nsize, i, j, sh, error; 11439679Smckusick daddr_t newb, lbn, *bap, pref, blkpref(); 1157443Sroot 11639679Smckusick *bpp = (struct buf *)0; 11737736Smckusick if (bn < 0) 11837736Smckusick return (EFBIG); 1197443Sroot fs = ip->i_fs; 1207443Sroot 1217443Sroot /* 1227443Sroot * If the next write will extend the file into a new block, 1237443Sroot * and the file is currently composed of a fragment 1247443Sroot * this fragment has to be extended to be a full block. 1257443Sroot */ 1267443Sroot nb = lblkno(fs, ip->i_size); 12737736Smckusick if (nb < NDADDR && nb < bn) { 1287443Sroot osize = blksize(fs, ip, nb); 1297443Sroot if (osize < fs->fs_bsize && osize > 0) { 13039679Smckusick error = realloccg(ip, nb, 1319165Ssam blkpref(ip, nb, (int)nb, &ip->i_db[0]), 13237736Smckusick osize, (int)fs->fs_bsize, &bp); 13339679Smckusick if (error) 13437736Smckusick return (error); 1357443Sroot ip->i_size = (nb + 1) * fs->fs_bsize; 13645720Smckusick vnode_pager_setsize(ITOV(ip), (u_long)ip->i_size); 1377443Sroot ip->i_db[nb] = dbtofsb(fs, bp->b_blkno); 1387443Sroot ip->i_flag |= IUPD|ICHG; 13939679Smckusick if (flags & B_SYNC) 14039679Smckusick bwrite(bp); 14139679Smckusick else 14239679Smckusick bawrite(bp); 1437443Sroot } 1447443Sroot } 1457443Sroot /* 1467443Sroot * The first NDADDR blocks are direct blocks 1477443Sroot */ 1487443Sroot if (bn < NDADDR) { 1498258Smckusick nb = ip->i_db[bn]; 15039679Smckusick if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { 15139679Smckusick error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); 15239679Smckusick if (error) { 15339679Smckusick brelse(bp); 15439679Smckusick return (error); 15539679Smckusick } 15639679Smckusick *bpp = bp; 15739679Smckusick return (0); 15839679Smckusick } 15939679Smckusick if (nb != 0) { 16039679Smckusick /* 16139679Smckusick * Consider need to reallocate a fragment. 16239679Smckusick */ 16339679Smckusick osize = fragroundup(fs, blkoff(fs, ip->i_size)); 16439679Smckusick nsize = fragroundup(fs, size); 16539679Smckusick if (nsize <= osize) { 16639679Smckusick error = bread(vp, bn, osize, NOCRED, &bp); 16739679Smckusick if (error) { 16839679Smckusick brelse(bp); 16939679Smckusick return (error); 17039679Smckusick } 17139679Smckusick } else { 17239679Smckusick error = realloccg(ip, bn, 1739165Ssam blkpref(ip, bn, (int)bn, &ip->i_db[0]), 17437736Smckusick osize, nsize, &bp); 17539679Smckusick if (error) 17639679Smckusick return (error); 1777443Sroot } 17839679Smckusick } else { 17939679Smckusick if (ip->i_size < (bn + 1) * fs->fs_bsize) 18039679Smckusick nsize = fragroundup(fs, size); 18139679Smckusick else 18239679Smckusick nsize = fs->fs_bsize; 18339679Smckusick error = alloc(ip, bn, 18439679Smckusick blkpref(ip, bn, (int)bn, &ip->i_db[0]), 18539679Smckusick nsize, &newb); 18639679Smckusick if (error) 18737736Smckusick return (error); 18839679Smckusick bp = getblk(vp, bn, nsize); 18939679Smckusick bp->b_blkno = fsbtodb(fs, newb); 19039679Smckusick if (flags & B_CLRBUF) 19139679Smckusick clrbuf(bp); 1927443Sroot } 19339679Smckusick ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); 19439679Smckusick ip->i_flag |= IUPD|ICHG; 19539679Smckusick *bpp = bp; 19637736Smckusick return (0); 1977443Sroot } 1987443Sroot /* 19939679Smckusick * Determine the number of levels of indirection. 2007443Sroot */ 2018258Smckusick pref = 0; 2027443Sroot sh = 1; 2038258Smckusick lbn = bn; 2047443Sroot bn -= NDADDR; 20537736Smckusick for (j = NIADDR; j > 0; j--) { 2067443Sroot sh *= NINDIR(fs); 2077443Sroot if (bn < sh) 2087443Sroot break; 2097443Sroot bn -= sh; 2107443Sroot } 21137736Smckusick if (j == 0) 21237736Smckusick return (EFBIG); 2137443Sroot /* 21439679Smckusick * Fetch the first indirect block allocating if necessary. 2157443Sroot */ 2167443Sroot nb = ip->i_ib[NIADDR - j]; 2177443Sroot if (nb == 0) { 2189165Ssam pref = blkpref(ip, lbn, 0, (daddr_t *)0); 21939679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) 22037736Smckusick return (error); 22139679Smckusick nb = newb; 22239679Smckusick bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 22339679Smckusick clrbuf(bp); 2247443Sroot /* 2257443Sroot * Write synchronously so that indirect blocks 2267443Sroot * never point at garbage. 2277443Sroot */ 22839679Smckusick if (error = bwrite(bp)) { 22939679Smckusick blkfree(ip, nb, fs->fs_bsize); 23039679Smckusick return (error); 23139679Smckusick } 2327443Sroot ip->i_ib[NIADDR - j] = nb; 2337443Sroot ip->i_flag |= IUPD|ICHG; 2347443Sroot } 2357443Sroot /* 23639679Smckusick * Fetch through the indirect blocks, allocating as necessary. 2377443Sroot */ 23839679Smckusick for (; ; j++) { 23939679Smckusick error = bread(ip->i_devvp, fsbtodb(fs, nb), 24039679Smckusick (int)fs->fs_bsize, NOCRED, &bp); 24139679Smckusick if (error) { 2427443Sroot brelse(bp); 24337736Smckusick return (error); 2447443Sroot } 2457443Sroot bap = bp->b_un.b_daddr; 2467443Sroot sh /= NINDIR(fs); 2477443Sroot i = (bn / sh) % NINDIR(fs); 2487443Sroot nb = bap[i]; 24939679Smckusick if (j == NIADDR) 25039679Smckusick break; 25139679Smckusick if (nb != 0) { 25239679Smckusick brelse(bp); 25339679Smckusick continue; 25439679Smckusick } 25539679Smckusick if (pref == 0) 25639679Smckusick pref = blkpref(ip, lbn, 0, (daddr_t *)0); 25739679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 25839679Smckusick brelse(bp); 25939679Smckusick return (error); 26039679Smckusick } 26139679Smckusick nb = newb; 26239679Smckusick nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize); 26339679Smckusick clrbuf(nbp); 26439679Smckusick /* 26539679Smckusick * Write synchronously so that indirect blocks 26639679Smckusick * never point at garbage. 26739679Smckusick */ 26839679Smckusick if (error = bwrite(nbp)) { 26939679Smckusick blkfree(ip, nb, fs->fs_bsize); 27039679Smckusick brelse(bp); 27139679Smckusick return (error); 27239679Smckusick } 27339679Smckusick bap[i] = nb; 27439878Smckusick /* 27539878Smckusick * If required, write synchronously, otherwise use 27639878Smckusick * delayed write. If this is the first instance of 27739878Smckusick * the delayed write, reassociate the buffer with the 27839878Smckusick * file so it will be written if the file is sync'ed. 27939878Smckusick */ 28039878Smckusick if (flags & B_SYNC) { 28139679Smckusick bwrite(bp); 28239878Smckusick } else if (bp->b_flags & B_DELWRI) { 2837443Sroot bdwrite(bp); 28439878Smckusick } else { 28539878Smckusick bdwrite(bp); 28639878Smckusick reassignbuf(bp, vp); 28739878Smckusick } 28839679Smckusick } 28939679Smckusick /* 29039679Smckusick * Get the data block, allocating if necessary. 29139679Smckusick */ 29239679Smckusick if (nb == 0) { 29339679Smckusick pref = blkpref(ip, lbn, i, &bap[0]); 29439679Smckusick if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) { 2957443Sroot brelse(bp); 29639679Smckusick return (error); 29739679Smckusick } 29839679Smckusick nb = newb; 29939679Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 30039679Smckusick nbp->b_blkno = fsbtodb(fs, nb); 30139679Smckusick if (flags & B_CLRBUF) 30239679Smckusick clrbuf(nbp); 30339679Smckusick bap[i] = nb; 30439878Smckusick /* 30539878Smckusick * If required, write synchronously, otherwise use 30639878Smckusick * delayed write. If this is the first instance of 30739878Smckusick * the delayed write, reassociate the buffer with the 30839878Smckusick * file so it will be written if the file is sync'ed. 30939878Smckusick */ 31039878Smckusick if (flags & B_SYNC) { 31139679Smckusick bwrite(bp); 31239878Smckusick } else if (bp->b_flags & B_DELWRI) { 31339679Smckusick bdwrite(bp); 31439878Smckusick } else { 31539878Smckusick bdwrite(bp); 31639878Smckusick reassignbuf(bp, vp); 31739878Smckusick } 31839679Smckusick *bpp = nbp; 31939679Smckusick return (0); 3207443Sroot } 32139679Smckusick brelse(bp); 32241333Smckusick if (flags & B_CLRBUF) { 32339679Smckusick error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); 32439679Smckusick if (error) { 32539679Smckusick brelse(nbp); 32639679Smckusick return (error); 32739679Smckusick } 32841333Smckusick } else { 32941333Smckusick nbp = getblk(vp, lbn, fs->fs_bsize); 33041333Smckusick nbp->b_blkno = fsbtodb(fs, nb); 33139679Smckusick } 33239679Smckusick *bpp = nbp; 33337736Smckusick return (0); 3347443Sroot } 335