diff options
Diffstat (limited to 'fs/ocfs2/suballoc.c')
-rw-r--r-- | fs/ocfs2/suballoc.c | 91 |
1 files changed, 64 insertions, 27 deletions
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 766a00b26441..226fe21f2608 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -145,14 +145,6 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) | |||
145 | return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc); | 145 | return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc); |
146 | } | 146 | } |
147 | 147 | ||
148 | int ocfs2_validate_group_descriptor(struct super_block *sb, | ||
149 | struct ocfs2_dinode *di, | ||
150 | struct buffer_head *bh, | ||
151 | int clean_error) | ||
152 | { | ||
153 | unsigned int max_bits; | ||
154 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | ||
155 | |||
156 | #define do_error(fmt, ...) \ | 148 | #define do_error(fmt, ...) \ |
157 | do{ \ | 149 | do{ \ |
158 | if (clean_error) \ | 150 | if (clean_error) \ |
@@ -161,6 +153,12 @@ int ocfs2_validate_group_descriptor(struct super_block *sb, | |||
161 | ocfs2_error(sb, fmt, ##__VA_ARGS__); \ | 153 | ocfs2_error(sb, fmt, ##__VA_ARGS__); \ |
162 | } while (0) | 154 | } while (0) |
163 | 155 | ||
156 | static int ocfs2_validate_gd_self(struct super_block *sb, | ||
157 | struct buffer_head *bh, | ||
158 | int clean_error) | ||
159 | { | ||
160 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | ||
161 | |||
164 | if (!OCFS2_IS_VALID_GROUP_DESC(gd)) { | 162 | if (!OCFS2_IS_VALID_GROUP_DESC(gd)) { |
165 | do_error("Group descriptor #%llu has bad signature %.*s", | 163 | do_error("Group descriptor #%llu has bad signature %.*s", |
166 | (unsigned long long)bh->b_blocknr, 7, | 164 | (unsigned long long)bh->b_blocknr, 7, |
@@ -184,6 +182,35 @@ int ocfs2_validate_group_descriptor(struct super_block *sb, | |||
184 | return -EINVAL; | 182 | return -EINVAL; |
185 | } | 183 | } |
186 | 184 | ||
185 | if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) { | ||
186 | do_error("Group descriptor #%llu has bit count %u but " | ||
187 | "claims that %u are free", | ||
188 | (unsigned long long)bh->b_blocknr, | ||
189 | le16_to_cpu(gd->bg_bits), | ||
190 | le16_to_cpu(gd->bg_free_bits_count)); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) { | ||
195 | do_error("Group descriptor #%llu has bit count %u but " | ||
196 | "max bitmap bits of %u", | ||
197 | (unsigned long long)bh->b_blocknr, | ||
198 | le16_to_cpu(gd->bg_bits), | ||
199 | 8 * le16_to_cpu(gd->bg_size)); | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int ocfs2_validate_gd_parent(struct super_block *sb, | ||
207 | struct ocfs2_dinode *di, | ||
208 | struct buffer_head *bh, | ||
209 | int clean_error) | ||
210 | { | ||
211 | unsigned int max_bits; | ||
212 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | ||
213 | |||
187 | if (di->i_blkno != gd->bg_parent_dinode) { | 214 | if (di->i_blkno != gd->bg_parent_dinode) { |
188 | do_error("Group descriptor #%llu has bad parent " | 215 | do_error("Group descriptor #%llu has bad parent " |
189 | "pointer (%llu, expected %llu)", | 216 | "pointer (%llu, expected %llu)", |
@@ -209,26 +236,35 @@ int ocfs2_validate_group_descriptor(struct super_block *sb, | |||
209 | return -EINVAL; | 236 | return -EINVAL; |
210 | } | 237 | } |
211 | 238 | ||
212 | if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) { | 239 | return 0; |
213 | do_error("Group descriptor #%llu has bit count %u but " | 240 | } |
214 | "claims that %u are free", | ||
215 | (unsigned long long)bh->b_blocknr, | ||
216 | le16_to_cpu(gd->bg_bits), | ||
217 | le16_to_cpu(gd->bg_free_bits_count)); | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | 241 | ||
221 | if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) { | ||
222 | do_error("Group descriptor #%llu has bit count %u but " | ||
223 | "max bitmap bits of %u", | ||
224 | (unsigned long long)bh->b_blocknr, | ||
225 | le16_to_cpu(gd->bg_bits), | ||
226 | 8 * le16_to_cpu(gd->bg_size)); | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | #undef do_error | 242 | #undef do_error |
230 | 243 | ||
231 | return 0; | 244 | /* |
245 | * This version only prints errors. It does not fail the filesystem, and | ||
246 | * exists only for resize. | ||
247 | */ | ||
248 | int ocfs2_check_group_descriptor(struct super_block *sb, | ||
249 | struct ocfs2_dinode *di, | ||
250 | struct buffer_head *bh) | ||
251 | { | ||
252 | int rc; | ||
253 | |||
254 | rc = ocfs2_validate_gd_self(sb, bh, 1); | ||
255 | if (!rc) | ||
256 | rc = ocfs2_validate_gd_parent(sb, di, bh, 1); | ||
257 | |||
258 | return rc; | ||
259 | } | ||
260 | |||
261 | static int ocfs2_validate_group_descriptor(struct super_block *sb, | ||
262 | struct buffer_head *bh) | ||
263 | { | ||
264 | mlog(0, "Validating group descriptor %llu\n", | ||
265 | (unsigned long long)bh->b_blocknr); | ||
266 | |||
267 | return ocfs2_validate_gd_self(sb, bh, 0); | ||
232 | } | 268 | } |
233 | 269 | ||
234 | int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di, | 270 | int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di, |
@@ -237,11 +273,12 @@ int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di, | |||
237 | int rc; | 273 | int rc; |
238 | struct buffer_head *tmp = *bh; | 274 | struct buffer_head *tmp = *bh; |
239 | 275 | ||
240 | rc = ocfs2_read_block(inode, gd_blkno, &tmp); | 276 | rc = ocfs2_read_block(inode, gd_blkno, &tmp, |
277 | ocfs2_validate_group_descriptor); | ||
241 | if (rc) | 278 | if (rc) |
242 | goto out; | 279 | goto out; |
243 | 280 | ||
244 | rc = ocfs2_validate_group_descriptor(inode->i_sb, di, tmp, 0); | 281 | rc = ocfs2_validate_gd_parent(inode->i_sb, di, tmp, 0); |
245 | if (rc) { | 282 | if (rc) { |
246 | brelse(tmp); | 283 | brelse(tmp); |
247 | goto out; | 284 | goto out; |