diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-05-21 19:20:01 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-05-28 02:03:04 -0400 |
commit | 39cf72cf09c8f36a383919e7675bdb15bd4db53b (patch) | |
tree | c0cfa3c97591790f03224959453a36aa44235e63 /fs/f2fs | |
parent | b292dcab068e141d8a820b77cbcc88d98c610eb4 (diff) |
f2fs: fix to handle do_recover_data errors
This patch adds error handling codes of check_index_in_prev_nodes and its
caller, do_recover_data.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/recovery.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index eceb6652532d..dcd8e860aad3 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -188,7 +188,7 @@ static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, | |||
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | 191 | static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, |
192 | block_t blkaddr, struct dnode_of_data *dn) | 192 | block_t blkaddr, struct dnode_of_data *dn) |
193 | { | 193 | { |
194 | struct seg_entry *sentry; | 194 | struct seg_entry *sentry; |
@@ -205,7 +205,7 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
205 | 205 | ||
206 | sentry = get_seg_entry(sbi, segno); | 206 | sentry = get_seg_entry(sbi, segno); |
207 | if (!f2fs_test_bit(blkoff, sentry->cur_valid_map)) | 207 | if (!f2fs_test_bit(blkoff, sentry->cur_valid_map)) |
208 | return; | 208 | return 0; |
209 | 209 | ||
210 | /* Get the previous summary */ | 210 | /* Get the previous summary */ |
211 | for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) { | 211 | for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) { |
@@ -232,16 +232,18 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
232 | tdn.node_page = dn->inode_page; | 232 | tdn.node_page = dn->inode_page; |
233 | tdn.ofs_in_node = sum.ofs_in_node; | 233 | tdn.ofs_in_node = sum.ofs_in_node; |
234 | truncate_data_blocks_range(&tdn, 1); | 234 | truncate_data_blocks_range(&tdn, 1); |
235 | return; | 235 | return 0; |
236 | } else if (dn->nid == nid) { | 236 | } else if (dn->nid == nid) { |
237 | struct dnode_of_data tdn = *dn; | 237 | struct dnode_of_data tdn = *dn; |
238 | tdn.ofs_in_node = sum.ofs_in_node; | 238 | tdn.ofs_in_node = sum.ofs_in_node; |
239 | truncate_data_blocks_range(&tdn, 1); | 239 | truncate_data_blocks_range(&tdn, 1); |
240 | return; | 240 | return 0; |
241 | } | 241 | } |
242 | 242 | ||
243 | /* Get the node page */ | 243 | /* Get the node page */ |
244 | node_page = get_node_page(sbi, nid); | 244 | node_page = get_node_page(sbi, nid); |
245 | if (IS_ERR(node_page)) | ||
246 | return PTR_ERR(node_page); | ||
245 | bidx = start_bidx_of_node(ofs_of_node(node_page)) + | 247 | bidx = start_bidx_of_node(ofs_of_node(node_page)) + |
246 | le16_to_cpu(sum.ofs_in_node); | 248 | le16_to_cpu(sum.ofs_in_node); |
247 | ino = ino_of_node(node_page); | 249 | ino = ino_of_node(node_page); |
@@ -250,10 +252,11 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
250 | /* Deallocate previous index in the node page */ | 252 | /* Deallocate previous index in the node page */ |
251 | inode = f2fs_iget(sbi->sb, ino); | 253 | inode = f2fs_iget(sbi->sb, ino); |
252 | if (IS_ERR(inode)) | 254 | if (IS_ERR(inode)) |
253 | return; | 255 | return PTR_ERR(inode); |
254 | 256 | ||
255 | truncate_hole(inode, bidx, bidx + 1); | 257 | truncate_hole(inode, bidx, bidx + 1); |
256 | iput(inode); | 258 | iput(inode); |
259 | return 0; | ||
257 | } | 260 | } |
258 | 261 | ||
259 | static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | 262 | static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, |
@@ -301,7 +304,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
301 | } | 304 | } |
302 | 305 | ||
303 | /* Check the previous node page having this index */ | 306 | /* Check the previous node page having this index */ |
304 | check_index_in_prev_nodes(sbi, dest, &dn); | 307 | err = check_index_in_prev_nodes(sbi, dest, &dn); |
308 | if (err) | ||
309 | goto err; | ||
305 | 310 | ||
306 | set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); | 311 | set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); |
307 | 312 | ||
@@ -324,13 +329,14 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
324 | set_page_dirty(dn.node_page); | 329 | set_page_dirty(dn.node_page); |
325 | 330 | ||
326 | recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); | 331 | recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); |
332 | err: | ||
327 | f2fs_put_dnode(&dn); | 333 | f2fs_put_dnode(&dn); |
328 | mutex_unlock_op(sbi, ilock); | 334 | mutex_unlock_op(sbi, ilock); |
329 | 335 | ||
330 | f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, " | 336 | f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, " |
331 | "recovered_data = %d blocks", | 337 | "recovered_data = %d blocks, err = %d", |
332 | inode->i_ino, recovered); | 338 | inode->i_ino, recovered, err); |
333 | return 0; | 339 | return err; |
334 | } | 340 | } |
335 | 341 | ||
336 | static int recover_data(struct f2fs_sb_info *sbi, | 342 | static int recover_data(struct f2fs_sb_info *sbi, |