Remove building with NOCRYPTO option
[minix.git] / usr.sbin / makefs / ffs / ffs_balloc.c
blobbf1350470772dad57b9357c49e5fa6e246a35538
1 /* $NetBSD: ffs_balloc.c,v 1.21 2015/03/29 05:52:59 agc Exp $ */
2 /* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */
4 /*
5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
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.
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.
32 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
35 #if HAVE_NBTOOL_CONFIG_H
36 #include "nbtool_config.h"
37 #endif
39 #include <sys/cdefs.h>
40 #if defined(__RCSID) && !defined(__lint)
41 __RCSID("$NetBSD: ffs_balloc.c,v 1.21 2015/03/29 05:52:59 agc Exp $");
42 #endif /* !__lint */
44 #include <sys/param.h>
45 #include <sys/time.h>
47 #include <assert.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
53 #include "makefs.h"
55 #include <ufs/ufs/dinode.h>
56 #include <ufs/ufs/ufs_bswap.h>
57 #include <ufs/ffs/fs.h>
59 #include "ffs/buf.h"
60 #include "ffs/ufs_inode.h"
61 #include "ffs/ffs_extern.h"
63 static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **);
64 static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **);
67 * Balloc defines the structure of file system storage
68 * by allocating the physical blocks on a device given
69 * the inode and the logical block number in a file.
71 * Assume: flags == B_SYNC | B_CLRBUF
74 int
75 ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
77 if (ip->i_fs->fs_magic == FS_UFS2_MAGIC)
78 return ffs_balloc_ufs2(ip, offset, bufsize, bpp);
79 else
80 return ffs_balloc_ufs1(ip, offset, bufsize, bpp);
83 static int
84 ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
86 daddr_t lbn, lastlbn;
87 int size;
88 int32_t nb;
89 struct buf *bp, *nbp;
90 struct fs *fs = ip->i_fs;
91 struct indir indirs[UFS_NIADDR + 2];
92 daddr_t newb, pref;
93 int32_t *bap;
94 int osize, nsize, num, i, error;
95 int32_t *allocblk, allociblk[UFS_NIADDR + 1];
96 int32_t *allocib;
97 const int needswap = UFS_FSNEEDSWAP(fs);
99 lbn = ffs_lblkno(fs, offset);
100 size = ffs_blkoff(fs, offset) + bufsize;
101 if (bpp != NULL) {
102 *bpp = NULL;
105 assert(size <= fs->fs_bsize);
106 if (lbn < 0)
107 return (EFBIG);
110 * If the next write will extend the file into a new block,
111 * and the file is currently composed of a fragment
112 * this fragment has to be extended to be a full block.
115 lastlbn = ffs_lblkno(fs, ip->i_ffs1_size);
116 if (lastlbn < UFS_NDADDR && lastlbn < lbn) {
117 nb = lastlbn;
118 osize = ffs_blksize(fs, ip, nb);
119 if (osize < fs->fs_bsize && osize > 0) {
120 warnx("need to ffs_realloccg; not supported!");
121 abort();
126 * The first UFS_NDADDR blocks are direct blocks
129 if (lbn < UFS_NDADDR) {
130 nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap);
131 if (nb != 0 && ip->i_ffs1_size >= ffs_lblktosize(fs, lbn + 1)) {
134 * The block is an already-allocated direct block
135 * and the file already extends past this block,
136 * thus this must be a whole block.
137 * Just read the block (if requested).
140 if (bpp != NULL) {
141 error = bread(ip->i_devvp, lbn, fs->fs_bsize,
142 0, bpp);
143 if (error) {
144 brelse(*bpp, 0);
145 return (error);
148 return (0);
150 if (nb != 0) {
153 * Consider need to reallocate a fragment.
156 osize = ffs_fragroundup(fs, ffs_blkoff(fs, ip->i_ffs1_size));
157 nsize = ffs_fragroundup(fs, size);
158 if (nsize <= osize) {
161 * The existing block is already
162 * at least as big as we want.
163 * Just read the block (if requested).
166 if (bpp != NULL) {
167 error = bread(ip->i_devvp, lbn, osize,
168 0, bpp);
169 if (error) {
170 brelse(*bpp, 0);
171 return (error);
174 return 0;
175 } else {
176 warnx("need to ffs_realloccg; not supported!");
177 abort();
179 } else {
182 * the block was not previously allocated,
183 * allocate a new block or fragment.
186 if (ip->i_ffs1_size < ffs_lblktosize(fs, lbn + 1))
187 nsize = ffs_fragroundup(fs, size);
188 else
189 nsize = fs->fs_bsize;
190 error = ffs_alloc(ip, lbn,
191 ffs_blkpref_ufs1(ip, lbn, (int)lbn,
192 &ip->i_ffs1_db[0]),
193 nsize, &newb);
194 if (error)
195 return (error);
196 if (bpp != NULL) {
197 bp = getblk(ip->i_devvp, lbn, nsize, 0, 0);
198 bp->b_blkno = FFS_FSBTODB(fs, newb);
199 clrbuf(bp);
200 *bpp = bp;
203 ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap);
204 return (0);
208 * Determine the number of levels of indirection.
211 pref = 0;
212 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
213 return (error);
215 if (num < 1) {
216 warnx("ffs_balloc: ufs_getlbns returned indirect block");
217 abort();
221 * Fetch the first indirect block allocating if necessary.
224 --num;
225 nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap);
226 allocib = NULL;
227 allocblk = allociblk;
228 if (nb == 0) {
229 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
230 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
231 if (error)
232 return error;
233 nb = newb;
234 *allocblk++ = nb;
235 bp = getblk(ip->i_devvp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
236 bp->b_blkno = FFS_FSBTODB(fs, nb);
237 clrbuf(bp);
239 * Write synchronously so that indirect blocks
240 * never point at garbage.
242 if ((error = bwrite(bp)) != 0)
243 return error;
244 allocib = &ip->i_ffs1_ib[indirs[0].in_off];
245 *allocib = ufs_rw32((int32_t)nb, needswap);
249 * Fetch through the indirect blocks, allocating as necessary.
252 for (i = 1;;) {
253 error = bread(ip->i_devvp, indirs[i].in_lbn, fs->fs_bsize,
254 0, &bp);
255 if (error) {
256 brelse(bp, 0);
257 return error;
259 bap = (int32_t *)bp->b_data;
260 nb = ufs_rw32(bap[indirs[i].in_off], needswap);
261 if (i == num)
262 break;
263 i++;
264 if (nb != 0) {
265 brelse(bp, 0);
266 continue;
268 if (pref == 0)
269 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
270 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
271 if (error) {
272 brelse(bp, 0);
273 return error;
275 nb = newb;
276 *allocblk++ = nb;
277 nbp = getblk(ip->i_devvp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
278 nbp->b_blkno = FFS_FSBTODB(fs, nb);
279 clrbuf(nbp);
281 * Write synchronously so that indirect blocks
282 * never point at garbage.
285 if ((error = bwrite(nbp)) != 0) {
286 brelse(bp, 0);
287 return error;
289 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
291 bwrite(bp);
295 * Get the data block, allocating if necessary.
298 if (nb == 0) {
299 pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
300 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
301 if (error) {
302 brelse(bp, 0);
303 return error;
305 nb = newb;
306 *allocblk++ = nb;
307 if (bpp != NULL) {
308 nbp = getblk(ip->i_devvp, lbn, fs->fs_bsize, 0, 0);
309 nbp->b_blkno = FFS_FSBTODB(fs, nb);
310 clrbuf(nbp);
311 *bpp = nbp;
313 bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
316 * If required, write synchronously, otherwise use
317 * delayed write.
319 bwrite(bp);
320 return (0);
322 brelse(bp, 0);
323 if (bpp != NULL) {
324 error = bread(ip->i_devvp, lbn, (int)fs->fs_bsize, 0, &nbp);
325 if (error) {
326 brelse(nbp, 0);
327 return error;
329 *bpp = nbp;
331 return (0);
334 static int
335 ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
337 daddr_t lbn, lastlbn;
338 int size;
339 struct buf *bp, *nbp;
340 struct fs *fs = ip->i_fs;
341 struct indir indirs[UFS_NIADDR + 2];
342 daddr_t newb, pref, nb;
343 int64_t *bap;
344 int osize, nsize, num, i, error;
345 int64_t *allocblk, allociblk[UFS_NIADDR + 1];
346 int64_t *allocib;
347 const int needswap = UFS_FSNEEDSWAP(fs);
349 lbn = ffs_lblkno(fs, offset);
350 size = ffs_blkoff(fs, offset) + bufsize;
351 if (bpp != NULL) {
352 *bpp = NULL;
355 assert(size <= fs->fs_bsize);
356 if (lbn < 0)
357 return (EFBIG);
360 * If the next write will extend the file into a new block,
361 * and the file is currently composed of a fragment
362 * this fragment has to be extended to be a full block.
365 lastlbn = ffs_lblkno(fs, ip->i_ffs2_size);
366 if (lastlbn < UFS_NDADDR && lastlbn < lbn) {
367 nb = lastlbn;
368 osize = ffs_blksize(fs, ip, nb);
369 if (osize < fs->fs_bsize && osize > 0) {
370 warnx("need to ffs_realloccg; not supported!");
371 abort();
376 * The first UFS_NDADDR blocks are direct blocks
379 if (lbn < UFS_NDADDR) {
380 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
381 if (nb != 0 && ip->i_ffs2_size >= ffs_lblktosize(fs, lbn + 1)) {
384 * The block is an already-allocated direct block
385 * and the file already extends past this block,
386 * thus this must be a whole block.
387 * Just read the block (if requested).
390 if (bpp != NULL) {
391 error = bread(ip->i_devvp, lbn, fs->fs_bsize,
392 0, bpp);
393 if (error) {
394 brelse(*bpp, 0);
395 return (error);
398 return (0);
400 if (nb != 0) {
403 * Consider need to reallocate a fragment.
406 osize = ffs_fragroundup(fs, ffs_blkoff(fs, ip->i_ffs2_size));
407 nsize = ffs_fragroundup(fs, size);
408 if (nsize <= osize) {
411 * The existing block is already
412 * at least as big as we want.
413 * Just read the block (if requested).
416 if (bpp != NULL) {
417 error = bread(ip->i_devvp, lbn, osize,
418 0, bpp);
419 if (error) {
420 brelse(*bpp, 0);
421 return (error);
424 return 0;
425 } else {
426 warnx("need to ffs_realloccg; not supported!");
427 abort();
429 } else {
432 * the block was not previously allocated,
433 * allocate a new block or fragment.
436 if (ip->i_ffs2_size < ffs_lblktosize(fs, lbn + 1))
437 nsize = ffs_fragroundup(fs, size);
438 else
439 nsize = fs->fs_bsize;
440 error = ffs_alloc(ip, lbn,
441 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
442 &ip->i_ffs2_db[0]),
443 nsize, &newb);
444 if (error)
445 return (error);
446 if (bpp != NULL) {
447 bp = getblk(ip->i_devvp, lbn, nsize, 0, 0);
448 bp->b_blkno = FFS_FSBTODB(fs, newb);
449 clrbuf(bp);
450 *bpp = bp;
453 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
454 return (0);
458 * Determine the number of levels of indirection.
461 pref = 0;
462 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
463 return (error);
465 if (num < 1) {
466 warnx("ffs_balloc: ufs_getlbns returned indirect block");
467 abort();
471 * Fetch the first indirect block allocating if necessary.
474 --num;
475 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
476 allocib = NULL;
477 allocblk = allociblk;
478 if (nb == 0) {
479 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
480 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
481 if (error)
482 return error;
483 nb = newb;
484 *allocblk++ = nb;
485 bp = getblk(ip->i_devvp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
486 bp->b_blkno = FFS_FSBTODB(fs, nb);
487 clrbuf(bp);
489 * Write synchronously so that indirect blocks
490 * never point at garbage.
492 if ((error = bwrite(bp)) != 0)
493 return error;
494 allocib = &ip->i_ffs2_ib[indirs[0].in_off];
495 *allocib = ufs_rw64(nb, needswap);
499 * Fetch through the indirect blocks, allocating as necessary.
502 for (i = 1;;) {
503 error = bread(ip->i_devvp, indirs[i].in_lbn, fs->fs_bsize,
504 0, &bp);
505 if (error) {
506 brelse(bp, 0);
507 return error;
509 bap = (int64_t *)bp->b_data;
510 nb = ufs_rw64(bap[indirs[i].in_off], needswap);
511 if (i == num)
512 break;
513 i++;
514 if (nb != 0) {
515 brelse(bp, 0);
516 continue;
518 if (pref == 0)
519 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
520 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
521 if (error) {
522 brelse(bp, 0);
523 return error;
525 nb = newb;
526 *allocblk++ = nb;
527 nbp = getblk(ip->i_devvp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
528 nbp->b_blkno = FFS_FSBTODB(fs, nb);
529 clrbuf(nbp);
531 * Write synchronously so that indirect blocks
532 * never point at garbage.
535 if ((error = bwrite(nbp)) != 0) {
536 brelse(bp, 0);
537 return error;
539 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
541 bwrite(bp);
545 * Get the data block, allocating if necessary.
548 if (nb == 0) {
549 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
550 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
551 if (error) {
552 brelse(bp, 0);
553 return error;
555 nb = newb;
556 *allocblk++ = nb;
557 if (bpp != NULL) {
558 nbp = getblk(ip->i_devvp, lbn, fs->fs_bsize, 0, 0);
559 nbp->b_blkno = FFS_FSBTODB(fs, nb);
560 clrbuf(nbp);
561 *bpp = nbp;
563 bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
566 * If required, write synchronously, otherwise use
567 * delayed write.
569 bwrite(bp);
570 return (0);
572 brelse(bp, 0);
573 if (bpp != NULL) {
574 error = bread(ip->i_devvp, lbn, (int)fs->fs_bsize, 0,
575 &nbp);
576 if (error) {
577 brelse(nbp, 0);
578 return error;
580 *bpp = nbp;
582 return (0);