1 Fix ext4_ext_find_extent() to already pre-allocate ext4_ext_path[]
2 array of the max depth instead of current depth.
3 This will avoid racy cases of concurrent ext_depth() growth in
4 current and unsafe implementation with ext4_ext_path[] array
5 re-[sizing,allocation], even with more recent and related patches
6 that will be integrated in more recent Kernels.
8 Index: linux-2.6.32-504.el6.x86_64/fs/ext4/ext4.h
9 ===================================================================
10 --- linux-2.6.32-504.el6.x86_64.orig/fs/ext4/ext4.h
11 +++ linux-2.6.32-504.el6.x86_64/fs/ext4/ext4.h
13 unsigned long s_ext_extents;
16 + /* maximum possible extents tree depth, to be computed at mount time */
17 + unsigned int s_max_ext_tree_depth;
19 /* for buddy allocator */
20 struct ext4_group_info ***s_group_info;
21 struct inode *s_buddy_cache;
22 Index: linux-2.6.32-504.el6.x86_64/fs/ext4/super.c
23 ===================================================================
24 --- linux-2.6.32-504.el6.x86_64.orig/fs/ext4/super.c
25 +++ linux-2.6.32-504.el6.x86_64/fs/ext4/super.c
27 if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
30 + ext4_ext_init(sb); /* needed before using extent-mapped journal */
33 * The first inode we look at is the journal inode. Don't try
34 * root first: it may be modified in the journal!
40 err = ext4_mb_init(sb, needs_recovery);
42 ext4_msg(sb, KERN_ERR, "failed to initalize mballoc (%d)",
43 Index: linux-2.6.32-504.el6.x86_64/fs/ext4/extents.c
44 ===================================================================
45 --- linux-2.6.32-504.el6.x86_64.orig/fs/ext4/extents.c
46 +++ linux-2.6.32-504.el6.x86_64/fs/ext4/extents.c
49 /* account possible depth increase */
51 - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
53 + path = kzalloc(sizeof(struct ext4_ext_path) *
54 + EXT4_SB(inode->i_sb)->s_max_ext_tree_depth,
57 return ERR_PTR(-ENOMEM);
59 @@ -1915,11 +1916,8 @@
60 /* find extent for this block */
61 down_read(&EXT4_I(inode)->i_data_sem);
63 - if (path && ext_depth(inode) != depth) {
64 - /* depth was changed. we have to realloc path */
68 + /* path of max possible depth will be allocated during
69 + * first pass, so its space can be re-used for each loop */
71 path = ext4_ext_find_extent(inode, block, path);
75 le16_to_cpu(path[k].p_hdr->eh_entries)+1;
77 - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
79 + path = kzalloc(sizeof(struct ext4_ext_path) *
80 + EXT4_SB(inode->i_sb)->s_max_ext_tree_depth,
83 ext4_journal_stop(handle);
85 @@ -2790,13 +2789,15 @@
87 void ext4_ext_init(struct super_block *sb)
89 + ext4_fsblk_t maxblocks;
92 * possible initialization would be here
95 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
96 -#if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS)
97 - printk(KERN_INFO "EXT4-fs: file extents enabled");
98 + printk(KERN_INFO "EXT4-fs (%s): file extents enabled",
100 #ifdef AGGRESSIVE_TEST
101 printk(", aggressive tests");
103 @@ -2805,14 +2806,35 @@
110 -#ifdef EXTENTS_STATS
111 spin_lock_init(&EXT4_SB(sb)->s_ext_stats_lock);
112 EXT4_SB(sb)->s_ext_min = 1 << 30;
113 EXT4_SB(sb)->s_ext_max = 0;
115 + EXT4_SB(sb)->s_max_ext_tree_depth = 1;
117 + maxblocks = sb->s_maxbytes / sb->s_blocksize;
119 + /* 1st/root level/node of extents tree stands in i_data and
120 + * entries stored in tree nodes can be of type ext4_extent
121 + * (leaf node) or ext4_extent_idx (internal node) */
122 + maxblocks /= (sizeof(((struct ext4_inode_info *)0x0)->i_data) -
123 + sizeof(struct ext4_extent_header)) /
124 + max(sizeof(struct ext4_extent),
125 + sizeof(struct ext4_extent_idx));
127 + /* compute maximum extents tree depth for a fully populated
128 + * file of max size made of only minimal/1-block extents */
129 + while (maxblocks > 0) {
130 + maxblocks /= (sb->s_blocksize -
131 + sizeof(struct ext4_extent_header)) /
132 + max(sizeof(struct ext4_extent),
133 + sizeof(struct ext4_extent_idx));
134 + EXT4_SB(sb)->s_max_ext_tree_depth++;
137 + printk(", maximum tree depth=%u",
138 + EXT4_SB(sb)->s_max_ext_tree_depth);
143 @@ -4614,11 +4636,8 @@
147 - if (ext_depth(inode) != depth) {
148 - /* depth was changed. we have to realloc path */
152 + /* path of max possible depth will be allocated during
153 + * first pass, so its space can be re-used for each loop */
155 block = cbex.ec_block + cbex.ec_len;