1 Index: linux-2.6.16.27-0.9-full/include/linux/ext3_fs_i.h
2 ===================================================================
3 --- linux-2.6.16.27-0.9-full.orig/include/linux/ext3_fs_i.h 2007-03-28 05:12:50.000000000 +0400
4 +++ linux-2.6.16.27-0.9-full/include/linux/ext3_fs_i.h 2007-03-28 16:03:20.000000000 +0400
5 @@ -135,6 +135,10 @@ struct ext3_inode_info {
6 struct inode vfs_inode;
8 __u32 i_cached_extent[4];
11 + struct list_head i_prealloc_list;
12 + spinlock_t i_prealloc_lock;
15 #endif /* _LINUX_EXT3_FS_I */
16 Index: linux-2.6.16.27-0.9-full/include/linux/ext3_fs_sb.h
17 ===================================================================
18 --- linux-2.6.16.27-0.9-full.orig/include/linux/ext3_fs_sb.h 2007-03-28 16:03:19.000000000 +0400
19 +++ linux-2.6.16.27-0.9-full/include/linux/ext3_fs_sb.h 2007-03-28 16:03:20.000000000 +0400
21 #include <linux/wait.h>
22 #include <linux/blockgroup_lock.h>
23 #include <linux/percpu_counter.h>
24 +#include <linux/list.h>
26 #include <linux/rbtree.h>
27 +#include <linux/proc_fs.h>
29 +struct ext3_buddy_group_blocks;
30 +struct ext3_locality_group;
31 +struct ext3_mb_history;
32 +#define EXT3_BB_MAX_BLOCKS
35 * third extended-fs super-block data in memory
36 Index: linux-2.6.16.27-0.9-full/include/linux/ext3_fs.h
37 ===================================================================
38 --- linux-2.6.16.27-0.9-full.orig/include/linux/ext3_fs.h 2007-03-28 16:03:19.000000000 +0400
39 +++ linux-2.6.16.27-0.9-full/include/linux/ext3_fs.h 2007-03-28 16:03:20.000000000 +0400
40 @@ -407,6 +407,7 @@ struct ext3_inode {
41 #define EXT3_MOUNT_IOPEN_NOPRIV 0x800000/* Make iopen world-readable */
42 #define EXT3_MOUNT_EXTENTS 0x1000000/* Extents support */
43 #define EXT3_MOUNT_EXTDEBUG 0x2000000/* Extents debug */
44 +#define EXT3_MOUNT_MBALLOC 0x4000000/* Buddy allocation support */
46 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
48 @@ -767,8 +768,9 @@ struct dir_private_info {
49 extern int ext3_bg_has_super(struct super_block *sb, int group);
50 extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
51 extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
52 +extern int ext3_new_block_old (handle_t *, struct inode *, unsigned long, int *);
53 extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
55 + unsigned long, int);
56 extern void ext3_free_blocks_sb (handle_t *, struct super_block *,
57 unsigned long, unsigned long, int *);
58 extern unsigned long ext3_count_free_blocks (struct super_block *);
59 Index: linux-2.6.16.27-0.9-full/fs/ext3/super.c
60 ===================================================================
61 --- linux-2.6.16.27-0.9-full.orig/fs/ext3/super.c 2007-03-28 16:03:19.000000000 +0400
62 +++ linux-2.6.16.27-0.9-full/fs/ext3/super.c 2007-03-28 16:03:20.000000000 +0400
63 @@ -688,6 +688,7 @@ enum {
64 Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
65 Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
66 Opt_extents, Opt_noextents, Opt_extdebug,
67 + Opt_mballoc, Opt_nomballoc, Opt_stripe,
71 @@ -743,6 +744,9 @@ static match_table_t tokens = {
72 {Opt_noextents, "noextents"},
73 {Opt_extdebug, "extdebug"},
74 {Opt_barrier, "barrier=%u"},
75 + {Opt_mballoc, "mballoc"},
76 + {Opt_nomballoc, "nomballoc"},
77 + {Opt_stripe, "stripe=%u"},
79 {Opt_resize, "resize"},
81 @@ -1092,6 +1096,19 @@ clear_qf_name:
83 set_opt (sbi->s_mount_opt, EXTDEBUG);
86 + set_opt(sbi->s_mount_opt, MBALLOC);
89 + clear_opt(sbi->s_mount_opt, MBALLOC);
92 + if (match_int(&args[0], &option))
96 + sbi->s_stripe = option;
100 "EXT3-fs: Unrecognized mount option \"%s\" "
101 @@ -1819,6 +1836,7 @@ static int ext3_fill_super (struct super
102 ext3_count_dirs(sb));
105 + ext3_mb_init(sb, needs_recovery);
109 Index: linux-2.6.16.27-0.9-full/fs/ext3/extents.c
110 ===================================================================
111 --- linux-2.6.16.27-0.9-full.orig/fs/ext3/extents.c 2007-03-28 05:13:39.000000000 +0400
112 +++ linux-2.6.16.27-0.9-full/fs/ext3/extents.c 2007-03-28 16:03:20.000000000 +0400
113 @@ -779,7 +779,7 @@ cleanup:
114 for (i = 0; i < depth; i++) {
117 - ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
118 + ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
122 @@ -1586,7 +1586,7 @@ int ext3_ext_rm_idx(handle_t *handle, st
123 path->p_idx->ei_leaf);
124 bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
125 ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
126 - ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
127 + ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1, 1);
131 @@ -2071,10 +2071,12 @@ ext3_remove_blocks(struct ext3_extents_t
132 int needed = ext3_remove_blocks_credits(tree, ex, from, to);
133 handle_t *handle = ext3_journal_start(tree->inode, needed);
134 struct buffer_head *bh;
136 + int i, metadata = 0;
139 return PTR_ERR(handle);
140 + if (S_ISDIR(tree->inode->i_mode) || S_ISLNK(tree->inode->i_mode))
142 if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
144 unsigned long num, start;
145 @@ -2086,7 +2088,7 @@ ext3_remove_blocks(struct ext3_extents_t
146 bh = sb_find_get_block(tree->inode->i_sb, start + i);
147 ext3_forget(handle, 0, tree->inode, bh, start + i);
149 - ext3_free_blocks(handle, tree->inode, start, num);
150 + ext3_free_blocks(handle, tree->inode, start, num, metadata);
151 } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
152 printk("strange request: removal %lu-%lu from %u:%u\n",
153 from, to, ex->ee_block, ex->ee_len);
154 @@ -2177,11 +2179,8 @@ int ext3_ext_get_block(handle_t *handle,
155 struct ext3_extent *ex;
156 int goal, newblock, err = 0, depth;
157 struct ext3_extents_tree tree;
158 - unsigned long next;
161 - /* until we have multiblock allocation */
163 + unsigned long allocated = 0;
164 + struct ext3_allocation_request ar;
166 clear_buffer_new(bh_result);
167 ext3_init_tree_desc(&tree, inode);
168 @@ -2253,18 +2252,33 @@ int ext3_ext_get_block(handle_t *handle,
172 + /* find neighbour allocated blocks */
174 + err = ext3_ext_search_left(&tree, path, &ar.lleft, &ar.pleft);
177 + ar.lright = iblock;
178 + err = ext3_ext_search_right(&tree, path, &ar.lright, &ar.pright);
182 /* find next allocated block so that we know how many
183 * blocks we can allocate without ovelapping next extent */
184 - EXT_ASSERT(iblock >= ex->ee_block + ex->ee_len);
185 - next = ext3_ext_next_allocated_block(path);
186 - EXT_ASSERT(next > iblock);
187 - allocated = next - iblock;
188 + EXT_ASSERT(ar.pright == 0 || ar.lright > iblock);
189 + if (ar.pright == 0)
190 + allocated = EXT_MAX_BLOCK - iblock;
192 + allocated = ar.lright - iblock;
193 if (allocated > max_blocks)
194 allocated = max_blocks;
196 /* allocate new block */
197 - goal = ext3_ext_find_goal(inode, path, iblock);
198 - newblock = ext3_new_block(handle, inode, goal, &err);
200 + ar.goal = ext3_ext_find_goal(inode, path, iblock);
201 + ar.logical = iblock;
202 + ar.len = allocated;
203 + ar.flags = EXT3_MB_HINT_DATA;
204 + newblock = ext3_mb_new_blocks(handle, &ar, &err);
207 ext_debug(&tree, "allocate new block: goal %d, found %d\n",
208 @@ -2274,11 +2288,14 @@ int ext3_ext_get_block(handle_t *handle,
209 newex.ee_block = iblock;
210 newex.ee_start = newblock;
211 newex.ee_start_hi = 0;
213 + newex.ee_len = ar.len;
214 err = ext3_ext_insert_extent(handle, &tree, path, &newex);
216 /* free data blocks we just allocated */
217 - ext3_free_blocks(handle, inode, newex.ee_start, newex.ee_len);
218 + /* not a good idea to call discard here directly,
219 + * but otherwise we'd need to call it every free() */
220 + ext3_mb_discard_inode_preallocations(inode);
221 + ext3_free_blocks(handle, inode, newex.ee_start, newex.ee_len, 0);
225 @@ -2287,6 +2304,7 @@ int ext3_ext_get_block(handle_t *handle,
227 /* previous routine could use block we allocated */
228 newblock = newex.ee_start;
229 + allocated = newex.ee_len;
230 set_buffer_new(bh_result);
232 ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
233 @@ -2339,6 +2357,9 @@ void ext3_ext_truncate(struct inode * in
234 down(&EXT3_I(inode)->truncate_sem);
235 ext3_ext_invalidate_cache(&tree);
237 + /* it's important to discard preallocations under truncate_sem */
238 + ext3_mb_discard_inode_preallocations(inode);
241 * TODO: optimization is possible here
242 * probably we need not scaning at all,
243 Index: linux-2.6.16.27-0.9-full/fs/ext3/Makefile
244 ===================================================================
245 --- linux-2.6.16.27-0.9-full.orig/fs/ext3/Makefile 2007-03-28 05:12:50.000000000 +0400
246 +++ linux-2.6.16.27-0.9-full/fs/ext3/Makefile 2007-03-28 16:03:20.000000000 +0400
247 @@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
249 ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
250 ioctl.o namei.o super.o symlink.o hash.o resize.o \
252 + extents.o mballoc.o
254 ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
255 ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
256 Index: linux-2.6.16.27-0.9-full/fs/ext3/xattr.c
257 ===================================================================
258 --- linux-2.6.16.27-0.9-full.orig/fs/ext3/xattr.c 2007-03-13 02:56:52.000000000 +0300
259 +++ linux-2.6.16.27-0.9-full/fs/ext3/xattr.c 2007-03-28 16:03:20.000000000 +0400
260 @@ -484,7 +484,7 @@ ext3_xattr_release_block(handle_t *handl
261 ea_bdebug(bh, "refcount now=0; freeing");
263 mb_cache_entry_free(ce);
264 - ext3_free_blocks(handle, inode, bh->b_blocknr, 1);
265 + ext3_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
267 ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
269 @@ -804,7 +804,7 @@ inserted:
270 new_bh = sb_getblk(sb, block);
273 - ext3_free_blocks(handle, inode, block, 1);
274 + ext3_free_blocks(handle, inode, block, 1, 1);
278 Index: linux-2.6.16.27-0.9-full/fs/ext3/balloc.c
279 ===================================================================
280 --- linux-2.6.16.27-0.9-full.orig/fs/ext3/balloc.c 2007-03-13 02:56:52.000000000 +0300
281 +++ linux-2.6.16.27-0.9-full/fs/ext3/balloc.c 2007-03-28 16:03:20.000000000 +0400
282 @@ -80,7 +80,7 @@ struct ext3_group_desc * ext3_get_group_
284 * Return buffer_head on success or NULL in case of failure.
286 -static struct buffer_head *
287 +struct buffer_head *
288 read_block_bitmap(struct super_block *sb, unsigned int block_group)
290 struct ext3_group_desc * desc;
291 @@ -296,6 +296,8 @@ void ext3_discard_reservation(struct ino
292 struct ext3_reserve_window_node *rsv;
293 spinlock_t *rsv_lock = &EXT3_SB(inode->i_sb)->s_rsv_window_lock;
295 + ext3_mb_discard_inode_preallocations(inode);
300 @@ -491,21 +493,25 @@ error_return:
304 -/* Free given blocks, update quota and i_blocks field */
305 -void ext3_free_blocks(handle_t *handle, struct inode *inode,
306 - unsigned long block, unsigned long count)
307 +void ext3_free_blocks(handle_t *handle, struct inode * inode,
308 + unsigned long block, unsigned long count, int metadata)
310 - struct super_block * sb;
311 - int dquot_freed_blocks;
312 + struct super_block *sb;
315 + /* this isn't the right place to decide whether block is metadata
316 + * inode.c/extents.c knows better, but for safety ... */
317 + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) ||
318 + ext3_should_journal_data(inode))
323 - printk ("ext3_free_blocks: nonexistent device");
326 - ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
327 - if (dquot_freed_blocks)
328 - DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
329 + if (!test_opt(sb, MBALLOC) || !EXT3_SB(sb)->s_group_info)
330 + ext3_free_blocks_sb(handle, sb, block, count, &freed);
332 + ext3_mb_free_blocks(handle, inode, block, count, metadata, &freed);
334 + DQUOT_FREE_BLOCK(inode, freed);
338 @@ -1154,7 +1160,7 @@ int ext3_should_retry_alloc(struct super
339 * bitmap, and then for any free bit if that fails.
340 * This function also updates quota and i_blocks field.
342 -int ext3_new_block(handle_t *handle, struct inode *inode,
343 +int ext3_new_block_old(handle_t *handle, struct inode *inode,
344 unsigned long goal, int *errp)
346 struct buffer_head *bitmap_bh = NULL;
347 Index: linux-2.6.16.27-0.9-full/fs/ext3/inode.c
348 ===================================================================
349 --- linux-2.6.16.27-0.9-full.orig/fs/ext3/inode.c 2007-03-28 05:13:38.000000000 +0400
350 +++ linux-2.6.16.27-0.9-full/fs/ext3/inode.c 2007-03-28 16:03:20.000000000 +0400
351 @@ -568,7 +568,7 @@ static int ext3_alloc_branch(handle_t *h
352 ext3_journal_forget(handle, branch[i].bh);
354 for (i = 0; i < keys; i++)
355 - ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
356 + ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1, 0);
360 @@ -1865,7 +1865,7 @@ ext3_clear_blocks(handle_t *handle, stru
364 - ext3_free_blocks(handle, inode, block_to_free, count);
365 + ext3_free_blocks(handle, inode, block_to_free, count, 0);
369 @@ -2038,7 +2038,7 @@ static void ext3_free_branches(handle_t
370 ext3_journal_test_restart(handle, inode);
373 - ext3_free_blocks(handle, inode, nr, 1);
374 + ext3_free_blocks(handle, inode, nr, 1, 1);