1 Index: linux-2.4.24/fs/ext3/balloc.c
2 ===================================================================
3 --- linux-2.4.24.orig/fs/ext3/balloc.c 2004-01-10 17:04:42.000000000 +0300
4 +++ linux-2.4.24/fs/ext3/balloc.c 2004-02-06 11:05:42.000000000 +0300
6 * David S. Miller (davem@caip.rutgers.edu), 1995
9 +#include <linux/module.h>
10 #include <linux/config.h>
11 #include <linux/sched.h>
13 @@ -1007,3 +1008,303 @@
20 +#define mbdebug(fmt,a...) printk(fmt, ##a)
22 +#define mbdebug(fmt,a...)
26 + * in alloc_status we track allocation: the best found extent, how many
27 + * extents we've skipped, etc
29 +struct alloc_status {
30 + struct inode *inode;
31 + struct super_block *sb;
32 + int goal; /* goal for allocation */
33 + int target_len; /* goal for len */
34 + int start, len; /* the best found extent */
35 + int num; /* number of extent: to limit searching */
39 + * ext3_test_extent() compares requested extent with existing in as.
40 + * if requested extent is better than that, then replace old one.
41 + * then it tries to understand is new extent suitable or not
42 + * return 1 if caller can complete searching
44 +inline int ext3_test_extent(struct alloc_status *as, int group,
47 + struct ext3_super_block * es = EXT3_SB(as->sb)->s_es;
50 + J_ASSERT(as->target_len >= len);
52 + mbdebug("found extent %d:%d\n", start, len);
53 + tmp = start + group * EXT3_BLOCKS_PER_GROUP(as->sb)
54 + + le32_to_cpu(es->s_first_data_block);
56 + /* account requests in order to limit searching */
62 + /* if hit goal, then searching may complete right now */
63 + if (tmp == as->goal) {
70 + /* if found extent has length we need, return it right now */
71 + if (as->target_len == len)
74 + /* first, check is found extent better than we have in as */
75 + if (as->len > len) {
82 + /* FIXME: more checks! */
86 + /* 1) closeness to goal */
88 + /* 2) extent length */
89 + /* 3) number of tested extent (we check all found extents) */
95 + * this routine tries to find upto *len free contig. blocks
96 + * return number of found block (+ length of extent in *len)
97 + * or -1 if no free blocks at all
99 +int ext3_find_free_extent(struct buffer_head *bh, int goal, int *len, int max)
106 + /* find first free block */
107 + i = ext3_find_next_zero_bit(bh->b_data, max, goal);
109 + /* no free block */
112 + /* check upto len block for ability to be allocated */
113 + while (l < *len && i + l < max) {
114 + if (!ext3_test_allocatable(i + l, bh))
127 + * this routine loops over group, finds free extents and tests them
128 + * for some criterias
129 + * it may return negative value if group can't be loaded, 0 - if
130 + * no good extent can be found, 1 - if good extent found
132 +int ext3_find_extent_in_group(struct alloc_status *as, int group,
133 + unsigned long goal, int len)
135 + int k, i, l, bitmap_nr, found = 0;
136 + struct super_block *sb = as->sb;
137 + int max = EXT3_BLOCKS_PER_GROUP(sb);
138 + struct buffer_head *bh, *bmbh;
139 + struct ext3_group_desc *gdp;
141 + mbdebug("look for %d blocks in group %d starting from %lu\n",
144 + gdp = ext3_get_group_desc(as->sb, group, &bh);
148 + if (le16_to_cpu(gdp->bg_free_blocks_count) == 0)
151 + bitmap_nr = load_block_bitmap(as->sb, group);
155 + bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
158 + /* scan from goal to the end */
162 + k = ext3_find_free_extent(bmbh, i, &l, max);
166 + if (ext3_test_extent(as, group, k, l)) {
173 + /* scan from 0 upto goal */
174 + mbdebug("repeat from %lu in %d\n", goal, group);
183 +#define check_in_committed(bh,j) \
184 + J_ASSERT_BH((bh), !ext3_test_bit((j), bh2jh((bh))->b_committed_data))
186 +int ext3_new_blocks(handle_t *handle, struct inode *inode, int *num,
187 + unsigned long goal, int *errp)
189 + struct super_block *sb = inode->i_sb;
190 + int first_group, group, bitmap_nr;
191 + struct buffer_head *bh, *bmbh;
192 + struct ext3_super_block *es;
193 + struct ext3_group_desc *gdp;
194 + struct alloc_status as;
197 + J_ASSERT(num && *num > 0);
199 + if (DQUOT_ALLOC_BLOCK(inode, *num)) {
204 + es = EXT3_SB(inode->i_sb)->s_es;
207 + as.target_len = *num;
215 + if (goal < le32_to_cpu(es->s_first_data_block) ||
216 + goal >= le32_to_cpu(es->s_blocks_count))
217 + goal = le32_to_cpu(es->s_first_data_block);
220 + first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
221 + EXT3_BLOCKS_PER_GROUP(sb);
222 + goal = (goal - le32_to_cpu(es->s_first_data_block)) %
223 + EXT3_BLOCKS_PER_GROUP(sb);
224 + group = first_group;
226 + err = ext3_find_extent_in_group(&as, group, goal, *num);
232 + /* reset goal for next groups */
235 + /* try next group */
236 + if (++group == EXT3_SB(sb)->s_groups_count)
238 + } while (group != first_group);
245 + /* in the end we've found something, allocate it */
246 + mbdebug("best extent: %u:%u\n", as.start, as.len);
248 + group = (as.start - le32_to_cpu(es->s_first_data_block)) /
249 + EXT3_BLOCKS_PER_GROUP(sb);
250 + bit = (as.start - le32_to_cpu(es->s_first_data_block)) %
251 + EXT3_BLOCKS_PER_GROUP(sb);
252 + gdp = ext3_get_group_desc(sb, group, &bh);
258 + /* mark block(s) used in bitmap ... */
259 + bitmap_nr = load_block_bitmap(sb, group);
260 + if (bitmap_nr < 0) {
264 + bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
265 + /* Make sure we use undo access for the bitmap, because it is
266 + critical that we do the frozen_data COW on bitmap buffers in
267 + all cases even if the buffer is in BJ_Forget state in the
268 + committing transaction. */
269 + err = ext3_journal_get_undo_access(handle, bmbh);
272 + err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
275 + err = ext3_journal_get_write_access(handle, bh);
278 + for (i = 0; i < as.len; i++) {
279 + J_ASSERT(!ext3_test_bit(bit + i, bmbh->b_data));
280 + if (buffer_jbd(bmbh) && bh2jh(bmbh)->b_committed_data)
281 + check_in_committed(bmbh, bit + i);
282 + set_bit(bit + i, bmbh->b_data);
284 + err = ext3_journal_dirty_metadata(handle, bmbh);
288 + /* ... and correct group descriptor */
289 + gdp->bg_free_blocks_count =
290 + cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - as.len);
291 + es->s_free_blocks_count =
292 + cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - as.len);
293 + err = ext3_journal_dirty_metadata(handle, bmbh);
296 + err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
301 + if (*num != as.len)
302 + DQUOT_FREE_BLOCK(inode, *num - as.len);
315 +EXPORT_SYMBOL(ext3_new_blocks);
317 Index: linux-2.4.24/fs/ext3/file.c
318 ===================================================================
319 --- linux-2.4.24.orig/fs/ext3/file.c 2004-01-31 02:06:18.000000000 +0300
320 +++ linux-2.4.24/fs/ext3/file.c 2004-02-06 10:20:46.000000000 +0300
323 struct inode *inode = file->f_dentry->d_inode;
326 + /* allocate all the space to be written */
327 + if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
328 + int blocksize = inode->i_sb->s_blocksize;
329 + unsigned long start, end;
331 + start = (unsigned long) *ppos / blocksize;
332 + end = ((unsigned long) *ppos + count + blocksize - 1)
334 + ext3_ext_allocate_nblocks(inode, start, end - start);
337 ret = generic_file_write(file, buf, count, ppos);
339 /* Skip file flushing code if there was an error, or if nothing
340 Index: linux-2.4.24/fs/ext3/Makefile
341 ===================================================================
342 --- linux-2.4.24.orig/fs/ext3/Makefile 2004-02-05 18:44:25.000000000 +0300
343 +++ linux-2.4.24/fs/ext3/Makefile 2004-02-06 10:20:46.000000000 +0300
345 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
346 ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
347 xattr_trusted.o extents.o
348 -export-objs += extents.o
349 +export-objs += extents.o balloc.o
353 Index: linux-2.4.24/include/linux/ext3_fs.h
354 ===================================================================
355 --- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-01-30 00:09:37.000000000 +0300
356 +++ linux-2.4.24/include/linux/ext3_fs.h 2004-02-06 10:20:46.000000000 +0300
358 #define ext3_debug(f, a...) do {} while (0)
361 +#define EXT3_MULTIBLOCK_ALLOCATOR 1
364 * Special inodes numbers
367 extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
368 unsigned int block_group,
369 struct buffer_head ** bh);
370 +extern int ext3_new_blocks(handle_t*, struct inode*, int*, unsigned long, int*);
373 extern int ext3_check_dir_entry(const char *, struct inode *,