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