aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r--fs/xfs/xfs_inode.c100
1 files changed, 51 insertions, 49 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 8d6963010489..514eac913f1c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -382,6 +382,46 @@ xfs_inobp_check(
382} 382}
383#endif 383#endif
384 384
385static void
386xfs_inode_buf_verify(
387 struct xfs_buf *bp)
388{
389 struct xfs_mount *mp = bp->b_target->bt_mount;
390 int i;
391 int ni;
392
393 /*
394 * Validate the magic number and version of every inode in the buffer
395 */
396 ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
397 for (i = 0; i < ni; i++) {
398 int di_ok;
399 xfs_dinode_t *dip;
400
401 dip = (struct xfs_dinode *)xfs_buf_offset(bp,
402 (i << mp->m_sb.sb_inodelog));
403 di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
404 XFS_DINODE_GOOD_VERSION(dip->di_version);
405 if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
406 XFS_ERRTAG_ITOBP_INOTOBP,
407 XFS_RANDOM_ITOBP_INOTOBP))) {
408 xfs_buf_ioerror(bp, EFSCORRUPTED);
409 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
410 mp, dip);
411#ifdef DEBUG
412 xfs_emerg(mp,
413 "bad inode magic/vsn daddr %lld #%d (magic=%x)",
414 (unsigned long long)bp->b_bn, i,
415 be16_to_cpu(dip->di_magic));
416 ASSERT(0);
417#endif
418 }
419 }
420 xfs_inobp_check(mp, bp);
421 bp->b_iodone = NULL;
422 xfs_buf_ioend(bp, 0);
423}
424
385/* 425/*
386 * This routine is called to map an inode to the buffer containing the on-disk 426 * This routine is called to map an inode to the buffer containing the on-disk
387 * version of the inode. It returns a pointer to the buffer containing the 427 * version of the inode. It returns a pointer to the buffer containing the
@@ -396,71 +436,33 @@ xfs_imap_to_bp(
396 struct xfs_mount *mp, 436 struct xfs_mount *mp,
397 struct xfs_trans *tp, 437 struct xfs_trans *tp,
398 struct xfs_imap *imap, 438 struct xfs_imap *imap,
399 struct xfs_dinode **dipp, 439 struct xfs_dinode **dipp,
400 struct xfs_buf **bpp, 440 struct xfs_buf **bpp,
401 uint buf_flags, 441 uint buf_flags,
402 uint iget_flags) 442 uint iget_flags)
403{ 443{
404 struct xfs_buf *bp; 444 struct xfs_buf *bp;
405 int error; 445 int error;
406 int i;
407 int ni;
408 446
409 buf_flags |= XBF_UNMAPPED; 447 buf_flags |= XBF_UNMAPPED;
410 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno, 448 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
411 (int)imap->im_len, buf_flags, &bp, NULL); 449 (int)imap->im_len, buf_flags, &bp,
450 xfs_inode_buf_verify);
412 if (error) { 451 if (error) {
413 if (error != EAGAIN) { 452 if (error == EAGAIN) {
414 xfs_warn(mp,
415 "%s: xfs_trans_read_buf() returned error %d.",
416 __func__, error);
417 } else {
418 ASSERT(buf_flags & XBF_TRYLOCK); 453 ASSERT(buf_flags & XBF_TRYLOCK);
454 return error;
419 } 455 }
420 return error;
421 }
422 456
423 /* 457 if (error == EFSCORRUPTED &&
424 * Validate the magic number and version of every inode in the buffer 458 (iget_flags & XFS_IGET_UNTRUSTED))
425 * (if DEBUG kernel) or the first inode in the buffer, otherwise. 459 return XFS_ERROR(EINVAL);
426 */
427#ifdef DEBUG
428 ni = BBTOB(imap->im_len) >> mp->m_sb.sb_inodelog;
429#else /* usual case */
430 ni = 1;
431#endif
432 460
433 for (i = 0; i < ni; i++) { 461 xfs_warn(mp, "%s: xfs_trans_read_buf() returned error %d.",
434 int di_ok; 462 __func__, error);
435 xfs_dinode_t *dip; 463 return error;
436
437 dip = (xfs_dinode_t *)xfs_buf_offset(bp,
438 (i << mp->m_sb.sb_inodelog));
439 di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
440 XFS_DINODE_GOOD_VERSION(dip->di_version);
441 if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
442 XFS_ERRTAG_ITOBP_INOTOBP,
443 XFS_RANDOM_ITOBP_INOTOBP))) {
444 if (iget_flags & XFS_IGET_UNTRUSTED) {
445 xfs_trans_brelse(tp, bp);
446 return XFS_ERROR(EINVAL);
447 }
448 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
449 mp, dip);
450#ifdef DEBUG
451 xfs_emerg(mp,
452 "bad inode magic/vsn daddr %lld #%d (magic=%x)",
453 (unsigned long long)imap->im_blkno, i,
454 be16_to_cpu(dip->di_magic));
455 ASSERT(0);
456#endif
457 xfs_trans_brelse(tp, bp);
458 return XFS_ERROR(EFSCORRUPTED);
459 }
460 } 464 }
461 465
462 xfs_inobp_check(mp, bp);
463
464 *bpp = bp; 466 *bpp = bp;
465 *dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset); 467 *dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset);
466 return 0; 468 return 0;