Whamcloud - gitweb
LU-11535 ldiskfs: allocate extra ldiskfs_ext_path for root
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / sles11sp3 / ext4_s_max_ext_tree_depth.patch
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.
7
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
12 @@ -1147,6 +1147,9 @@
13         unsigned long s_ext_extents;
14  #endif
15  
16 +       /* maximum possible extents tree depth, to be computed at mount time */
17 +       unsigned int s_max_ext_tree_depth;
18 +
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
26 @@ -3529,6 +3529,8 @@
27                 if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
28                         goto failed_mount3;
29  
30 +       ext4_ext_init(sb); /* needed before using extent-mapped journal */
31 +
32         /*
33          * The first inode we look at is the journal inode.  Don't try
34          * root first: it may be modified in the journal!
35 @@ -3722,7 +3724,6 @@
36                 goto failed_mount4a;
37         }
38  
39 -       ext4_ext_init(sb);
40         err = ext4_mb_init(sb, needs_recovery);
41         if (err) {
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
47 @@ -687,8 +687,9 @@
48  
49         /* account possible depth increase */
50         if (!path) {
51 -               path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
52 -                               GFP_NOFS);
53 +               path = kzalloc(sizeof(struct ext4_ext_path) *
54 +                              (EXT4_SB(inode->i_sb)->s_max_ext_tree_depth + 1),
55 +                              GFP_NOFS);
56                 if (!path)
57                         return ERR_PTR(-ENOMEM);
58                 alloc = 1;
59 @@ -1985,12 +1986,6 @@
60                         break;
61                 }
62  
63 -               if (ext_depth(inode) != depth) {
64 -                       /* depth was changed. we have to realloc path */
65 -                       kfree(path);
66 -                       path = NULL;
67 -               }
68 -
69                 block = cbex.ec_block + cbex.ec_len;
70         }
71  
72 @@ -2636,7 +2631,8 @@
73          * after i_size and walking into the tree depth-wise.
74          */
75         depth = ext_depth(inode);
76 -       path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS);
77 +       path = kzalloc(sizeof(struct ext4_ext_path) *
78 +                      (EXT4_SB(inode->i_sb)->s_max_ext_tree_depth + 1),
79 +                      GFP_NOFS);
80         if (path == NULL) {
81                 ext4_journal_stop(handle);
82                 return -ENOMEM;
83 @@ -2755,13 +2751,15 @@
84   */
85  void ext4_ext_init(struct super_block *sb)
86  {
87 +       ext4_fsblk_t maxblocks;
88 +
89         /*
90          * possible initialization would be here
91          */
92  
93         if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
94 -#if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS)
95 -               printk(KERN_INFO "EXT4-fs: file extents enabled");
96 +               printk(KERN_INFO "EXT4-fs (%s): file extents enabled",
97 +                      sb->s_id);
98  #ifdef AGGRESSIVE_TEST
99                 printk(", aggressive tests");
100  #endif
101 @@ -2770,14 +2768,35 @@
102  #endif
103  #ifdef EXTENTS_STATS
104                 printk(", stats");
105 -#endif
106 -               printk("\n");
107 -#endif
108 -#ifdef EXTENTS_STATS
109                 spin_lock_init(&EXT4_SB(sb)->s_ext_stats_lock);
110                 EXT4_SB(sb)->s_ext_min = 1 << 30;
111                 EXT4_SB(sb)->s_ext_max = 0;
112  #endif
113 +               EXT4_SB(sb)->s_max_ext_tree_depth = 1;
114 +
115 +               maxblocks = sb->s_maxbytes / sb->s_blocksize;
116 +
117 +               /* 1st/root level/node of extents tree stands in i_data and
118 +                * entries stored in tree nodes can be of type ext4_extent
119 +                * (leaf node) or ext4_extent_idx (internal node) */
120 +               maxblocks /= (sizeof(((struct ext4_inode_info *)0x0)->i_data) -
121 +                             sizeof(struct ext4_extent_header)) /
122 +                            max(sizeof(struct ext4_extent),
123 +                                sizeof(struct ext4_extent_idx));
124 +
125 +               /* compute maximum extents tree depth for a fully populated
126 +                * file of max size made of only minimal/1-block extents */
127 +               while (maxblocks > 0) {
128 +                       maxblocks /= (sb->s_blocksize -
129 +                                     sizeof(struct ext4_extent_header)) /
130 +                                    max(sizeof(struct ext4_extent),
131 +                                        sizeof(struct ext4_extent_idx));
132 +                       EXT4_SB(sb)->s_max_ext_tree_depth++;
133 +               }
134 +
135 +               printk(", maximum tree depth=%u",
136 +                      EXT4_SB(sb)->s_max_ext_tree_depth);
137 +               printk("\n");
138         }
139  }
140  
141 @@ -3592,15 +3611,10 @@
142                                  * the start of the hole
143                                  */
144                                 ext4_ext_drop_refs(path);
145 -                               kfree(path);
146  
147 +                               /* keep/reuse path */
148                                 path = ext4_ext_find_extent(inode,
149 -                               map->m_lblk, NULL);
150 -                               if (IS_ERR(path)) {
151 -                                       err = PTR_ERR(path);
152 -                                       path = NULL;
153 -                                       goto out2;
154 -                               }
155 +                                                           map->m_lblk, path);
156  
157                                 depth = ext_depth(inode);
158                                 ex = path[depth].p_ext;