xref: /original-bsd/sys/ufs/lfs/lfs_balloc.c (revision fac0c393)
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