2 * modified for Lites 1.1
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
8 * Copyright (c) 1982, 1986, 1989, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
40 * $FreeBSD: src/sys/gnu/ext2fs/ext2_balloc.c,v 1.9.2.1 2000/08/03 00:52:57 peter Exp $
43 #include <sys/param.h>
44 #include <sys/systm.h>
47 #include <sys/ucred.h>
48 #include <sys/vnode.h>
53 #include "ext2_fs_sb.h"
55 #include "ext2_extern.h"
58 * Balloc defines the structure of file system storage
59 * by allocating the physical blocks on a device given
60 * the inode and the logical block number in a file.
63 ext2_balloc(struct inode
*ip
, daddr_t bn
, int size
, struct ucred
*cred
,
64 struct buf
**bpp
, int flags
)
66 struct ext2_sb_info
*fs
;
69 struct vnode
*vp
= ITOV(ip
);
70 struct indir indirs
[NIADDR
+ 2];
71 daddr_t newb
, lbn
, *bap
, pref
;
72 int osize
, nsize
, num
, i
, error
;
74 ext2_debug("ext2_balloc called (%d, %d, %d)\n",
75 ip->i_number, (int)bn, (int)size);
84 * check if this is a sequential block allocation.
85 * If so, increment next_alloc fields to allow ext2_blkpref
86 * to make a good guess
88 if (lbn
== ip
->i_next_alloc_block
+ 1) {
89 ip
->i_next_alloc_block
++;
90 ip
->i_next_alloc_goal
++;
94 * The first NDADDR blocks are direct blocks
98 /* no new block is to be allocated, and no need to expand
100 if (nb
!= 0 && ip
->i_size
>= (bn
+ 1) * fs
->s_blocksize
) {
101 error
= bread(vp
, lblktodoff(fs
, bn
),
102 fs
->s_blocksize
, &bp
);
112 * Consider need to reallocate a fragment.
114 osize
= fragroundup(fs
, blkoff(fs
, ip
->i_size
));
115 nsize
= fragroundup(fs
, size
);
116 if (nsize
<= osize
) {
117 error
= bread(vp
, lblktodoff(fs
, bn
),
124 /* Godmar thinks: this shouldn't happen w/o fragments */
125 kprintf("nsize %d(%d) > osize %d(%d) nb %d\n",
126 (int)nsize
, (int)size
, (int)osize
,
127 (int)ip
->i_size
, (int)nb
);
129 "ext2_balloc: Something is terribly wrong");
131 * please note there haven't been any changes from here on -
136 if (ip
->i_size
< (bn
+ 1) * fs
->s_blocksize
)
137 nsize
= fragroundup(fs
, size
);
139 nsize
= fs
->s_blocksize
;
140 error
= ext2_alloc(ip
, bn
,
141 ext2_blkpref(ip
, bn
, (int)bn
, &ip
->i_db
[0], 0),
145 bp
= getblk(vp
, lblktodoff(fs
, bn
), nsize
, 0, 0);
146 bp
->b_bio2
.bio_offset
= fsbtodoff(fs
, newb
);
147 if (flags
& B_CLRBUF
)
150 ip
->i_db
[bn
] = dofftofsb(fs
, bp
->b_bio2
.bio_offset
);
151 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
156 * Determine the number of levels of indirection.
159 if ((error
= ext2_getlbns(vp
, bn
, indirs
, &num
)) != 0)
163 panic ("ext2_balloc: ext2_bmaparray returned indirect block");
166 * Fetch the first indirect block allocating if necessary.
169 nb
= ip
->i_ib
[indirs
[0].in_off
];
172 pref
= ext2_blkpref(ip
, lbn
, 0, NULL
, 0);
174 /* see the comment by ext2_blkpref. What we do here is
175 to pretend that it'd be good for a block holding indirect
176 pointers to be allocated near its predecessor in terms
177 of indirection, or the last direct block.
178 We shamelessly exploit the fact that i_ib immediately
180 Godmar thinks it make sense to allocate i_ib[0] immediately
181 after i_db[11], but it's not utterly clear whether this also
182 applies to i_ib[1] and i_ib[0]
185 pref
= ext2_blkpref(ip
, lbn
, indirs
[0].in_off
+
186 EXT2_NDIR_BLOCKS
, &ip
->i_db
[0], 0);
188 if ((error
= ext2_alloc(ip
, lbn
, pref
, (int)fs
->s_blocksize
,
192 bp
= getblk(vp
, lblktodoff(fs
, indirs
[1].in_lbn
),
193 fs
->s_blocksize
, 0, 0);
194 bp
->b_bio2
.bio_offset
= fsbtodoff(fs
, newb
);
197 * Write synchronously so that indirect blocks
198 * never point at garbage.
200 if ((error
= bwrite(bp
)) != 0) {
201 ext2_blkfree(ip
, nb
, fs
->s_blocksize
);
204 ip
->i_ib
[indirs
[0].in_off
] = newb
;
205 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
208 * Fetch through the indirect blocks, allocating as necessary.
212 lblktodoff(fs
, indirs
[i
].in_lbn
),
213 (int)fs
->s_blocksize
, &bp
);
218 bap
= (daddr_t
*)bp
->b_data
;
219 nb
= bap
[indirs
[i
].in_off
];
229 /* see the comment above and by ext2_blkpref
230 * I think this implements Linux policy, but
231 * does it really make sense to allocate to
232 * block containing pointers together ?
233 * Also, will it ever succeed ?
235 pref
= ext2_blkpref(ip
, lbn
, indirs
[i
].in_off
, bap
,
236 lblkno(fs
, bp
->b_loffset
));
238 pref
= ext2_blkpref(ip
, lbn
, 0, NULL
, 0);
241 ext2_alloc(ip
, lbn
, pref
, (int)fs
->s_blocksize
, cred
, &newb
)) != 0) {
246 nbp
= getblk(vp
, lblktodoff(fs
, indirs
[i
].in_lbn
),
247 fs
->s_blocksize
, 0, 0);
248 nbp
->b_bio2
.bio_offset
= fsbtodoff(fs
, nb
);
251 * Write synchronously so that indirect blocks
252 * never point at garbage.
254 if ((error
= bwrite(nbp
)) != 0) {
255 ext2_blkfree(ip
, nb
, fs
->s_blocksize
);
259 bap
[indirs
[i
- 1].in_off
] = nb
;
261 * If required, write synchronously, otherwise use
264 if (flags
& B_SYNC
) {
271 * Get the data block, allocating if necessary.
274 pref
= ext2_blkpref(ip
, lbn
, indirs
[i
].in_off
, &bap
[0],
275 lblkno(fs
, bp
->b_loffset
));
276 if ((error
= ext2_alloc(ip
,
277 lbn
, pref
, (int)fs
->s_blocksize
, cred
, &newb
)) != 0) {
282 nbp
= getblk(vp
, lblktodoff(fs
, lbn
), fs
->s_blocksize
, 0, 0);
283 nbp
->b_bio2
.bio_offset
= fsbtodoff(fs
, nb
);
284 if (flags
& B_CLRBUF
)
286 bap
[indirs
[i
].in_off
] = nb
;
288 * If required, write synchronously, otherwise use
291 if (flags
& B_SYNC
) {
300 if (flags
& B_CLRBUF
) {
301 error
= bread(vp
, lblktodoff(fs
, lbn
),
302 (int)fs
->s_blocksize
, &nbp
);
308 nbp
= getblk(vp
, lblktodoff(fs
, lbn
), fs
->s_blocksize
, 0, 0);
309 nbp
->b_bio2
.bio_offset
= fsbtodoff(fs
, nb
);