diff options
author | Dave Chinner <dchinner@redhat.com> | 2013-08-12 06:49:35 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-08-12 17:39:05 -0400 |
commit | 1fd7115eda5661e872463694fc4a12821c4f914a (patch) | |
tree | 147f8c4d1f4fac5c7f876e96ae4a4c8d201972f4 /fs/xfs/xfs_inode.c | |
parent | 7bb85ef3608bf740e285b4436776526b7afd4903 (diff) |
xfs: introduce xfs_inode_buf.c for inode buffer operations
The only thing remaining in xfs_inode.[ch] are the operations that
read, write or verify physical inodes in their underlying buffers.
Move all this code to xfs_inode_buf.[ch] and so we can stop sharing
xfs_inode.[ch] with userspace.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 420 |
1 files changed, 0 insertions, 420 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 18308aceebc1..fcda5b39cc17 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -322,236 +322,6 @@ __xfs_iflock( | |||
322 | finish_wait(wq, &wait.wait); | 322 | finish_wait(wq, &wait.wait); |
323 | } | 323 | } |
324 | 324 | ||
325 | /* | ||
326 | * Check that none of the inode's in the buffer have a next | ||
327 | * unlinked field of 0. | ||
328 | */ | ||
329 | #if defined(DEBUG) | ||
330 | void | ||
331 | xfs_inobp_check( | ||
332 | xfs_mount_t *mp, | ||
333 | xfs_buf_t *bp) | ||
334 | { | ||
335 | int i; | ||
336 | int j; | ||
337 | xfs_dinode_t *dip; | ||
338 | |||
339 | j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog; | ||
340 | |||
341 | for (i = 0; i < j; i++) { | ||
342 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, | ||
343 | i * mp->m_sb.sb_inodesize); | ||
344 | if (!dip->di_next_unlinked) { | ||
345 | xfs_alert(mp, | ||
346 | "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.", | ||
347 | bp); | ||
348 | ASSERT(dip->di_next_unlinked); | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | #endif | ||
353 | |||
354 | static void | ||
355 | xfs_inode_buf_verify( | ||
356 | struct xfs_buf *bp) | ||
357 | { | ||
358 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
359 | int i; | ||
360 | int ni; | ||
361 | |||
362 | /* | ||
363 | * Validate the magic number and version of every inode in the buffer | ||
364 | */ | ||
365 | ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock; | ||
366 | for (i = 0; i < ni; i++) { | ||
367 | int di_ok; | ||
368 | xfs_dinode_t *dip; | ||
369 | |||
370 | dip = (struct xfs_dinode *)xfs_buf_offset(bp, | ||
371 | (i << mp->m_sb.sb_inodelog)); | ||
372 | di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) && | ||
373 | XFS_DINODE_GOOD_VERSION(dip->di_version); | ||
374 | if (unlikely(XFS_TEST_ERROR(!di_ok, mp, | ||
375 | XFS_ERRTAG_ITOBP_INOTOBP, | ||
376 | XFS_RANDOM_ITOBP_INOTOBP))) { | ||
377 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
378 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, | ||
379 | mp, dip); | ||
380 | #ifdef DEBUG | ||
381 | xfs_emerg(mp, | ||
382 | "bad inode magic/vsn daddr %lld #%d (magic=%x)", | ||
383 | (unsigned long long)bp->b_bn, i, | ||
384 | be16_to_cpu(dip->di_magic)); | ||
385 | ASSERT(0); | ||
386 | #endif | ||
387 | } | ||
388 | } | ||
389 | xfs_inobp_check(mp, bp); | ||
390 | } | ||
391 | |||
392 | |||
393 | static void | ||
394 | xfs_inode_buf_read_verify( | ||
395 | struct xfs_buf *bp) | ||
396 | { | ||
397 | xfs_inode_buf_verify(bp); | ||
398 | } | ||
399 | |||
400 | static void | ||
401 | xfs_inode_buf_write_verify( | ||
402 | struct xfs_buf *bp) | ||
403 | { | ||
404 | xfs_inode_buf_verify(bp); | ||
405 | } | ||
406 | |||
407 | const struct xfs_buf_ops xfs_inode_buf_ops = { | ||
408 | .verify_read = xfs_inode_buf_read_verify, | ||
409 | .verify_write = xfs_inode_buf_write_verify, | ||
410 | }; | ||
411 | |||
412 | |||
413 | /* | ||
414 | * This routine is called to map an inode to the buffer containing the on-disk | ||
415 | * version of the inode. It returns a pointer to the buffer containing the | ||
416 | * on-disk inode in the bpp parameter, and in the dipp parameter it returns a | ||
417 | * pointer to the on-disk inode within that buffer. | ||
418 | * | ||
419 | * If a non-zero error is returned, then the contents of bpp and dipp are | ||
420 | * undefined. | ||
421 | */ | ||
422 | int | ||
423 | xfs_imap_to_bp( | ||
424 | struct xfs_mount *mp, | ||
425 | struct xfs_trans *tp, | ||
426 | struct xfs_imap *imap, | ||
427 | struct xfs_dinode **dipp, | ||
428 | struct xfs_buf **bpp, | ||
429 | uint buf_flags, | ||
430 | uint iget_flags) | ||
431 | { | ||
432 | struct xfs_buf *bp; | ||
433 | int error; | ||
434 | |||
435 | buf_flags |= XBF_UNMAPPED; | ||
436 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno, | ||
437 | (int)imap->im_len, buf_flags, &bp, | ||
438 | &xfs_inode_buf_ops); | ||
439 | if (error) { | ||
440 | if (error == EAGAIN) { | ||
441 | ASSERT(buf_flags & XBF_TRYLOCK); | ||
442 | return error; | ||
443 | } | ||
444 | |||
445 | if (error == EFSCORRUPTED && | ||
446 | (iget_flags & XFS_IGET_UNTRUSTED)) | ||
447 | return XFS_ERROR(EINVAL); | ||
448 | |||
449 | xfs_warn(mp, "%s: xfs_trans_read_buf() returned error %d.", | ||
450 | __func__, error); | ||
451 | return error; | ||
452 | } | ||
453 | |||
454 | *bpp = bp; | ||
455 | *dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset); | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | STATIC void | ||
460 | xfs_dinode_from_disk( | ||
461 | xfs_icdinode_t *to, | ||
462 | xfs_dinode_t *from) | ||
463 | { | ||
464 | to->di_magic = be16_to_cpu(from->di_magic); | ||
465 | to->di_mode = be16_to_cpu(from->di_mode); | ||
466 | to->di_version = from ->di_version; | ||
467 | to->di_format = from->di_format; | ||
468 | to->di_onlink = be16_to_cpu(from->di_onlink); | ||
469 | to->di_uid = be32_to_cpu(from->di_uid); | ||
470 | to->di_gid = be32_to_cpu(from->di_gid); | ||
471 | to->di_nlink = be32_to_cpu(from->di_nlink); | ||
472 | to->di_projid_lo = be16_to_cpu(from->di_projid_lo); | ||
473 | to->di_projid_hi = be16_to_cpu(from->di_projid_hi); | ||
474 | memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); | ||
475 | to->di_flushiter = be16_to_cpu(from->di_flushiter); | ||
476 | to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec); | ||
477 | to->di_atime.t_nsec = be32_to_cpu(from->di_atime.t_nsec); | ||
478 | to->di_mtime.t_sec = be32_to_cpu(from->di_mtime.t_sec); | ||
479 | to->di_mtime.t_nsec = be32_to_cpu(from->di_mtime.t_nsec); | ||
480 | to->di_ctime.t_sec = be32_to_cpu(from->di_ctime.t_sec); | ||
481 | to->di_ctime.t_nsec = be32_to_cpu(from->di_ctime.t_nsec); | ||
482 | to->di_size = be64_to_cpu(from->di_size); | ||
483 | to->di_nblocks = be64_to_cpu(from->di_nblocks); | ||
484 | to->di_extsize = be32_to_cpu(from->di_extsize); | ||
485 | to->di_nextents = be32_to_cpu(from->di_nextents); | ||
486 | to->di_anextents = be16_to_cpu(from->di_anextents); | ||
487 | to->di_forkoff = from->di_forkoff; | ||
488 | to->di_aformat = from->di_aformat; | ||
489 | to->di_dmevmask = be32_to_cpu(from->di_dmevmask); | ||
490 | to->di_dmstate = be16_to_cpu(from->di_dmstate); | ||
491 | to->di_flags = be16_to_cpu(from->di_flags); | ||
492 | to->di_gen = be32_to_cpu(from->di_gen); | ||
493 | |||
494 | if (to->di_version == 3) { | ||
495 | to->di_changecount = be64_to_cpu(from->di_changecount); | ||
496 | to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); | ||
497 | to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); | ||
498 | to->di_flags2 = be64_to_cpu(from->di_flags2); | ||
499 | to->di_ino = be64_to_cpu(from->di_ino); | ||
500 | to->di_lsn = be64_to_cpu(from->di_lsn); | ||
501 | memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2)); | ||
502 | uuid_copy(&to->di_uuid, &from->di_uuid); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | void | ||
507 | xfs_dinode_to_disk( | ||
508 | xfs_dinode_t *to, | ||
509 | xfs_icdinode_t *from) | ||
510 | { | ||
511 | to->di_magic = cpu_to_be16(from->di_magic); | ||
512 | to->di_mode = cpu_to_be16(from->di_mode); | ||
513 | to->di_version = from ->di_version; | ||
514 | to->di_format = from->di_format; | ||
515 | to->di_onlink = cpu_to_be16(from->di_onlink); | ||
516 | to->di_uid = cpu_to_be32(from->di_uid); | ||
517 | to->di_gid = cpu_to_be32(from->di_gid); | ||
518 | to->di_nlink = cpu_to_be32(from->di_nlink); | ||
519 | to->di_projid_lo = cpu_to_be16(from->di_projid_lo); | ||
520 | to->di_projid_hi = cpu_to_be16(from->di_projid_hi); | ||
521 | memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); | ||
522 | to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec); | ||
523 | to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec); | ||
524 | to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec); | ||
525 | to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec); | ||
526 | to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec); | ||
527 | to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec); | ||
528 | to->di_size = cpu_to_be64(from->di_size); | ||
529 | to->di_nblocks = cpu_to_be64(from->di_nblocks); | ||
530 | to->di_extsize = cpu_to_be32(from->di_extsize); | ||
531 | to->di_nextents = cpu_to_be32(from->di_nextents); | ||
532 | to->di_anextents = cpu_to_be16(from->di_anextents); | ||
533 | to->di_forkoff = from->di_forkoff; | ||
534 | to->di_aformat = from->di_aformat; | ||
535 | to->di_dmevmask = cpu_to_be32(from->di_dmevmask); | ||
536 | to->di_dmstate = cpu_to_be16(from->di_dmstate); | ||
537 | to->di_flags = cpu_to_be16(from->di_flags); | ||
538 | to->di_gen = cpu_to_be32(from->di_gen); | ||
539 | |||
540 | if (from->di_version == 3) { | ||
541 | to->di_changecount = cpu_to_be64(from->di_changecount); | ||
542 | to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); | ||
543 | to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); | ||
544 | to->di_flags2 = cpu_to_be64(from->di_flags2); | ||
545 | to->di_ino = cpu_to_be64(from->di_ino); | ||
546 | to->di_lsn = cpu_to_be64(from->di_lsn); | ||
547 | memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2)); | ||
548 | uuid_copy(&to->di_uuid, &from->di_uuid); | ||
549 | to->di_flushiter = 0; | ||
550 | } else { | ||
551 | to->di_flushiter = cpu_to_be16(from->di_flushiter); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | STATIC uint | 325 | STATIC uint |
556 | _xfs_dic2xflags( | 326 | _xfs_dic2xflags( |
557 | __uint16_t di_flags) | 327 | __uint16_t di_flags) |
@@ -610,196 +380,6 @@ xfs_dic2xflags( | |||
610 | (XFS_DFORK_Q(dip) ? XFS_XFLAG_HASATTR : 0); | 380 | (XFS_DFORK_Q(dip) ? XFS_XFLAG_HASATTR : 0); |
611 | } | 381 | } |
612 | 382 | ||
613 | static bool | ||
614 | xfs_dinode_verify( | ||
615 | struct xfs_mount *mp, | ||
616 | struct xfs_inode *ip, | ||
617 | struct xfs_dinode *dip) | ||
618 | { | ||
619 | if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) | ||
620 | return false; | ||
621 | |||
622 | /* only version 3 or greater inodes are extensively verified here */ | ||
623 | if (dip->di_version < 3) | ||
624 | return true; | ||
625 | |||
626 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
627 | return false; | ||
628 | if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize, | ||
629 | offsetof(struct xfs_dinode, di_crc))) | ||
630 | return false; | ||
631 | if (be64_to_cpu(dip->di_ino) != ip->i_ino) | ||
632 | return false; | ||
633 | if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_uuid)) | ||
634 | return false; | ||
635 | return true; | ||
636 | } | ||
637 | |||
638 | void | ||
639 | xfs_dinode_calc_crc( | ||
640 | struct xfs_mount *mp, | ||
641 | struct xfs_dinode *dip) | ||
642 | { | ||
643 | __uint32_t crc; | ||
644 | |||
645 | if (dip->di_version < 3) | ||
646 | return; | ||
647 | |||
648 | ASSERT(xfs_sb_version_hascrc(&mp->m_sb)); | ||
649 | crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize, | ||
650 | offsetof(struct xfs_dinode, di_crc)); | ||
651 | dip->di_crc = xfs_end_cksum(crc); | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Read the disk inode attributes into the in-core inode structure. | ||
656 | * | ||
657 | * For version 5 superblocks, if we are initialising a new inode and we are not | ||
658 | * utilising the XFS_MOUNT_IKEEP inode cluster mode, we can simple build the new | ||
659 | * inode core with a random generation number. If we are keeping inodes around, | ||
660 | * we need to read the inode cluster to get the existing generation number off | ||
661 | * disk. Further, if we are using version 4 superblocks (i.e. v1/v2 inode | ||
662 | * format) then log recovery is dependent on the di_flushiter field being | ||
663 | * initialised from the current on-disk value and hence we must also read the | ||
664 | * inode off disk. | ||
665 | */ | ||
666 | int | ||
667 | xfs_iread( | ||
668 | xfs_mount_t *mp, | ||
669 | xfs_trans_t *tp, | ||
670 | xfs_inode_t *ip, | ||
671 | uint iget_flags) | ||
672 | { | ||
673 | xfs_buf_t *bp; | ||
674 | xfs_dinode_t *dip; | ||
675 | int error; | ||
676 | |||
677 | /* | ||
678 | * Fill in the location information in the in-core inode. | ||
679 | */ | ||
680 | error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags); | ||
681 | if (error) | ||
682 | return error; | ||
683 | |||
684 | /* shortcut IO on inode allocation if possible */ | ||
685 | if ((iget_flags & XFS_IGET_CREATE) && | ||
686 | xfs_sb_version_hascrc(&mp->m_sb) && | ||
687 | !(mp->m_flags & XFS_MOUNT_IKEEP)) { | ||
688 | /* initialise the on-disk inode core */ | ||
689 | memset(&ip->i_d, 0, sizeof(ip->i_d)); | ||
690 | ip->i_d.di_magic = XFS_DINODE_MAGIC; | ||
691 | ip->i_d.di_gen = prandom_u32(); | ||
692 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
693 | ip->i_d.di_version = 3; | ||
694 | ip->i_d.di_ino = ip->i_ino; | ||
695 | uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid); | ||
696 | } else | ||
697 | ip->i_d.di_version = 2; | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | /* | ||
702 | * Get pointers to the on-disk inode and the buffer containing it. | ||
703 | */ | ||
704 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &bp, 0, iget_flags); | ||
705 | if (error) | ||
706 | return error; | ||
707 | |||
708 | /* even unallocated inodes are verified */ | ||
709 | if (!xfs_dinode_verify(mp, ip, dip)) { | ||
710 | xfs_alert(mp, "%s: validation failed for inode %lld failed", | ||
711 | __func__, ip->i_ino); | ||
712 | |||
713 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, dip); | ||
714 | error = XFS_ERROR(EFSCORRUPTED); | ||
715 | goto out_brelse; | ||
716 | } | ||
717 | |||
718 | /* | ||
719 | * If the on-disk inode is already linked to a directory | ||
720 | * entry, copy all of the inode into the in-core inode. | ||
721 | * xfs_iformat_fork() handles copying in the inode format | ||
722 | * specific information. | ||
723 | * Otherwise, just get the truly permanent information. | ||
724 | */ | ||
725 | if (dip->di_mode) { | ||
726 | xfs_dinode_from_disk(&ip->i_d, dip); | ||
727 | error = xfs_iformat_fork(ip, dip); | ||
728 | if (error) { | ||
729 | #ifdef DEBUG | ||
730 | xfs_alert(mp, "%s: xfs_iformat() returned error %d", | ||
731 | __func__, error); | ||
732 | #endif /* DEBUG */ | ||
733 | goto out_brelse; | ||
734 | } | ||
735 | } else { | ||
736 | /* | ||
737 | * Partial initialisation of the in-core inode. Just the bits | ||
738 | * that xfs_ialloc won't overwrite or relies on being correct. | ||
739 | */ | ||
740 | ip->i_d.di_magic = be16_to_cpu(dip->di_magic); | ||
741 | ip->i_d.di_version = dip->di_version; | ||
742 | ip->i_d.di_gen = be32_to_cpu(dip->di_gen); | ||
743 | ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter); | ||
744 | |||
745 | if (dip->di_version == 3) { | ||
746 | ip->i_d.di_ino = be64_to_cpu(dip->di_ino); | ||
747 | uuid_copy(&ip->i_d.di_uuid, &dip->di_uuid); | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * Make sure to pull in the mode here as well in | ||
752 | * case the inode is released without being used. | ||
753 | * This ensures that xfs_inactive() will see that | ||
754 | * the inode is already free and not try to mess | ||
755 | * with the uninitialized part of it. | ||
756 | */ | ||
757 | ip->i_d.di_mode = 0; | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * The inode format changed when we moved the link count and | ||
762 | * made it 32 bits long. If this is an old format inode, | ||
763 | * convert it in memory to look like a new one. If it gets | ||
764 | * flushed to disk we will convert back before flushing or | ||
765 | * logging it. We zero out the new projid field and the old link | ||
766 | * count field. We'll handle clearing the pad field (the remains | ||
767 | * of the old uuid field) when we actually convert the inode to | ||
768 | * the new format. We don't change the version number so that we | ||
769 | * can distinguish this from a real new format inode. | ||
770 | */ | ||
771 | if (ip->i_d.di_version == 1) { | ||
772 | ip->i_d.di_nlink = ip->i_d.di_onlink; | ||
773 | ip->i_d.di_onlink = 0; | ||
774 | xfs_set_projid(ip, 0); | ||
775 | } | ||
776 | |||
777 | ip->i_delayed_blks = 0; | ||
778 | |||
779 | /* | ||
780 | * Mark the buffer containing the inode as something to keep | ||
781 | * around for a while. This helps to keep recently accessed | ||
782 | * meta-data in-core longer. | ||
783 | */ | ||
784 | xfs_buf_set_ref(bp, XFS_INO_REF); | ||
785 | |||
786 | /* | ||
787 | * Use xfs_trans_brelse() to release the buffer containing the on-disk | ||
788 | * inode, because it was acquired with xfs_trans_read_buf() in | ||
789 | * xfs_imap_to_bp() above. If tp is NULL, this is just a normal | ||
790 | * brelse(). If we're within a transaction, then xfs_trans_brelse() | ||
791 | * will only release the buffer if it is not dirty within the | ||
792 | * transaction. It will be OK to release the buffer in this case, | ||
793 | * because inodes on disk are never destroyed and we will be locking the | ||
794 | * new in-core inode before putting it in the cache where other | ||
795 | * processes can find it. Thus we don't have to worry about the inode | ||
796 | * being changed just because we released the buffer. | ||
797 | */ | ||
798 | out_brelse: | ||
799 | xfs_trans_brelse(tp, bp); | ||
800 | return error; | ||
801 | } | ||
802 | |||
803 | /* | 383 | /* |
804 | * Allocate an inode on disk and return a copy of its in-core version. | 384 | * Allocate an inode on disk and return a copy of its in-core version. |
805 | * The in-core inode is locked exclusively. Set mode, nlink, and rdev | 385 | * The in-core inode is locked exclusively. Set mode, nlink, and rdev |