Whamcloud - gitweb
LU-228 kernel update [RHEL5 U6 2.6.18-238.9.1.el5]
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-mballoc-pa_free-mismatch.patch
1 Index: linux-stage/fs/ext4/mballoc.c
2 ===================================================================
3 --- linux-stage.orig/fs/ext4/mballoc.c  2010-01-26 22:50:37.000000000 +0800
4 +++ linux-stage/fs/ext4/mballoc.c       2010-01-26 22:57:24.000000000 +0800
5 @@ -3892,6 +3892,7 @@
6         INIT_LIST_HEAD(&pa->pa_group_list);
7         pa->pa_deleted = 0;
8         pa->pa_type = MB_INODE_PA;
9 +       pa->pa_error = 0;
10  
11         mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
12                         pa->pa_pstart, pa->pa_len, pa->pa_lstart);
13 @@ -3956,6 +3957,7 @@
14         INIT_LIST_HEAD(&pa->pa_group_list);
15         pa->pa_deleted = 0;
16         pa->pa_type = MB_GROUP_PA;
17 +       pa->pa_error = 0;
18  
19         mb_debug("new group pa %p: %llu/%u for %u\n", pa,
20                  pa->pa_pstart, pa->pa_len, pa->pa_lstart);
21 @@ -4019,7 +4021,9 @@
22         int err = 0;
23         int free = 0;
24  
25 +       assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
26         BUG_ON(pa->pa_deleted == 0);
27 +       BUG_ON(pa->pa_inode == NULL);
28         ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
29         grp_blk_start = pa->pa_pstart - bit;
30         BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
31 @@ -4059,11 +4064,18 @@
32                 mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
33                 bit = next + 1;
34         }
35 -       if (free != pa->pa_free) {
36 -               printk(KERN_CRIT "pa %p: logic %lu, phys. %lu, len %lu\n",
37 -                       pa, (unsigned long) pa->pa_lstart,
38 -                       (unsigned long) pa->pa_pstart,
39 -                       (unsigned long) pa->pa_len);
40 +
41 +        /* "free < pa->pa_free" means we maybe double alloc the same blocks,
42 +         * otherwise maybe leave some free blocks unavailable, no need to BUG.*/
43 +        if ((free > pa->pa_free && !pa->pa_error) || (free < pa->pa_free)) {
44 +                ext4_error(sb,"pa free mismatch: [pa %p] "
45 +                              "[phy %lu] [logic %lu] [len %u] [free %u] "
46 +                              "[error %u] [inode %lu] [freed %u]", pa,
47 +                              (unsigned long)pa->pa_pstart,
48 +                              (unsigned long)pa->pa_lstart,
49 +                              (unsigned)pa->pa_len, (unsigned)pa->pa_free,
50 +                              (unsigned)pa->pa_error, pa->pa_inode->i_ino,
51 +                              free);
52                 ext4_grp_locked_error(sb, group,
53                                         __func__, "free %u, pa_free %u",
54                                         free, pa->pa_free);
55 @@ -4072,6 +4084,7 @@
56                  * from the bitmap and continue.
57                  */
58         }
59 +        BUG_ON(pa->pa_free != free);
60         atomic_add(free, &sbi->s_mb_discarded);
61  
62         return err;
63 @@ -4800,6 +4813,24 @@
64                 }
65         }
66  
67 +
68 +        if (dev_check_rdonly(sb->s_bdev)) {
69 +                struct block_device *bdev = sb->s_bdev;
70 +
71 +                printk(KERN_WARNING "Alloc from readonly device %s (%#x): "
72 +                       "[inode %lu] [logic %llu] [goal %llu] [ll %llu] "
73 +                      "[pl %llu] [lr %llu] [pr %llu] [len %u] [flags %u]\n",
74 +                       bdev->bd_disk ? bdev->bd_disk->disk_name : "",
75 +                       bdev->bd_dev, ar->inode->i_ino,
76 +                      (unsigned long long)ar->logical, 
77 +                      (unsigned long long)ar->goal,
78 +                       (unsigned long long)ar->lleft,
79 +                      (unsigned long long)ar->pleft,
80 +                      (unsigned long long)ar->lright,
81 +                      (unsigned long long)ar->pright,
82 +                      ar->len, ar->flags);
83 +        }
84 +
85         ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
86         if (!ac) {
87                 ar->len = 0;
88 @@ -4850,6 +4881,25 @@
89                         ac->ac_b_ex.fe_len = 0;
90                         ar->len = 0;
91                         ext4_mb_show_ac(ac);
92 +                        if (ac->ac_pa) {
93 +                               struct ext4_prealloc_space *pa = ac->ac_pa;
94 +
95 +                               /* We can not make sure whether the bitmap has
96 +                                        * been updated or not when fail case. So can
97 +                                 * not revert pa_free back, just mark pa_error*/
98 +                                pa->pa_error++;
99 +                                ext4_error(sb,
100 +                                            "Updating bitmap error: [err %d] "
101 +                                            "[pa %p] [phy %lu] [logic %lu] "
102 +                                            "[len %u] [free %u] [error %u] "
103 +                                            "[inode %lu]", *errp, pa,
104 +                                            (unsigned long)pa->pa_pstart,
105 +                                            (unsigned long)pa->pa_lstart,
106 +                                            (unsigned)pa->pa_len,
107 +                                            (unsigned)pa->pa_free,
108 +                                            (unsigned)pa->pa_error,
109 +                                       pa->pa_inode ? pa->pa_inode->i_ino : 0);
110 +                        }
111                 } else {
112                         block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
113                         ar->len = ac->ac_b_ex.fe_len;
114 @@ -5025,6 +5075,15 @@
115                 goto error_return;
116         }
117  
118 +        if (dev_check_rdonly(sb->s_bdev)) {
119 +                struct block_device *bdev = sb->s_bdev;
120 +
121 +                printk(KERN_WARNING "Release to readonly device %s (%#x): "
122 +                       "[inode %lu] [block %lu] [count %lu] [is_meta %d]\n",
123 +                       bdev->bd_disk ? bdev->bd_disk->disk_name : "",
124 +                       bdev->bd_dev, inode->i_ino, (unsigned long)block, count, metadata);
125 +        }
126 +
127         ext4_debug("freeing block %llu\n", block);
128         trace_mark(ext4_free_blocks,
129                    "dev %s block %llu count %lu metadata %d ino %lu",
130 Index: linux-stage/fs/ext4/mballoc.h
131 ===================================================================
132 --- linux-stage.orig/fs/ext4/mballoc.h  2010-01-26 22:50:36.000000000 +0800
133 +++ linux-stage/fs/ext4/mballoc.h       2010-01-26 22:52:58.000000000 +0800
134 @@ -21,6 +21,7 @@
135  #include <linux/blkdev.h>
136  #include <linux/marker.h>
137  #include <linux/mutex.h>
138 +#include <linux/genhd.h>
139  #include "ext4_jbd2.h"
140  #include "ext4.h"
141  #include "group.h"
142 @@ -134,6 +135,7 @@
143         ext4_grpblk_t           pa_len;         /* len of preallocated chunk */
144         ext4_grpblk_t           pa_free;        /* how many blocks are free */
145         unsigned short          pa_type;        /* pa type. inode or group */
146 +       unsigned short          pa_error;
147         spinlock_t              *pa_obj_lock;
148         struct inode            *pa_inode;      /* hack, for history only */
149  };