1 /* 2 * Copyright (c) 1989, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_balloc.c 8.2 (Berkeley) 03/21/95 8 */ 9 #include <sys/param.h> 10 #include <sys/buf.h> 11 #include <sys/proc.h> 12 #include <sys/vnode.h> 13 #include <sys/mount.h> 14 #include <sys/resourcevar.h> 15 #include <sys/trace.h> 16 17 #include <miscfs/specfs/specdev.h> 18 19 #include <ufs/ufs/quota.h> 20 #include <ufs/ufs/inode.h> 21 #include <ufs/ufs/ufsmount.h> 22 23 #include <ufs/lfs/lfs.h> 24 #include <ufs/lfs/lfs_extern.h> 25 26 int 27 lfs_balloc(vp, iosize, lbn, bpp) 28 struct vnode *vp; 29 u_long iosize; 30 ufs_daddr_t lbn; 31 struct buf **bpp; 32 { 33 struct buf *ibp, *bp; 34 struct inode *ip; 35 struct lfs *fs; 36 struct indir indirs[NIADDR+2]; 37 ufs_daddr_t daddr; 38 int bb, error, i, num; 39 40 ip = VTOI(vp); 41 fs = ip->i_lfs; 42 43 /* 44 * Three cases: it's a block beyond the end of file, it's a block in 45 * the file that may or may not have been assigned a disk address or 46 * we're writing an entire block. Note, if the daddr is unassigned, 47 * the block might still have existed in the cache (if it was read 48 * or written earlier). If it did, make sure we don't count it as a 49 * new block or zero out its contents. If it did not, make sure 50 * we allocate any necessary indirect blocks. 51 */ 52 53 *bpp = NULL; 54 if (error = ufs_bmaparray(vp, lbn, &daddr, &indirs[0], &num, NULL )) 55 return (error); 56 57 *bpp = bp = getblk(vp, lbn, fs->lfs_bsize, 0, 0); 58 bb = VFSTOUFS(vp->v_mount)->um_seqinc; 59 if (daddr == UNASSIGNED) 60 /* May need to allocate indirect blocks */ 61 for (i = 1; i < num; ++i) 62 if (!indirs[i].in_exists) { 63 ibp = 64 getblk(vp, indirs[i].in_lbn, fs->lfs_bsize, 65 0, 0); 66 if (!(ibp->b_flags & (B_DONE | B_DELWRI))) { 67 if (!ISSPACE(fs, bb, curproc->p_ucred)){ 68 ibp->b_flags |= B_INVAL; 69 brelse(ibp); 70 error = ENOSPC; 71 } else { 72 ip->i_blocks += bb; 73 ip->i_lfs->lfs_bfree -= bb; 74 clrbuf(ibp); 75 error = VOP_BWRITE(ibp); 76 } 77 } else 78 panic ("Indirect block should not exist"); 79 } 80 if (error) { 81 if (bp) 82 brelse(bp); 83 return(error); 84 } 85 86 87 /* Now, we may need to allocate the data block */ 88 if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) { 89 if (daddr == UNASSIGNED) 90 if (!ISSPACE(fs, bb, curproc->p_ucred)) { 91 bp->b_flags |= B_INVAL; 92 brelse(bp); 93 return(ENOSPC); 94 } else { 95 ip->i_blocks += bb; 96 ip->i_lfs->lfs_bfree -= bb; 97 if (iosize != fs->lfs_bsize) 98 clrbuf(bp); 99 } 100 else if (iosize == fs->lfs_bsize) 101 bp->b_blkno = daddr; /* Skip the I/O */ 102 else { 103 bp->b_blkno = daddr; 104 bp->b_flags |= B_READ; 105 VOP_STRATEGY(bp); 106 return(biowait(bp)); 107 } 108 } 109 return (error); 110 } 111