diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-11-13 17:49:16 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:53 -0500 |
commit | 5e96581a377fc6bd76e9b112da9aeb8a7ae8bf22 (patch) | |
tree | ce2e1d8819b6020567828ca9021438c0824aa8d4 /fs/ocfs2/alloc.c | |
parent | 4203530613280281868b3ca36c817530bca3825c (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>
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r-- | fs/ocfs2/alloc.c | 151 |
1 files changed, 98 insertions, 53 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 | ||
681 | static 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 | |||
716 | int 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 | |||
736 | out: | ||
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; |