Whamcloud - gitweb
Branch b1_8
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext3-block-bitmap-validation-2.6-sles10.patch
1  fs/ext3/balloc.c |   99 ++++++++++++++++++++++++++++++++++++++++++++----------
2  1 files changed, 81 insertions(+), 18 deletions(-)
3 diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
4 index ff3428e..a9140ea 100644
5 Index: linux-stage/fs/ext3/balloc.c
6 ===================================================================
7 --- linux-stage.orig/fs/ext3/balloc.c
8 +++ linux-stage/fs/ext3/balloc.c
9 @@ -144,9 +144,96 @@ unsigned ext3_init_block_bitmap(struct s
10         return free_blocks - sbi->s_itb_per_group - 2;
11  }
12  
13 -/*
14 - * Read the bitmap for a given block_group, reading into the specified 
15 - * slot in the superblock's bitmap cache.
16 +/**
17 +* bh_uptodate_or_lock: Test whether the buffer is uptodate
18 +* @bh: struct buffer_head
19 +*
20 +* Return true if the buffer is up-to-date and false,
21 +* with the buffer locked, if not.
22 +*/
23 +int bh_uptodate_or_lock(struct buffer_head *bh)
24 +{
25 +       if (!buffer_uptodate(bh)) {
26 +               lock_buffer(bh);
27 +               if (!buffer_uptodate(bh))
28 +                       return 0;
29 +               unlock_buffer(bh);
30 +       }
31 +       return 1;
32 +}
33 +
34 +/**
35 +* bh_submit_read: Submit a locked buffer for reading
36 +* @bh: struct buffer_head
37 +*
38 +* Returns a negative error
39 +*/
40 +int bh_submit_read(struct buffer_head *bh)
41 +{
42 +       if (!buffer_locked(bh))
43 +               lock_buffer(bh);
44 +       if (buffer_uptodate(bh))
45 +               return 0;
46 +       get_bh(bh);
47 +       bh->b_end_io = end_buffer_read_sync;
48 +       submit_bh(READ, bh);
49 +       wait_on_buffer(bh);
50 +       if (buffer_uptodate(bh))
51 +               return 0;
52 +       return -EIO;
53 +}
54 +
55 +static int ext3_valid_block_bitmap(struct super_block *sb,
56 +                                  struct ext3_group_desc *desc,
57 +                                  unsigned int block_group,
58 +                                  struct buffer_head *bh)
59 +{
60 +       unsigned long long offset;
61 +       unsigned long long next_zero_bit;
62 +       unsigned long long bitmap_blk;
63 +       unsigned long long group_first_block;
64 +
65 +       group_first_block = ext3_group_first_block_no(sb, block_group);
66 +
67 +       /* check whether block bitmap block number is set */
68 +       bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
69 +       offset = bitmap_blk - group_first_block;
70 +       if (!ext3_test_bit(offset, bh->b_data))
71 +               /* bad block bitmap */
72 +               goto err_out;
73 +
74 +       /* check whether the inode bitmap block number is set */
75 +       bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
76 +       offset = bitmap_blk - group_first_block;
77 +       if (!ext3_test_bit(offset, bh->b_data))
78 +               /* bad block bitmap */
79 +               goto err_out;
80 +
81 +       /* check whether the inode table block number is set */
82 +       bitmap_blk = le32_to_cpu(desc->bg_inode_table);
83 +       offset = bitmap_blk - group_first_block;
84 +       next_zero_bit = ext3_find_next_zero_bit(bh->b_data,
85 +                               offset + EXT3_SB(sb)->s_itb_per_group,
86 +                               offset);
87 +       if (next_zero_bit >= offset + EXT3_SB(sb)->s_itb_per_group)
88 +               /* good bitmap for inode tables */
89 +               return 1;
90 +
91 +err_out:
92 +       ext3_error(sb, __FUNCTION__,
93 +                  "Invalid block bitmap - "
94 +                  "block_group = %d, block = %llu",
95 +                  block_group, bitmap_blk);
96 +       return 0;
97 +}
98 +
99 +/**
100 + * read_block_bitmap()
101 + * @sb:                 super block
102 + * @block_group: given block group
103 + *
104 + * Read the bitmap for a given block_group,and validate the
105 + * bits for block/inode/inode tables are set in the bitmaps.
106   *
107   * Return buffer_head on success or NULL in case of failure.
108   */
109 @@ -155,29 +242,42 @@ read_block_bitmap(struct super_block *sb
110  {
111         struct ext3_group_desc * desc;
112         struct buffer_head * bh = NULL;
113 +       unsigned long long bitmap_blk;
114  
115         desc = ext3_get_group_desc (sb, block_group, NULL);
116         if (!desc)
117 -               goto error_out;
118 +               return NULL;
119 +       bitmap_blk = desc->bg_block_bitmap;
120 +       bh = sb_getblk(sb, bitmap_blk);
121 +       if (unlikely(!bh)) {
122 +               ext3_error(sb, __FUNCTION__,
123 +                          "Can not read block bitmap - "
124 +                          "block group = %d, block_bitmap = %llu",
125 +                          (int)block_group, bitmap_blk);
126 +               return NULL;
127 +       }
128 +       if (bh_uptodate_or_lock(bh))
129 +               return bh;
130 +
131         if (desc->bg_flags & cpu_to_le16(EXT3_BG_BLOCK_UNINIT)) {
132 -               bh = sb_getblk(sb, le32_to_cpu(desc->bg_block_bitmap));
133 -               if (!buffer_uptodate(bh)) {
134 -                       lock_buffer(bh);
135 -                       if (!buffer_uptodate(bh)) {
136 -                               ext3_init_block_bitmap(sb, bh,block_group,desc);
137 -                               set_buffer_uptodate(bh);
138 -                       }
139 -                       unlock_buffer(bh);
140 -               }
141 -       } else {
142 -               bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
143 +               ext3_init_block_bitmap(sb, bh, block_group, desc);
144 +               set_buffer_uptodate(bh);
145 +               unlock_buffer(bh);
146 +               return bh;
147 +       }
148 +       if (bh_submit_read(bh) < 0) {
149 +               brelse(bh);
150 +               ext3_error(sb, __FUNCTION__,
151 +                          "Cannot read block bitmap - "
152 +                          "block group = %d block_bitmap = %llu",
153 +                          (int)block_group, bitmap_blk);
154 +               return NULL;
155         }
156 -       if (!bh)
157 -               ext3_error (sb, "read_block_bitmap",
158 -                           "Cannot read block bitmap - "
159 -                           "block_group = %d, block_bitmap = %u",
160 -                           block_group, le32_to_cpu(desc->bg_block_bitmap));
161 -error_out:
162 +       if (!ext3_valid_block_bitmap(sb, desc, block_group, bh)) {
163 +               brelse(bh);
164 +               return NULL;
165 +       }
166 +
167         return bh;
168  }
169  /*
170 Index: linux-stage/include/linux/ext3_fs.h
171 ===================================================================
172 --- linux-stage.orig/include/linux/ext3_fs.h
173 +++ linux-stage/include/linux/ext3_fs.h
174 @@ -872,6 +872,14 @@ struct dir_private_info {
175         __u32           next_hash;
176  };
177  
178 +/* calculate the first block number of the group */
179 +static inline long long
180 +ext3_group_first_block_no(struct super_block *sb, unsigned long group_no)
181 +{
182 +               return group_no * (long long)EXT3_BLOCKS_PER_GROUP(sb) +
183 +                       le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block);
184 +}
185 +
186  /*
187   * Special error return code only used by dx_probe() and its callers.
188   */