]>
Commit | Line | Data |
---|---|---|
4c4902c2 GKH |
1 | From 7827a7f6ebfcb7f388dc47fddd48567a314701ba Mon Sep 17 00:00:00 2001 |
2 | From: Theodore Ts'o <tytso@mit.edu> | |
3 | Date: Sat, 30 Apr 2016 00:49:54 -0400 | |
4 | Subject: ext4: clean up error handling when orphan list is corrupted | |
5 | ||
6 | From: Theodore Ts'o <tytso@mit.edu> | |
7 | ||
8 | commit 7827a7f6ebfcb7f388dc47fddd48567a314701ba upstream. | |
9 | ||
10 | Instead of just printing warning messages, if the orphan list is | |
11 | corrupted, declare the file system is corrupted. If there are any | |
12 | reserved inodes in the orphaned inode list, declare the file system | |
13 | corrupted and stop right away to avoid doing more potential damage to | |
14 | the file system. | |
15 | ||
16 | Signed-off-by: Theodore Ts'o <tytso@mit.edu> | |
17 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
18 | ||
19 | --- | |
20 | fs/ext4/ialloc.c | 49 ++++++++++++++++++++++--------------------------- | |
21 | 1 file changed, 22 insertions(+), 27 deletions(-) | |
22 | ||
23 | --- a/fs/ext4/ialloc.c | |
24 | +++ b/fs/ext4/ialloc.c | |
25 | @@ -1150,25 +1150,20 @@ struct inode *ext4_orphan_get(struct sup | |
26 | unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count); | |
27 | ext4_group_t block_group; | |
28 | int bit; | |
29 | - struct buffer_head *bitmap_bh; | |
30 | + struct buffer_head *bitmap_bh = NULL; | |
31 | struct inode *inode = NULL; | |
32 | - long err = -EIO; | |
33 | + int err = -EFSCORRUPTED; | |
34 | ||
35 | - /* Error cases - e2fsck has already cleaned up for us */ | |
36 | - if (ino > max_ino) { | |
37 | - ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino); | |
38 | - err = -EFSCORRUPTED; | |
39 | - goto error; | |
40 | - } | |
41 | + if (ino < EXT4_FIRST_INO(sb) || ino > max_ino) | |
42 | + goto bad_orphan; | |
43 | ||
44 | block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); | |
45 | bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); | |
46 | bitmap_bh = ext4_read_inode_bitmap(sb, block_group); | |
47 | if (IS_ERR(bitmap_bh)) { | |
48 | - err = PTR_ERR(bitmap_bh); | |
49 | - ext4_warning(sb, "inode bitmap error %ld for orphan %lu", | |
50 | - ino, err); | |
51 | - goto error; | |
52 | + ext4_error(sb, "inode bitmap error %ld for orphan %lu", | |
53 | + ino, PTR_ERR(bitmap_bh)); | |
54 | + return (struct inode *) bitmap_bh; | |
55 | } | |
56 | ||
57 | /* Having the inode bit set should be a 100% indicator that this | |
58 | @@ -1179,8 +1174,12 @@ struct inode *ext4_orphan_get(struct sup | |
59 | goto bad_orphan; | |
60 | ||
61 | inode = ext4_iget(sb, ino); | |
62 | - if (IS_ERR(inode)) | |
63 | - goto iget_failed; | |
64 | + if (IS_ERR(inode)) { | |
65 | + err = PTR_ERR(inode); | |
66 | + ext4_error(sb, "couldn't read orphan inode %lu (err %d)", | |
67 | + ino, err); | |
68 | + return inode; | |
69 | + } | |
70 | ||
71 | /* | |
72 | * If the orphans has i_nlinks > 0 then it should be able to | |
73 | @@ -1197,29 +1196,25 @@ struct inode *ext4_orphan_get(struct sup | |
74 | brelse(bitmap_bh); | |
75 | return inode; | |
76 | ||
77 | -iget_failed: | |
78 | - err = PTR_ERR(inode); | |
79 | - inode = NULL; | |
80 | bad_orphan: | |
81 | - ext4_warning(sb, "bad orphan inode %lu! e2fsck was run?", ino); | |
82 | - printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n", | |
83 | - bit, (unsigned long long)bitmap_bh->b_blocknr, | |
84 | - ext4_test_bit(bit, bitmap_bh->b_data)); | |
85 | - printk(KERN_WARNING "inode=%p\n", inode); | |
86 | + ext4_error(sb, "bad orphan inode %lu", ino); | |
87 | + if (bitmap_bh) | |
88 | + printk(KERN_ERR "ext4_test_bit(bit=%d, block=%llu) = %d\n", | |
89 | + bit, (unsigned long long)bitmap_bh->b_blocknr, | |
90 | + ext4_test_bit(bit, bitmap_bh->b_data)); | |
91 | if (inode) { | |
92 | - printk(KERN_WARNING "is_bad_inode(inode)=%d\n", | |
93 | + printk(KERN_ERR "is_bad_inode(inode)=%d\n", | |
94 | is_bad_inode(inode)); | |
95 | - printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n", | |
96 | + printk(KERN_ERR "NEXT_ORPHAN(inode)=%u\n", | |
97 | NEXT_ORPHAN(inode)); | |
98 | - printk(KERN_WARNING "max_ino=%lu\n", max_ino); | |
99 | - printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink); | |
100 | + printk(KERN_ERR "max_ino=%lu\n", max_ino); | |
101 | + printk(KERN_ERR "i_nlink=%u\n", inode->i_nlink); | |
102 | /* Avoid freeing blocks if we got a bad deleted inode */ | |
103 | if (inode->i_nlink == 0) | |
104 | inode->i_blocks = 0; | |
105 | iput(inode); | |
106 | } | |
107 | brelse(bitmap_bh); | |
108 | -error: | |
109 | return ERR_PTR(err); | |
110 | } | |
111 |