123396Smckusick /* 251494Sbostic * Copyright (c) 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*57803Smckusick * @(#)lfs_balloc.c 7.42 (Berkeley) 02/02/93 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 { 3356609Smargo struct buf *ibp, *bp; 3452082Sbostic struct inode *ip; 3552082Sbostic struct lfs *fs; 3656609Smargo struct indir indirs[NIADDR+2]; 3752082Sbostic daddr_t daddr; 3856609Smargo 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, 4756609Smargo * the block might still have existed in the cache (if it was read 4856609Smargo * or written earlier). If it did, make sure we don't count it as a 4956609Smargo * new block or zero out its contents. If it did not, make sure 5056609Smargo * we allocate any necessary indirect blocks. 5152082Sbostic */ 5255942Sbostic 5355942Sbostic *bpp = NULL; 5456609Smargo if (error = ufs_bmaparray(vp, lbn, &daddr, &indirs[0], &num, NULL )) 5552994Sbostic return (error); 5652082Sbostic 57*57803Smckusick *bpp = bp = getblk(vp, lbn, fs->lfs_bsize, 0, 0); 5856609Smargo bb = VFSTOUFS(vp->v_mount)->um_seqinc; 5956609Smargo if (daddr == UNASSIGNED) 6056609Smargo /* May need to allocate indirect blocks */ 6156609Smargo for (i = 1; i < num; ++i) 6256609Smargo if (!indirs[i].in_exists) { 6356609Smargo ibp = 64*57803Smckusick getblk(vp, indirs[i].in_lbn, fs->lfs_bsize, 65*57803Smckusick 0, 0); 6656609Smargo if (!(ibp->b_flags & (B_DONE | B_DELWRI))) { 6756609Smargo if (!ISSPACE(fs, bb, curproc->p_ucred)){ 6856609Smargo ibp->b_flags |= B_INVAL; 6956609Smargo brelse(ibp); 7056609Smargo error = ENOSPC; 7156609Smargo } else { 7256609Smargo ip->i_blocks += bb; 7356609Smargo ip->i_lfs->lfs_bfree -= bb; 7456609Smargo clrbuf(ibp); 7556609Smargo error = VOP_BWRITE(ibp); 7656609Smargo } 7756609Smargo } else 7856609Smargo panic ("Indirect block should not exist"); 7956609Smargo } 8056609Smargo if (error) { 8156609Smargo if (bp) 8256609Smargo brelse(bp); 8356609Smargo return(error); 8456609Smargo } 8556609Smargo 8656609Smargo 8756609Smargo /* Now, we may need to allocate the data block */ 8856609Smargo if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) { 8956609Smargo if (daddr == UNASSIGNED) 9056609Smargo if (!ISSPACE(fs, bb, curproc->p_ucred)) { 9156160Smargo bp->b_flags |= B_INVAL; 9256160Smargo brelse(bp); 9356609Smargo return(ENOSPC); 9456609Smargo } else { 9556609Smargo ip->i_blocks += bb; 9656609Smargo ip->i_lfs->lfs_bfree -= bb; 9756609Smargo if (iosize != fs->lfs_bsize) 9856609Smargo clrbuf(bp); 9956160Smargo } 10056609Smargo else if (iosize == fs->lfs_bsize) 10156609Smargo bp->b_blkno = daddr; /* Skip the I/O */ 10256609Smargo else { 10356609Smargo bp->b_blkno = daddr; 10457063Smargo bp->b_flags |= B_READ; 10556609Smargo VOP_STRATEGY(bp); 10656864Smargo return(biowait(bp)); 10752082Sbostic } 10852082Sbostic } 10956609Smargo return (error); 11052082Sbostic } 111