123396Smckusick /* 251494Sbostic * Copyright (c) 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*56609Smargo * @(#)lfs_balloc.c 7.39 (Berkeley) 10/22/92 823396Smckusick */ 951486Sbostic #include <sys/param.h> 1051486Sbostic #include <sys/buf.h> 1151486Sbostic #include <sys/proc.h> 1251486Sbostic #include <sys/vnode.h> 1351486Sbostic #include <sys/mount.h> 1451486Sbostic #include <sys/resourcevar.h> 1551486Sbostic #include <sys/trace.h> 167443Sroot 1755048Smckusick #include <miscfs/specfs/specdev.h> 1855048Smckusick 1951494Sbostic #include <ufs/ufs/quota.h> 2051494Sbostic #include <ufs/ufs/inode.h> 2151494Sbostic #include <ufs/ufs/ufsmount.h> 2247571Skarels 2351494Sbostic #include <ufs/lfs/lfs.h> 2451494Sbostic #include <ufs/lfs/lfs_extern.h> 2551486Sbostic 2651855Sbostic int 2752082Sbostic lfs_balloc(vp, iosize, lbn, bpp) 2852082Sbostic struct vnode *vp; 2952082Sbostic u_long iosize; 3052082Sbostic daddr_t lbn; 3152082Sbostic struct buf **bpp; 3252082Sbostic { 33*56609Smargo struct buf *ibp, *bp; 3452082Sbostic struct inode *ip; 3552082Sbostic struct lfs *fs; 36*56609Smargo struct indir indirs[NIADDR+2]; 3752082Sbostic daddr_t daddr; 38*56609Smargo int bb, error, i, num; 3952082Sbostic 4052082Sbostic ip = VTOI(vp); 4152082Sbostic fs = ip->i_lfs; 4252082Sbostic 4352082Sbostic /* 4452082Sbostic * Three cases: it's a block beyond the end of file, it's a block in 4552082Sbostic * the file that may or may not have been assigned a disk address or 4652082Sbostic * we're writing an entire block. Note, if the daddr is unassigned, 47*56609Smargo * the block might still have existed in the cache (if it was read 48*56609Smargo * or written earlier). If it did, make sure we don't count it as a 49*56609Smargo * new block or zero out its contents. If it did not, make sure 50*56609Smargo * we allocate any necessary indirect blocks. 5152082Sbostic */ 5255942Sbostic 5355942Sbostic *bpp = NULL; 54*56609Smargo if (error = ufs_bmaparray(vp, lbn, &daddr, &indirs[0], &num, NULL )) 5552994Sbostic return (error); 5652082Sbostic 57*56609Smargo *bpp = bp = getblk(vp, lbn, fs->lfs_bsize); 58*56609Smargo bb = VFSTOUFS(vp->v_mount)->um_seqinc; 59*56609Smargo if (daddr == UNASSIGNED) 60*56609Smargo /* May need to allocate indirect blocks */ 61*56609Smargo for (i = 1; i < num; ++i) 62*56609Smargo if (!indirs[i].in_exists) { 63*56609Smargo ibp = 64*56609Smargo getblk(vp, indirs[i].in_lbn, fs->lfs_bsize); 65*56609Smargo if (!(ibp->b_flags & (B_DONE | B_DELWRI))) { 66*56609Smargo if (!ISSPACE(fs, bb, curproc->p_ucred)){ 67*56609Smargo ibp->b_flags |= B_INVAL; 68*56609Smargo brelse(ibp); 69*56609Smargo error = ENOSPC; 70*56609Smargo } else { 71*56609Smargo ip->i_blocks += bb; 72*56609Smargo ip->i_lfs->lfs_bfree -= bb; 73*56609Smargo clrbuf(ibp); 74*56609Smargo error = VOP_BWRITE(ibp); 75*56609Smargo } 76*56609Smargo } else 77*56609Smargo panic ("Indirect block should not exist"); 78*56609Smargo } 79*56609Smargo if (error) { 80*56609Smargo if (bp) 81*56609Smargo brelse(bp); 82*56609Smargo return(error); 83*56609Smargo } 84*56609Smargo 85*56609Smargo 86*56609Smargo /* Now, we may need to allocate the data block */ 87*56609Smargo if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) { 88*56609Smargo if (daddr == UNASSIGNED) 89*56609Smargo if (!ISSPACE(fs, bb, curproc->p_ucred)) { 9056160Smargo bp->b_flags |= B_INVAL; 9156160Smargo brelse(bp); 92*56609Smargo return(ENOSPC); 93*56609Smargo } else { 94*56609Smargo ip->i_blocks += bb; 95*56609Smargo ip->i_lfs->lfs_bfree -= bb; 96*56609Smargo if (iosize != fs->lfs_bsize) 97*56609Smargo clrbuf(bp); 9856160Smargo } 99*56609Smargo else if (iosize == fs->lfs_bsize) 100*56609Smargo bp->b_blkno = daddr; /* Skip the I/O */ 101*56609Smargo else { 102*56609Smargo bp->b_blkno = daddr; 103*56609Smargo VOP_STRATEGY(bp); 10452082Sbostic } 10552082Sbostic } 106*56609Smargo return (error); 10752082Sbostic } 108