aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-02-07 03:15:37 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 11:42:27 -0500
commit1d1fe1ee02b9ac2660995b10e35dd41448fef011 (patch)
tree8961bbe5a36a07dc8ad8c6cd3e973ce0fcde5850
parent473043dcee1874aab99f66b0362b344618eb3790 (diff)
iget: stop EXT4 from using iget() and read_inode()
Stop the EXT4 filesystem from using iget() and read_inode(). Replace ext4_read_inode() with ext4_iget(), and call that instead of iget(). ext4_iget() then uses iget_locked() directly and returns a proper error code instead of an inode in the event of an error. ext4_fill_super() returns any error incurred when getting the root inode instead of EINVAL. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: "Theodore Ts'o" <tytso@mit.edu> Acked-by: Jan Kara <jack@suse.cz> Cc: <linux-ext4@vger.kernel.org> Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ext4/ialloc.c58
-rw-r--r--fs/ext4/inode.c25
-rw-r--r--fs/ext4/namei.c29
-rw-r--r--fs/ext4/resize.c7
-rw-r--r--fs/ext4/super.c36
-rw-r--r--include/linux/ext4_fs.h2
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", 821iget_failed:
821 NEXT_ORPHAN(inode)); 822 err = PTR_ERR(inode);
822 printk(KERN_NOTICE "max_ino=%lu\n", max_ino); 823 inode = NULL;
823 } 824bad_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 }
830out:
831 brelse(bitmap_bh); 842 brelse(bitmap_bh);
832 return inode; 843error:
844 return ERR_PTR(err);
833} 845}
834 846
835unsigned long ext4_count_free_inodes (struct super_block * sb) 847unsigned 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
2683void ext4_read_inode(struct inode * inode) 2683struct 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
2816bad_inode: 2829bad_inode:
2817 make_bad_inode(inode); 2830 iget_failed(inode);
2818 return; 2831 return ERR_PTR(ret);
2819} 2832}
2820 2833
2821static int ext4_inode_blocks_set(handle_t *handle, 2834static 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 = {
850static const struct super_operations ext4_sops = { 849static 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
1027extern void ext4_read_inode (struct inode *); 1027extern struct inode *ext4_iget(struct super_block *, unsigned long);
1028extern int ext4_write_inode (struct inode *, int); 1028extern int ext4_write_inode (struct inode *, int);
1029extern int ext4_setattr (struct dentry *, struct iattr *); 1029extern int ext4_setattr (struct dentry *, struct iattr *);
1030extern void ext4_delete_inode (struct inode *); 1030extern void ext4_delete_inode (struct inode *);