diff options
author | Theodore Ts'o <tytso@mit.edu> | 2012-02-06 20:12:03 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-02-06 20:12:03 -0500 |
commit | 119c0d4460b001e44b41dcf73dc6ee794b98bd31 (patch) | |
tree | 55a278470454bf3a066eec7f807222782cc9b77d /fs | |
parent | 62aa2b537c6f5957afd98e29f96897419ed5ebab (diff) |
ext4: fold ext4_claim_inode into ext4_new_inode
The function ext4_claim_inode() is only called by one function,
ext4_new_inode(), and by folding the functionality into
ext4_new_inode(), we can remove almost 50 lines of code, and put all
of the logic of allocating a new inode into a single place.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ialloc.c | 209 |
1 files changed, 76 insertions, 133 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 25d8c9781ad9..84e6e9a3986b 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -593,94 +593,6 @@ static int find_group_other(struct super_block *sb, struct inode *parent, | |||
593 | } | 593 | } |
594 | 594 | ||
595 | /* | 595 | /* |
596 | * claim the inode from the inode bitmap. If the group | ||
597 | * is uninit we need to take the groups's ext4_group_lock | ||
598 | * and clear the uninit flag. The inode bitmap update | ||
599 | * and group desc uninit flag clear should be done | ||
600 | * after holding ext4_group_lock so that ext4_read_inode_bitmap | ||
601 | * doesn't race with the ext4_claim_inode | ||
602 | */ | ||
603 | static int ext4_claim_inode(struct super_block *sb, | ||
604 | struct buffer_head *inode_bitmap_bh, | ||
605 | unsigned long ino, ext4_group_t group, umode_t mode) | ||
606 | { | ||
607 | int free = 0, retval = 0, count; | ||
608 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
609 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | ||
610 | struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL); | ||
611 | |||
612 | /* | ||
613 | * We have to be sure that new inode allocation does not race with | ||
614 | * inode table initialization, because otherwise we may end up | ||
615 | * allocating and writing new inode right before sb_issue_zeroout | ||
616 | * takes place and overwriting our new inode with zeroes. So we | ||
617 | * take alloc_sem to prevent it. | ||
618 | */ | ||
619 | down_read(&grp->alloc_sem); | ||
620 | ext4_lock_group(sb, group); | ||
621 | if (ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data)) { | ||
622 | /* not a free inode */ | ||
623 | retval = 1; | ||
624 | goto err_ret; | ||
625 | } | ||
626 | ino++; | ||
627 | if ((group == 0 && ino < EXT4_FIRST_INO(sb)) || | ||
628 | ino > EXT4_INODES_PER_GROUP(sb)) { | ||
629 | ext4_unlock_group(sb, group); | ||
630 | up_read(&grp->alloc_sem); | ||
631 | ext4_error(sb, "reserved inode or inode > inodes count - " | ||
632 | "block_group = %u, inode=%lu", group, | ||
633 | ino + group * EXT4_INODES_PER_GROUP(sb)); | ||
634 | return 1; | ||
635 | } | ||
636 | /* If we didn't allocate from within the initialized part of the inode | ||
637 | * table then we need to initialize up to this inode. */ | ||
638 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { | ||
639 | |||
640 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { | ||
641 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); | ||
642 | /* When marking the block group with | ||
643 | * ~EXT4_BG_INODE_UNINIT we don't want to depend | ||
644 | * on the value of bg_itable_unused even though | ||
645 | * mke2fs could have initialized the same for us. | ||
646 | * Instead we calculated the value below | ||
647 | */ | ||
648 | |||
649 | free = 0; | ||
650 | } else { | ||
651 | free = EXT4_INODES_PER_GROUP(sb) - | ||
652 | ext4_itable_unused_count(sb, gdp); | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * Check the relative inode number against the last used | ||
657 | * relative inode number in this group. if it is greater | ||
658 | * we need to update the bg_itable_unused count | ||
659 | * | ||
660 | */ | ||
661 | if (ino > free) | ||
662 | ext4_itable_unused_set(sb, gdp, | ||
663 | (EXT4_INODES_PER_GROUP(sb) - ino)); | ||
664 | } | ||
665 | count = ext4_free_inodes_count(sb, gdp) - 1; | ||
666 | ext4_free_inodes_set(sb, gdp, count); | ||
667 | if (S_ISDIR(mode)) { | ||
668 | count = ext4_used_dirs_count(sb, gdp) + 1; | ||
669 | ext4_used_dirs_set(sb, gdp, count); | ||
670 | if (sbi->s_log_groups_per_flex) { | ||
671 | ext4_group_t f = ext4_flex_group(sbi, group); | ||
672 | |||
673 | atomic_inc(&sbi->s_flex_groups[f].used_dirs); | ||
674 | } | ||
675 | } | ||
676 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); | ||
677 | err_ret: | ||
678 | ext4_unlock_group(sb, group); | ||
679 | up_read(&grp->alloc_sem); | ||
680 | return retval; | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * There are two policies for allocating an inode. If the new inode is | 596 | * There are two policies for allocating an inode. If the new inode is |
685 | * a directory, then a forward search is made for a block group with both | 597 | * a directory, then a forward search is made for a block group with both |
686 | * free space and a low directory-to-inode ratio; if that fails, then of | 598 | * free space and a low directory-to-inode ratio; if that fails, then of |
@@ -741,6 +653,11 @@ got_group: | |||
741 | if (ret2 == -1) | 653 | if (ret2 == -1) |
742 | goto out; | 654 | goto out; |
743 | 655 | ||
656 | /* | ||
657 | * Normally we will only go through one pass of this loop, | ||
658 | * unless we get unlucky and it turns out the group we selected | ||
659 | * had its last inode grabbed by someone else. | ||
660 | */ | ||
744 | for (i = 0; i < ngroups; i++, ino = 0) { | 661 | for (i = 0; i < ngroups; i++, ino = 0) { |
745 | err = -EIO; | 662 | err = -EIO; |
746 | 663 | ||
@@ -757,51 +674,24 @@ repeat_in_this_group: | |||
757 | ino = ext4_find_next_zero_bit((unsigned long *) | 674 | ino = ext4_find_next_zero_bit((unsigned long *) |
758 | inode_bitmap_bh->b_data, | 675 | inode_bitmap_bh->b_data, |
759 | EXT4_INODES_PER_GROUP(sb), ino); | 676 | EXT4_INODES_PER_GROUP(sb), ino); |
760 | 677 | if (ino >= EXT4_INODES_PER_GROUP(sb)) { | |
761 | if (ino < EXT4_INODES_PER_GROUP(sb)) { | 678 | if (++group == ngroups) |
762 | 679 | group = 0; | |
763 | BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); | 680 | continue; |
764 | err = ext4_journal_get_write_access(handle, | ||
765 | inode_bitmap_bh); | ||
766 | if (err) | ||
767 | goto fail; | ||
768 | |||
769 | BUFFER_TRACE(group_desc_bh, "get_write_access"); | ||
770 | err = ext4_journal_get_write_access(handle, | ||
771 | group_desc_bh); | ||
772 | if (err) | ||
773 | goto fail; | ||
774 | if (!ext4_claim_inode(sb, inode_bitmap_bh, | ||
775 | ino, group, mode)) { | ||
776 | /* we won it */ | ||
777 | BUFFER_TRACE(inode_bitmap_bh, | ||
778 | "call ext4_handle_dirty_metadata"); | ||
779 | err = ext4_handle_dirty_metadata(handle, | ||
780 | NULL, | ||
781 | inode_bitmap_bh); | ||
782 | if (err) | ||
783 | goto fail; | ||
784 | /* zero bit is inode number 1*/ | ||
785 | ino++; | ||
786 | goto got; | ||
787 | } | ||
788 | /* we lost it */ | ||
789 | ext4_handle_release_buffer(handle, inode_bitmap_bh); | ||
790 | ext4_handle_release_buffer(handle, group_desc_bh); | ||
791 | |||
792 | if (++ino < EXT4_INODES_PER_GROUP(sb)) | ||
793 | goto repeat_in_this_group; | ||
794 | } | 681 | } |
795 | 682 | if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) { | |
796 | /* | 683 | ext4_error(sb, "reserved inode found cleared - " |
797 | * This case is possible in concurrent environment. It is very | 684 | "inode=%lu", ino + 1); |
798 | * rare. We cannot repeat the find_group_xxx() call because | 685 | continue; |
799 | * that will simply return the same blockgroup, because the | 686 | } |
800 | * group descriptor metadata has not yet been updated. | 687 | ext4_lock_group(sb, group); |
801 | * So we just go onto the next blockgroup. | 688 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); |
802 | */ | 689 | ext4_unlock_group(sb, group); |
803 | if (++group == ngroups) | 690 | ino++; /* the inode bitmap is zero-based */ |
804 | group = 0; | 691 | if (!ret2) |
692 | goto got; /* we grabbed the inode! */ | ||
693 | if (ino < EXT4_INODES_PER_GROUP(sb)) | ||
694 | goto repeat_in_this_group; | ||
805 | } | 695 | } |
806 | err = -ENOSPC; | 696 | err = -ENOSPC; |
807 | goto out; | 697 | goto out; |
@@ -838,6 +728,59 @@ got: | |||
838 | if (err) | 728 | if (err) |
839 | goto fail; | 729 | goto fail; |
840 | } | 730 | } |
731 | |||
732 | BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); | ||
733 | err = ext4_journal_get_write_access(handle, inode_bitmap_bh); | ||
734 | if (err) | ||
735 | goto fail; | ||
736 | |||
737 | BUFFER_TRACE(group_desc_bh, "get_write_access"); | ||
738 | err = ext4_journal_get_write_access(handle, group_desc_bh); | ||
739 | if (err) | ||
740 | goto fail; | ||
741 | |||
742 | /* Update the relevant bg descriptor fields */ | ||
743 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { | ||
744 | int free; | ||
745 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | ||
746 | |||
747 | down_read(&grp->alloc_sem); /* protect vs itable lazyinit */ | ||
748 | ext4_lock_group(sb, group); /* while we modify the bg desc */ | ||
749 | free = EXT4_INODES_PER_GROUP(sb) - | ||
750 | ext4_itable_unused_count(sb, gdp); | ||
751 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { | ||
752 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); | ||
753 | free = 0; | ||
754 | } | ||
755 | /* | ||
756 | * Check the relative inode number against the last used | ||
757 | * relative inode number in this group. if it is greater | ||
758 | * we need to update the bg_itable_unused count | ||
759 | */ | ||
760 | if (ino > free) | ||
761 | ext4_itable_unused_set(sb, gdp, | ||
762 | (EXT4_INODES_PER_GROUP(sb) - ino)); | ||
763 | up_read(&grp->alloc_sem); | ||
764 | } | ||
765 | ext4_free_inodes_set(sb, gdp, ext4_free_inodes_count(sb, gdp) - 1); | ||
766 | if (S_ISDIR(mode)) { | ||
767 | ext4_used_dirs_set(sb, gdp, ext4_used_dirs_count(sb, gdp) + 1); | ||
768 | if (sbi->s_log_groups_per_flex) { | ||
769 | ext4_group_t f = ext4_flex_group(sbi, group); | ||
770 | |||
771 | atomic_inc(&sbi->s_flex_groups[f].used_dirs); | ||
772 | } | ||
773 | } | ||
774 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { | ||
775 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); | ||
776 | ext4_unlock_group(sb, group); | ||
777 | } | ||
778 | |||
779 | BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); | ||
780 | err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); | ||
781 | if (err) | ||
782 | goto fail; | ||
783 | |||
841 | BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); | 784 | BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); |
842 | err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); | 785 | err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); |
843 | if (err) | 786 | if (err) |
@@ -1101,7 +1044,7 @@ unsigned long ext4_count_dirs(struct super_block * sb) | |||
1101 | * where it is called from on active part of filesystem is ext4lazyinit | 1044 | * where it is called from on active part of filesystem is ext4lazyinit |
1102 | * thread, so we do not need any special locks, however we have to prevent | 1045 | * thread, so we do not need any special locks, however we have to prevent |
1103 | * inode allocation from the current group, so we take alloc_sem lock, to | 1046 | * inode allocation from the current group, so we take alloc_sem lock, to |
1104 | * block ext4_claim_inode until we are finished. | 1047 | * block ext4_new_inode() until we are finished. |
1105 | */ | 1048 | */ |
1106 | int ext4_init_inode_table(struct super_block *sb, ext4_group_t group, | 1049 | int ext4_init_inode_table(struct super_block *sb, ext4_group_t group, |
1107 | int barrier) | 1050 | int barrier) |