xref: /original-bsd/sys/ufs/lfs/lfs_balloc.c (revision 44178c51)
1 /*
2  * Copyright (c) 1989, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_balloc.c	7.41 (Berkeley) 12/10/92
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 	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 	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);
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 				if (!(ibp->b_flags & (B_DONE | B_DELWRI))) {
66 					if (!ISSPACE(fs, bb, curproc->p_ucred)){
67 						ibp->b_flags |= B_INVAL;
68 						brelse(ibp);
69 						error = ENOSPC;
70 					} else {
71 						ip->i_blocks += bb;
72 						ip->i_lfs->lfs_bfree -= bb;
73 						clrbuf(ibp);
74 						error = VOP_BWRITE(ibp);
75 					}
76 				} else
77 					panic ("Indirect block should not exist");
78 			}
79 	if (error) {
80 		if (bp)
81 			brelse(bp);
82 		return(error);
83 	}
84 
85 
86 	/* Now, we may need to allocate the data block */
87 	if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) {
88 		if (daddr == UNASSIGNED)
89 			if (!ISSPACE(fs, bb, curproc->p_ucred)) {
90 				bp->b_flags |= B_INVAL;
91 				brelse(bp);
92 				return(ENOSPC);
93 			} else {
94 				ip->i_blocks += bb;
95 				ip->i_lfs->lfs_bfree -= bb;
96 				if (iosize != fs->lfs_bsize)
97 					clrbuf(bp);
98 			}
99 		else if (iosize == fs->lfs_bsize)
100 			bp->b_blkno = daddr;		/* Skip the I/O */
101 		else  {
102 			bp->b_blkno = daddr;
103 			bp->b_flags |= B_READ;
104 			VOP_STRATEGY(bp);
105 			return(biowait(bp));
106 		}
107 	}
108 	return (error);
109 }
110