1 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
2 index 938487a..47313fd 100644
5 @@ -1178,6 +1178,7 @@ struct ext4_sb_info {
6 unsigned int s_mb_group_prealloc;
7 unsigned int s_max_writeback_mb_bump;
8 unsigned long s_max_dir_size;
9 + unsigned long s_warning_dir_size;
10 /* where last allocation was done - for stream allocation */
11 unsigned long s_mb_last_group;
12 unsigned long s_mb_last_start;
13 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
14 index 992dc58..57ff920 100644
17 @@ -370,11 +370,19 @@ struct ext4_dir_lock_data {
19 #define ext4_htree_lock_data(l) ((struct ext4_dir_lock_data *)(l)->lk_private)
20 #define ext4_find_entry(dir, name, dirent) __ext4_find_entry(dir, name, dirent, NULL)
21 -#define ext4_add_entry(handle, dentry, inode) __ext4_add_entry(handle, dentry, inode, NULL)
23 /* NB: ext4_lblk_t is 32 bits so we use high bits to identify invalid blk */
24 #define EXT4_HTREE_NODE_CHANGED (0xcafeULL << 32)
26 +inline int ext4_add_entry(handle_t *handle, struct dentry *dentry,
27 + struct inode *inode)
29 + int ret = __ext4_add_entry(handle, dentry, inode, NULL);
31 + if (ret == -ENOBUFS)
36 static void ext4_htree_event_cb(void *target, void *event)
38 u64 *block = (u64 *)target;
39 @@ -2053,6 +2061,54 @@ int __ext4_add_entry(handle_t *handle, struct dentry *dentry,
41 EXPORT_SYMBOL(__ext4_add_entry);
43 +static unsigned long __ext4_max_dir_size(struct dx_frame *frames,
44 + struct dx_frame *frame, struct inode *dir)
46 + unsigned long max_dir_size;
48 + if (EXT4_SB(dir->i_sb)->s_max_dir_size) {
49 + max_dir_size = EXT4_SB(dir->i_sb)->s_max_dir_size;
51 + max_dir_size = EXT4_BLOCK_SIZE(dir->i_sb);
52 + while (frame >= frames) {
53 + max_dir_size *= dx_get_limit(frame->entries);
54 + if (frame == frames)
58 + /* use 75% of max dir size in average */
59 + max_dir_size = max_dir_size / 4 * 3;
61 + return max_dir_size;
65 + * With hash tree growing, it is easy to hit ENOSPC, but it is hard
66 + * to predict when it will happen. let's give administrators warning
67 + * when reaching 5/8 and 11/16 of limit
69 +static inline bool dir_size_in_warning_range(struct dx_frame *frames,
70 + struct dx_frame *frame,
73 + unsigned long size1, size2;
74 + struct super_block *sb = dir->i_sb;
76 + if (unlikely(!EXT4_SB(sb)->s_warning_dir_size))
77 + EXT4_SB(sb)->s_warning_dir_size =
78 + __ext4_max_dir_size(frames, frame, dir);
80 + size1 = EXT4_SB(sb)->s_warning_dir_size / 16 * 10;
81 + size1 = size1 & ~(EXT4_BLOCK_SIZE(sb) - 1);
82 + size2 = EXT4_SB(sb)->s_warning_dir_size / 16 * 11;
83 + size2 = size2 & ~(EXT4_BLOCK_SIZE(sb) - 1);
84 + if (in_range(dir->i_size, size1, EXT4_BLOCK_SIZE(sb)) ||
85 + in_range(dir->i_size, size2, EXT4_BLOCK_SIZE(sb)))
92 * Returns 0 for success, or a negative error value
94 @@ -2068,6 +2124,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
95 struct ext4_dir_entry_2 *de;
98 + bool ret_warn = false;
102 @@ -2088,6 +2145,11 @@ again:
103 /* Block full, should compress but for now just split */
104 dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n",
105 dx_get_count(entries), dx_get_limit(entries)));
107 + if (frame - frames + 1 >= ext4_dir_htree_level(sb) ||
108 + EXT4_SB(dir->i_sb)->s_max_dir_size)
109 + ret_warn = dir_size_in_warning_range(frames, frame, dir);
111 /* Need to split index? */
112 if (dx_get_count(entries) == dx_get_limit(entries)) {
113 ext4_lblk_t newblock;
114 @@ -2119,7 +2181,7 @@ again:
115 "reach max htree level :%d",
117 if (ext4_dir_htree_level(sb) < EXT4_HTREE_LEVEL) {
118 - ext4_warning(sb, "Large directory feature is"
119 + ext4_warning(sb, "Large directory feature is "
120 "not enabled on this "
123 @@ -2248,6 +2310,8 @@ cleanup:
124 * repeat dx_probe() to find out valid htree-path */
125 if (restart && err == 0)
127 + if (err == 0 && ret_warn)
132 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
133 index f02a632..b8ed072 100644
134 --- a/fs/ext4/super.c
135 +++ b/fs/ext4/super.c
136 @@ -1813,6 +1813,8 @@ set_qf_format:
139 sbi->s_max_dir_size = option * 1024;
140 + /* reset s_warning_dir_size and make it re-calculated */
141 + sbi->s_warning_dir_size = 0;
144 if (match_int(&args[0], &option))
145 @@ -2577,6 +2579,7 @@ EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
146 inode_readahead_blks_store, s_inode_readahead_blks);
147 EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
148 EXT4_RW_ATTR_SBI_UI(max_dir_size, s_max_dir_size);
149 +EXT4_RW_ATTR_SBI_UI(warning_dir_size, s_warning_dir_size);
150 EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
151 EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
152 EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
153 @@ -2594,6 +2597,7 @@ static struct attribute *ext4_attrs[] = {
154 ATTR_LIST(inode_readahead_blks),
155 ATTR_LIST(inode_goal),
156 ATTR_LIST(max_dir_size),
157 + ATTR_LIST(warning_dir_size),
159 ATTR_LIST(mb_max_to_scan),
160 ATTR_LIST(mb_min_to_scan),
161 @@ -3119,6 +3123,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
163 sbi->s_mount_opt = 0;
164 sbi->s_max_dir_size = 0;
165 + sbi->s_warning_dir_size = 0;
166 sbi->s_resuid = EXT4_DEF_RESUID;
167 sbi->s_resgid = EXT4_DEF_RESGID;
168 sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;