123396Smckusick /* 251494Sbostic * Copyright (c) 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*56864Smargo * @(#)lfs_balloc.c 7.40 (Berkeley) 11/17/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 { 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 5756609Smargo *bpp = bp = getblk(vp, lbn, fs->lfs_bsize); 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 = 6456609Smargo getblk(vp, indirs[i].in_lbn, fs->lfs_bsize); 6556609Smargo if (!(ibp->b_flags & (B_DONE | B_DELWRI))) { 6656609Smargo if (!ISSPACE(fs, bb, curproc->p_ucred)){ 6756609Smargo ibp->b_flags |= B_INVAL; 6856609Smargo brelse(ibp); 6956609Smargo error = ENOSPC; 7056609Smargo } else { 7156609Smargo ip->i_blocks += bb; 7256609Smargo ip->i_lfs->lfs_bfree -= bb; 7356609Smargo clrbuf(ibp); 7456609Smargo error = VOP_BWRITE(ibp); 7556609Smargo } 7656609Smargo } else 7756609Smargo panic ("Indirect block should not exist"); 7856609Smargo } 7956609Smargo if (error) { 8056609Smargo if (bp) 8156609Smargo brelse(bp); 8256609Smargo return(error); 8356609Smargo } 8456609Smargo 8556609Smargo 8656609Smargo /* Now, we may need to allocate the data block */ 8756609Smargo if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) { 8856609Smargo if (daddr == UNASSIGNED) 8956609Smargo if (!ISSPACE(fs, bb, curproc->p_ucred)) { 9056160Smargo bp->b_flags |= B_INVAL; 9156160Smargo brelse(bp); 9256609Smargo return(ENOSPC); 9356609Smargo } else { 9456609Smargo ip->i_blocks += bb; 9556609Smargo ip->i_lfs->lfs_bfree -= bb; 9656609Smargo if (iosize != fs->lfs_bsize) 9756609Smargo clrbuf(bp); 9856160Smargo } 9956609Smargo else if (iosize == fs->lfs_bsize) 10056609Smargo bp->b_blkno = daddr; /* Skip the I/O */ 10156609Smargo else { 10256609Smargo bp->b_blkno = daddr; 103*56864Smargo bp->b_flags != B_READ; 10456609Smargo VOP_STRATEGY(bp); 105*56864Smargo return(biowait(bp)); 10652082Sbostic } 10752082Sbostic } 10856609Smargo return (error); 10952082Sbostic } 110