diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-11-13 17:49:11 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:52 -0500 |
commit | b657c95c11088d77fc1bfc9c84d940f778bf9d12 (patch) | |
tree | 7e52e73aabbdbc55f644ad26735edc25a652ac32 /fs | |
parent | a68979b857283daf4acc405e476dcc8812a3ff2b (diff) |
ocfs2: Wrap inode block reads in a dedicated function.
The ocfs2 code currently reads inodes off disk with a simple
ocfs2_read_block() call. Each place that does this has a different set
of sanity checks it performs. Some check only the signature. A couple
validate the block number (the block read vs di->i_blkno). A couple
others check for VALID_FL. Only one place validates i_fs_generation. A
couple check nothing. Even when an error is found, they don't all do
the same thing.
We wrap inode reading into ocfs2_read_inode_block(). This will validate
all the above fields, going readonly if they are invalid (they never
should be). ocfs2_read_inode_block_full() is provided for the places
that want to pass read_block flags. Every caller is passing a struct
inode with a valid ip_blkno, so we don't need a separate blkno argument
either.
We will remove the validation checks from the rest of the code in a
later commit, as they are no longer necessary.
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 | 2 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 11 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.c | 12 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 21 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 136 | ||||
-rw-r--r-- | fs/ocfs2/inode.h | 16 | ||||
-rw-r--r-- | fs/ocfs2/journal.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/localalloc.c | 8 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 14 | ||||
-rw-r--r-- | fs/ocfs2/symlink.c | 2 |
12 files changed, 136 insertions, 97 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 5592a2f6335b..9c598adc9475 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -5658,7 +5658,7 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb, | |||
5658 | goto bail; | 5658 | goto bail; |
5659 | } | 5659 | } |
5660 | 5660 | ||
5661 | status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh); | 5661 | status = ocfs2_read_inode_block(inode, &bh); |
5662 | if (status < 0) { | 5662 | if (status < 0) { |
5663 | iput(inode); | 5663 | iput(inode); |
5664 | mlog_errno(status); | 5664 | mlog_errno(status); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c22543b33420..e219f8b546ac 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -68,20 +68,13 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, | |||
68 | goto bail; | 68 | goto bail; |
69 | } | 69 | } |
70 | 70 | ||
71 | status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh); | 71 | status = ocfs2_read_inode_block(inode, &bh); |
72 | if (status < 0) { | 72 | if (status < 0) { |
73 | mlog_errno(status); | 73 | mlog_errno(status); |
74 | goto bail; | 74 | goto bail; |
75 | } | 75 | } |
76 | fe = (struct ocfs2_dinode *) bh->b_data; | 76 | fe = (struct ocfs2_dinode *) bh->b_data; |
77 | 77 | ||
78 | if (!OCFS2_IS_VALID_DINODE(fe)) { | ||
79 | mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n", | ||
80 | (unsigned long long)le64_to_cpu(fe->i_blkno), 7, | ||
81 | fe->i_signature); | ||
82 | goto bail; | ||
83 | } | ||
84 | |||
85 | if ((u64)iblock >= ocfs2_clusters_to_blocks(inode->i_sb, | 78 | if ((u64)iblock >= ocfs2_clusters_to_blocks(inode->i_sb, |
86 | le32_to_cpu(fe->i_clusters))) { | 79 | le32_to_cpu(fe->i_clusters))) { |
87 | mlog(ML_ERROR, "block offset is outside the allocated size: " | 80 | mlog(ML_ERROR, "block offset is outside the allocated size: " |
@@ -262,7 +255,7 @@ static int ocfs2_readpage_inline(struct inode *inode, struct page *page) | |||
262 | BUG_ON(!PageLocked(page)); | 255 | BUG_ON(!PageLocked(page)); |
263 | BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)); | 256 | BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)); |
264 | 257 | ||
265 | ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh); | 258 | ret = ocfs2_read_inode_block(inode, &di_bh); |
266 | if (ret) { | 259 | if (ret) { |
267 | mlog_errno(ret); | 260 | mlog_errno(ret); |
268 | goto out; | 261 | goto out; |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 026e6eb85187..5777045f1a67 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -231,7 +231,7 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name, | |||
231 | struct ocfs2_dinode *di; | 231 | struct ocfs2_dinode *di; |
232 | struct ocfs2_inline_data *data; | 232 | struct ocfs2_inline_data *data; |
233 | 233 | ||
234 | ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh); | 234 | ret = ocfs2_read_inode_block(dir, &di_bh); |
235 | if (ret) { | 235 | if (ret) { |
236 | mlog_errno(ret); | 236 | mlog_errno(ret); |
237 | goto out; | 237 | goto out; |
@@ -458,7 +458,7 @@ static inline int ocfs2_delete_entry_id(handle_t *handle, | |||
458 | struct ocfs2_dinode *di; | 458 | struct ocfs2_dinode *di; |
459 | struct ocfs2_inline_data *data; | 459 | struct ocfs2_inline_data *data; |
460 | 460 | ||
461 | ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh); | 461 | ret = ocfs2_read_inode_block(dir, &di_bh); |
462 | if (ret) { | 462 | if (ret) { |
463 | mlog_errno(ret); | 463 | mlog_errno(ret); |
464 | goto out; | 464 | goto out; |
@@ -636,7 +636,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, | |||
636 | struct ocfs2_inline_data *data; | 636 | struct ocfs2_inline_data *data; |
637 | struct ocfs2_dir_entry *de; | 637 | struct ocfs2_dir_entry *de; |
638 | 638 | ||
639 | ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh); | 639 | ret = ocfs2_read_inode_block(inode, &di_bh); |
640 | if (ret) { | 640 | if (ret) { |
641 | mlog(ML_ERROR, "Unable to read inode block for dir %llu\n", | 641 | mlog(ML_ERROR, "Unable to read inode block for dir %llu\n", |
642 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 642 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 6e6cc0a2e5f7..9f2a7f75d1b3 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -2024,7 +2024,7 @@ static int ocfs2_inode_lock_update(struct inode *inode, | |||
2024 | } else { | 2024 | } else { |
2025 | /* Boo, we have to go to disk. */ | 2025 | /* Boo, we have to go to disk. */ |
2026 | /* read bh, cast, ocfs2_refresh_inode */ | 2026 | /* read bh, cast, ocfs2_refresh_inode */ |
2027 | status = ocfs2_read_block(inode, oi->ip_blkno, bh); | 2027 | status = ocfs2_read_inode_block(inode, bh); |
2028 | if (status < 0) { | 2028 | if (status < 0) { |
2029 | mlog_errno(status); | 2029 | mlog_errno(status); |
2030 | goto bail_refresh; | 2030 | goto bail_refresh; |
@@ -2032,18 +2032,14 @@ static int ocfs2_inode_lock_update(struct inode *inode, | |||
2032 | fe = (struct ocfs2_dinode *) (*bh)->b_data; | 2032 | fe = (struct ocfs2_dinode *) (*bh)->b_data; |
2033 | 2033 | ||
2034 | /* This is a good chance to make sure we're not | 2034 | /* This is a good chance to make sure we're not |
2035 | * locking an invalid object. | 2035 | * locking an invalid object. ocfs2_read_inode_block() |
2036 | * already checked that the inode block is sane. | ||
2036 | * | 2037 | * |
2037 | * We bug on a stale inode here because we checked | 2038 | * We bug on a stale inode here because we checked |
2038 | * above whether it was wiped from disk. The wiping | 2039 | * above whether it was wiped from disk. The wiping |
2039 | * node provides a guarantee that we receive that | 2040 | * node provides a guarantee that we receive that |
2040 | * message and can mark the inode before dropping any | 2041 | * message and can mark the inode before dropping any |
2041 | * locks associated with it. */ | 2042 | * locks associated with it. */ |
2042 | if (!OCFS2_IS_VALID_DINODE(fe)) { | ||
2043 | OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe); | ||
2044 | status = -EIO; | ||
2045 | goto bail_refresh; | ||
2046 | } | ||
2047 | mlog_bug_on_msg(inode->i_generation != | 2043 | mlog_bug_on_msg(inode->i_generation != |
2048 | le32_to_cpu(fe->i_generation), | 2044 | le32_to_cpu(fe->i_generation), |
2049 | "Invalid dinode %llu disk generation: %u " | 2045 | "Invalid dinode %llu disk generation: %u " |
@@ -2085,7 +2081,7 @@ static int ocfs2_assign_bh(struct inode *inode, | |||
2085 | return 0; | 2081 | return 0; |
2086 | } | 2082 | } |
2087 | 2083 | ||
2088 | status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, ret_bh); | 2084 | status = ocfs2_read_inode_block(inode, ret_bh); |
2089 | if (status < 0) | 2085 | if (status < 0) |
2090 | mlog_errno(status); | 2086 | mlog_errno(status); |
2091 | 2087 | ||
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 2baedac58234..b686b31cf49c 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c | |||
@@ -630,7 +630,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | |||
630 | if (ret == 0) | 630 | if (ret == 0) |
631 | goto out; | 631 | goto out; |
632 | 632 | ||
633 | ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh); | 633 | ret = ocfs2_read_inode_block(inode, &di_bh); |
634 | if (ret) { | 634 | if (ret) { |
635 | mlog_errno(ret); | 635 | mlog_errno(ret); |
636 | goto out; | 636 | goto out; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 4636aa6b0117..41001d515fae 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -402,12 +402,9 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
402 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 402 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
403 | (unsigned long long)new_i_size); | 403 | (unsigned long long)new_i_size); |
404 | 404 | ||
405 | /* We trust di_bh because it comes from ocfs2_inode_lock(), which | ||
406 | * already validated it */ | ||
405 | fe = (struct ocfs2_dinode *) di_bh->b_data; | 407 | fe = (struct ocfs2_dinode *) di_bh->b_data; |
406 | if (!OCFS2_IS_VALID_DINODE(fe)) { | ||
407 | OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe); | ||
408 | status = -EIO; | ||
409 | goto bail; | ||
410 | } | ||
411 | 408 | ||
412 | mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode), | 409 | mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode), |
413 | "Inode %llu, inode i_size = %lld != di " | 410 | "Inode %llu, inode i_size = %lld != di " |
@@ -546,18 +543,12 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | |||
546 | */ | 543 | */ |
547 | BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb)); | 544 | BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb)); |
548 | 545 | ||
549 | status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh); | 546 | status = ocfs2_read_inode_block(inode, &bh); |
550 | if (status < 0) { | 547 | if (status < 0) { |
551 | mlog_errno(status); | 548 | mlog_errno(status); |
552 | goto leave; | 549 | goto leave; |
553 | } | 550 | } |
554 | |||
555 | fe = (struct ocfs2_dinode *) bh->b_data; | 551 | fe = (struct ocfs2_dinode *) bh->b_data; |
556 | if (!OCFS2_IS_VALID_DINODE(fe)) { | ||
557 | OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe); | ||
558 | status = -EIO; | ||
559 | goto leave; | ||
560 | } | ||
561 | 552 | ||
562 | restart_all: | 553 | restart_all: |
563 | BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); | 554 | BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); |
@@ -1135,9 +1126,8 @@ static int ocfs2_write_remove_suid(struct inode *inode) | |||
1135 | { | 1126 | { |
1136 | int ret; | 1127 | int ret; |
1137 | struct buffer_head *bh = NULL; | 1128 | struct buffer_head *bh = NULL; |
1138 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
1139 | 1129 | ||
1140 | ret = ocfs2_read_block(inode, oi->ip_blkno, &bh); | 1130 | ret = ocfs2_read_inode_block(inode, &bh); |
1141 | if (ret < 0) { | 1131 | if (ret < 0) { |
1142 | mlog_errno(ret); | 1132 | mlog_errno(ret); |
1143 | goto out; | 1133 | goto out; |
@@ -1163,8 +1153,7 @@ static int ocfs2_allocate_unwritten_extents(struct inode *inode, | |||
1163 | struct buffer_head *di_bh = NULL; | 1153 | struct buffer_head *di_bh = NULL; |
1164 | 1154 | ||
1165 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | 1155 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { |
1166 | ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, | 1156 | ret = ocfs2_read_inode_block(inode, &di_bh); |
1167 | &di_bh); | ||
1168 | if (ret) { | 1157 | if (ret) { |
1169 | mlog_errno(ret); | 1158 | mlog_errno(ret); |
1170 | goto out; | 1159 | goto out; |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 7aa00d511874..9eb701b86466 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -214,12 +214,11 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) | |||
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | 217 | void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, |
218 | int create_ino) | 218 | int create_ino) |
219 | { | 219 | { |
220 | struct super_block *sb; | 220 | struct super_block *sb; |
221 | struct ocfs2_super *osb; | 221 | struct ocfs2_super *osb; |
222 | int status = -EINVAL; | ||
223 | int use_plocks = 1; | 222 | int use_plocks = 1; |
224 | 223 | ||
225 | mlog_entry("(0x%p, size:%llu)\n", inode, | 224 | mlog_entry("(0x%p, size:%llu)\n", inode, |
@@ -232,25 +231,17 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
232 | ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks()) | 231 | ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks()) |
233 | use_plocks = 0; | 232 | use_plocks = 0; |
234 | 233 | ||
235 | /* this means that read_inode cannot create a superblock inode | 234 | /* |
236 | * today. change if needed. */ | 235 | * These have all been checked by ocfs2_read_inode_block() or set |
237 | if (!OCFS2_IS_VALID_DINODE(fe) || | 236 | * by ocfs2_mknod_locked(), so a failure is a code bug. |
238 | !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) { | 237 | */ |
239 | mlog(0, "Invalid dinode: i_ino=%lu, i_blkno=%llu, " | 238 | BUG_ON(!OCFS2_IS_VALID_DINODE(fe)); /* This means that read_inode |
240 | "signature = %.*s, flags = 0x%x\n", | 239 | cannot create a superblock |
241 | inode->i_ino, | 240 | inode today. change if |
242 | (unsigned long long)le64_to_cpu(fe->i_blkno), 7, | 241 | that is needed. */ |
243 | fe->i_signature, le32_to_cpu(fe->i_flags)); | 242 | BUG_ON(!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))); |
244 | goto bail; | 243 | BUG_ON(le32_to_cpu(fe->i_fs_generation) != osb->fs_generation); |
245 | } | ||
246 | 244 | ||
247 | if (le32_to_cpu(fe->i_fs_generation) != osb->fs_generation) { | ||
248 | mlog(ML_ERROR, "file entry generation does not match " | ||
249 | "superblock! osb->fs_generation=%x, " | ||
250 | "fe->i_fs_generation=%x\n", | ||
251 | osb->fs_generation, le32_to_cpu(fe->i_fs_generation)); | ||
252 | goto bail; | ||
253 | } | ||
254 | 245 | ||
255 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 246 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
256 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | 247 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); |
@@ -354,10 +345,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
354 | 345 | ||
355 | ocfs2_set_inode_flags(inode); | 346 | ocfs2_set_inode_flags(inode); |
356 | 347 | ||
357 | status = 0; | 348 | mlog_exit_void(); |
358 | bail: | ||
359 | mlog_exit(status); | ||
360 | return status; | ||
361 | } | 349 | } |
362 | 350 | ||
363 | static int ocfs2_read_locked_inode(struct inode *inode, | 351 | static int ocfs2_read_locked_inode(struct inode *inode, |
@@ -460,11 +448,14 @@ static int ocfs2_read_locked_inode(struct inode *inode, | |||
460 | } | 448 | } |
461 | } | 449 | } |
462 | 450 | ||
463 | if (can_lock) | 451 | if (can_lock) { |
464 | status = ocfs2_read_blocks(inode, args->fi_blkno, 1, &bh, | 452 | status = ocfs2_read_inode_block_full(inode, &bh, |
465 | OCFS2_BH_IGNORE_CACHE); | 453 | OCFS2_BH_IGNORE_CACHE); |
466 | else | 454 | } else { |
467 | status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh); | 455 | status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh); |
456 | if (!status) | ||
457 | status = ocfs2_validate_inode_block(osb->sb, bh); | ||
458 | } | ||
468 | if (status < 0) { | 459 | if (status < 0) { |
469 | mlog_errno(status); | 460 | mlog_errno(status); |
470 | goto bail; | 461 | goto bail; |
@@ -472,12 +463,6 @@ static int ocfs2_read_locked_inode(struct inode *inode, | |||
472 | 463 | ||
473 | status = -EINVAL; | 464 | status = -EINVAL; |
474 | fe = (struct ocfs2_dinode *) bh->b_data; | 465 | fe = (struct ocfs2_dinode *) bh->b_data; |
475 | if (!OCFS2_IS_VALID_DINODE(fe)) { | ||
476 | mlog(0, "Invalid dinode #%llu: signature = %.*s\n", | ||
477 | (unsigned long long)args->fi_blkno, 7, | ||
478 | fe->i_signature); | ||
479 | goto bail; | ||
480 | } | ||
481 | 466 | ||
482 | /* | 467 | /* |
483 | * This is a code bug. Right now the caller needs to | 468 | * This is a code bug. Right now the caller needs to |
@@ -491,10 +476,9 @@ static int ocfs2_read_locked_inode(struct inode *inode, | |||
491 | 476 | ||
492 | if (S_ISCHR(le16_to_cpu(fe->i_mode)) || | 477 | if (S_ISCHR(le16_to_cpu(fe->i_mode)) || |
493 | S_ISBLK(le16_to_cpu(fe->i_mode))) | 478 | S_ISBLK(le16_to_cpu(fe->i_mode))) |
494 | inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); | 479 | inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); |
495 | 480 | ||
496 | if (ocfs2_populate_inode(inode, fe, 0) < 0) | 481 | ocfs2_populate_inode(inode, fe, 0); |
497 | goto bail; | ||
498 | 482 | ||
499 | BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno)); | 483 | BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno)); |
500 | 484 | ||
@@ -1264,3 +1248,79 @@ void ocfs2_refresh_inode(struct inode *inode, | |||
1264 | 1248 | ||
1265 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1249 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
1266 | } | 1250 | } |
1251 | |||
1252 | int ocfs2_validate_inode_block(struct super_block *sb, | ||
1253 | struct buffer_head *bh) | ||
1254 | { | ||
1255 | int rc = -EINVAL; | ||
1256 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | ||
1257 | |||
1258 | BUG_ON(!buffer_uptodate(bh)); | ||
1259 | |||
1260 | if (!OCFS2_IS_VALID_DINODE(di)) { | ||
1261 | ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n", | ||
1262 | (unsigned long long)bh->b_blocknr, 7, | ||
1263 | di->i_signature); | ||
1264 | goto bail; | ||
1265 | } | ||
1266 | |||
1267 | if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) { | ||
1268 | ocfs2_error(sb, "Invalid dinode #%llu: i_blkno is %llu\n", | ||
1269 | (unsigned long long)bh->b_blocknr, | ||
1270 | (unsigned long long)le64_to_cpu(di->i_blkno)); | ||
1271 | goto bail; | ||
1272 | } | ||
1273 | |||
1274 | if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) { | ||
1275 | ocfs2_error(sb, | ||
1276 | "Invalid dinode #%llu: OCFS2_VALID_FL not set\n", | ||
1277 | (unsigned long long)bh->b_blocknr); | ||
1278 | goto bail; | ||
1279 | } | ||
1280 | |||
1281 | if (le32_to_cpu(di->i_fs_generation) != | ||
1282 | OCFS2_SB(sb)->fs_generation) { | ||
1283 | ocfs2_error(sb, | ||
1284 | "Invalid dinode #%llu: fs_generation is %u\n", | ||
1285 | (unsigned long long)bh->b_blocknr, | ||
1286 | le32_to_cpu(di->i_fs_generation)); | ||
1287 | goto bail; | ||
1288 | } | ||
1289 | |||
1290 | rc = 0; | ||
1291 | |||
1292 | bail: | ||
1293 | return rc; | ||
1294 | } | ||
1295 | |||
1296 | int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh, | ||
1297 | int flags) | ||
1298 | { | ||
1299 | int rc; | ||
1300 | struct buffer_head *tmp = *bh; | ||
1301 | |||
1302 | rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp, | ||
1303 | flags); | ||
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 | |||
1315 | /* If ocfs2_read_blocks() got us a new bh, pass it up. */ | ||
1316 | if (!*bh) | ||
1317 | *bh = tmp; | ||
1318 | |||
1319 | out: | ||
1320 | return rc; | ||
1321 | } | ||
1322 | |||
1323 | int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh) | ||
1324 | { | ||
1325 | return ocfs2_read_inode_block_full(inode, bh, 0); | ||
1326 | } | ||
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 2f37af9bcc4a..b79c371a9d27 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
@@ -128,8 +128,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 feoff, unsigned flags, | |||
128 | int sysfile_type); | 128 | int sysfile_type); |
129 | int ocfs2_inode_init_private(struct inode *inode); | 129 | int ocfs2_inode_init_private(struct inode *inode); |
130 | int ocfs2_inode_revalidate(struct dentry *dentry); | 130 | int ocfs2_inode_revalidate(struct dentry *dentry); |
131 | int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | 131 | void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, |
132 | int create_ino); | 132 | int create_ino); |
133 | void ocfs2_read_inode(struct inode *inode); | 133 | void ocfs2_read_inode(struct inode *inode); |
134 | void ocfs2_read_inode2(struct inode *inode, void *opaque); | 134 | void ocfs2_read_inode2(struct inode *inode, void *opaque); |
135 | ssize_t ocfs2_rw_direct(int rw, struct file *filp, char *buf, | 135 | ssize_t ocfs2_rw_direct(int rw, struct file *filp, char *buf, |
@@ -153,4 +153,16 @@ static inline blkcnt_t ocfs2_inode_sector_count(struct inode *inode) | |||
153 | return (blkcnt_t)(OCFS2_I(inode)->ip_clusters << c_to_s_bits); | 153 | return (blkcnt_t)(OCFS2_I(inode)->ip_clusters << c_to_s_bits); |
154 | } | 154 | } |
155 | 155 | ||
156 | /* Validate that a bh contains a valid inode */ | ||
157 | int ocfs2_validate_inode_block(struct super_block *sb, | ||
158 | struct buffer_head *bh); | ||
159 | /* | ||
160 | * Read an inode block into *bh. If *bh is NULL, a bh will be allocated. | ||
161 | * This is a cached read. The inode will be validated with | ||
162 | * ocfs2_validate_inode_block(). | ||
163 | */ | ||
164 | int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh); | ||
165 | /* The same, but can be passed OCFS2_BH_* flags */ | ||
166 | int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh, | ||
167 | int flags); | ||
156 | #endif /* OCFS2_INODE_H */ | 168 | #endif /* OCFS2_INODE_H */ |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 99fe9d584f3c..877aaa05e199 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -1135,8 +1135,7 @@ static int ocfs2_read_journal_inode(struct ocfs2_super *osb, | |||
1135 | } | 1135 | } |
1136 | SET_INODE_JOURNAL(inode); | 1136 | SET_INODE_JOURNAL(inode); |
1137 | 1137 | ||
1138 | status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, bh, | 1138 | status = ocfs2_read_inode_block_full(inode, bh, OCFS2_BH_IGNORE_CACHE); |
1139 | OCFS2_BH_IGNORE_CACHE); | ||
1140 | if (status < 0) { | 1139 | if (status < 0) { |
1141 | mlog_errno(status); | 1140 | mlog_errno(status); |
1142 | goto bail; | 1141 | goto bail; |
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 687b28713c32..19cfb1b9ce09 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -248,8 +248,8 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb) | |||
248 | goto bail; | 248 | goto bail; |
249 | } | 249 | } |
250 | 250 | ||
251 | status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, | 251 | status = ocfs2_read_inode_block_full(inode, &alloc_bh, |
252 | &alloc_bh, OCFS2_BH_IGNORE_CACHE); | 252 | OCFS2_BH_IGNORE_CACHE); |
253 | if (status < 0) { | 253 | if (status < 0) { |
254 | mlog_errno(status); | 254 | mlog_errno(status); |
255 | goto bail; | 255 | goto bail; |
@@ -459,8 +459,8 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, | |||
459 | 459 | ||
460 | mutex_lock(&inode->i_mutex); | 460 | mutex_lock(&inode->i_mutex); |
461 | 461 | ||
462 | status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, | 462 | status = ocfs2_read_inode_block_full(inode, &alloc_bh, |
463 | &alloc_bh, OCFS2_BH_IGNORE_CACHE); | 463 | OCFS2_BH_IGNORE_CACHE); |
464 | if (status < 0) { | 464 | if (status < 0) { |
465 | mlog_errno(status); | 465 | mlog_errno(status); |
466 | goto bail; | 466 | goto bail; |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 765514512096..0134bafdab9e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -531,15 +531,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
531 | goto leave; | 531 | goto leave; |
532 | } | 532 | } |
533 | 533 | ||
534 | if (ocfs2_populate_inode(inode, fe, 1) < 0) { | 534 | ocfs2_populate_inode(inode, fe, 1); |
535 | mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, " | ||
536 | "i_blkno=%llu, i_ino=%lu\n", | ||
537 | (unsigned long long)(*new_fe_bh)->b_blocknr, | ||
538 | (unsigned long long)le64_to_cpu(fe->i_blkno), | ||
539 | inode->i_ino); | ||
540 | BUG(); | ||
541 | } | ||
542 | |||
543 | ocfs2_inode_set_new(osb, inode); | 535 | ocfs2_inode_set_new(osb, inode); |
544 | if (!ocfs2_mount_local(osb)) { | 536 | if (!ocfs2_mount_local(osb)) { |
545 | status = ocfs2_create_new_inode_locks(inode); | 537 | status = ocfs2_create_new_inode_locks(inode); |
@@ -1864,9 +1856,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
1864 | 1856 | ||
1865 | mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); | 1857 | mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); |
1866 | 1858 | ||
1867 | status = ocfs2_read_block(orphan_dir_inode, | 1859 | status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); |
1868 | OCFS2_I(orphan_dir_inode)->ip_blkno, | ||
1869 | &orphan_dir_bh); | ||
1870 | if (status < 0) { | 1860 | if (status < 0) { |
1871 | mlog_errno(status); | 1861 | mlog_errno(status); |
1872 | goto leave; | 1862 | goto leave; |
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index cbd03dfdc7b9..ed0a0cfd68d2 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c | |||
@@ -84,7 +84,7 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode, | |||
84 | 84 | ||
85 | mlog_entry_void(); | 85 | mlog_entry_void(); |
86 | 86 | ||
87 | status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, bh); | 87 | status = ocfs2_read_inode_block(inode, bh); |
88 | if (status < 0) { | 88 | if (status < 0) { |
89 | mlog_errno(status); | 89 | mlog_errno(status); |
90 | link = ERR_PTR(status); | 90 | link = ERR_PTR(status); |