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/ocfs2/inode.c | |
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/ocfs2/inode.c')
-rw-r--r-- | fs/ocfs2/inode.c | 136 |
1 files changed, 98 insertions, 38 deletions
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 | } | ||