diff options
-rw-r--r-- | fs/ext4/ialloc.c | 58 | ||||
-rw-r--r-- | fs/ext4/inode.c | 25 | ||||
-rw-r--r-- | fs/ext4/namei.c | 29 | ||||
-rw-r--r-- | fs/ext4/resize.c | 7 | ||||
-rw-r--r-- | fs/ext4/super.c | 36 | ||||
-rw-r--r-- | include/linux/ext4_fs.h | 2 |
6 files changed, 87 insertions, 70 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 575b5215c808..da18a74b966a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -782,14 +782,15 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) | |||
782 | unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count); | 782 | unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count); |
783 | ext4_group_t block_group; | 783 | ext4_group_t block_group; |
784 | int bit; | 784 | int bit; |
785 | struct buffer_head *bitmap_bh = NULL; | 785 | struct buffer_head *bitmap_bh; |
786 | struct inode *inode = NULL; | 786 | struct inode *inode = NULL; |
787 | long err = -EIO; | ||
787 | 788 | ||
788 | /* Error cases - e2fsck has already cleaned up for us */ | 789 | /* Error cases - e2fsck has already cleaned up for us */ |
789 | if (ino > max_ino) { | 790 | if (ino > max_ino) { |
790 | ext4_warning(sb, __FUNCTION__, | 791 | ext4_warning(sb, __FUNCTION__, |
791 | "bad orphan ino %lu! e2fsck was run?", ino); | 792 | "bad orphan ino %lu! e2fsck was run?", ino); |
792 | goto out; | 793 | goto error; |
793 | } | 794 | } |
794 | 795 | ||
795 | block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); | 796 | block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); |
@@ -798,38 +799,49 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) | |||
798 | if (!bitmap_bh) { | 799 | if (!bitmap_bh) { |
799 | ext4_warning(sb, __FUNCTION__, | 800 | ext4_warning(sb, __FUNCTION__, |
800 | "inode bitmap error for orphan %lu", ino); | 801 | "inode bitmap error for orphan %lu", ino); |
801 | goto out; | 802 | goto error; |
802 | } | 803 | } |
803 | 804 | ||
804 | /* Having the inode bit set should be a 100% indicator that this | 805 | /* Having the inode bit set should be a 100% indicator that this |
805 | * is a valid orphan (no e2fsck run on fs). Orphans also include | 806 | * is a valid orphan (no e2fsck run on fs). Orphans also include |
806 | * inodes that were being truncated, so we can't check i_nlink==0. | 807 | * inodes that were being truncated, so we can't check i_nlink==0. |
807 | */ | 808 | */ |
808 | if (!ext4_test_bit(bit, bitmap_bh->b_data) || | 809 | if (!ext4_test_bit(bit, bitmap_bh->b_data)) |
809 | !(inode = iget(sb, ino)) || is_bad_inode(inode) || | 810 | goto bad_orphan; |
810 | NEXT_ORPHAN(inode) > max_ino) { | 811 | |
811 | ext4_warning(sb, __FUNCTION__, | 812 | inode = ext4_iget(sb, ino); |
812 | "bad orphan inode %lu! e2fsck was run?", ino); | 813 | if (IS_ERR(inode)) |
813 | printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n", | 814 | goto iget_failed; |
814 | bit, (unsigned long long)bitmap_bh->b_blocknr, | 815 | |
815 | ext4_test_bit(bit, bitmap_bh->b_data)); | 816 | if (NEXT_ORPHAN(inode) > max_ino) |
816 | printk(KERN_NOTICE "inode=%p\n", inode); | 817 | goto bad_orphan; |
817 | if (inode) { | 818 | brelse(bitmap_bh); |
818 | printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", | 819 | return inode; |
819 | is_bad_inode(inode)); | 820 | |
820 | printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", | 821 | iget_failed: |
821 | NEXT_ORPHAN(inode)); | 822 | err = PTR_ERR(inode); |
822 | printk(KERN_NOTICE "max_ino=%lu\n", max_ino); | 823 | inode = NULL; |
823 | } | 824 | bad_orphan: |
825 | ext4_warning(sb, __FUNCTION__, | ||
826 | "bad orphan inode %lu! e2fsck was run?", ino); | ||
827 | printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n", | ||
828 | bit, (unsigned long long)bitmap_bh->b_blocknr, | ||
829 | ext4_test_bit(bit, bitmap_bh->b_data)); | ||
830 | printk(KERN_NOTICE "inode=%p\n", inode); | ||
831 | if (inode) { | ||
832 | printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", | ||
833 | is_bad_inode(inode)); | ||
834 | printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", | ||
835 | NEXT_ORPHAN(inode)); | ||
836 | printk(KERN_NOTICE "max_ino=%lu\n", max_ino); | ||
824 | /* Avoid freeing blocks if we got a bad deleted inode */ | 837 | /* Avoid freeing blocks if we got a bad deleted inode */ |
825 | if (inode && inode->i_nlink == 0) | 838 | if (inode->i_nlink == 0) |
826 | inode->i_blocks = 0; | 839 | inode->i_blocks = 0; |
827 | iput(inode); | 840 | iput(inode); |
828 | inode = NULL; | ||
829 | } | 841 | } |
830 | out: | ||
831 | brelse(bitmap_bh); | 842 | brelse(bitmap_bh); |
832 | return inode; | 843 | error: |
844 | return ERR_PTR(err); | ||
833 | } | 845 | } |
834 | 846 | ||
835 | unsigned long ext4_count_free_inodes (struct super_block * sb) | 847 | unsigned long ext4_count_free_inodes (struct super_block * sb) |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0e9055cf700e..f4e387452246 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2680,21 +2680,31 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | |||
2680 | } | 2680 | } |
2681 | } | 2681 | } |
2682 | 2682 | ||
2683 | void ext4_read_inode(struct inode * inode) | 2683 | struct inode *ext4_iget(struct super_block *sb, unsigned long ino) |
2684 | { | 2684 | { |
2685 | struct ext4_iloc iloc; | 2685 | struct ext4_iloc iloc; |
2686 | struct ext4_inode *raw_inode; | 2686 | struct ext4_inode *raw_inode; |
2687 | struct ext4_inode_info *ei = EXT4_I(inode); | 2687 | struct ext4_inode_info *ei; |
2688 | struct buffer_head *bh; | 2688 | struct buffer_head *bh; |
2689 | struct inode *inode; | ||
2690 | long ret; | ||
2689 | int block; | 2691 | int block; |
2690 | 2692 | ||
2693 | inode = iget_locked(sb, ino); | ||
2694 | if (!inode) | ||
2695 | return ERR_PTR(-ENOMEM); | ||
2696 | if (!(inode->i_state & I_NEW)) | ||
2697 | return inode; | ||
2698 | |||
2699 | ei = EXT4_I(inode); | ||
2691 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 2700 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL |
2692 | ei->i_acl = EXT4_ACL_NOT_CACHED; | 2701 | ei->i_acl = EXT4_ACL_NOT_CACHED; |
2693 | ei->i_default_acl = EXT4_ACL_NOT_CACHED; | 2702 | ei->i_default_acl = EXT4_ACL_NOT_CACHED; |
2694 | #endif | 2703 | #endif |
2695 | ei->i_block_alloc_info = NULL; | 2704 | ei->i_block_alloc_info = NULL; |
2696 | 2705 | ||
2697 | if (__ext4_get_inode_loc(inode, &iloc, 0)) | 2706 | ret = __ext4_get_inode_loc(inode, &iloc, 0); |
2707 | if (ret < 0) | ||
2698 | goto bad_inode; | 2708 | goto bad_inode; |
2699 | bh = iloc.bh; | 2709 | bh = iloc.bh; |
2700 | raw_inode = ext4_raw_inode(&iloc); | 2710 | raw_inode = ext4_raw_inode(&iloc); |
@@ -2720,6 +2730,7 @@ void ext4_read_inode(struct inode * inode) | |||
2720 | !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { | 2730 | !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { |
2721 | /* this inode is deleted */ | 2731 | /* this inode is deleted */ |
2722 | brelse (bh); | 2732 | brelse (bh); |
2733 | ret = -ESTALE; | ||
2723 | goto bad_inode; | 2734 | goto bad_inode; |
2724 | } | 2735 | } |
2725 | /* The only unlinked inodes we let through here have | 2736 | /* The only unlinked inodes we let through here have |
@@ -2758,6 +2769,7 @@ void ext4_read_inode(struct inode * inode) | |||
2758 | if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > | 2769 | if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > |
2759 | EXT4_INODE_SIZE(inode->i_sb)) { | 2770 | EXT4_INODE_SIZE(inode->i_sb)) { |
2760 | brelse (bh); | 2771 | brelse (bh); |
2772 | ret = -EIO; | ||
2761 | goto bad_inode; | 2773 | goto bad_inode; |
2762 | } | 2774 | } |
2763 | if (ei->i_extra_isize == 0) { | 2775 | if (ei->i_extra_isize == 0) { |
@@ -2811,11 +2823,12 @@ void ext4_read_inode(struct inode * inode) | |||
2811 | } | 2823 | } |
2812 | brelse (iloc.bh); | 2824 | brelse (iloc.bh); |
2813 | ext4_set_inode_flags(inode); | 2825 | ext4_set_inode_flags(inode); |
2814 | return; | 2826 | unlock_new_inode(inode); |
2827 | return inode; | ||
2815 | 2828 | ||
2816 | bad_inode: | 2829 | bad_inode: |
2817 | make_bad_inode(inode); | 2830 | iget_failed(inode); |
2818 | return; | 2831 | return ERR_PTR(ret); |
2819 | } | 2832 | } |
2820 | 2833 | ||
2821 | static int ext4_inode_blocks_set(handle_t *handle, | 2834 | static int ext4_inode_blocks_set(handle_t *handle, |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 67b6d8a1ceff..d153bb5922fc 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1039,17 +1039,11 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str | |||
1039 | if (!ext4_valid_inum(dir->i_sb, ino)) { | 1039 | if (!ext4_valid_inum(dir->i_sb, ino)) { |
1040 | ext4_error(dir->i_sb, "ext4_lookup", | 1040 | ext4_error(dir->i_sb, "ext4_lookup", |
1041 | "bad inode number: %lu", ino); | 1041 | "bad inode number: %lu", ino); |
1042 | inode = NULL; | 1042 | return ERR_PTR(-EIO); |
1043 | } else | ||
1044 | inode = iget(dir->i_sb, ino); | ||
1045 | |||
1046 | if (!inode) | ||
1047 | return ERR_PTR(-EACCES); | ||
1048 | |||
1049 | if (is_bad_inode(inode)) { | ||
1050 | iput(inode); | ||
1051 | return ERR_PTR(-ENOENT); | ||
1052 | } | 1043 | } |
1044 | inode = ext4_iget(dir->i_sb, ino); | ||
1045 | if (IS_ERR(inode)) | ||
1046 | return ERR_CAST(inode); | ||
1053 | } | 1047 | } |
1054 | return d_splice_alias(inode, dentry); | 1048 | return d_splice_alias(inode, dentry); |
1055 | } | 1049 | } |
@@ -1078,18 +1072,13 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
1078 | if (!ext4_valid_inum(child->d_inode->i_sb, ino)) { | 1072 | if (!ext4_valid_inum(child->d_inode->i_sb, ino)) { |
1079 | ext4_error(child->d_inode->i_sb, "ext4_get_parent", | 1073 | ext4_error(child->d_inode->i_sb, "ext4_get_parent", |
1080 | "bad inode number: %lu", ino); | 1074 | "bad inode number: %lu", ino); |
1081 | inode = NULL; | 1075 | return ERR_PTR(-EIO); |
1082 | } else | ||
1083 | inode = iget(child->d_inode->i_sb, ino); | ||
1084 | |||
1085 | if (!inode) | ||
1086 | return ERR_PTR(-EACCES); | ||
1087 | |||
1088 | if (is_bad_inode(inode)) { | ||
1089 | iput(inode); | ||
1090 | return ERR_PTR(-ENOENT); | ||
1091 | } | 1076 | } |
1092 | 1077 | ||
1078 | inode = ext4_iget(child->d_inode->i_sb, ino); | ||
1079 | if (IS_ERR(inode)) | ||
1080 | return ERR_CAST(inode); | ||
1081 | |||
1093 | parent = d_alloc_anon(inode); | 1082 | parent = d_alloc_anon(inode); |
1094 | if (!parent) { | 1083 | if (!parent) { |
1095 | iput(inode); | 1084 | iput(inode); |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 4fbba60816f4..9477a2bd6ff2 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -779,12 +779,11 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
779 | "No reserved GDT blocks, can't resize"); | 779 | "No reserved GDT blocks, can't resize"); |
780 | return -EPERM; | 780 | return -EPERM; |
781 | } | 781 | } |
782 | inode = iget(sb, EXT4_RESIZE_INO); | 782 | inode = ext4_iget(sb, EXT4_RESIZE_INO); |
783 | if (!inode || is_bad_inode(inode)) { | 783 | if (IS_ERR(inode)) { |
784 | ext4_warning(sb, __FUNCTION__, | 784 | ext4_warning(sb, __FUNCTION__, |
785 | "Error opening resize inode"); | 785 | "Error opening resize inode"); |
786 | iput(inode); | 786 | return PTR_ERR(inode); |
787 | return -ENOENT; | ||
788 | } | 787 | } |
789 | } | 788 | } |
790 | 789 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c89bb8797765..93beb865c20d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -777,11 +777,10 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb, | |||
777 | * Currently we don't know the generation for parent directory, so | 777 | * Currently we don't know the generation for parent directory, so |
778 | * a generation of 0 means "accept any" | 778 | * a generation of 0 means "accept any" |
779 | */ | 779 | */ |
780 | inode = iget(sb, ino); | 780 | inode = ext4_iget(sb, ino); |
781 | if (inode == NULL) | 781 | if (IS_ERR(inode)) |
782 | return ERR_PTR(-ENOMEM); | 782 | return ERR_CAST(inode); |
783 | if (is_bad_inode(inode) || | 783 | if (generation && inode->i_generation != generation) { |
784 | (generation && inode->i_generation != generation)) { | ||
785 | iput(inode); | 784 | iput(inode); |
786 | return ERR_PTR(-ESTALE); | 785 | return ERR_PTR(-ESTALE); |
787 | } | 786 | } |
@@ -850,7 +849,6 @@ static struct quotactl_ops ext4_qctl_operations = { | |||
850 | static const struct super_operations ext4_sops = { | 849 | static const struct super_operations ext4_sops = { |
851 | .alloc_inode = ext4_alloc_inode, | 850 | .alloc_inode = ext4_alloc_inode, |
852 | .destroy_inode = ext4_destroy_inode, | 851 | .destroy_inode = ext4_destroy_inode, |
853 | .read_inode = ext4_read_inode, | ||
854 | .write_inode = ext4_write_inode, | 852 | .write_inode = ext4_write_inode, |
855 | .dirty_inode = ext4_dirty_inode, | 853 | .dirty_inode = ext4_dirty_inode, |
856 | .delete_inode = ext4_delete_inode, | 854 | .delete_inode = ext4_delete_inode, |
@@ -1805,6 +1803,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1805 | unsigned long journal_devnum = 0; | 1803 | unsigned long journal_devnum = 0; |
1806 | unsigned long def_mount_opts; | 1804 | unsigned long def_mount_opts; |
1807 | struct inode *root; | 1805 | struct inode *root; |
1806 | int ret = -EINVAL; | ||
1808 | int blocksize; | 1807 | int blocksize; |
1809 | int db_count; | 1808 | int db_count; |
1810 | int i; | 1809 | int i; |
@@ -2237,19 +2236,24 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
2237 | * so we can safely mount the rest of the filesystem now. | 2236 | * so we can safely mount the rest of the filesystem now. |
2238 | */ | 2237 | */ |
2239 | 2238 | ||
2240 | root = iget(sb, EXT4_ROOT_INO); | 2239 | root = ext4_iget(sb, EXT4_ROOT_INO); |
2241 | sb->s_root = d_alloc_root(root); | 2240 | if (IS_ERR(root)) { |
2242 | if (!sb->s_root) { | ||
2243 | printk(KERN_ERR "EXT4-fs: get root inode failed\n"); | 2241 | printk(KERN_ERR "EXT4-fs: get root inode failed\n"); |
2244 | iput(root); | 2242 | ret = PTR_ERR(root); |
2245 | goto failed_mount4; | 2243 | goto failed_mount4; |
2246 | } | 2244 | } |
2247 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { | 2245 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { |
2248 | dput(sb->s_root); | 2246 | iput(root); |
2249 | sb->s_root = NULL; | ||
2250 | printk(KERN_ERR "EXT4-fs: corrupt root inode, run e2fsck\n"); | 2247 | printk(KERN_ERR "EXT4-fs: corrupt root inode, run e2fsck\n"); |
2251 | goto failed_mount4; | 2248 | goto failed_mount4; |
2252 | } | 2249 | } |
2250 | sb->s_root = d_alloc_root(root); | ||
2251 | if (!sb->s_root) { | ||
2252 | printk(KERN_ERR "EXT4-fs: get root dentry failed\n"); | ||
2253 | iput(root); | ||
2254 | ret = -ENOMEM; | ||
2255 | goto failed_mount4; | ||
2256 | } | ||
2253 | 2257 | ||
2254 | ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY); | 2258 | ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY); |
2255 | 2259 | ||
@@ -2330,7 +2334,7 @@ out_fail: | |||
2330 | sb->s_fs_info = NULL; | 2334 | sb->s_fs_info = NULL; |
2331 | kfree(sbi); | 2335 | kfree(sbi); |
2332 | lock_kernel(); | 2336 | lock_kernel(); |
2333 | return -EINVAL; | 2337 | return ret; |
2334 | } | 2338 | } |
2335 | 2339 | ||
2336 | /* | 2340 | /* |
@@ -2366,8 +2370,8 @@ static journal_t *ext4_get_journal(struct super_block *sb, | |||
2366 | * things happen if we iget() an unused inode, as the subsequent | 2370 | * things happen if we iget() an unused inode, as the subsequent |
2367 | * iput() will try to delete it. */ | 2371 | * iput() will try to delete it. */ |
2368 | 2372 | ||
2369 | journal_inode = iget(sb, journal_inum); | 2373 | journal_inode = ext4_iget(sb, journal_inum); |
2370 | if (!journal_inode) { | 2374 | if (IS_ERR(journal_inode)) { |
2371 | printk(KERN_ERR "EXT4-fs: no journal found.\n"); | 2375 | printk(KERN_ERR "EXT4-fs: no journal found.\n"); |
2372 | return NULL; | 2376 | return NULL; |
2373 | } | 2377 | } |
@@ -2380,7 +2384,7 @@ static journal_t *ext4_get_journal(struct super_block *sb, | |||
2380 | 2384 | ||
2381 | jbd_debug(2, "Journal inode found at %p: %Ld bytes\n", | 2385 | jbd_debug(2, "Journal inode found at %p: %Ld bytes\n", |
2382 | journal_inode, journal_inode->i_size); | 2386 | journal_inode, journal_inode->i_size); |
2383 | if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) { | 2387 | if (!S_ISREG(journal_inode->i_mode)) { |
2384 | printk(KERN_ERR "EXT4-fs: invalid journal inode.\n"); | 2388 | printk(KERN_ERR "EXT4-fs: invalid journal inode.\n"); |
2385 | iput(journal_inode); | 2389 | iput(journal_inode); |
2386 | return NULL; | 2390 | return NULL; |
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h index 1852313fc7c7..c4f635a4dd25 100644 --- a/include/linux/ext4_fs.h +++ b/include/linux/ext4_fs.h | |||
@@ -1024,7 +1024,7 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
1024 | struct buffer_head *bh_result, | 1024 | struct buffer_head *bh_result, |
1025 | int create, int extend_disksize); | 1025 | int create, int extend_disksize); |
1026 | 1026 | ||
1027 | extern void ext4_read_inode (struct inode *); | 1027 | extern struct inode *ext4_iget(struct super_block *, unsigned long); |
1028 | extern int ext4_write_inode (struct inode *, int); | 1028 | extern int ext4_write_inode (struct inode *, int); |
1029 | extern int ext4_setattr (struct dentry *, struct iattr *); | 1029 | extern int ext4_setattr (struct dentry *, struct iattr *); |
1030 | extern void ext4_delete_inode (struct inode *); | 1030 | extern void ext4_delete_inode (struct inode *); |