--- /dev/null
+Index: linux-2.6.27.21-0.1/fs/ext4/ialloc.c
+===================================================================
+--- linux-2.6.27.21-0.1.orig/fs/ext4/ialloc.c
++++ linux-2.6.27.21-0.1/fs/ext4/ialloc.c
+@@ -721,12 +721,15 @@ struct inode *ext4_new_inode(handle_t *h
+ return ERR_PTR(-EPERM);
+
+ sb = dir->i_sb;
++ sbi = EXT4_SB(sb);
++ if (sbi->s_max_dir_size > 0 && i_size_read(dir) >= sbi->s_max_dir_size)
++ return ERR_PTR(-EFBIG);
++
+ inode = new_inode(sb);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ ei = EXT4_I(inode);
+
+- sbi = EXT4_SB(sb);
+ es = sbi->s_es;
+
+ if (goal) {
+Index: linux-2.6.27.21-0.1/fs/ext4/super.c
+===================================================================
+--- linux-2.6.27.21-0.1.orig/fs/ext4/super.c
++++ linux-2.6.27.21-0.1/fs/ext4/super.c
+@@ -41,6 +41,7 @@
+ #include <asm/uaccess.h>
+ #include <linux/kthread.h>
+ #include <linux/utsname.h>
++#include <linux/proc_fs.h>
+
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+@@ -71,6 +72,8 @@ static void ext4_write_super(struct supe
+ static void ext4_write_super_lockfs(struct super_block *sb);
+
+
++struct proc_dir_entry *proc_root_ext4;
++
+ ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+ struct ext4_group_desc *bg)
+ {
+@@ -602,6 +605,9 @@ static void ext4_put_super(struct super_
+ }
+ if (sbi->s_mmp_tsk)
+ kthread_stop(sbi->s_mmp_tsk);
++
++ remove_proc_entry(EXT4_MAX_DIR_SIZE_NAME, sbi->s_proc);
++
+ sb->s_fs_info = NULL;
+ kfree(sbi);
+ return;
+@@ -2287,6 +2293,46 @@ static unsigned long ext4_get_stripe_siz
+ return 0;
+ }
+
++static int ext4_max_dir_size_read(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct ext4_sb_info *sbi = data;
++ int len;
++
++ *eof = 1;
++ if (off != 0)
++ return 0;
++
++ len = sprintf(page, "%lu\n", sbi->s_max_dir_size);
++ *start = page;
++ return len;
++}
++
++static int ext4_max_dir_size_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ struct ext4_sb_info *sbi = data;
++ char str[32];
++ unsigned long value;
++ char *end;
++
++ if (count >= sizeof(str)) {
++ printk(KERN_ERR "EXT4-fs: %s string too long, max %u bytes\n",
++ EXT4_MAX_DIR_SIZE_NAME, (int)sizeof(str));
++ return -EOVERFLOW;
++ }
++
++ if (copy_from_user(str, buffer, count))
++ return -EFAULT;
++
++ value = simple_strtol(str, &end, 0);
++ if (value < 0)
++ return -ERANGE;
++
++ sbi->s_max_dir_size = value;
++ return count;
++}
++
+ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ __releases(kernel_lock)
+ __acquires(kernel_lock)
+@@ -2311,6 +2357,7 @@ static int ext4_fill_super(struct super_
+ int needs_recovery, has_huge_files;
+ int features;
+ __u64 blocks_count;
++ struct proc_dir_entry *proc;
+ int err;
+
+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+@@ -2881,6 +2928,22 @@ static int ext4_fill_super(struct super_
+ test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA ? "ordered":
+ "writeback");
+
++ sbi->s_max_dir_size = EXT4_DEFAULT_MAX_DIR_SIZE;
++ proc = create_proc_entry(EXT4_MAX_DIR_SIZE_NAME,
++ S_IFREG | S_IRUGO | S_IWUSR, sbi->s_proc);
++ if (proc == NULL) {
++ printk(KERN_ERR "EXT4-fs: unable to create %s\n",
++ EXT4_MAX_DIR_SIZE_NAME);
++ remove_proc_entry(EXT4_MAX_DIR_SIZE_NAME, sbi->s_proc);
++ remove_proc_entry(sbi->s_proc->name, proc_root_ext4);
++ sbi->s_proc = NULL;
++ ret = -ENOMEM;
++ goto failed_mount4;
++ }
++ proc->data = sbi;
++ proc->read_proc = ext4_max_dir_size_read;
++ proc->write_proc = ext4_max_dir_size_write;
++
+ lock_kernel();
+ return 0;
+
+@@ -3254,7 +3317,6 @@ static void ext4_commit_super(struct sup
+ }
+ }
+
+-
+ /*
+ * Have we just finished recovery? If so, and if we are mounting (or
+ * remounting) the filesystem readonly, then we will end up with a
+Index: linux-2.6.27.21-0.1/fs/ext4/ext4_sb.h
+===================================================================
+--- linux-2.6.27.21-0.1.orig/fs/ext4/ext4_sb.h
++++ linux-2.6.27.21-0.1/fs/ext4/ext4_sb.h
+@@ -120,6 +120,7 @@ struct ext4_sb_info {
+ /* where last allocation was done - for stream allocation */
+ unsigned long s_mb_last_group;
+ unsigned long s_mb_last_start;
++ unsigned long s_max_dir_size;
+
+ /* history to debug policy */
+ struct ext4_mb_history *s_mb_history;
+Index: linux-2.6.27.21-0.1/fs/ext4/ext4.h
+===================================================================
+--- linux-2.6.27.21-0.1.orig/fs/ext4/ext4.h
++++ linux-2.6.27.21-0.1/fs/ext4/ext4.h
+@@ -1017,6 +1017,14 @@ struct mmp_struct {
+ */
+ #define EXT4_MMP_MIN_CHECK_INTERVAL 5
+
++extern struct proc_dir_entry *proc_root_ext4;
++
++/*
++ * max directory size tunable
++ */
++#define EXT4_DEFAULT_MAX_DIR_SIZE 0
++#define EXT4_MAX_DIR_SIZE_NAME "max_dir_size"
++
+ /*
+ * Function prototypes
+ */
+Index: linux-2.6.27.21-0.1/fs/ext4/mballoc.c
+===================================================================
+--- linux-2.6.27.21-0.1.orig/fs/ext4/mballoc.c
++++ linux-2.6.27.21-0.1/fs/ext4/mballoc.c
+@@ -2943,6 +2943,7 @@ err_out:
+ remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
+ remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
+ remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
++ remove_proc_entry(EXT4_MAX_DIR_SIZE_NAME, sbi->s_proc);
+ return -ENOMEM;
+ #else
+ return 0;
+@@ -2963,6 +2964,7 @@ static int ext4_mb_destroy_per_dev_proc(
+ remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
+ remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
+ remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
++ remove_proc_entry(EXT4_MAX_DIR_SIZE_NAME, sbi->s_proc);
+ #endif
+ return 0;
+ }