diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-11-13 17:49:19 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:53 -0500 |
commit | 970e4936d7d15f35d00fd15a14f5343ba78b2fc8 (patch) | |
tree | 92057c7deab6b9d8e5c3889d6a354b5989a3b68d /fs | |
parent | 4ae1d69bedc8d174cb8a558694607e013157cde1 (diff) |
ocfs2: Validate metadata only when it's read from disk.
Add an optional validation hook to ocfs2_read_blocks(). Now the
validation function is only called when a block was actually read off of
disk. It is not called when the buffer was in cache.
We add a buffer state bit BH_NeedsValidate to flag these buffers. It
must always be one higher than the last JBD2 buffer state bit.
The dinode, dirblock, extent_block, and xattr_block validators are
lifted to this scheme directly. The group_descriptor validator needs to
be split into two pieces. The first part only needs the gd buffer and
is passed to ocfs2_read_block(). The second part requires the dinode as
well, and is called every time. It's only 3 compares, so it's tiny.
This also allows us to clean up the non-fatal gd check used by resize.c.
It now has no magic argument.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/alloc.c | 17 | ||||
-rw-r--r-- | fs/ocfs2/buffer_head_io.c | 33 | ||||
-rw-r--r-- | fs/ocfs2/buffer_head_io.h | 27 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 13 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 18 | ||||
-rw-r--r-- | fs/ocfs2/resize.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/slot_map.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.c | 91 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.h | 15 | ||||
-rw-r--r-- | fs/ocfs2/xattr.c | 26 |
10 files changed, 149 insertions, 97 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f430cc6e0f35..e823a27ba340 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -684,6 +684,9 @@ static int ocfs2_validate_extent_block(struct super_block *sb, | |||
684 | struct ocfs2_extent_block *eb = | 684 | struct ocfs2_extent_block *eb = |
685 | (struct ocfs2_extent_block *)bh->b_data; | 685 | (struct ocfs2_extent_block *)bh->b_data; |
686 | 686 | ||
687 | mlog(0, "Validating extent block %llu\n", | ||
688 | (unsigned long long)bh->b_blocknr); | ||
689 | |||
687 | if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { | 690 | if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { |
688 | ocfs2_error(sb, | 691 | ocfs2_error(sb, |
689 | "Extent block #%llu has bad signature %.*s", | 692 | "Extent block #%llu has bad signature %.*s", |
@@ -719,21 +722,13 @@ int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno, | |||
719 | int rc; | 722 | int rc; |
720 | struct buffer_head *tmp = *bh; | 723 | struct buffer_head *tmp = *bh; |
721 | 724 | ||
722 | rc = ocfs2_read_block(inode, eb_blkno, &tmp); | 725 | rc = ocfs2_read_block(inode, eb_blkno, &tmp, |
723 | if (rc) | 726 | ocfs2_validate_extent_block); |
724 | goto out; | ||
725 | |||
726 | rc = ocfs2_validate_extent_block(inode->i_sb, tmp); | ||
727 | if (rc) { | ||
728 | brelse(tmp); | ||
729 | goto out; | ||
730 | } | ||
731 | 727 | ||
732 | /* If ocfs2_read_block() got us a new bh, pass it up. */ | 728 | /* If ocfs2_read_block() got us a new bh, pass it up. */ |
733 | if (!*bh) | 729 | if (!rc && !*bh) |
734 | *bh = tmp; | 730 | *bh = tmp; |
735 | 731 | ||
736 | out: | ||
737 | return rc; | 732 | return rc; |
738 | } | 733 | } |
739 | 734 | ||
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 3a178ec48d7c..0e9eed0c223f 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -39,6 +39,19 @@ | |||
39 | 39 | ||
40 | #include "buffer_head_io.h" | 40 | #include "buffer_head_io.h" |
41 | 41 | ||
42 | /* | ||
43 | * Bits on bh->b_state used by ocfs2. | ||
44 | * | ||
45 | * These MUST be after the JBD2 bits. Currently BH_Unshadow is the last | ||
46 | * JBD2 bit. | ||
47 | */ | ||
48 | enum ocfs2_state_bits { | ||
49 | BH_NeedsValidate = BH_Unshadow + 1, | ||
50 | }; | ||
51 | |||
52 | /* Expand the magic b_state functions */ | ||
53 | BUFFER_FNS(NeedsValidate, needs_validate); | ||
54 | |||
42 | int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, | 55 | int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, |
43 | struct inode *inode) | 56 | struct inode *inode) |
44 | { | 57 | { |
@@ -166,7 +179,9 @@ bail: | |||
166 | } | 179 | } |
167 | 180 | ||
168 | int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, | 181 | int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, |
169 | struct buffer_head *bhs[], int flags) | 182 | struct buffer_head *bhs[], int flags, |
183 | int (*validate)(struct super_block *sb, | ||
184 | struct buffer_head *bh)) | ||
170 | { | 185 | { |
171 | int status = 0; | 186 | int status = 0; |
172 | int i, ignore_cache = 0; | 187 | int i, ignore_cache = 0; |
@@ -298,6 +313,8 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, | |||
298 | 313 | ||
299 | clear_buffer_uptodate(bh); | 314 | clear_buffer_uptodate(bh); |
300 | get_bh(bh); /* for end_buffer_read_sync() */ | 315 | get_bh(bh); /* for end_buffer_read_sync() */ |
316 | if (validate) | ||
317 | set_buffer_needs_validate(bh); | ||
301 | bh->b_end_io = end_buffer_read_sync; | 318 | bh->b_end_io = end_buffer_read_sync; |
302 | submit_bh(READ, bh); | 319 | submit_bh(READ, bh); |
303 | continue; | 320 | continue; |
@@ -328,6 +345,20 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, | |||
328 | bhs[i] = NULL; | 345 | bhs[i] = NULL; |
329 | continue; | 346 | continue; |
330 | } | 347 | } |
348 | |||
349 | if (buffer_needs_validate(bh)) { | ||
350 | /* We never set NeedsValidate if the | ||
351 | * buffer was held by the journal, so | ||
352 | * that better not have changed */ | ||
353 | BUG_ON(buffer_jbd(bh)); | ||
354 | clear_buffer_needs_validate(bh); | ||
355 | status = validate(inode->i_sb, bh); | ||
356 | if (status) { | ||
357 | put_bh(bh); | ||
358 | bhs[i] = NULL; | ||
359 | continue; | ||
360 | } | ||
361 | } | ||
331 | } | 362 | } |
332 | 363 | ||
333 | /* Always set the buffer in the cache, even if it was | 364 | /* Always set the buffer in the cache, even if it was |
diff --git a/fs/ocfs2/buffer_head_io.h b/fs/ocfs2/buffer_head_io.h index 75e1dcb1ade7..c75d682dadd8 100644 --- a/fs/ocfs2/buffer_head_io.h +++ b/fs/ocfs2/buffer_head_io.h | |||
@@ -31,21 +31,24 @@ | |||
31 | void ocfs2_end_buffer_io_sync(struct buffer_head *bh, | 31 | void ocfs2_end_buffer_io_sync(struct buffer_head *bh, |
32 | int uptodate); | 32 | int uptodate); |
33 | 33 | ||
34 | static inline int ocfs2_read_block(struct inode *inode, | ||
35 | u64 off, | ||
36 | struct buffer_head **bh); | ||
37 | |||
38 | int ocfs2_write_block(struct ocfs2_super *osb, | 34 | int ocfs2_write_block(struct ocfs2_super *osb, |
39 | struct buffer_head *bh, | 35 | struct buffer_head *bh, |
40 | struct inode *inode); | 36 | struct inode *inode); |
41 | int ocfs2_read_blocks(struct inode *inode, | ||
42 | u64 block, | ||
43 | int nr, | ||
44 | struct buffer_head *bhs[], | ||
45 | int flags); | ||
46 | int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, | 37 | int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, |
47 | unsigned int nr, struct buffer_head *bhs[]); | 38 | unsigned int nr, struct buffer_head *bhs[]); |
48 | 39 | ||
40 | /* | ||
41 | * If not NULL, validate() will be called on a buffer that is freshly | ||
42 | * read from disk. It will not be called if the buffer was in cache. | ||
43 | * Note that if validate() is being used for this buffer, it needs to | ||
44 | * be set even for a READAHEAD call, as it marks the buffer for later | ||
45 | * validation. | ||
46 | */ | ||
47 | int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, | ||
48 | struct buffer_head *bhs[], int flags, | ||
49 | int (*validate)(struct super_block *sb, | ||
50 | struct buffer_head *bh)); | ||
51 | |||
49 | int ocfs2_write_super_or_backup(struct ocfs2_super *osb, | 52 | int ocfs2_write_super_or_backup(struct ocfs2_super *osb, |
50 | struct buffer_head *bh); | 53 | struct buffer_head *bh); |
51 | 54 | ||
@@ -53,7 +56,9 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, | |||
53 | #define OCFS2_BH_READAHEAD 8 | 56 | #define OCFS2_BH_READAHEAD 8 |
54 | 57 | ||
55 | static inline int ocfs2_read_block(struct inode *inode, u64 off, | 58 | static inline int ocfs2_read_block(struct inode *inode, u64 off, |
56 | struct buffer_head **bh) | 59 | struct buffer_head **bh, |
60 | int (*validate)(struct super_block *sb, | ||
61 | struct buffer_head *bh)) | ||
57 | { | 62 | { |
58 | int status = 0; | 63 | int status = 0; |
59 | 64 | ||
@@ -63,7 +68,7 @@ static inline int ocfs2_read_block(struct inode *inode, u64 off, | |||
63 | goto bail; | 68 | goto bail; |
64 | } | 69 | } |
65 | 70 | ||
66 | status = ocfs2_read_blocks(inode, off, 1, bh, 0); | 71 | status = ocfs2_read_blocks(inode, off, 1, bh, 0, validate); |
67 | 72 | ||
68 | bail: | 73 | bail: |
69 | return status; | 74 | return status; |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index c2f3fd93be5c..7e863d40380d 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -214,6 +214,8 @@ static int ocfs2_validate_dir_block(struct super_block *sb, | |||
214 | * Nothing yet. We don't validate dirents here, that's handled | 214 | * Nothing yet. We don't validate dirents here, that's handled |
215 | * in-place when the code walks them. | 215 | * in-place when the code walks them. |
216 | */ | 216 | */ |
217 | mlog(0, "Validating dirblock %llu\n", | ||
218 | (unsigned long long)bh->b_blocknr); | ||
217 | 219 | ||
218 | return 0; | 220 | return 0; |
219 | } | 221 | } |
@@ -255,20 +257,13 @@ static int ocfs2_read_dir_block(struct inode *inode, u64 v_block, | |||
255 | goto out; | 257 | goto out; |
256 | } | 258 | } |
257 | 259 | ||
258 | rc = ocfs2_read_blocks(inode, p_blkno, 1, &tmp, flags); | 260 | rc = ocfs2_read_blocks(inode, p_blkno, 1, &tmp, flags, |
261 | ocfs2_validate_dir_block); | ||
259 | if (rc) { | 262 | if (rc) { |
260 | mlog_errno(rc); | 263 | mlog_errno(rc); |
261 | goto out; | 264 | goto out; |
262 | } | 265 | } |
263 | 266 | ||
264 | if (!(flags & OCFS2_BH_READAHEAD)) { | ||
265 | rc = ocfs2_validate_dir_block(inode->i_sb, tmp); | ||
266 | if (rc) { | ||
267 | brelse(tmp); | ||
268 | goto out; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | /* If ocfs2_read_blocks() got us a new bh, pass it up. */ | 267 | /* If ocfs2_read_blocks() got us a new bh, pass it up. */ |
273 | if (!*bh) | 268 | if (!*bh) |
274 | *bh = tmp; | 269 | *bh = tmp; |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 9eb701b86466..ec3497bafda6 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -1255,6 +1255,9 @@ int ocfs2_validate_inode_block(struct super_block *sb, | |||
1255 | int rc = -EINVAL; | 1255 | int rc = -EINVAL; |
1256 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | 1256 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; |
1257 | 1257 | ||
1258 | mlog(0, "Validating dinode %llu\n", | ||
1259 | (unsigned long long)bh->b_blocknr); | ||
1260 | |||
1258 | BUG_ON(!buffer_uptodate(bh)); | 1261 | BUG_ON(!buffer_uptodate(bh)); |
1259 | 1262 | ||
1260 | if (!OCFS2_IS_VALID_DINODE(di)) { | 1263 | if (!OCFS2_IS_VALID_DINODE(di)) { |
@@ -1300,23 +1303,12 @@ int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh, | |||
1300 | struct buffer_head *tmp = *bh; | 1303 | struct buffer_head *tmp = *bh; |
1301 | 1304 | ||
1302 | rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp, | 1305 | rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp, |
1303 | flags); | 1306 | flags, ocfs2_validate_inode_block); |
1304 | if (rc) | ||
1305 | goto out; | ||
1306 | |||
1307 | if (!(flags & OCFS2_BH_READAHEAD)) { | ||
1308 | rc = ocfs2_validate_inode_block(inode->i_sb, tmp); | ||
1309 | if (rc) { | ||
1310 | brelse(tmp); | ||
1311 | goto out; | ||
1312 | } | ||
1313 | } | ||
1314 | 1307 | ||
1315 | /* If ocfs2_read_blocks() got us a new bh, pass it up. */ | 1308 | /* If ocfs2_read_blocks() got us a new bh, pass it up. */ |
1316 | if (!*bh) | 1309 | if (!rc && !*bh) |
1317 | *bh = tmp; | 1310 | *bh = tmp; |
1318 | 1311 | ||
1319 | out: | ||
1320 | return rc; | 1312 | return rc; |
1321 | } | 1313 | } |
1322 | 1314 | ||
diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index 252baff5eb84..867de3ebfcaf 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c | |||
@@ -394,7 +394,7 @@ static int ocfs2_check_new_group(struct inode *inode, | |||
394 | (struct ocfs2_group_desc *)group_bh->b_data; | 394 | (struct ocfs2_group_desc *)group_bh->b_data; |
395 | u16 cl_bpc = le16_to_cpu(di->id2.i_chain.cl_bpc); | 395 | u16 cl_bpc = le16_to_cpu(di->id2.i_chain.cl_bpc); |
396 | 396 | ||
397 | ret = ocfs2_validate_group_descriptor(inode->i_sb, di, group_bh, 1); | 397 | ret = ocfs2_check_group_descriptor(inode->i_sb, di, group_bh); |
398 | if (ret) | 398 | if (ret) |
399 | goto out; | 399 | goto out; |
400 | 400 | ||
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index bdda2d8f8508..40661e7824e9 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c | |||
@@ -151,7 +151,7 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb) | |||
151 | * this is not true, the read of -1 (UINT64_MAX) will fail. | 151 | * this is not true, the read of -1 (UINT64_MAX) will fail. |
152 | */ | 152 | */ |
153 | ret = ocfs2_read_blocks(si->si_inode, -1, si->si_blocks, si->si_bh, | 153 | ret = ocfs2_read_blocks(si->si_inode, -1, si->si_blocks, si->si_bh, |
154 | OCFS2_BH_IGNORE_CACHE); | 154 | OCFS2_BH_IGNORE_CACHE, NULL); |
155 | if (ret == 0) { | 155 | if (ret == 0) { |
156 | spin_lock(&osb->osb_lock); | 156 | spin_lock(&osb->osb_lock); |
157 | ocfs2_update_slot_info(si); | 157 | ocfs2_update_slot_info(si); |
@@ -405,7 +405,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, | |||
405 | 405 | ||
406 | bh = NULL; /* Acquire a fresh bh */ | 406 | bh = NULL; /* Acquire a fresh bh */ |
407 | status = ocfs2_read_blocks(si->si_inode, blkno, 1, &bh, | 407 | status = ocfs2_read_blocks(si->si_inode, blkno, 1, &bh, |
408 | OCFS2_BH_IGNORE_CACHE); | 408 | OCFS2_BH_IGNORE_CACHE, NULL); |
409 | if (status < 0) { | 409 | if (status < 0) { |
410 | mlog_errno(status); | 410 | mlog_errno(status); |
411 | goto bail; | 411 | goto bail; |
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; |
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index 43de4fd826d3..e3c13c77f9e8 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h | |||
@@ -165,16 +165,15 @@ void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac); | |||
165 | u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster); | 165 | u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster); |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * By default, ocfs2_validate_group_descriptor() calls ocfs2_error() when it | 168 | * By default, ocfs2_read_group_descriptor() calls ocfs2_error() when it |
169 | * finds a problem. A caller that wants to check a group descriptor | 169 | * finds a problem. A caller that wants to check a group descriptor |
170 | * without going readonly passes a nonzero clean_error. This is only | 170 | * without going readonly should read the block with ocfs2_read_block[s]() |
171 | * resize, really. Everyone else should be using | 171 | * and then checking it with this function. This is only resize, really. |
172 | * ocfs2_read_group_descriptor(). | 172 | * Everyone else should be using ocfs2_read_group_descriptor(). |
173 | */ | 173 | */ |
174 | int ocfs2_validate_group_descriptor(struct super_block *sb, | 174 | int ocfs2_check_group_descriptor(struct super_block *sb, |
175 | struct ocfs2_dinode *di, | 175 | struct ocfs2_dinode *di, |
176 | struct buffer_head *bh, | 176 | struct buffer_head *bh); |
177 | int clean_error); | ||
178 | /* | 177 | /* |
179 | * Read a group descriptor block into *bh. If *bh is NULL, a bh will be | 178 | * Read a group descriptor block into *bh. If *bh is NULL, a bh will be |
180 | * allocated. This is a cached read. The descriptor will be validated with | 179 | * allocated. This is a cached read. The descriptor will be validated with |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index ef4aa5482d01..8af29b3bd6de 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -266,7 +266,8 @@ static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket, | |||
266 | int rc; | 266 | int rc; |
267 | 267 | ||
268 | rc = ocfs2_read_blocks(bucket->bu_inode, xb_blkno, | 268 | rc = ocfs2_read_blocks(bucket->bu_inode, xb_blkno, |
269 | bucket->bu_blocks, bucket->bu_bhs, 0); | 269 | bucket->bu_blocks, bucket->bu_bhs, 0, |
270 | NULL); | ||
270 | if (rc) | 271 | if (rc) |
271 | ocfs2_xattr_bucket_relse(bucket); | 272 | ocfs2_xattr_bucket_relse(bucket); |
272 | return rc; | 273 | return rc; |
@@ -359,12 +360,8 @@ static int ocfs2_read_xattr_block(struct inode *inode, u64 xb_blkno, | |||
359 | int rc; | 360 | int rc; |
360 | struct buffer_head *tmp = *bh; | 361 | struct buffer_head *tmp = *bh; |
361 | 362 | ||
362 | rc = ocfs2_read_block(inode, xb_blkno, &tmp); | 363 | rc = ocfs2_read_block(inode, xb_blkno, &tmp, |
363 | if (!rc) { | 364 | ocfs2_validate_xattr_block); |
364 | rc = ocfs2_validate_xattr_block(inode->i_sb, tmp); | ||
365 | if (rc) | ||
366 | brelse(tmp); | ||
367 | } | ||
368 | 365 | ||
369 | /* If ocfs2_read_block() got us a new bh, pass it up. */ | 366 | /* If ocfs2_read_block() got us a new bh, pass it up. */ |
370 | if (!rc && !*bh) | 367 | if (!rc && !*bh) |
@@ -925,7 +922,7 @@ static int ocfs2_xattr_get_value_outside(struct inode *inode, | |||
925 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); | 922 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); |
926 | /* Copy ocfs2_xattr_value */ | 923 | /* Copy ocfs2_xattr_value */ |
927 | for (i = 0; i < num_clusters * bpc; i++, blkno++) { | 924 | for (i = 0; i < num_clusters * bpc; i++, blkno++) { |
928 | ret = ocfs2_read_block(inode, blkno, &bh); | 925 | ret = ocfs2_read_block(inode, blkno, &bh, NULL); |
929 | if (ret) { | 926 | if (ret) { |
930 | mlog_errno(ret); | 927 | mlog_errno(ret); |
931 | goto out; | 928 | goto out; |
@@ -1174,7 +1171,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1174 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); | 1171 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); |
1175 | 1172 | ||
1176 | for (i = 0; i < num_clusters * bpc; i++, blkno++) { | 1173 | for (i = 0; i < num_clusters * bpc; i++, blkno++) { |
1177 | ret = ocfs2_read_block(inode, blkno, &bh); | 1174 | ret = ocfs2_read_block(inode, blkno, &bh, NULL); |
1178 | if (ret) { | 1175 | if (ret) { |
1179 | mlog_errno(ret); | 1176 | mlog_errno(ret); |
1180 | goto out; | 1177 | goto out; |
@@ -2206,7 +2203,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2206 | base = xis->base; | 2203 | base = xis->base; |
2207 | credits += OCFS2_INODE_UPDATE_CREDITS; | 2204 | credits += OCFS2_INODE_UPDATE_CREDITS; |
2208 | } else { | 2205 | } else { |
2209 | int i, block_off; | 2206 | int i, block_off = 0; |
2210 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; | 2207 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; |
2211 | xe = xbs->here; | 2208 | xe = xbs->here; |
2212 | name_offset = le16_to_cpu(xe->xe_name_offset); | 2209 | name_offset = le16_to_cpu(xe->xe_name_offset); |
@@ -2840,6 +2837,7 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode, | |||
2840 | break; | 2837 | break; |
2841 | } | 2838 | } |
2842 | 2839 | ||
2840 | |||
2843 | xe_name = bucket_block(bucket, block_off) + new_offset; | 2841 | xe_name = bucket_block(bucket, block_off) + new_offset; |
2844 | if (!memcmp(name, xe_name, name_len)) { | 2842 | if (!memcmp(name, xe_name, name_len)) { |
2845 | *xe_index = i; | 2843 | *xe_index = i; |
@@ -3598,7 +3596,7 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode, | |||
3598 | goto out; | 3596 | goto out; |
3599 | } | 3597 | } |
3600 | 3598 | ||
3601 | ret = ocfs2_read_block(inode, prev_blkno, &old_bh); | 3599 | ret = ocfs2_read_block(inode, prev_blkno, &old_bh, NULL); |
3602 | if (ret < 0) { | 3600 | if (ret < 0) { |
3603 | mlog_errno(ret); | 3601 | mlog_errno(ret); |
3604 | brelse(new_bh); | 3602 | brelse(new_bh); |
@@ -3990,7 +3988,7 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode, | |||
3990 | ocfs2_journal_dirty(handle, first_bh); | 3988 | ocfs2_journal_dirty(handle, first_bh); |
3991 | 3989 | ||
3992 | /* update the new bucket header. */ | 3990 | /* update the new bucket header. */ |
3993 | ret = ocfs2_read_block(inode, to_blk_start, &bh); | 3991 | ret = ocfs2_read_block(inode, to_blk_start, &bh, NULL); |
3994 | if (ret < 0) { | 3992 | if (ret < 0) { |
3995 | mlog_errno(ret); | 3993 | mlog_errno(ret); |
3996 | goto out; | 3994 | goto out; |
@@ -4337,7 +4335,7 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4337 | goto out; | 4335 | goto out; |
4338 | } | 4336 | } |
4339 | 4337 | ||
4340 | ret = ocfs2_read_block(inode, p_blkno, &first_bh); | 4338 | ret = ocfs2_read_block(inode, p_blkno, &first_bh, NULL); |
4341 | if (ret) { | 4339 | if (ret) { |
4342 | mlog_errno(ret); | 4340 | mlog_errno(ret); |
4343 | goto out; | 4341 | goto out; |
@@ -4635,7 +4633,7 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4635 | BUG_ON(value_blk != (offset + OCFS2_XATTR_ROOT_SIZE - 1) / blocksize); | 4633 | BUG_ON(value_blk != (offset + OCFS2_XATTR_ROOT_SIZE - 1) / blocksize); |
4636 | value_blk += header_bh->b_blocknr; | 4634 | value_blk += header_bh->b_blocknr; |
4637 | 4635 | ||
4638 | ret = ocfs2_read_block(inode, value_blk, &value_bh); | 4636 | ret = ocfs2_read_block(inode, value_blk, &value_bh, NULL); |
4639 | if (ret) { | 4637 | if (ret) { |
4640 | mlog_errno(ret); | 4638 | mlog_errno(ret); |
4641 | goto out; | 4639 | goto out; |