OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [disk/] [tools/] [fs-NetBSD/] [makefs/] [ffs_balloc.c] - Blame information for rev 185

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.