]>
Commit | Line | Data |
---|---|---|
1a306361 GKH |
1 | From 860d21e2c585f7ee8a4ecc06f474fdc33c9474f4 Mon Sep 17 00:00:00 2001 |
2 | From: Theodore Ts'o <tytso@mit.edu> | |
3 | Date: Sat, 12 Jan 2013 16:19:36 -0500 | |
4 | Subject: ext4: return ENOMEM if sb_getblk() fails | |
5 | ||
6 | From: Theodore Ts'o <tytso@mit.edu> | |
7 | ||
8 | commit 860d21e2c585f7ee8a4ecc06f474fdc33c9474f4 upstream. | |
9 | ||
10 | The only reason for sb_getblk() failing is if it can't allocate the | |
11 | buffer_head. So ENOMEM is more appropriate than EIO. In addition, | |
12 | make sure that the file system is marked as being inconsistent if | |
13 | sb_getblk() fails. | |
14 | ||
15 | Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> | |
16 | [xr: Backported to 3.4: | |
17 | - Drop change to inline.c | |
18 | - Call to ext4_ext_check() from ext4_ext_find_extent() is conditional] | |
19 | Signed-off-by: Rui Xiang <rui.xiang@huawei.com> | |
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
21 | ||
22 | --- | |
23 | fs/ext4/extents.c | 25 ++++++++++++++----------- | |
24 | fs/ext4/indirect.c | 9 ++++++--- | |
25 | fs/ext4/inode.c | 9 +++------ | |
26 | fs/ext4/mmp.c | 2 ++ | |
27 | fs/ext4/resize.c | 8 ++++---- | |
28 | fs/ext4/xattr.c | 3 ++- | |
29 | 6 files changed, 31 insertions(+), 25 deletions(-) | |
30 | ||
31 | --- a/fs/ext4/extents.c | |
32 | +++ b/fs/ext4/extents.c | |
33 | @@ -670,6 +670,7 @@ ext4_ext_find_extent(struct inode *inode | |
34 | struct ext4_extent_header *eh; | |
35 | struct buffer_head *bh; | |
36 | short int depth, i, ppos = 0, alloc = 0; | |
37 | + int ret; | |
38 | ||
39 | eh = ext_inode_hdr(inode); | |
40 | depth = ext_depth(inode); | |
41 | @@ -699,12 +700,15 @@ ext4_ext_find_extent(struct inode *inode | |
42 | path[ppos].p_ext = NULL; | |
43 | ||
44 | bh = sb_getblk(inode->i_sb, path[ppos].p_block); | |
45 | - if (unlikely(!bh)) | |
46 | + if (unlikely(!bh)) { | |
47 | + ret = -ENOMEM; | |
48 | goto err; | |
49 | + } | |
50 | if (!bh_uptodate_or_lock(bh)) { | |
51 | trace_ext4_ext_load_extent(inode, block, | |
52 | path[ppos].p_block); | |
53 | - if (bh_submit_read(bh) < 0) { | |
54 | + ret = bh_submit_read(bh); | |
55 | + if (ret < 0) { | |
56 | put_bh(bh); | |
57 | goto err; | |
58 | } | |
59 | @@ -717,13 +721,15 @@ ext4_ext_find_extent(struct inode *inode | |
60 | put_bh(bh); | |
61 | EXT4_ERROR_INODE(inode, | |
62 | "ppos %d > depth %d", ppos, depth); | |
63 | + ret = -EIO; | |
64 | goto err; | |
65 | } | |
66 | path[ppos].p_bh = bh; | |
67 | path[ppos].p_hdr = eh; | |
68 | i--; | |
69 | ||
70 | - if (need_to_validate && ext4_ext_check(inode, eh, i)) | |
71 | + ret = need_to_validate ? ext4_ext_check(inode, eh, i) : 0; | |
72 | + if (ret < 0) | |
73 | goto err; | |
74 | } | |
75 | ||
76 | @@ -745,7 +751,7 @@ err: | |
77 | ext4_ext_drop_refs(path); | |
78 | if (alloc) | |
79 | kfree(path); | |
80 | - return ERR_PTR(-EIO); | |
81 | + return ERR_PTR(ret); | |
82 | } | |
83 | ||
84 | /* | |
85 | @@ -900,7 +906,7 @@ static int ext4_ext_split(handle_t *hand | |
86 | } | |
87 | bh = sb_getblk(inode->i_sb, newblock); | |
88 | if (!bh) { | |
89 | - err = -EIO; | |
90 | + err = -ENOMEM; | |
91 | goto cleanup; | |
92 | } | |
93 | lock_buffer(bh); | |
94 | @@ -972,7 +978,7 @@ static int ext4_ext_split(handle_t *hand | |
95 | newblock = ablocks[--a]; | |
96 | bh = sb_getblk(inode->i_sb, newblock); | |
97 | if (!bh) { | |
98 | - err = -EIO; | |
99 | + err = -ENOMEM; | |
100 | goto cleanup; | |
101 | } | |
102 | lock_buffer(bh); | |
103 | @@ -1083,11 +1089,8 @@ static int ext4_ext_grow_indepth(handle_ | |
104 | return err; | |
105 | ||
106 | bh = sb_getblk(inode->i_sb, newblock); | |
107 | - if (!bh) { | |
108 | - err = -EIO; | |
109 | - ext4_std_error(inode->i_sb, err); | |
110 | - return err; | |
111 | - } | |
112 | + if (!bh) | |
113 | + return -ENOMEM; | |
114 | lock_buffer(bh); | |
115 | ||
116 | err = ext4_journal_get_create_access(handle, bh); | |
117 | --- a/fs/ext4/indirect.c | |
118 | +++ b/fs/ext4/indirect.c | |
119 | @@ -145,6 +145,7 @@ static Indirect *ext4_get_branch(struct | |
120 | struct super_block *sb = inode->i_sb; | |
121 | Indirect *p = chain; | |
122 | struct buffer_head *bh; | |
123 | + int ret = -EIO; | |
124 | ||
125 | *err = 0; | |
126 | /* i_data is not going away, no lock needed */ | |
127 | @@ -153,8 +154,10 @@ static Indirect *ext4_get_branch(struct | |
128 | goto no_block; | |
129 | while (--depth) { | |
130 | bh = sb_getblk(sb, le32_to_cpu(p->key)); | |
131 | - if (unlikely(!bh)) | |
132 | + if (unlikely(!bh)) { | |
133 | + ret = -ENOMEM; | |
134 | goto failure; | |
135 | + } | |
136 | ||
137 | if (!bh_uptodate_or_lock(bh)) { | |
138 | if (bh_submit_read(bh) < 0) { | |
139 | @@ -176,7 +179,7 @@ static Indirect *ext4_get_branch(struct | |
140 | return NULL; | |
141 | ||
142 | failure: | |
143 | - *err = -EIO; | |
144 | + *err = ret; | |
145 | no_block: | |
146 | return p; | |
147 | } | |
148 | @@ -470,7 +473,7 @@ static int ext4_alloc_branch(handle_t *h | |
149 | */ | |
150 | bh = sb_getblk(inode->i_sb, new_blocks[n-1]); | |
151 | if (unlikely(!bh)) { | |
152 | - err = -EIO; | |
153 | + err = -ENOMEM; | |
154 | goto failed; | |
155 | } | |
156 | ||
157 | --- a/fs/ext4/inode.c | |
158 | +++ b/fs/ext4/inode.c | |
159 | @@ -663,7 +663,7 @@ struct buffer_head *ext4_getblk(handle_t | |
160 | ||
161 | bh = sb_getblk(inode->i_sb, map.m_pblk); | |
162 | if (!bh) { | |
163 | - *errp = -EIO; | |
164 | + *errp = -ENOMEM; | |
165 | return NULL; | |
166 | } | |
167 | if (map.m_flags & EXT4_MAP_NEW) { | |
168 | @@ -3461,11 +3461,8 @@ static int __ext4_get_inode_loc(struct i | |
169 | iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb); | |
170 | ||
171 | bh = sb_getblk(sb, block); | |
172 | - if (!bh) { | |
173 | - EXT4_ERROR_INODE_BLOCK(inode, block, | |
174 | - "unable to read itable block"); | |
175 | - return -EIO; | |
176 | - } | |
177 | + if (!bh) | |
178 | + return -ENOMEM; | |
179 | if (!buffer_uptodate(bh)) { | |
180 | lock_buffer(bh); | |
181 | ||
182 | --- a/fs/ext4/mmp.c | |
183 | +++ b/fs/ext4/mmp.c | |
184 | @@ -41,6 +41,8 @@ static int read_mmp_block(struct super_b | |
185 | * is not blocked in the elevator. */ | |
186 | if (!*bh) | |
187 | *bh = sb_getblk(sb, mmp_block); | |
188 | + if (!*bh) | |
189 | + return -ENOMEM; | |
190 | if (*bh) { | |
191 | get_bh(*bh); | |
192 | lock_buffer(*bh); | |
193 | --- a/fs/ext4/resize.c | |
194 | +++ b/fs/ext4/resize.c | |
195 | @@ -315,7 +315,7 @@ static struct buffer_head *bclean(handle | |
196 | ||
197 | bh = sb_getblk(sb, blk); | |
198 | if (!bh) | |
199 | - return ERR_PTR(-EIO); | |
200 | + return ERR_PTR(-ENOMEM); | |
201 | if ((err = ext4_journal_get_write_access(handle, bh))) { | |
202 | brelse(bh); | |
203 | bh = ERR_PTR(err); | |
204 | @@ -392,7 +392,7 @@ static int set_flexbg_block_bitmap(struc | |
205 | ||
206 | bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap); | |
207 | if (!bh) | |
208 | - return -EIO; | |
209 | + return -ENOMEM; | |
210 | ||
211 | err = ext4_journal_get_write_access(handle, bh); | |
212 | if (err) | |
213 | @@ -470,7 +470,7 @@ static int setup_new_flex_group_blocks(s | |
214 | ||
215 | gdb = sb_getblk(sb, block); | |
216 | if (!gdb) { | |
217 | - err = -EIO; | |
218 | + err = -ENOMEM; | |
219 | goto out; | |
220 | } | |
221 | ||
222 | @@ -991,7 +991,7 @@ static void update_backups(struct super_ | |
223 | ||
224 | bh = sb_getblk(sb, group * bpg + blk_off); | |
225 | if (!bh) { | |
226 | - err = -EIO; | |
227 | + err = -ENOMEM; | |
228 | break; | |
229 | } | |
230 | ext4_debug("update metadata backup %#04lx\n", | |
231 | --- a/fs/ext4/xattr.c | |
232 | +++ b/fs/ext4/xattr.c | |
233 | @@ -840,16 +840,17 @@ inserted: | |
234 | ||
235 | new_bh = sb_getblk(sb, block); | |
236 | if (!new_bh) { | |
237 | + error = -ENOMEM; | |
238 | getblk_failed: | |
239 | ext4_free_blocks(handle, inode, NULL, block, 1, | |
240 | EXT4_FREE_BLOCKS_METADATA); | |
241 | - error = -EIO; | |
242 | goto cleanup; | |
243 | } | |
244 | lock_buffer(new_bh); | |
245 | error = ext4_journal_get_create_access(handle, new_bh); | |
246 | if (error) { | |
247 | unlock_buffer(new_bh); | |
248 | + error = -EIO; | |
249 | goto getblk_failed; | |
250 | } | |
251 | memcpy(new_bh->b_data, s->base, new_bh->b_size); |