Whamcloud - gitweb
LU-6722 ldiskfs: fix credits at ldiskfs_delete_inode
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / sles11sp2 / ext4-corrupted-inode-block-bitmaps-handling-patches.patch
1 diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
2 index db5b7a3..332078f 100644
3 --- a/fs/ext4/balloc.c
4 +++ b/fs/ext4/balloc.c
5 @@ -99,12 +99,11 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
6                 /* If checksum is bad mark all blocks used to prevent allocation
7                  * essentially implementing a per-group read-only flag. */
8                 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
9 -                       ext4_error(sb, "Checksum bad for group %u",
10 +                       ext4_corrupted_block_group(sb, block_group,
11 +                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT |
12 +                                       EXT4_GROUP_INFO_IBITMAP_CORRUPT,
13 +                                       "Checksum bad for group %u",
14                                         block_group);
15 -                       ext4_free_blks_set(sb, gdp, 0);
16 -                       ext4_free_inodes_set(sb, gdp, 0);
17 -                       ext4_itable_unused_set(sb, gdp, 0);
18 -                       memset(bh->b_data, 0xff, sb->s_blocksize);
19                         return 0;
20                 }
21                 memset(bh->b_data, 0, sb->s_blocksize);
22 @@ -279,8 +278,10 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
23                 return 1;
24  
25  err_out:
26 -       ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
27 -                       block_group, bitmap_blk);
28 +       ext4_corrupted_block_group(sb, block_group,
29 +                                  EXT4_GROUP_INFO_BBITMAP_CORRUPT,
30 +                                  "Invalid block bitmap - block_group = %d, block = %llu",
31 +                                  block_group, bitmap_blk);
32         return 0;
33  }
34  /**
35 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
36 index a18fd36..949d7be 100644
37 --- a/fs/ext4/ext4.h
38 +++ b/fs/ext4/ext4.h
39 @@ -78,6 +78,18 @@ typedef __u32 ext4_lblk_t;
40  /* data type for block group number */
41  typedef unsigned int ext4_group_t;
42  
43 +void __ext4_corrupted_block_group(struct super_block *sb,
44 +                                 ext4_group_t group, unsigned int flags,
45 +                                 const char *function,
46 +                                 unsigned int line);
47 +
48 +#define ext4_corrupted_block_group(sb, group, flags, fmt...)           \
49 +       do {                                                            \
50 +               __ext4_warning(sb, __func__, __LINE__, ## fmt);         \
51 +               __ext4_corrupted_block_group(sb, group, flags,          \
52 +                       __func__, __LINE__);                            \
53 +       } while (0)
54 +
55  /*
56   * Flags used in mballoc's allocation_context flags field.
57   *
58 @@ -2257,9 +2269,19 @@ struct ext4_group_info {
59  
60  #define EXT4_GROUP_INFO_NEED_INIT_BIT          0
61  #define EXT4_GROUP_INFO_WAS_TRIMMED_BIT                1
62 +#define EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT    2
63 +#define EXT4_GROUP_INFO_BBITMAP_CORRUPT                \
64 +               (1 << EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT)
65 +#define EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT    3
66 +#define EXT4_GROUP_INFO_IBITMAP_CORRUPT                \
67 +               (1 << EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT)
68  
69  #define EXT4_MB_GRP_NEED_INIT(grp)     \
70         (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
71 +#define EXT4_MB_GRP_BBITMAP_CORRUPT(grp)       \
72 +       (test_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
73 +#define EXT4_MB_GRP_IBITMAP_CORRUPT(grp)       \
74 +       (test_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
75  
76  #define EXT4_MB_GRP_WAS_TRIMMED(grp)   \
77         (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
78 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
79 index 532dcaa..6082e54 100644
80 --- a/fs/ext4/ialloc.c
81 +++ b/fs/ext4/ialloc.c
82 @@ -78,11 +78,10 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
83         /* If checksum is bad mark all blocks and inodes use to prevent
84          * allocation, essentially implementing a per-group read-only flag. */
85         if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
86 -               ext4_error(sb, "Checksum bad for group %u", block_group);
87 -               ext4_free_blks_set(sb, gdp, 0);
88 -               ext4_free_inodes_set(sb, gdp, 0);
89 -               ext4_itable_unused_set(sb, gdp, 0);
90 -               memset(bh->b_data, 0xff, sb->s_blocksize);
91 +               ext4_corrupted_block_group(sb, block_group,
92 +                               EXT4_GROUP_INFO_BBITMAP_CORRUPT |
93 +                               EXT4_GROUP_INFO_IBITMAP_CORRUPT,
94 +                               "Checksum bad for group %u", block_group);
95                 return 0;
96         }
97  
98 @@ -195,6 +194,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
99         struct ext4_super_block *es;
100         struct ext4_sb_info *sbi;
101         int fatal = 0, err, count, cleared;
102 +       struct ext4_group_info *grp;
103  
104         if (atomic_read(&inode->i_count) > 1) {
105                 printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
106 @@ -238,7 +238,9 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
107         block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
108         bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
109         bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
110 -       if (!bitmap_bh)
111 +       /* Don't bother if the inode bitmap is corrupt. */
112 +       grp = ext4_get_group_info(sb, block_group);
113 +       if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || !bitmap_bh)
114                 goto error_return;
115  
116         BUFFER_TRACE(bitmap_bh, "get_write_access");
117 @@ -286,8 +288,12 @@ out:
118                 if (!fatal)
119                         fatal = err;
120                 ext4_mark_super_dirty(sb);
121 -       } else
122 -               ext4_error(sb, "bit already cleared for inode %lu", ino);
123 +       } else {
124 +               ext4_corrupted_block_group(sb, block_group,
125 +                               EXT4_GROUP_INFO_IBITMAP_CORRUPT,
126 +                               "bit already cleared for inode %lu",
127 +                               ino);
128 +       }
129  
130  error_return:
131         brelse(bitmap_bh);
132 @@ -820,6 +826,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
133         int free = 0;
134         static int once = 1;
135         ext4_group_t flex_group;
136 +       struct ext4_group_info *grp;
137  
138         /* Cannot create files in a deleted directory */
139         if (!dir || !dir->i_nlink)
140 @@ -879,10 +886,21 @@ got_group:
141                 if (!gdp)
142                         goto fail;
143  
144 +               grp = ext4_get_group_info(sb, group);
145 +               /* Skip groups with already-known suspicious inode tables */
146 +               if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
147 +                       if (++group == ngroups)
148 +                               group = 0;
149 +                       continue;
150 +               }
151                 brelse(inode_bitmap_bh);
152                 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
153 -               if (!inode_bitmap_bh)
154 -                       goto fail;
155 +               /* Skip groups with suspicious inode tables */
156 +               if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || !inode_bitmap_bh) {
157 +                       if (++group == ngroups)
158 +                               group = 0;
159 +                       continue;
160 +               }
161  
162  repeat_in_this_group:
163                 ino = ext4_find_next_zero_bit((unsigned long *)
164 diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
165 index 1d77581..4d6558e 100644
166 --- a/fs/ext4/mballoc.c
167 +++ b/fs/ext4/mballoc.c
168 @@ -740,7 +740,6 @@ int ext4_mb_generate_buddy(struct super_block *sb,
169                                       "%u blocks in bitmap, %u in bb, %u in gd",
170                                       free, grp->bb_free,
171                                       ext4_free_blks_count(sb, gdp));
172 -
173                 /*
174                  * If we intent to continue, we consider group descritor
175                  * corrupt and update bb_free using bitmap value
176 @@ -1124,7 +1123,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
177         int block;
178         int pnum;
179         int poff;
180 -       struct page *page;
181 +       struct page *page = NULL;
182         int ret;
183         struct ext4_group_info *grp;
184         struct ext4_sb_info *sbi = EXT4_SB(sb);
185 @@ -1149,7 +1148,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
186                  */
187                 ret = ext4_mb_init_group(sb, group);
188                 if (ret)
189 -                       return ret;
190 +                       goto err;
191         }
192  
193         /*
194 @@ -1233,6 +1232,8 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
195         return 0;
196  
197  err:
198 +       ext4_warning(sb, "Error in loading buddy information for %u",
199 +                       group);
200         if (page)
201                 page_cache_release(page);
202         if (e4b->bd_bitmap_page)
203 @@ -1322,6 +1323,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
204  
205         BUG_ON(first + count > (sb->s_blocksize << 3));
206         assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
207 +       /* Don't bother if the block group is corrupt. */
208 +       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
209 +               return;
210 +
211         mb_check_buddy(e4b);
212         mb_free_blocks_double(inode, e4b, first, count);
213  
214 @@ -1729,6 +1734,11 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
215         if (err)
216                 return err;
217  
218 +       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) {
219 +               ext4_mb_unload_buddy(e4b);
220 +               return 0;
221 +       }
222 +
223         ext4_lock_group(ac->ac_sb, group);
224         max = mb_find_extent(e4b, 0, ac->ac_g_ex.fe_start,
225                              ac->ac_g_ex.fe_len, &ex);
226 @@ -1940,6 +1950,9 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
227  
228         BUG_ON(cr < 0 || cr >= 4);
229  
230 +       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
231 +               return 0;
232 +
233         /* We only do this if the grp has never been initialized */
234         if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
235                 int ret = ext4_mb_init_group(ac->ac_sb, group);
236 @@ -3458,9 +3471,11 @@ int ext4_mb_check_ondisk_bitmap(struct super_block *sb, void *bitmap,
237         }
238  
239         if (free != ext4_free_blks_count(sb, gdp)) {
240 -               ext4_error(sb, "on-disk bitmap for group %d"
241 -                       "corrupted: %u blocks free in bitmap, %u - in gd\n",
242 -                       group, free, ext4_free_blks_count(sb, gdp));
243 +               ext4_corrupted_block_group(sb, group,
244 +                               EXT4_GROUP_INFO_BBITMAP_CORRUPT,
245 +                               "on-disk bitmap for group %d corrupted: %u blocks free in bitmap, %u - in gd\n",
246 +                               group, free,
247 +                               ext4_free_blks_count(sb, gdp));
248                 return -EIO;
249         }
250         return 0;
251 @@ -3813,17 +3828,9 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
252         /* "free < pa->pa_free" means we maybe double alloc the same blocks,
253          * otherwise maybe leave some free blocks unavailable, no need to BUG.*/
254         if ((free > pa->pa_free && !pa->pa_error) || (free < pa->pa_free)) {
255 -               ext4_error(sb, "pa free mismatch: [pa %p] "
256 -                               "[phy %lu] [logic %lu] [len %u] [free %u] "
257 -                               "[error %u] [inode %lu] [freed %u]", pa,
258 -                               (unsigned long)pa->pa_pstart,
259 -                               (unsigned long)pa->pa_lstart,
260 -                               (unsigned)pa->pa_len, (unsigned)pa->pa_free,
261 -                               (unsigned)pa->pa_error, pa->pa_inode->i_ino,
262 -                               free);
263                 ext4_grp_locked_error(sb, group, 0, 0,
264 -                                       "free %u, pa_free %u",
265 -                                       free, pa->pa_free);
266 +                                     "free %u, pa_free %u",
267 +                                     free, pa->pa_free);
268                 /*
269                  * pa is already deleted so we use the value obtained
270                  * from the bitmap and continue.
271 @@ -3883,14 +3890,11 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
272                 return 0;
273  
274         bitmap_bh = ext4_read_block_bitmap(sb, group);
275 -       if (bitmap_bh == NULL) {
276 -               ext4_error(sb, "Error reading block bitmap for %u", group);
277 +       if (bitmap_bh == NULL)
278                 return 0;
279 -       }
280  
281         err = ext4_mb_load_buddy(sb, group, &e4b);
282         if (err) {
283 -               ext4_error(sb, "Error loading buddy information for %u", group);
284                 put_bh(bitmap_bh);
285                 return 0;
286         }
287 @@ -4054,16 +4058,11 @@ repeat:
288                 ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
289  
290                 err = ext4_mb_load_buddy(sb, group, &e4b);
291 -               if (err) {
292 -                       ext4_error(sb, "Error loading buddy information for %u",
293 -                                       group);
294 +               if (err)
295                         return;
296 -               }
297  
298                 bitmap_bh = ext4_read_block_bitmap(sb, group);
299                 if (bitmap_bh == NULL) {
300 -                       ext4_error(sb, "Error reading block bitmap for %u",
301 -                                       group);
302                         ext4_mb_unload_buddy(&e4b);
303                         continue;
304                 }
305 @@ -4324,11 +4323,8 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
306         list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) {
307  
308                 ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
309 -               if (ext4_mb_load_buddy(sb, group, &e4b)) {
310 -                       ext4_error(sb, "Error loading buddy information for %u",
311 -                                       group);
312 +               if (ext4_mb_load_buddy(sb, group, &e4b))
313                         continue;
314 -               }
315                 ext4_lock_group(sb, group);
316                 list_del(&pa->pa_group_list);
317                 ext4_get_group_info(sb, group)->bb_prealloc_nr--;
318 @@ -4585,7 +4581,7 @@ repeat:
319                         * been updated or not when fail case. So can
320                         * not revert pa_free back, just mark pa_error*/
321                         pa->pa_error++;
322 -                       ext4_error(sb,
323 +                       ext4_corrupted_block_group(sb, 0, 0,
324                                 "Updating bitmap error: [err %d] "
325                                 "[pa %p] [phy %lu] [logic %lu] "
326                                 "[len %u] [free %u] [error %u] "
327 @@ -4731,6 +4727,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
328         struct ext4_buddy e4b;
329         int err = 0;
330         int ret;
331 +       int skip_error = 0;
332  
333         if (bh) {
334                 if (block)
335 @@ -4781,6 +4778,10 @@ do_more:
336         overflow = 0;
337         ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
338  
339 +       if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(
340 +                       ext4_get_group_info(sb, block_group))))
341 +               return;
342 +
343         /*
344          * Check to see if we are freeing blocks across a group
345          * boundary.
346 @@ -4837,8 +4838,10 @@ do_more:
347         trace_ext4_mballoc_free(sb, inode, block_group, bit, count);
348  
349         err = ext4_mb_load_buddy(sb, block_group, &e4b);
350 -       if (err)
351 +       if (err) {
352 +               skip_error = 1;
353                 goto error_return;
354 +       }
355  
356         if ((flags & EXT4_FREE_BLOCKS_METADATA) && ext4_handle_valid(handle)) {
357                 struct ext4_free_data *new_entry;
358 @@ -4905,8 +4908,9 @@ do_more:
359  error_return:
360         if (freed && !(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
361                 dquot_free_block(inode, freed);
362 +       if (!skip_error)
363 +               ext4_std_error(sb, err);
364         brelse(bitmap_bh);
365 -       ext4_std_error(sb, err);
366         return;
367  }
368  
369 @@ -4991,7 +4995,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
370  
371         err = ext4_mb_load_buddy(sb, block_group, &e4b);
372         if (err)
373 -               goto error_return;
374 +               goto error_brelse;
375  
376         /*
377          * need to update group_info->bb_free and bitmap
378 @@ -5026,8 +5030,9 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
379                 err = ret;
380  
381  error_return:
382 -       brelse(bitmap_bh);
383         ext4_std_error(sb, err);
384 +error_brelse:
385 +       brelse(bitmap_bh);
386         return;
387  }
388  
389 @@ -5094,11 +5099,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
390         int ret;
391  
392         ret = ext4_mb_load_buddy(sb, group, &e4b);
393 -       if (ret) {
394 -               ext4_error(sb, "Error in loading buddy "
395 -                               "information for %u", group);
396 +       if (ret)
397                 return ret;
398 -       }
399         bitmap = e4b.bd_bitmap;
400  
401         ext4_lock_group(sb, group);
402 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
403 index a21e903..2fca810 100644
404 --- a/fs/ext4/super.c
405 +++ b/fs/ext4/super.c
406 @@ -666,6 +666,32 @@ void __ext4_warning(struct super_block *sb, const char *function,
407         va_end(args);
408  }
409  
410 +void __ext4_corrupted_block_group(struct super_block *sb, ext4_group_t group,
411 +                                 unsigned int flags, const char *function,
412 +                                 unsigned int line)
413 +{
414 +       struct ext4_group_info *grp = ext4_get_group_info(sb, group);
415 +       struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
416 +
417 +       if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT &&
418 +           !EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) {
419 +               ext4_free_blks_set(sb, gdp, 0);
420 +               set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
421 +                       &grp->bb_state);
422 +       }
423 +
424 +       if (flags & EXT4_GROUP_INFO_IBITMAP_CORRUPT &&
425 +           !EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
426 +               if (gdp) {
427 +                       ext4_free_inodes_set(sb, gdp, 0);
428 +                       ext4_itable_unused_set(sb, gdp, 0);
429 +               }
430 +               set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT,
431 +                       &grp->bb_state);
432 +       }
433 +       save_error_info(sb, function, line);
434 +}
435 +
436  void __ext4_grp_locked_error(const char *function, unsigned int line,
437                              struct super_block *sb, ext4_group_t grp,
438                              unsigned long ino, ext4_fsblk_t block,