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