diff --git a/lustre/kernel_patches/patches/ext3-mballoc-2.4.24.patch b/lustre/kernel_patches/patches/ext3-mballoc-2.4.24.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a234f96c227ecb31a87a7cd5e34a24fb433aa897
--- /dev/null
+++ b/lustre/kernel_patches/patches/ext3-mballoc-2.4.24.patch
@@ -0,0 +1,343 @@
+Index: linux-2.4.24/fs/ext3/balloc.c
+===================================================================
+--- linux-2.4.24.orig/fs/ext3/balloc.c	2004-01-10 17:04:42.000000000 +0300
++++ linux-2.4.24/fs/ext3/balloc.c	2004-01-29 17:27:54.000000000 +0300
+@@ -1007,3 +1007,294 @@
+ 			bitmap_count);
+ }
+ #endif
++
++#define MBDEBUG_
++#ifdef MBDEBUG
++#define mbdebug(fmt,a...) 	printk(fmt, ##a)
++#else
++#define mbdebug(fmt,a...)
++#endif
++
++/*
++ * in alloc_status we track allocation: the best found extent, how many
++ * extents we've skipped, etc
++ */
++struct alloc_status {
++	struct super_block *sb;
++	int goal;		/* goal for allocation */
++	int target_len;		/* goal for len */
++	int start, len;		/* the best found extent */
++	int num;		/* number of extent: to limit searching */
++};
++
++/*
++ * ext3_test_extent() compares requested extent with existing in as.
++ * if requested extent is better than that, then replace old one.
++ * then it tries to understand is new extent suitable or not
++ * return 1 if caller can complete searching
++ */
++inline int ext3_test_extent(struct alloc_status *as, int group,
++				int start, int len)
++{
++	struct ext3_super_block * es = EXT3_SB(as->sb)->s_es;
++	unsigned long tmp;
++
++	J_ASSERT(as->target_len >= len);
++
++	mbdebug("found extent %d:%d\n", start, len);
++	tmp = start + group * EXT3_BLOCKS_PER_GROUP(as->sb)
++			+ le32_to_cpu(es->s_first_data_block);
++
++	/* account requests in order to limit searching */
++	as->num++;
++
++	if (as->num == 20)
++		return 1;
++
++	/* if hit goal, then searching may complete right now */
++	if (tmp == as->goal) {
++nice:
++		as->start = tmp;
++		as->len = len;
++		return 1;
++	}
++
++	/* if found extent has lenght we need, return it right now */
++	if (as->target_len == len)
++		goto nice;
++
++	/* first, check is found extent better than we have in as */
++	if (as->len > len) {
++better:
++		as->start = tmp;
++		as->len = len;
++		return 0;
++	}
++
++	/* FIXME: more checks! */
++	as->start = tmp;
++	as->len = len;
++
++	/* 1) closeness to goal */
++	
++	/* 2) extent lenght */
++	/* 3) number of tested extent (we check all found extents) */
++	/* */
++	return 0;
++}
++
++/*
++ * this routine tries to find upto *len free contig. blocks
++ * return number of found block (+ lenght of extent in *len)
++ * or -1 if no free blocks at all
++ */
++int ext3_find_free_extent(struct buffer_head *bh, int goal, int *len, int max)
++{
++	int i, l = 0;
++
++repeat:
++	if (goal >= max)
++		return -1;
++	/* find first free block */
++	i = ext3_find_next_zero_bit(bh->b_data, max, goal);
++	if (i >= max) {
++		/* no free block */
++		return -1;
++	}
++	/* check upto len block for ability to be allocated */
++	while (l < *len && i + l < max) {
++		if (!ext3_test_allocatable(i + l, bh))
++			break;
++		l++;
++	}
++	if (l == 0) {
++		goal = i + 1;
++		goto repeat;
++	}
++	*len = l;
++	return i;
++}
++
++/*
++ * this routine loops over group, finds free extents and tests them
++ * for some criterias
++ * it may return negative value if group can't be loaded, 0 - if
++ * no good extent can be found, 1 - if good extent found
++ */
++int ext3_find_extent_in_group(struct alloc_status *as, int group,
++				unsigned long goal, int len)
++{
++	int k, i, l, bitmap_nr, found = 0;
++	struct super_block *sb = as->sb;
++	int max = EXT3_BLOCKS_PER_GROUP(sb);
++	struct buffer_head *bh, *bmbh;
++	struct ext3_group_desc *gdp;
++
++	mbdebug("look for %d blocks in group %d starting from %lu\n",
++			len, group, goal);
++
++	gdp = ext3_get_group_desc(as->sb, group, &bh);
++	if (!gdp)
++		return -EIO;
++
++	if (le16_to_cpu(gdp->bg_free_blocks_count) == 0)
++		return 0;
++
++	bitmap_nr = load_block_bitmap(as->sb, group);
++	if (bitmap_nr < 0)
++		return -EIO;
++
++	bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
++
++	i = goal;
++	/* scan from goal to the end */
++repeat:
++	while (i < max) {
++		l = len;
++		k = ext3_find_free_extent(bmbh, i, &l, max);
++		i = k + l;
++		if (k < 0)
++			break;
++		if (ext3_test_extent(as, group, k, l)) {
++			found = 1;
++			goto out;
++		}
++	}
++
++	if (goal) {
++		/* scan from 0 upto goal */
++		mbdebug("repeat from %lu in %d\n", goal, group);
++		max = goal - 1;
++		goal = i = 0;
++		goto repeat;
++	}
++out:
++	return found; 
++}
++
++#define check_in_committed(bh,j)	\
++	J_ASSERT_BH((bh), !ext3_test_bit((j), bh2jh((bh))->b_committed_data))
++
++int ext3_new_blocks(handle_t *handle, struct inode *inode, int *num,
++			unsigned long goal, int *errp)
++{
++	struct super_block *sb = inode->i_sb;
++	int first_group, group, bitmap_nr;
++	struct buffer_head *bh, *bmbh;
++	struct ext3_super_block *es;
++	struct ext3_group_desc *gdp;
++	struct alloc_status as;
++	int err, bit, i;
++
++	int scaned = 0;
++
++	J_ASSERT(num && *num > 0);
++
++	if (DQUOT_ALLOC_BLOCK(inode, *num)) {
++		*errp = -EDQUOT;
++		return 0;
++	}
++
++	es = EXT3_SB(inode->i_sb)->s_es;
++
++	*errp = 0;
++	as.target_len = *num;
++	as.sb = sb;
++	as.goal = goal;
++	as.start = -1;
++	as.len = 0;
++	as.num = 0;
++
++	lock_super(sb);
++	first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
++		      	EXT3_BLOCKS_PER_GROUP(sb);
++	goal = (goal - le32_to_cpu(es->s_first_data_block)) %
++		      	EXT3_BLOCKS_PER_GROUP(sb);
++	group = first_group;
++	do {
++		scaned++;
++		err = ext3_find_extent_in_group(&as, group, goal, *num);
++		if (err < 0) 
++			goto error_out;
++		else if (err)
++			break;
++
++		/* reset goal for next groups */
++		goal = 0;
++
++		/* try next group */
++		if (++group == EXT3_SB(sb)->s_groups_count)
++			group = 0;
++	} while (group != first_group);
++
++	if (as.len == 0) {
++		err = -ENOSPC;
++		goto error_out;
++	}
++
++	/* in the end we've found something, allocate it */
++	mbdebug("best extent: %u:%u\n", as.start, as.len);
++
++	group = (as.start - le32_to_cpu(es->s_first_data_block)) /
++		EXT3_BLOCKS_PER_GROUP(sb);
++	bit = (as.start - le32_to_cpu(es->s_first_data_block)) %
++		EXT3_BLOCKS_PER_GROUP(sb);
++	gdp = ext3_get_group_desc(sb, group, &bh);
++	if (!gdp) {
++		err = -EIO;
++		goto error_out; 
++	}
++
++	/* mark block(s) used in bitmap ... */
++	bitmap_nr = load_block_bitmap(sb, group);
++	if (bitmap_nr < 0) {
++		err = -EIO;
++		goto error_out;
++	}
++	bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
++	err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++	if (err)
++		goto error_out;
++	err = ext3_journal_get_write_access(handle, bmbh);
++	if (err)
++		goto error_out;
++	err = ext3_journal_get_write_access(handle, bh);
++	if (err)
++		goto error_out;
++	for (i = 0; i < as.len; i++) {
++		J_ASSERT(!ext3_test_bit(bit + i, bmbh->b_data));
++		if (buffer_jbd(bmbh) && bh2jh(bmbh)->b_committed_data)
++			check_in_committed(bmbh, bit + i);
++		set_bit(bit + i, bmbh->b_data);
++	}
++	err = ext3_journal_dirty_metadata(handle, bmbh);
++	if (err)
++		goto error_out;
++
++	/* ... and correct group descriptor */
++	gdp->bg_free_blocks_count =
++		cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - as.len);
++	es->s_free_blocks_count =
++		cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - as.len);
++	err = ext3_journal_dirty_metadata(handle, bmbh);
++	if (err)
++		goto error_out;
++	err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++	if (err)
++		goto error_out;
++	sb->s_dirt = 1;
++
++	if (*num != as.len)
++		DQUOT_FREE_BLOCK(inode, *num - as.len);
++	*num = as.len;
++
++out:
++	unlock_super(sb);
++	return as.start;
++
++error_out:
++	as.start = 0;
++	*errp = err;
++	goto out;
++}
++
+Index: linux-2.4.24/fs/ext3/file.c
+===================================================================
+--- linux-2.4.24.orig/fs/ext3/file.c	2004-01-12 20:36:32.000000000 +0300
++++ linux-2.4.24/fs/ext3/file.c	2004-01-29 18:26:23.000000000 +0300
+@@ -69,6 +69,18 @@
+ 	int err;
+ 	struct inode *inode = file->f_dentry->d_inode;
+ 
++#if 0
++	/* allocate all the space to be written */
++	if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
++		int blocksize = inode->i_sb->s_blocksize;
++		unsigned long start, end;
++
++		start = (unsigned long) *ppos / blocksize;
++		end = ((unsigned long) *ppos + count + blocksize - 1)
++				/ blocksize;
++		ext3_ext_allocate_nblocks(inode, start, end - start);
++	}
++#endif
+ 	ret = generic_file_write(file, buf, count, ppos);
+ 
+ 	/* Skip file flushing code if there was an error, or if nothing
+Index: linux-2.4.24/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.4.24.orig/include/linux/ext3_fs.h	2004-01-26 23:17:19.000000000 +0300
++++ linux-2.4.24/include/linux/ext3_fs.h	2004-01-29 16:29:36.000000000 +0300
+@@ -58,6 +58,8 @@
+ #define ext3_debug(f, a...)	do {} while (0)
+ #endif
+ 
++#define EXT3_MULTIBLOCK_ALLOCATOR	1
++
+ /*
+  * Special inodes numbers
+  */
+@@ -667,6 +669,7 @@
+ extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
+ 						    unsigned int block_group,
+ 						    struct buffer_head ** bh);
++extern int ext3_new_blocks(handle_t*, struct inode*, int*, unsigned long, int*);
+ 
+ /* dir.c */
+ extern int ext3_check_dir_entry(const char *, struct inode *,