xref: /original-bsd/sys/ufs/ffs/ffs_balloc.c (revision 04218a6a)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)ffs_balloc.c	7.9 (Berkeley) 05/03/90
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "user.h"
23 #include "buf.h"
24 #include "proc.h"
25 #include "file.h"
26 #include "vnode.h"
27 #include "../ufs/quota.h"
28 #include "../ufs/inode.h"
29 #include "../ufs/fs.h"
30 
31 /*
32  * Bmap defines the structure of file system storage
33  * by returning the physical block number on a device
34  * given the inode and the logical block number in a file.
35  */
36 bmap(ip, bn, bnp)
37 	register struct inode *ip;
38 	register daddr_t bn;
39 	daddr_t	*bnp;
40 {
41 	register struct fs *fs;
42 	register daddr_t nb;
43 	struct buf *bp;
44 	daddr_t *bap;
45 	int i, j, sh;
46 	int error;
47 
48 	if (bn < 0)
49 		return (EFBIG);
50 	fs = ip->i_fs;
51 
52 	/*
53 	 * The first NDADDR blocks are direct blocks
54 	 */
55 	if (bn < NDADDR) {
56 		nb = ip->i_db[bn];
57 		if (nb == 0) {
58 			*bnp = (daddr_t)-1;
59 			return (0);
60 		}
61 		*bnp = fsbtodb(fs, nb);
62 		return (0);
63 	}
64 	/*
65 	 * Determine the number of levels of indirection.
66 	 */
67 	sh = 1;
68 	bn -= NDADDR;
69 	for (j = NIADDR; j > 0; j--) {
70 		sh *= NINDIR(fs);
71 		if (bn < sh)
72 			break;
73 		bn -= sh;
74 	}
75 	if (j == 0)
76 		return (EFBIG);
77 	/*
78 	 * Fetch through the indirect blocks.
79 	 */
80 	nb = ip->i_ib[NIADDR - j];
81 	if (nb == 0) {
82 		*bnp = (daddr_t)-1;
83 		return (0);
84 	}
85 	for (; j <= NIADDR; j++) {
86 		if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
87 		    (int)fs->fs_bsize, NOCRED, &bp)) {
88 			brelse(bp);
89 			return (error);
90 		}
91 		bap = bp->b_un.b_daddr;
92 		sh /= NINDIR(fs);
93 		i = (bn / sh) % NINDIR(fs);
94 		nb = bap[i];
95 		if (nb == 0) {
96 			*bnp = (daddr_t)-1;
97 			brelse(bp);
98 			return (0);
99 		}
100 		brelse(bp);
101 	}
102 	*bnp = fsbtodb(fs, nb);
103 	return (0);
104 }
105 
106 /*
107  * Balloc defines the structure of file system storage
108  * by allocating the physical blocks on a device given
109  * the inode and the logical block number in a file.
110  */
111 balloc(ip, bn, size, bpp, flags)
112 	register struct inode *ip;
113 	register daddr_t bn;
114 	int size;
115 	struct buf **bpp;
116 	int flags;
117 {
118 	register struct fs *fs;
119 	register daddr_t nb;
120 	struct buf *bp, *nbp;
121 	struct vnode *vp = ITOV(ip);
122 	int osize, nsize, i, j, sh, error;
123 	daddr_t newb, lbn, *bap, pref, blkpref();
124 
125 	*bpp = (struct buf *)0;
126 	if (bn < 0)
127 		return (EFBIG);
128 	fs = ip->i_fs;
129 
130 	/*
131 	 * If the next write will extend the file into a new block,
132 	 * and the file is currently composed of a fragment
133 	 * this fragment has to be extended to be a full block.
134 	 */
135 	nb = lblkno(fs, ip->i_size);
136 	if (nb < NDADDR && nb < bn) {
137 		osize = blksize(fs, ip, nb);
138 		if (osize < fs->fs_bsize && osize > 0) {
139 			error = realloccg(ip, nb,
140 				blkpref(ip, nb, (int)nb, &ip->i_db[0]),
141 				osize, (int)fs->fs_bsize, &bp);
142 			if (error)
143 				return (error);
144 			ip->i_size = (nb + 1) * fs->fs_bsize;
145 			ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
146 			ip->i_flag |= IUPD|ICHG;
147 			if (flags & B_SYNC)
148 				bwrite(bp);
149 			else
150 				bawrite(bp);
151 		}
152 	}
153 	/*
154 	 * The first NDADDR blocks are direct blocks
155 	 */
156 	if (bn < NDADDR) {
157 		nb = ip->i_db[bn];
158 		if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
159 			error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
160 			if (error) {
161 				brelse(bp);
162 				return (error);
163 			}
164 			*bpp = bp;
165 			return (0);
166 		}
167 		if (nb != 0) {
168 			/*
169 			 * Consider need to reallocate a fragment.
170 			 */
171 			osize = fragroundup(fs, blkoff(fs, ip->i_size));
172 			nsize = fragroundup(fs, size);
173 			if (nsize <= osize) {
174 				error = bread(vp, bn, osize, NOCRED, &bp);
175 				if (error) {
176 					brelse(bp);
177 					return (error);
178 				}
179 			} else {
180 				error = realloccg(ip, bn,
181 					blkpref(ip, bn, (int)bn, &ip->i_db[0]),
182 					osize, nsize, &bp);
183 				if (error)
184 					return (error);
185 			}
186 		} else {
187 			if (ip->i_size < (bn + 1) * fs->fs_bsize)
188 				nsize = fragroundup(fs, size);
189 			else
190 				nsize = fs->fs_bsize;
191 			error = alloc(ip, bn,
192 				blkpref(ip, bn, (int)bn, &ip->i_db[0]),
193 				nsize, &newb);
194 			if (error)
195 				return (error);
196 			bp = getblk(vp, bn, nsize);
197 			bp->b_blkno = fsbtodb(fs, newb);
198 			if (flags & B_CLRBUF)
199 				clrbuf(bp);
200 		}
201 		ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
202 		ip->i_flag |= IUPD|ICHG;
203 		*bpp = bp;
204 		return (0);
205 	}
206 	/*
207 	 * Determine the number of levels of indirection.
208 	 */
209 	pref = 0;
210 	sh = 1;
211 	lbn = bn;
212 	bn -= NDADDR;
213 	for (j = NIADDR; j > 0; j--) {
214 		sh *= NINDIR(fs);
215 		if (bn < sh)
216 			break;
217 		bn -= sh;
218 	}
219 	if (j == 0)
220 		return (EFBIG);
221 	/*
222 	 * Fetch the first indirect block allocating if necessary.
223 	 */
224 	nb = ip->i_ib[NIADDR - j];
225 	if (nb == 0) {
226 		pref = blkpref(ip, lbn, 0, (daddr_t *)0);
227 	        if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb))
228 			return (error);
229 		nb = newb;
230 		bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
231 		clrbuf(bp);
232 		/*
233 		 * Write synchronously so that indirect blocks
234 		 * never point at garbage.
235 		 */
236 		if (error = bwrite(bp)) {
237 			blkfree(ip, nb, fs->fs_bsize);
238 			return (error);
239 		}
240 		ip->i_ib[NIADDR - j] = nb;
241 		ip->i_flag |= IUPD|ICHG;
242 	}
243 	/*
244 	 * Fetch through the indirect blocks, allocating as necessary.
245 	 */
246 	for (; ; j++) {
247 		error = bread(ip->i_devvp, fsbtodb(fs, nb),
248 		    (int)fs->fs_bsize, NOCRED, &bp);
249 		if (error) {
250 			brelse(bp);
251 			return (error);
252 		}
253 		bap = bp->b_un.b_daddr;
254 		sh /= NINDIR(fs);
255 		i = (bn / sh) % NINDIR(fs);
256 		nb = bap[i];
257 		if (j == NIADDR)
258 			break;
259 		if (nb != 0) {
260 			brelse(bp);
261 			continue;
262 		}
263 		if (pref == 0)
264 			pref = blkpref(ip, lbn, 0, (daddr_t *)0);
265 		if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
266 			brelse(bp);
267 			return (error);
268 		}
269 		nb = newb;
270 		nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
271 		clrbuf(nbp);
272 		/*
273 		 * Write synchronously so that indirect blocks
274 		 * never point at garbage.
275 		 */
276 		if (error = bwrite(nbp)) {
277 			blkfree(ip, nb, fs->fs_bsize);
278 			brelse(bp);
279 			return (error);
280 		}
281 		bap[i] = nb;
282 		/*
283 		 * If required, write synchronously, otherwise use
284 		 * delayed write. If this is the first instance of
285 		 * the delayed write, reassociate the buffer with the
286 		 * file so it will be written if the file is sync'ed.
287 		 */
288 		if (flags & B_SYNC) {
289 			bwrite(bp);
290 		} else if (bp->b_flags & B_DELWRI) {
291 			bdwrite(bp);
292 		} else {
293 			bdwrite(bp);
294 			reassignbuf(bp, vp);
295 		}
296 	}
297 	/*
298 	 * Get the data block, allocating if necessary.
299 	 */
300 	if (nb == 0) {
301 		pref = blkpref(ip, lbn, i, &bap[0]);
302 		if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
303 			brelse(bp);
304 			return (error);
305 		}
306 		nb = newb;
307 		nbp = getblk(vp, lbn, fs->fs_bsize);
308 		nbp->b_blkno = fsbtodb(fs, nb);
309 		if (flags & B_CLRBUF)
310 			clrbuf(nbp);
311 		bap[i] = nb;
312 		/*
313 		 * If required, write synchronously, otherwise use
314 		 * delayed write. If this is the first instance of
315 		 * the delayed write, reassociate the buffer with the
316 		 * file so it will be written if the file is sync'ed.
317 		 */
318 		if (flags & B_SYNC) {
319 			bwrite(bp);
320 		} else if (bp->b_flags & B_DELWRI) {
321 			bdwrite(bp);
322 		} else {
323 			bdwrite(bp);
324 			reassignbuf(bp, vp);
325 		}
326 		*bpp = nbp;
327 		return (0);
328 	}
329 	brelse(bp);
330 	if (flags & B_CLRBUF) {
331 		error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
332 		if (error) {
333 			brelse(nbp);
334 			return (error);
335 		}
336 	} else {
337 		nbp = getblk(vp, lbn, fs->fs_bsize);
338 		nbp->b_blkno = fsbtodb(fs, nb);
339 	}
340 	*bpp = nbp;
341 	return (0);
342 }
343