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