Deleted Added
full compact
ffs_balloc.c (186261) ffs_balloc.c (186334)
1/* $NetBSD: ffs_balloc.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */
2/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */
3
4/*
5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
33 */
34
35#include <sys/cdefs.h>
1/* $NetBSD: ffs_balloc.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */
2/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */
3
4/*
5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
33 */
34
35#include <sys/cdefs.h>
36#if defined(__RCSID) && !defined(__lint)
37__RCSID("$NetBSD: ffs_balloc.c,v 1.13 2004/06/20 22:20:18 jmc Exp $");
38#endif /* !__lint */
36__FBSDID("$FreeBSD: projects/makefs/ffs/ffs_balloc.c 186334 2008-12-19 18:45:43Z sam $");
39
40#include <sys/param.h>
41#include <sys/time.h>
42
43#include <assert.h>
44#include <errno.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "makefs.h"
50
51#include <ufs/ufs/dinode.h>
52#include <ufs/ffs/fs.h>
53
54#include "ffs/ufs_bswap.h"
55#include "ffs/buf.h"
56#include "ffs/ufs_inode.h"
57#include "ffs/ffs_extern.h"
58
59static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **);
60static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **);
61
62/*
63 * Balloc defines the structure of file system storage
64 * by allocating the physical blocks on a device given
65 * the inode and the logical block number in a file.
66 *
67 * Assume: flags == B_SYNC | B_CLRBUF
68 */
69
70int
71ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
72{
73 if (ip->i_fs->fs_magic == FS_UFS2_MAGIC)
74 return ffs_balloc_ufs2(ip, offset, bufsize, bpp);
75 else
76 return ffs_balloc_ufs1(ip, offset, bufsize, bpp);
77}
78
79static int
80ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
81{
82 daddr_t lbn, lastlbn;
83 int size;
84 int32_t nb;
85 struct buf *bp, *nbp;
86 struct fs *fs = ip->i_fs;
87 struct indir indirs[NIADDR + 2];
88 daddr_t newb, pref;
89 int32_t *bap;
90 int osize, nsize, num, i, error;
91 int32_t *allocblk, allociblk[NIADDR + 1];
92 int32_t *allocib;
93 const int needswap = UFS_FSNEEDSWAP(fs);
94
95 lbn = lblkno(fs, offset);
96 size = blkoff(fs, offset) + bufsize;
97 if (bpp != NULL) {
98 *bpp = NULL;
99 }
100
101 assert(size <= fs->fs_bsize);
102 if (lbn < 0)
103 return (EFBIG);
104
105 /*
106 * If the next write will extend the file into a new block,
107 * and the file is currently composed of a fragment
108 * this fragment has to be extended to be a full block.
109 */
110
111 lastlbn = lblkno(fs, ip->i_ffs1_size);
112 if (lastlbn < NDADDR && lastlbn < lbn) {
113 nb = lastlbn;
114 osize = blksize(fs, ip, nb);
115 if (osize < fs->fs_bsize && osize > 0) {
116 warnx("need to ffs_realloccg; not supported!");
117 abort();
118 }
119 }
120
121 /*
122 * The first NDADDR blocks are direct blocks
123 */
124
125 if (lbn < NDADDR) {
126 nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap);
127 if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) {
128
129 /*
130 * The block is an already-allocated direct block
131 * and the file already extends past this block,
132 * thus this must be a whole block.
133 * Just read the block (if requested).
134 */
135
136 if (bpp != NULL) {
137 error = bread(ip->i_fd, ip->i_fs, lbn,
138 fs->fs_bsize, bpp);
139 if (error) {
140 brelse(*bpp);
141 return (error);
142 }
143 }
144 return (0);
145 }
146 if (nb != 0) {
147
148 /*
149 * Consider need to reallocate a fragment.
150 */
151
152 osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size));
153 nsize = fragroundup(fs, size);
154 if (nsize <= osize) {
155
156 /*
157 * The existing block is already
158 * at least as big as we want.
159 * Just read the block (if requested).
160 */
161
162 if (bpp != NULL) {
163 error = bread(ip->i_fd, ip->i_fs, lbn,
164 osize, bpp);
165 if (error) {
166 brelse(*bpp);
167 return (error);
168 }
169 }
170 return 0;
171 } else {
172 warnx("need to ffs_realloccg; not supported!");
173 abort();
174 }
175 } else {
176
177 /*
178 * the block was not previously allocated,
179 * allocate a new block or fragment.
180 */
181
182 if (ip->i_ffs1_size < lblktosize(fs, lbn + 1))
183 nsize = fragroundup(fs, size);
184 else
185 nsize = fs->fs_bsize;
186 error = ffs_alloc(ip, lbn,
187 ffs_blkpref_ufs1(ip, lbn, (int)lbn,
188 &ip->i_ffs1_db[0]),
189 nsize, &newb);
190 if (error)
191 return (error);
192 if (bpp != NULL) {
193 bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
194 bp->b_blkno = fsbtodb(fs, newb);
195 clrbuf(bp);
196 *bpp = bp;
197 }
198 }
199 ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap);
200 return (0);
201 }
202
203 /*
204 * Determine the number of levels of indirection.
205 */
206
207 pref = 0;
208 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
209 return (error);
210
211 if (num < 1) {
212 warnx("ffs_balloc: ufs_getlbns returned indirect block");
213 abort();
214 }
215
216 /*
217 * Fetch the first indirect block allocating if necessary.
218 */
219
220 --num;
221 nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap);
222 allocib = NULL;
223 allocblk = allociblk;
224 if (nb == 0) {
225 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
226 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
227 if (error)
228 return error;
229 nb = newb;
230 *allocblk++ = nb;
231 bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
232 bp->b_blkno = fsbtodb(fs, nb);
233 clrbuf(bp);
234 /*
235 * Write synchronously so that indirect blocks
236 * never point at garbage.
237 */
238 if ((error = bwrite(bp)) != 0)
239 return error;
240 allocib = &ip->i_ffs1_ib[indirs[0].in_off];
241 *allocib = ufs_rw32((int32_t)nb, needswap);
242 }
243
244 /*
245 * Fetch through the indirect blocks, allocating as necessary.
246 */
247
248 for (i = 1;;) {
249 error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
250 fs->fs_bsize, &bp);
251 if (error) {
252 brelse(bp);
253 return error;
254 }
255 bap = (int32_t *)bp->b_data;
256 nb = ufs_rw32(bap[indirs[i].in_off], needswap);
257 if (i == num)
258 break;
259 i++;
260 if (nb != 0) {
261 brelse(bp);
262 continue;
263 }
264 if (pref == 0)
265 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
266 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
267 if (error) {
268 brelse(bp);
269 return error;
270 }
271 nb = newb;
272 *allocblk++ = nb;
273 nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
274 fs->fs_bsize);
275 nbp->b_blkno = fsbtodb(fs, nb);
276 clrbuf(nbp);
277 /*
278 * Write synchronously so that indirect blocks
279 * never point at garbage.
280 */
281
282 if ((error = bwrite(nbp)) != 0) {
283 brelse(bp);
284 return error;
285 }
286 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
287
288 bwrite(bp);
289 }
290
291 /*
292 * Get the data block, allocating if necessary.
293 */
294
295 if (nb == 0) {
296 pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
297 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
298 if (error) {
299 brelse(bp);
300 return error;
301 }
302 nb = newb;
303 *allocblk++ = nb;
304 if (bpp != NULL) {
305 nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
306 nbp->b_blkno = fsbtodb(fs, nb);
307 clrbuf(nbp);
308 *bpp = nbp;
309 }
310 bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
311
312 /*
313 * If required, write synchronously, otherwise use
314 * delayed write.
315 */
316 bwrite(bp);
317 return (0);
318 }
319 brelse(bp);
320 if (bpp != NULL) {
321 error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
322 if (error) {
323 brelse(nbp);
324 return error;
325 }
326 *bpp = nbp;
327 }
328 return (0);
329}
330
331static int
332ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
333{
334 daddr_t lbn, lastlbn;
335 int size;
336 struct buf *bp, *nbp;
337 struct fs *fs = ip->i_fs;
338 struct indir indirs[NIADDR + 2];
339 daddr_t newb, pref, nb;
340 int64_t *bap;
341 int osize, nsize, num, i, error;
342 int64_t *allocblk, allociblk[NIADDR + 1];
343 int64_t *allocib;
344 const int needswap = UFS_FSNEEDSWAP(fs);
345
346 lbn = lblkno(fs, offset);
347 size = blkoff(fs, offset) + bufsize;
348 if (bpp != NULL) {
349 *bpp = NULL;
350 }
351
352 assert(size <= fs->fs_bsize);
353 if (lbn < 0)
354 return (EFBIG);
355
356 /*
357 * If the next write will extend the file into a new block,
358 * and the file is currently composed of a fragment
359 * this fragment has to be extended to be a full block.
360 */
361
362 lastlbn = lblkno(fs, ip->i_ffs2_size);
363 if (lastlbn < NDADDR && lastlbn < lbn) {
364 nb = lastlbn;
365 osize = blksize(fs, ip, nb);
366 if (osize < fs->fs_bsize && osize > 0) {
367 warnx("need to ffs_realloccg; not supported!");
368 abort();
369 }
370 }
371
372 /*
373 * The first NDADDR blocks are direct blocks
374 */
375
376 if (lbn < NDADDR) {
377 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
378 if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) {
379
380 /*
381 * The block is an already-allocated direct block
382 * and the file already extends past this block,
383 * thus this must be a whole block.
384 * Just read the block (if requested).
385 */
386
387 if (bpp != NULL) {
388 error = bread(ip->i_fd, ip->i_fs, lbn,
389 fs->fs_bsize, bpp);
390 if (error) {
391 brelse(*bpp);
392 return (error);
393 }
394 }
395 return (0);
396 }
397 if (nb != 0) {
398
399 /*
400 * Consider need to reallocate a fragment.
401 */
402
403 osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size));
404 nsize = fragroundup(fs, size);
405 if (nsize <= osize) {
406
407 /*
408 * The existing block is already
409 * at least as big as we want.
410 * Just read the block (if requested).
411 */
412
413 if (bpp != NULL) {
414 error = bread(ip->i_fd, ip->i_fs, lbn,
415 osize, bpp);
416 if (error) {
417 brelse(*bpp);
418 return (error);
419 }
420 }
421 return 0;
422 } else {
423 warnx("need to ffs_realloccg; not supported!");
424 abort();
425 }
426 } else {
427
428 /*
429 * the block was not previously allocated,
430 * allocate a new block or fragment.
431 */
432
433 if (ip->i_ffs2_size < lblktosize(fs, lbn + 1))
434 nsize = fragroundup(fs, size);
435 else
436 nsize = fs->fs_bsize;
437 error = ffs_alloc(ip, lbn,
438 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
439 &ip->i_ffs2_db[0]),
440 nsize, &newb);
441 if (error)
442 return (error);
443 if (bpp != NULL) {
444 bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
445 bp->b_blkno = fsbtodb(fs, newb);
446 clrbuf(bp);
447 *bpp = bp;
448 }
449 }
450 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
451 return (0);
452 }
453
454 /*
455 * Determine the number of levels of indirection.
456 */
457
458 pref = 0;
459 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
460 return (error);
461
462 if (num < 1) {
463 warnx("ffs_balloc: ufs_getlbns returned indirect block");
464 abort();
465 }
466
467 /*
468 * Fetch the first indirect block allocating if necessary.
469 */
470
471 --num;
472 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
473 allocib = NULL;
474 allocblk = allociblk;
475 if (nb == 0) {
476 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
477 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
478 if (error)
479 return error;
480 nb = newb;
481 *allocblk++ = nb;
482 bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
483 bp->b_blkno = fsbtodb(fs, nb);
484 clrbuf(bp);
485 /*
486 * Write synchronously so that indirect blocks
487 * never point at garbage.
488 */
489 if ((error = bwrite(bp)) != 0)
490 return error;
491 allocib = &ip->i_ffs2_ib[indirs[0].in_off];
492 *allocib = ufs_rw64(nb, needswap);
493 }
494
495 /*
496 * Fetch through the indirect blocks, allocating as necessary.
497 */
498
499 for (i = 1;;) {
500 error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
501 fs->fs_bsize, &bp);
502 if (error) {
503 brelse(bp);
504 return error;
505 }
506 bap = (int64_t *)bp->b_data;
507 nb = ufs_rw64(bap[indirs[i].in_off], needswap);
508 if (i == num)
509 break;
510 i++;
511 if (nb != 0) {
512 brelse(bp);
513 continue;
514 }
515 if (pref == 0)
516 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
517 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
518 if (error) {
519 brelse(bp);
520 return error;
521 }
522 nb = newb;
523 *allocblk++ = nb;
524 nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
525 fs->fs_bsize);
526 nbp->b_blkno = fsbtodb(fs, nb);
527 clrbuf(nbp);
528 /*
529 * Write synchronously so that indirect blocks
530 * never point at garbage.
531 */
532
533 if ((error = bwrite(nbp)) != 0) {
534 brelse(bp);
535 return error;
536 }
537 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
538
539 bwrite(bp);
540 }
541
542 /*
543 * Get the data block, allocating if necessary.
544 */
545
546 if (nb == 0) {
547 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
548 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
549 if (error) {
550 brelse(bp);
551 return error;
552 }
553 nb = newb;
554 *allocblk++ = nb;
555 if (bpp != NULL) {
556 nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
557 nbp->b_blkno = fsbtodb(fs, nb);
558 clrbuf(nbp);
559 *bpp = nbp;
560 }
561 bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
562
563 /*
564 * If required, write synchronously, otherwise use
565 * delayed write.
566 */
567 bwrite(bp);
568 return (0);
569 }
570 brelse(bp);
571 if (bpp != NULL) {
572 error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
573 if (error) {
574 brelse(nbp);
575 return error;
576 }
577 *bpp = nbp;
578 }
579 return (0);
580}
37
38#include <sys/param.h>
39#include <sys/time.h>
40
41#include <assert.h>
42#include <errno.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include "makefs.h"
48
49#include <ufs/ufs/dinode.h>
50#include <ufs/ffs/fs.h>
51
52#include "ffs/ufs_bswap.h"
53#include "ffs/buf.h"
54#include "ffs/ufs_inode.h"
55#include "ffs/ffs_extern.h"
56
57static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **);
58static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **);
59
60/*
61 * Balloc defines the structure of file system storage
62 * by allocating the physical blocks on a device given
63 * the inode and the logical block number in a file.
64 *
65 * Assume: flags == B_SYNC | B_CLRBUF
66 */
67
68int
69ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
70{
71 if (ip->i_fs->fs_magic == FS_UFS2_MAGIC)
72 return ffs_balloc_ufs2(ip, offset, bufsize, bpp);
73 else
74 return ffs_balloc_ufs1(ip, offset, bufsize, bpp);
75}
76
77static int
78ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
79{
80 daddr_t lbn, lastlbn;
81 int size;
82 int32_t nb;
83 struct buf *bp, *nbp;
84 struct fs *fs = ip->i_fs;
85 struct indir indirs[NIADDR + 2];
86 daddr_t newb, pref;
87 int32_t *bap;
88 int osize, nsize, num, i, error;
89 int32_t *allocblk, allociblk[NIADDR + 1];
90 int32_t *allocib;
91 const int needswap = UFS_FSNEEDSWAP(fs);
92
93 lbn = lblkno(fs, offset);
94 size = blkoff(fs, offset) + bufsize;
95 if (bpp != NULL) {
96 *bpp = NULL;
97 }
98
99 assert(size <= fs->fs_bsize);
100 if (lbn < 0)
101 return (EFBIG);
102
103 /*
104 * If the next write will extend the file into a new block,
105 * and the file is currently composed of a fragment
106 * this fragment has to be extended to be a full block.
107 */
108
109 lastlbn = lblkno(fs, ip->i_ffs1_size);
110 if (lastlbn < NDADDR && lastlbn < lbn) {
111 nb = lastlbn;
112 osize = blksize(fs, ip, nb);
113 if (osize < fs->fs_bsize && osize > 0) {
114 warnx("need to ffs_realloccg; not supported!");
115 abort();
116 }
117 }
118
119 /*
120 * The first NDADDR blocks are direct blocks
121 */
122
123 if (lbn < NDADDR) {
124 nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap);
125 if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) {
126
127 /*
128 * The block is an already-allocated direct block
129 * and the file already extends past this block,
130 * thus this must be a whole block.
131 * Just read the block (if requested).
132 */
133
134 if (bpp != NULL) {
135 error = bread(ip->i_fd, ip->i_fs, lbn,
136 fs->fs_bsize, bpp);
137 if (error) {
138 brelse(*bpp);
139 return (error);
140 }
141 }
142 return (0);
143 }
144 if (nb != 0) {
145
146 /*
147 * Consider need to reallocate a fragment.
148 */
149
150 osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size));
151 nsize = fragroundup(fs, size);
152 if (nsize <= osize) {
153
154 /*
155 * The existing block is already
156 * at least as big as we want.
157 * Just read the block (if requested).
158 */
159
160 if (bpp != NULL) {
161 error = bread(ip->i_fd, ip->i_fs, lbn,
162 osize, bpp);
163 if (error) {
164 brelse(*bpp);
165 return (error);
166 }
167 }
168 return 0;
169 } else {
170 warnx("need to ffs_realloccg; not supported!");
171 abort();
172 }
173 } else {
174
175 /*
176 * the block was not previously allocated,
177 * allocate a new block or fragment.
178 */
179
180 if (ip->i_ffs1_size < lblktosize(fs, lbn + 1))
181 nsize = fragroundup(fs, size);
182 else
183 nsize = fs->fs_bsize;
184 error = ffs_alloc(ip, lbn,
185 ffs_blkpref_ufs1(ip, lbn, (int)lbn,
186 &ip->i_ffs1_db[0]),
187 nsize, &newb);
188 if (error)
189 return (error);
190 if (bpp != NULL) {
191 bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
192 bp->b_blkno = fsbtodb(fs, newb);
193 clrbuf(bp);
194 *bpp = bp;
195 }
196 }
197 ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap);
198 return (0);
199 }
200
201 /*
202 * Determine the number of levels of indirection.
203 */
204
205 pref = 0;
206 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
207 return (error);
208
209 if (num < 1) {
210 warnx("ffs_balloc: ufs_getlbns returned indirect block");
211 abort();
212 }
213
214 /*
215 * Fetch the first indirect block allocating if necessary.
216 */
217
218 --num;
219 nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap);
220 allocib = NULL;
221 allocblk = allociblk;
222 if (nb == 0) {
223 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
224 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
225 if (error)
226 return error;
227 nb = newb;
228 *allocblk++ = nb;
229 bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
230 bp->b_blkno = fsbtodb(fs, nb);
231 clrbuf(bp);
232 /*
233 * Write synchronously so that indirect blocks
234 * never point at garbage.
235 */
236 if ((error = bwrite(bp)) != 0)
237 return error;
238 allocib = &ip->i_ffs1_ib[indirs[0].in_off];
239 *allocib = ufs_rw32((int32_t)nb, needswap);
240 }
241
242 /*
243 * Fetch through the indirect blocks, allocating as necessary.
244 */
245
246 for (i = 1;;) {
247 error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
248 fs->fs_bsize, &bp);
249 if (error) {
250 brelse(bp);
251 return error;
252 }
253 bap = (int32_t *)bp->b_data;
254 nb = ufs_rw32(bap[indirs[i].in_off], needswap);
255 if (i == num)
256 break;
257 i++;
258 if (nb != 0) {
259 brelse(bp);
260 continue;
261 }
262 if (pref == 0)
263 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
264 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
265 if (error) {
266 brelse(bp);
267 return error;
268 }
269 nb = newb;
270 *allocblk++ = nb;
271 nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
272 fs->fs_bsize);
273 nbp->b_blkno = fsbtodb(fs, nb);
274 clrbuf(nbp);
275 /*
276 * Write synchronously so that indirect blocks
277 * never point at garbage.
278 */
279
280 if ((error = bwrite(nbp)) != 0) {
281 brelse(bp);
282 return error;
283 }
284 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
285
286 bwrite(bp);
287 }
288
289 /*
290 * Get the data block, allocating if necessary.
291 */
292
293 if (nb == 0) {
294 pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
295 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
296 if (error) {
297 brelse(bp);
298 return error;
299 }
300 nb = newb;
301 *allocblk++ = nb;
302 if (bpp != NULL) {
303 nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
304 nbp->b_blkno = fsbtodb(fs, nb);
305 clrbuf(nbp);
306 *bpp = nbp;
307 }
308 bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
309
310 /*
311 * If required, write synchronously, otherwise use
312 * delayed write.
313 */
314 bwrite(bp);
315 return (0);
316 }
317 brelse(bp);
318 if (bpp != NULL) {
319 error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
320 if (error) {
321 brelse(nbp);
322 return error;
323 }
324 *bpp = nbp;
325 }
326 return (0);
327}
328
329static int
330ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
331{
332 daddr_t lbn, lastlbn;
333 int size;
334 struct buf *bp, *nbp;
335 struct fs *fs = ip->i_fs;
336 struct indir indirs[NIADDR + 2];
337 daddr_t newb, pref, nb;
338 int64_t *bap;
339 int osize, nsize, num, i, error;
340 int64_t *allocblk, allociblk[NIADDR + 1];
341 int64_t *allocib;
342 const int needswap = UFS_FSNEEDSWAP(fs);
343
344 lbn = lblkno(fs, offset);
345 size = blkoff(fs, offset) + bufsize;
346 if (bpp != NULL) {
347 *bpp = NULL;
348 }
349
350 assert(size <= fs->fs_bsize);
351 if (lbn < 0)
352 return (EFBIG);
353
354 /*
355 * If the next write will extend the file into a new block,
356 * and the file is currently composed of a fragment
357 * this fragment has to be extended to be a full block.
358 */
359
360 lastlbn = lblkno(fs, ip->i_ffs2_size);
361 if (lastlbn < NDADDR && lastlbn < lbn) {
362 nb = lastlbn;
363 osize = blksize(fs, ip, nb);
364 if (osize < fs->fs_bsize && osize > 0) {
365 warnx("need to ffs_realloccg; not supported!");
366 abort();
367 }
368 }
369
370 /*
371 * The first NDADDR blocks are direct blocks
372 */
373
374 if (lbn < NDADDR) {
375 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
376 if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) {
377
378 /*
379 * The block is an already-allocated direct block
380 * and the file already extends past this block,
381 * thus this must be a whole block.
382 * Just read the block (if requested).
383 */
384
385 if (bpp != NULL) {
386 error = bread(ip->i_fd, ip->i_fs, lbn,
387 fs->fs_bsize, bpp);
388 if (error) {
389 brelse(*bpp);
390 return (error);
391 }
392 }
393 return (0);
394 }
395 if (nb != 0) {
396
397 /*
398 * Consider need to reallocate a fragment.
399 */
400
401 osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size));
402 nsize = fragroundup(fs, size);
403 if (nsize <= osize) {
404
405 /*
406 * The existing block is already
407 * at least as big as we want.
408 * Just read the block (if requested).
409 */
410
411 if (bpp != NULL) {
412 error = bread(ip->i_fd, ip->i_fs, lbn,
413 osize, bpp);
414 if (error) {
415 brelse(*bpp);
416 return (error);
417 }
418 }
419 return 0;
420 } else {
421 warnx("need to ffs_realloccg; not supported!");
422 abort();
423 }
424 } else {
425
426 /*
427 * the block was not previously allocated,
428 * allocate a new block or fragment.
429 */
430
431 if (ip->i_ffs2_size < lblktosize(fs, lbn + 1))
432 nsize = fragroundup(fs, size);
433 else
434 nsize = fs->fs_bsize;
435 error = ffs_alloc(ip, lbn,
436 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
437 &ip->i_ffs2_db[0]),
438 nsize, &newb);
439 if (error)
440 return (error);
441 if (bpp != NULL) {
442 bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
443 bp->b_blkno = fsbtodb(fs, newb);
444 clrbuf(bp);
445 *bpp = bp;
446 }
447 }
448 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
449 return (0);
450 }
451
452 /*
453 * Determine the number of levels of indirection.
454 */
455
456 pref = 0;
457 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
458 return (error);
459
460 if (num < 1) {
461 warnx("ffs_balloc: ufs_getlbns returned indirect block");
462 abort();
463 }
464
465 /*
466 * Fetch the first indirect block allocating if necessary.
467 */
468
469 --num;
470 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
471 allocib = NULL;
472 allocblk = allociblk;
473 if (nb == 0) {
474 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
475 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
476 if (error)
477 return error;
478 nb = newb;
479 *allocblk++ = nb;
480 bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
481 bp->b_blkno = fsbtodb(fs, nb);
482 clrbuf(bp);
483 /*
484 * Write synchronously so that indirect blocks
485 * never point at garbage.
486 */
487 if ((error = bwrite(bp)) != 0)
488 return error;
489 allocib = &ip->i_ffs2_ib[indirs[0].in_off];
490 *allocib = ufs_rw64(nb, needswap);
491 }
492
493 /*
494 * Fetch through the indirect blocks, allocating as necessary.
495 */
496
497 for (i = 1;;) {
498 error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
499 fs->fs_bsize, &bp);
500 if (error) {
501 brelse(bp);
502 return error;
503 }
504 bap = (int64_t *)bp->b_data;
505 nb = ufs_rw64(bap[indirs[i].in_off], needswap);
506 if (i == num)
507 break;
508 i++;
509 if (nb != 0) {
510 brelse(bp);
511 continue;
512 }
513 if (pref == 0)
514 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
515 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
516 if (error) {
517 brelse(bp);
518 return error;
519 }
520 nb = newb;
521 *allocblk++ = nb;
522 nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
523 fs->fs_bsize);
524 nbp->b_blkno = fsbtodb(fs, nb);
525 clrbuf(nbp);
526 /*
527 * Write synchronously so that indirect blocks
528 * never point at garbage.
529 */
530
531 if ((error = bwrite(nbp)) != 0) {
532 brelse(bp);
533 return error;
534 }
535 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
536
537 bwrite(bp);
538 }
539
540 /*
541 * Get the data block, allocating if necessary.
542 */
543
544 if (nb == 0) {
545 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
546 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
547 if (error) {
548 brelse(bp);
549 return error;
550 }
551 nb = newb;
552 *allocblk++ = nb;
553 if (bpp != NULL) {
554 nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
555 nbp->b_blkno = fsbtodb(fs, nb);
556 clrbuf(nbp);
557 *bpp = nbp;
558 }
559 bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
560
561 /*
562 * If required, write synchronously, otherwise use
563 * delayed write.
564 */
565 bwrite(bp);
566 return (0);
567 }
568 brelse(bp);
569 if (bpp != NULL) {
570 error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
571 if (error) {
572 brelse(nbp);
573 return error;
574 }
575 *bpp = nbp;
576 }
577 return (0);
578}