--- /dev/null
+diff -urpN linux-stage.orig/fs/ext4/super.c linux-stage/fs/ext4/super.c
+--- linux-stage.orig/fs/ext4/super.c 2013-05-13 10:29:34.125478791 -0400
++++ linux-stage/fs/ext4/super.c 2013-05-13 10:31:59.800359005 -0400
+@@ -1264,8 +1264,8 @@ enum {
+ Opt_mballoc, Opt_bigendian_extents, Opt_force_over_128tb,
+ Opt_extents, Opt_noextents,
+ Opt_no_mbcache,
+- Opt_discard, Opt_nodiscard,
+- Opt_init_inode_table, Opt_noinit_inode_table,
++ Opt_discard, Opt_nodiscard, Opt_init_inode_table, Opt_noinit_inode_table,
++ Opt_max_dir_size_kb,
+ };
+
+ static const match_table_t tokens = {
+@@ -1346,6 +1346,7 @@ static const match_table_t tokens = {
+ {Opt_init_inode_table, "init_itable=%u"},
+ {Opt_init_inode_table, "init_itable"},
+ {Opt_noinit_inode_table, "noinit_itable"},
++ {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+ {Opt_err, NULL},
+ };
+
+@@ -1732,6 +1733,13 @@ set_qf_format:
+ case Opt_nodelalloc:
+ clear_opt(sbi->s_mount_opt, DELALLOC);
+ break;
++ case Opt_max_dir_size_kb:
++ if (match_int(&args[0], &option))
++ return 0;
++ if (option < 0)
++ return 0;
++ sbi->s_max_dir_size = option * 1024;
++ break;
+ case Opt_stripe:
+ if (match_int(&args[0], &option))
+ return 0;
-Index: linux-2.6.32-el6-beta/fs/ext4/ialloc.c
+Index: linux-2.6.32-el6-beta/fs/ext4/namei.c
===================================================================
---- linux-2.6.32-el6-beta.orig/fs/ext4/ialloc.c
-+++ linux-2.6.32-el6-beta/fs/ext4/ialloc.c
-@@ -825,11 +825,15 @@ struct inode *ext4_new_inode(handle_t *h
- sb = dir->i_sb;
- ngroups = ext4_get_groups_count(sb);
- trace_ext4_request_inode(dir, mode);
-+
-+ sbi = EXT4_SB(sb);
-+ if (sbi->s_max_dir_size > 0 && i_size_read(dir) >= sbi->s_max_dir_size)
-+ return ERR_PTR(-EFBIG);
+--- linux-2.6.32-el6-beta/fs/ext4/namei.c
++++ linux-2.6.32-el6-beta/fs/ext4/namei.c
+@@ -59,6 +59,14 @@ static struct buffer_head *ext4_append(h
+ * have to be serialized -bzzz */
+ down(&ei->i_append_sem);
+
++ if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size &&
++ (inode->i_size >=
++ EXT4_SB(inode->i_sb)->s_max_dir_size))) {
++ *err = -ENOSPC;
++ up(&ei->i_append_sem);
++ return NULL;
++ }
+
- inode = new_inode(sb);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- ei = EXT4_I(inode);
-- sbi = EXT4_SB(sb);
+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
- if (!goal)
- goal = sbi->s_inode_goal;
+ bh = ext4_bread(handle, inode, *block, 1, err);
Index: linux-2.6.32-el6-beta/fs/ext4/super.c
===================================================================
--- linux-2.6.32-el6-beta.orig/fs/ext4/super.c
+++ linux-2.6.32-el6-beta/fs/ext4/super.c
-@@ -2601,6 +2601,7 @@ EXT4_RO_ATTR(lifetime_write_kbytes);
+@@ -999,6 +999,9 @@ static int ext4_show_options(struct seq_
+ seq_printf(seq, ",init_itable=%u",
+ (unsigned) sbi->s_li_wait_mult);
+
++ if (sbi->s_max_dir_size)
++ seq_printf(seq, "max_dir_size=%lu", sbi->s_max_dir_size);
++
+ ext4_show_quota_options(seq, sb);
+
+ return 0;
+@@ -2373,6 +2384,7 @@ EXT4_RO_ATTR(lifetime_write_kbytes);
EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
inode_readahead_blks_store, s_inode_readahead_blks);
EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
-@@ -2615,6 +2616,7 @@ static struct attribute *ext4_attrs[] =
+@@ -2388,6 +2400,7 @@ static struct attribute *ext4_attrs[] =
ATTR_LIST(lifetime_write_kbytes),
ATTR_LIST(inode_readahead_blks),
ATTR_LIST(inode_goal),
ATTR_LIST(mb_stats),
ATTR_LIST(mb_max_to_scan),
ATTR_LIST(mb_min_to_scan),
+@@ -2877,6 +2890,7 @@ static int ext4_fill_super(struct super_
+ }
+ sb->s_fs_info = sbi;
+ sbi->s_mount_opt = 0;
++ sbi->s_max_dir_size = 0;
+ sbi->s_resuid = EXT4_DEF_RESUID;
+ sbi->s_resgid = EXT4_DEF_RESGID;
+ sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
Index: linux-2.6.32-el6-beta/fs/ext4/ext4.h
===================================================================
--- linux-2.6.32-el6-beta.orig/fs/ext4/ext4.h
+++ linux-2.6.32-el6-beta/fs/ext4/ext4.h
-@@ -1029,6 +1029,8 @@ struct ext4_sb_info {
-
- unsigned int s_log_groups_per_flex;
- struct flex_groups *s_flex_groups;
-+
+@@ -1113,6 +1113,7 @@ struct ext4_sb_info {
+ unsigned long s_mb_prealloc_table_size;
+ unsigned int s_mb_group_prealloc;
+ unsigned int s_max_writeback_mb_bump;
+ unsigned long s_max_dir_size;
-
- /* workqueue for dio unwritten */
- struct workqueue_struct *dio_unwritten_wq;
-@@ -1353,6 +1355,12 @@ struct mmp_struct {
- #define EXT4_MMP_MIN_CHECK_INTERVAL 5
-
- /*
-+ * max directory size tunable
-+ */
-+#define EXT4_DEFAULT_MAX_DIR_SIZE 0
-+#define EXT4_MAX_DIR_SIZE_NAME "max_dir_size"
-+
-+/*
- * Function prototypes
- */
-
+ /* where last allocation was done - for stream allocation */
+ unsigned long s_mb_last_group;
+ unsigned long s_mb_last_start;
--- /dev/null
+diff -urpN linux-stage.orig/fs/ext4/super.c linux-stage/fs/ext4/super.c
+--- linux-stage.orig/fs/ext4/super.c 2013-05-13 09:35:17.628478645 -0400
++++ linux-stage/fs/ext4/super.c 2013-05-13 09:46:08.062358974 -0400
+@@ -1268,8 +1268,8 @@ enum {
+ Opt_mballoc, Opt_bigendian_extents, Opt_force_over_128tb,
+ Opt_extents, Opt_noextents,
+ Opt_no_mbcache,
+- Opt_discard, Opt_nodiscard,
+- Opt_init_itable, Opt_noinit_itable,
++ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
++ Opt_max_dir_size_kb,
+ };
+
+ static const match_table_t tokens = {
+@@ -1350,6 +1350,7 @@ static const match_table_t tokens = {
+ {Opt_init_itable, "init_itable=%u"},
+ {Opt_init_itable, "init_itable"},
+ {Opt_noinit_itable, "noinit_itable"},
++ {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+ {Opt_err, NULL},
+ };
+
+@@ -1736,6 +1737,13 @@ set_qf_format:
+ case Opt_nodelalloc:
+ clear_opt(sbi->s_mount_opt, DELALLOC);
+ break;
++ case Opt_max_dir_size_kb:
++ if (match_int(&args[0], &option))
++ return 0;
++ if (option < 0)
++ return 0;
++ sbi->s_max_dir_size = option * 1024;
++ break;
+ case Opt_stripe:
+ if (match_int(&args[0], &option))
+ return 0;
--- /dev/null
+diff -urpN linux-stage.orig/fs/ext4/super.c linux-stage/fs/ext4/super.c
+--- linux-stage.orig/fs/ext4/super.c 2013-05-13 11:44:45.000000000 -0400
++++ linux-stage/fs/ext4/super.c 2013-05-13 11:50:19.000000000 -0400
+@@ -1248,8 +1248,8 @@ enum {
+ Opt_mballoc, Opt_bigendian_extents, Opt_force_over_128tb,
+ Opt_extents, Opt_noextents,
+ Opt_no_mbcache,
+- Opt_discard, Opt_nodiscard,
+- Opt_init_inode_table, Opt_noinit_inode_table,
++ Opt_discard, Opt_nodiscard, Opt_init_inode_table, Opt_noinit_inode_table,
++ Opt_max_dir_size_kb,
+ };
+
+ static const match_table_t tokens = {
+@@ -1326,6 +1326,7 @@ static const match_table_t tokens = {
+ {Opt_noextents, "noextents"},
+ {Opt_discard, "discard"},
+ {Opt_nodiscard, "nodiscard"},
++ {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+ {Opt_err, NULL},
+ };
+
+@@ -1708,6 +1709,13 @@ set_qf_format:
+ case Opt_nodelalloc:
+ clear_opt(sbi->s_mount_opt, DELALLOC);
+ break;
++ case Opt_max_dir_size_kb:
++ if (match_int(&args[0], &option))
++ return 0;
++ if (option < 0)
++ return 0;
++ sbi->s_max_dir_size = option * 1024;
++ break;
+ case Opt_stripe:
+ if (match_int(&args[0], &option))
+ return 0;
--- /dev/null
+diff -urpN linux-stage.orig/fs/ext4/super.c linux-stage/fs/ext4/super.c
+--- linux-stage.orig/fs/ext4/super.c 2013-05-13 11:04:01.000000000 -0400
++++ linux-stage/fs/ext4/super.c 2013-05-13 11:05:23.000000000 -0400
+@@ -1369,6 +1369,7 @@ enum {
+ Opt_extents, Opt_noextents,
+ Opt_no_mbcache,
+ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
++ Opt_max_dir_size_kb,
+ };
+
+ static const match_table_t tokens = {
+@@ -1453,6 +1454,7 @@ static const match_table_t tokens = {
+ {Opt_init_itable, "init_itable=%u"},
+ {Opt_init_itable, "init_itable"},
+ {Opt_noinit_itable, "noinit_itable"},
++ {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+ {Opt_err, NULL},
+ };
+
+@@ -1871,6 +1873,13 @@ set_qf_format:
+ case Opt_nomblk_io_submit:
+ clear_opt(sb, MBLK_IO_SUBMIT);
+ break;
++ case Opt_max_dir_size_kb:
++ if (match_int(&args[0], &option))
++ return 0;
++ if (option < 0)
++ return 0;
++ sbi->s_max_dir_size = option * 1024;
++ break;
+ case Opt_stripe:
+ if (match_int(&args[0], &option))
+ return 0;
rhel6.3/ext4-inode-version.patch
rhel6.4/ext4-mmp.patch
rhel6.3/ext4-lookup-dotdot.patch
-rhel6.3/ext4-max-dir-size.patch
rhel6.3/ext4-print-inum-in-htree-warning.patch
rhel6.3/ext4-xattr-no-update-ctime.patch
rhel6.4/ext4-prealloc.patch
rhel6.3/ext4-inode_info_reorganize.patch
rhel6.4/ext4-fix-mbgroups-access.patch
rhel6.3/ext4-fix-ext4_mb_add_n_trim.patch
+rhel6.3/ext4-max-dir-size.patch
+rhel6.4/ext4-max-dir-size-options.patch
rhel6.3/ext4-inode-version.patch
rhel6.3/ext4-mmp.patch
rhel6.3/ext4-lookup-dotdot.patch
-rhel6.3/ext4-max-dir-size.patch
rhel6.3/ext4-print-inum-in-htree-warning.patch
rhel6.3/ext4-xattr-no-update-ctime.patch
rhel6.3/ext4-prealloc.patch
rhel6.3/ext4-inode_info_reorganize.patch
rhel6.3/ext4-fix-mbgroups-access.patch
rhel6.3/ext4-fix-ext4_mb_add_n_trim.patch
+rhel6.3/ext4-max-dir-size.patch
+rhel6.3/ext4-max-dir-size-options.patch
sles11sp1/ext4-update-sles11-rhel6.patch
rhel6.3/ext4-mmp.patch
rhel6.3/ext4-lookup-dotdot.patch
-rhel6.3/ext4-max-dir-size.patch
rhel6.3/ext4-print-inum-in-htree-warning.patch
rhel6.3/ext4-xattr-no-update-ctime.patch
rhel6.3/ext4-prealloc.patch
rhel6.3/ext4-quota-dont-update-cmtime.patch
rhel6.3/ext4-quota-first-class.patch
rhel6.3/ext4-fix-ext4_mb_add_n_trim.patch
+rhel6.3/ext4-max-dir-size.patch
+sles11sp1/ext4-max-dir-size-options.patch
sles11sp2/ext4-ext_generation.patch
rhel6.3/ext4-inode-version.patch
sles11sp2/ext4-lookup-dotdot.patch
-rhel6.3/ext4-max-dir-size.patch
rhel6.3/ext4-print-inum-in-htree-warning.patch
rhel6.3/ext4-xattr-no-update-ctime.patch
sles11sp2/ext4-prealloc.patch
rhel6.3/ext4-export-64bit-name-hash.patch
sles11sp2/ext4-store-tree-generation-at-find.patch
sles11sp2/ext4_pdirop.patch
+rhel6.3/ext4-max-dir-size.patch
+sles11sp2/ext4-max-dir-size-options.patch
fi
remote_mds_nodsh && skip "remote MDS with nodsh" && return
+ ENOSPC=28
EFBIG=27
- MAX=16384
- set_dir_limits $MAX
test_mkdir -p $DIR/$tdir
+ MAX=$(stat -c%s "$DIR/$tdir")
+ set_dir_limits $MAX
local I=0
local J=0
- while [ ! $I -gt $((MAX * MDSCOUNT)) ]; do
+ while [ ! $I -gt $MAX ]; do
$MULTIOP $DIR/$tdir/$J Oc
rc=$?
- if [ $rc -eq $EFBIG ]; then
+ #check two errors ENOSPC for new version of ext4 max_dir_size patch
+ #mainline kernel commit df981d03eeff7971ac7e6ff37000bfa702327ef1
+ #and EFBIG for previous versions
+ if [ $rc -eq $EFBIG -o $rc -eq $ENOSPC ] && [ $I -gt 0 ]; then
set_dir_limits 0
echo "return code $rc received as expected"
- return 0
+ multiop $DIR/$tdir/$J Oc
+ rc=$?
+ I=$(stat -c%s "$DIR/$tdir")
+ if [ $I -gt $MAX ] && [ $rc -eq 0 ]; then
+ return 0
+ else
+ error_exit "return code $rc current dir size $I " \
+ "previous limit $MAX"
+ fi
elif [ $rc -ne 0 ]; then
set_dir_limits 0
- error_exit "return code $rc received instead of expected $EFBIG"
+ error_exit "return code $rc received instead of expected " \
+ "$EFBIG or $ENOSPC, files in dir $I"
fi
J=$((J+1))
I=$(stat -c%s "$DIR/$tdir")
done
set_dir_limits 0
- error "exceeded dir size limit $MAX x $MDSCOUNT $((MAX * MDSCOUNT)) : $I bytes"
+ error "exceeded dir size limit $MAX x $MDSCOUNT $MAX : $I bytes"
}
run_test 129 "test directory size limit ========================"