aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-11-13 17:49:16 -0500
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:36:53 -0500
commit5e96581a377fc6bd76e9b112da9aeb8a7ae8bf22 (patch)
treece2e1d8819b6020567828ca9021438c0824aa8d4
parent4203530613280281868b3ca36c817530bca3825c (diff)
ocfs2: Wrap extent block reads in a dedicated function.
We weren't consistently checking extent blocks after we read them. Most places checked the signature, but none checked h_blkno or h_fs_signature. Create a toplevel ocfs2_read_extent_block() that does the read and the validation. Signed-off-by: Joel Becker <joel.becker@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r--fs/ocfs2/alloc.c151
-rw-r--r--fs/ocfs2/alloc.h8
-rw-r--r--fs/ocfs2/extent_map.c23
-rw-r--r--fs/ocfs2/ocfs2.h8
4 files changed, 111 insertions, 79 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 320545b9fe12..f430cc6e0f35 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -678,6 +678,66 @@ struct ocfs2_merge_ctxt {
678 int c_split_covers_rec; 678 int c_split_covers_rec;
679}; 679};
680 680
681static int ocfs2_validate_extent_block(struct super_block *sb,
682 struct buffer_head *bh)
683{
684 struct ocfs2_extent_block *eb =
685 (struct ocfs2_extent_block *)bh->b_data;
686
687 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
688 ocfs2_error(sb,
689 "Extent block #%llu has bad signature %.*s",
690 (unsigned long long)bh->b_blocknr, 7,
691 eb->h_signature);
692 return -EINVAL;
693 }
694
695 if (le64_to_cpu(eb->h_blkno) != bh->b_blocknr) {
696 ocfs2_error(sb,
697 "Extent block #%llu has an invalid h_blkno "
698 "of %llu",
699 (unsigned long long)bh->b_blocknr,
700 (unsigned long long)le64_to_cpu(eb->h_blkno));
701 return -EINVAL;
702 }
703
704 if (le32_to_cpu(eb->h_fs_generation) != OCFS2_SB(sb)->fs_generation) {
705 ocfs2_error(sb,
706 "Extent block #%llu has an invalid "
707 "h_fs_generation of #%u",
708 (unsigned long long)bh->b_blocknr,
709 le32_to_cpu(eb->h_fs_generation));
710 return -EINVAL;
711 }
712
713 return 0;
714}
715
716int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
717 struct buffer_head **bh)
718{
719 int rc;
720 struct buffer_head *tmp = *bh;
721
722 rc = ocfs2_read_block(inode, eb_blkno, &tmp);
723 if (rc)
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
732 /* If ocfs2_read_block() got us a new bh, pass it up. */
733 if (!*bh)
734 *bh = tmp;
735
736out:
737 return rc;
738}
739
740
681/* 741/*
682 * How many free extents have we got before we need more meta data? 742 * How many free extents have we got before we need more meta data?
683 */ 743 */
@@ -697,8 +757,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
697 last_eb_blk = ocfs2_et_get_last_eb_blk(et); 757 last_eb_blk = ocfs2_et_get_last_eb_blk(et);
698 758
699 if (last_eb_blk) { 759 if (last_eb_blk) {
700 retval = ocfs2_read_block(inode, last_eb_blk, 760 retval = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
701 &eb_bh);
702 if (retval < 0) { 761 if (retval < 0) {
703 mlog_errno(retval); 762 mlog_errno(retval);
704 goto bail; 763 goto bail;
@@ -900,11 +959,8 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
900 for(i = 0; i < new_blocks; i++) { 959 for(i = 0; i < new_blocks; i++) {
901 bh = new_eb_bhs[i]; 960 bh = new_eb_bhs[i];
902 eb = (struct ocfs2_extent_block *) bh->b_data; 961 eb = (struct ocfs2_extent_block *) bh->b_data;
903 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { 962 /* ocfs2_create_new_meta_bhs() should create it right! */
904 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb); 963 BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
905 status = -EIO;
906 goto bail;
907 }
908 eb_el = &eb->h_list; 964 eb_el = &eb->h_list;
909 965
910 status = ocfs2_journal_access(handle, inode, bh, 966 status = ocfs2_journal_access(handle, inode, bh,
@@ -1044,11 +1100,8 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
1044 } 1100 }
1045 1101
1046 eb = (struct ocfs2_extent_block *) new_eb_bh->b_data; 1102 eb = (struct ocfs2_extent_block *) new_eb_bh->b_data;
1047 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { 1103 /* ocfs2_create_new_meta_bhs() should create it right! */
1048 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb); 1104 BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
1049 status = -EIO;
1050 goto bail;
1051 }
1052 1105
1053 eb_el = &eb->h_list; 1106 eb_el = &eb->h_list;
1054 root_el = et->et_root_el; 1107 root_el = et->et_root_el;
@@ -1168,18 +1221,13 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
1168 brelse(bh); 1221 brelse(bh);
1169 bh = NULL; 1222 bh = NULL;
1170 1223
1171 status = ocfs2_read_block(inode, blkno, &bh); 1224 status = ocfs2_read_extent_block(inode, blkno, &bh);
1172 if (status < 0) { 1225 if (status < 0) {
1173 mlog_errno(status); 1226 mlog_errno(status);
1174 goto bail; 1227 goto bail;
1175 } 1228 }
1176 1229
1177 eb = (struct ocfs2_extent_block *) bh->b_data; 1230 eb = (struct ocfs2_extent_block *) bh->b_data;
1178 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
1179 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
1180 status = -EIO;
1181 goto bail;
1182 }
1183 el = &eb->h_list; 1231 el = &eb->h_list;
1184 1232
1185 if (le16_to_cpu(el->l_next_free_rec) < 1233 if (le16_to_cpu(el->l_next_free_rec) <
@@ -1532,7 +1580,7 @@ static int __ocfs2_find_path(struct inode *inode,
1532 1580
1533 brelse(bh); 1581 brelse(bh);
1534 bh = NULL; 1582 bh = NULL;
1535 ret = ocfs2_read_block(inode, blkno, &bh); 1583 ret = ocfs2_read_extent_block(inode, blkno, &bh);
1536 if (ret) { 1584 if (ret) {
1537 mlog_errno(ret); 1585 mlog_errno(ret);
1538 goto out; 1586 goto out;
@@ -1540,11 +1588,6 @@ static int __ocfs2_find_path(struct inode *inode,
1540 1588
1541 eb = (struct ocfs2_extent_block *) bh->b_data; 1589 eb = (struct ocfs2_extent_block *) bh->b_data;
1542 el = &eb->h_list; 1590 el = &eb->h_list;
1543 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
1544 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
1545 ret = -EIO;
1546 goto out;
1547 }
1548 1591
1549 if (le16_to_cpu(el->l_next_free_rec) > 1592 if (le16_to_cpu(el->l_next_free_rec) >
1550 le16_to_cpu(el->l_count)) { 1593 le16_to_cpu(el->l_count)) {
@@ -4089,8 +4132,15 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
4089 le16_to_cpu(new_el->l_count)) { 4132 le16_to_cpu(new_el->l_count)) {
4090 bh = path_leaf_bh(left_path); 4133 bh = path_leaf_bh(left_path);
4091 eb = (struct ocfs2_extent_block *)bh->b_data; 4134 eb = (struct ocfs2_extent_block *)bh->b_data;
4092 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, 4135 ocfs2_error(inode->i_sb,
4093 eb); 4136 "Extent block #%llu has an "
4137 "invalid l_next_free_rec of "
4138 "%d. It should have "
4139 "matched the l_count of %d",
4140 (unsigned long long)le64_to_cpu(eb->h_blkno),
4141 le16_to_cpu(new_el->l_next_free_rec),
4142 le16_to_cpu(new_el->l_count));
4143 status = -EINVAL;
4094 goto out; 4144 goto out;
4095 } 4145 }
4096 rec = &new_el->l_recs[ 4146 rec = &new_el->l_recs[
@@ -4139,8 +4189,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
4139 if (le16_to_cpu(new_el->l_next_free_rec) <= 1) { 4189 if (le16_to_cpu(new_el->l_next_free_rec) <= 1) {
4140 bh = path_leaf_bh(right_path); 4190 bh = path_leaf_bh(right_path);
4141 eb = (struct ocfs2_extent_block *)bh->b_data; 4191 eb = (struct ocfs2_extent_block *)bh->b_data;
4142 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, 4192 ocfs2_error(inode->i_sb,
4143 eb); 4193 "Extent block #%llu has an "
4194 "invalid l_next_free_rec of %d",
4195 (unsigned long long)le64_to_cpu(eb->h_blkno),
4196 le16_to_cpu(new_el->l_next_free_rec));
4197 status = -EINVAL;
4144 goto out; 4198 goto out;
4145 } 4199 }
4146 rec = &new_el->l_recs[1]; 4200 rec = &new_el->l_recs[1];
@@ -4286,7 +4340,9 @@ static int ocfs2_figure_insert_type(struct inode *inode,
4286 * ocfs2_figure_insert_type() and ocfs2_add_branch() 4340 * ocfs2_figure_insert_type() and ocfs2_add_branch()
4287 * may want it later. 4341 * may want it later.
4288 */ 4342 */
4289 ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et), &bh); 4343 ret = ocfs2_read_extent_block(inode,
4344 ocfs2_et_get_last_eb_blk(et),
4345 &bh);
4290 if (ret) { 4346 if (ret) {
4291 mlog_exit(ret); 4347 mlog_exit(ret);
4292 goto out; 4348 goto out;
@@ -4752,20 +4808,15 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
4752 if (path->p_tree_depth) { 4808 if (path->p_tree_depth) {
4753 struct ocfs2_extent_block *eb; 4809 struct ocfs2_extent_block *eb;
4754 4810
4755 ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et), 4811 ret = ocfs2_read_extent_block(inode,
4756 &last_eb_bh); 4812 ocfs2_et_get_last_eb_blk(et),
4813 &last_eb_bh);
4757 if (ret) { 4814 if (ret) {
4758 mlog_exit(ret); 4815 mlog_exit(ret);
4759 goto out; 4816 goto out;
4760 } 4817 }
4761 4818
4762 eb = (struct ocfs2_extent_block *) last_eb_bh->b_data; 4819 eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
4763 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
4764 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
4765 ret = -EROFS;
4766 goto out;
4767 }
4768
4769 rightmost_el = &eb->h_list; 4820 rightmost_el = &eb->h_list;
4770 } else 4821 } else
4771 rightmost_el = path_root_el(path); 4822 rightmost_el = path_root_el(path);
@@ -4910,8 +4961,9 @@ static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
4910 4961
4911 depth = path->p_tree_depth; 4962 depth = path->p_tree_depth;
4912 if (depth > 0) { 4963 if (depth > 0) {
4913 ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et), 4964 ret = ocfs2_read_extent_block(inode,
4914 &last_eb_bh); 4965 ocfs2_et_get_last_eb_blk(et),
4966 &last_eb_bh);
4915 if (ret < 0) { 4967 if (ret < 0) {
4916 mlog_errno(ret); 4968 mlog_errno(ret);
4917 goto out; 4969 goto out;
@@ -6231,11 +6283,10 @@ static int ocfs2_find_new_last_ext_blk(struct inode *inode,
6231 6283
6232 eb = (struct ocfs2_extent_block *) bh->b_data; 6284 eb = (struct ocfs2_extent_block *) bh->b_data;
6233 el = &eb->h_list; 6285 el = &eb->h_list;
6234 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) { 6286
6235 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb); 6287 /* ocfs2_find_leaf() gets the eb from ocfs2_read_extent_block().
6236 ret = -EROFS; 6288 * Any corruption is a code bug. */
6237 goto out; 6289 BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
6238 }
6239 6290
6240 *new_last_eb = bh; 6291 *new_last_eb = bh;
6241 get_bh(*new_last_eb); 6292 get_bh(*new_last_eb);
@@ -7140,20 +7191,14 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
7140 ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc); 7191 ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
7141 7192
7142 if (fe->id2.i_list.l_tree_depth) { 7193 if (fe->id2.i_list.l_tree_depth) {
7143 status = ocfs2_read_block(inode, le64_to_cpu(fe->i_last_eb_blk), 7194 status = ocfs2_read_extent_block(inode,
7144 &last_eb_bh); 7195 le64_to_cpu(fe->i_last_eb_blk),
7196 &last_eb_bh);
7145 if (status < 0) { 7197 if (status < 0) {
7146 mlog_errno(status); 7198 mlog_errno(status);
7147 goto bail; 7199 goto bail;
7148 } 7200 }
7149 eb = (struct ocfs2_extent_block *) last_eb_bh->b_data; 7201 eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
7150 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
7151 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
7152
7153 brelse(last_eb_bh);
7154 status = -EIO;
7155 goto bail;
7156 }
7157 } 7202 }
7158 7203
7159 (*tc)->tc_last_eb_bh = last_eb_bh; 7204 (*tc)->tc_last_eb_bh = last_eb_bh;
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index 0fbf8fc55a49..59d37d1b7d4c 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -73,6 +73,14 @@ void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
73 struct buffer_head *bh, 73 struct buffer_head *bh,
74 struct ocfs2_xattr_value_root *xv); 74 struct ocfs2_xattr_value_root *xv);
75 75
76/*
77 * Read an extent block into *bh. If *bh is NULL, a bh will be
78 * allocated. This is a cached read. The extent block will be validated
79 * with ocfs2_validate_extent_block().
80 */
81int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
82 struct buffer_head **bh);
83
76struct ocfs2_alloc_context; 84struct ocfs2_alloc_context;
77int ocfs2_insert_extent(struct ocfs2_super *osb, 85int ocfs2_insert_extent(struct ocfs2_super *osb,
78 handle_t *handle, 86 handle_t *handle,
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index b686b31cf49c..0bd9d9698a24 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -293,7 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
293 struct ocfs2_extent_block *eb; 293 struct ocfs2_extent_block *eb;
294 struct ocfs2_extent_list *el; 294 struct ocfs2_extent_list *el;
295 295
296 ret = ocfs2_read_block(inode, last_eb_blk, &eb_bh); 296 ret = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
297 if (ret) { 297 if (ret) {
298 mlog_errno(ret); 298 mlog_errno(ret);
299 goto out; 299 goto out;
@@ -302,12 +302,6 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
302 eb = (struct ocfs2_extent_block *) eb_bh->b_data; 302 eb = (struct ocfs2_extent_block *) eb_bh->b_data;
303 el = &eb->h_list; 303 el = &eb->h_list;
304 304
305 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
306 ret = -EROFS;
307 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
308 goto out;
309 }
310
311 if (el->l_tree_depth) { 305 if (el->l_tree_depth) {
312 ocfs2_error(inode->i_sb, 306 ocfs2_error(inode->i_sb,
313 "Inode %lu has non zero tree depth in " 307 "Inode %lu has non zero tree depth in "
@@ -381,23 +375,16 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
381 if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL) 375 if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
382 goto no_more_extents; 376 goto no_more_extents;
383 377
384 ret = ocfs2_read_block(inode, 378 ret = ocfs2_read_extent_block(inode,
385 le64_to_cpu(eb->h_next_leaf_blk), 379 le64_to_cpu(eb->h_next_leaf_blk),
386 &next_eb_bh); 380 &next_eb_bh);
387 if (ret) { 381 if (ret) {
388 mlog_errno(ret); 382 mlog_errno(ret);
389 goto out; 383 goto out;
390 } 384 }
391 next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data;
392
393 if (!OCFS2_IS_VALID_EXTENT_BLOCK(next_eb)) {
394 ret = -EROFS;
395 OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, next_eb);
396 goto out;
397 }
398 385
386 next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data;
399 el = &next_eb->h_list; 387 el = &next_eb->h_list;
400
401 i = ocfs2_search_for_hole_index(el, v_cluster); 388 i = ocfs2_search_for_hole_index(el, v_cluster);
402 } 389 }
403 390
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 82ba887afa0d..f04b229fc757 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -447,14 +447,6 @@ static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
447#define OCFS2_IS_VALID_EXTENT_BLOCK(ptr) \ 447#define OCFS2_IS_VALID_EXTENT_BLOCK(ptr) \
448 (!strcmp((ptr)->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE)) 448 (!strcmp((ptr)->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE))
449 449
450#define OCFS2_RO_ON_INVALID_EXTENT_BLOCK(__sb, __eb) do { \
451 typeof(__eb) ____eb = (__eb); \
452 ocfs2_error((__sb), \
453 "Extent Block # %llu has bad signature %.*s", \
454 (unsigned long long)le64_to_cpu((____eb)->h_blkno), 7, \
455 (____eb)->h_signature); \
456} while (0)
457
458#define OCFS2_IS_VALID_GROUP_DESC(ptr) \ 450#define OCFS2_IS_VALID_GROUP_DESC(ptr) \
459 (!strcmp((ptr)->bg_signature, OCFS2_GROUP_DESC_SIGNATURE)) 451 (!strcmp((ptr)->bg_signature, OCFS2_GROUP_DESC_SIGNATURE))
460 452