aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-12-27 03:04:17 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2014-01-06 02:42:21 -0500
commita8865372a8414298982e07f4ac8d6dc0ab1e0a3d (patch)
treed854711c56be4c135701610710c0fda95a297d13 /fs/f2fs
parent1e1bb4baf10be371f72150e2801d97a04d40b3b9 (diff)
f2fs: handle errors correctly during f2fs_reserve_block
The get_dnode_of_data nullifies inode and node page when error is occurred. There are two cases that passes inode page into get_dnode_of_data(). 1. make_empty_dir() -> get_new_data_page() -> f2fs_reserve_block(ipage) -> get_dnode_of_data() 2. f2fs_convert_inline_data() -> __f2fs_convert_inline_data() -> f2fs_reserve_block(ipage) -> get_dnode_of_data() This patch adds correct error handling codes when get_dnode_of_data() returns an error. At first, f2fs_reserve_block() calls f2fs_put_dnode() whenever reserve_new_block returns an error. So, the rule of f2fs_reserve_block() is to nullify inode page when there is any error internally. Finally, two callers of f2fs_reserve_block() should call f2fs_put_dnode() appropriately if they got an error since successful f2fs_reserve_block(). Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/data.c29
-rw-r--r--fs/f2fs/dir.c7
-rw-r--r--fs/f2fs/inline.c6
3 files changed, 26 insertions, 16 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index fc7a28c5ad23..63d190264a36 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -258,13 +258,16 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index)
258 bool need_put = dn->inode_page ? false : true; 258 bool need_put = dn->inode_page ? false : true;
259 int err; 259 int err;
260 260
261 /* if inode_page exists, index should be zero */
262 f2fs_bug_on(!need_put && index);
263
261 err = get_dnode_of_data(dn, index, ALLOC_NODE); 264 err = get_dnode_of_data(dn, index, ALLOC_NODE);
262 if (err) 265 if (err)
263 return err; 266 return err;
267
264 if (dn->data_blkaddr == NULL_ADDR) 268 if (dn->data_blkaddr == NULL_ADDR)
265 err = reserve_new_block(dn); 269 err = reserve_new_block(dn);
266 270 if (err || need_put)
267 if (need_put)
268 f2fs_put_dnode(dn); 271 f2fs_put_dnode(dn);
269 return err; 272 return err;
270} 273}
@@ -510,10 +513,10 @@ repeat:
510 * 513 *
511 * Also, caller should grab and release a rwsem by calling f2fs_lock_op() and 514 * Also, caller should grab and release a rwsem by calling f2fs_lock_op() and
512 * f2fs_unlock_op(). 515 * f2fs_unlock_op().
513 * Note that, npage is set only by make_empty_dir. 516 * Note that, ipage is set only by make_empty_dir.
514 */ 517 */
515struct page *get_new_data_page(struct inode *inode, 518struct page *get_new_data_page(struct inode *inode,
516 struct page *npage, pgoff_t index, bool new_i_size) 519 struct page *ipage, pgoff_t index, bool new_i_size)
517{ 520{
518 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 521 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
519 struct address_space *mapping = inode->i_mapping; 522 struct address_space *mapping = inode->i_mapping;
@@ -521,14 +524,16 @@ struct page *get_new_data_page(struct inode *inode,
521 struct dnode_of_data dn; 524 struct dnode_of_data dn;
522 int err; 525 int err;
523 526
524 set_new_dnode(&dn, inode, npage, npage, 0); 527 set_new_dnode(&dn, inode, ipage, NULL, 0);
525 err = f2fs_reserve_block(&dn, index); 528 err = f2fs_reserve_block(&dn, index);
526 if (err) 529 if (err)
527 return ERR_PTR(err); 530 return ERR_PTR(err);
528repeat: 531repeat:
529 page = grab_cache_page(mapping, index); 532 page = grab_cache_page(mapping, index);
530 if (!page) 533 if (!page) {
531 return ERR_PTR(-ENOMEM); 534 err = -ENOMEM;
535 goto put_err;
536 }
532 537
533 if (PageUptodate(page)) 538 if (PageUptodate(page))
534 return page; 539 return page;
@@ -540,11 +545,13 @@ repeat:
540 err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, 545 err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
541 READ_SYNC); 546 READ_SYNC);
542 if (err) 547 if (err)
543 return ERR_PTR(err); 548 goto put_err;
549
544 lock_page(page); 550 lock_page(page);
545 if (unlikely(!PageUptodate(page))) { 551 if (unlikely(!PageUptodate(page))) {
546 f2fs_put_page(page, 1); 552 f2fs_put_page(page, 1);
547 return ERR_PTR(-EIO); 553 err = -EIO;
554 goto put_err;
548 } 555 }
549 if (unlikely(page->mapping != mapping)) { 556 if (unlikely(page->mapping != mapping)) {
550 f2fs_put_page(page, 1); 557 f2fs_put_page(page, 1);
@@ -560,6 +567,10 @@ repeat:
560 mark_inode_dirty_sync(inode); 567 mark_inode_dirty_sync(inode);
561 } 568 }
562 return page; 569 return page;
570
571put_err:
572 f2fs_put_dnode(&dn);
573 return ERR_PTR(err);
563} 574}
564 575
565static int __allocate_data_block(struct dnode_of_data *dn) 576static int __allocate_data_block(struct dnode_of_data *dn)
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 6da77e5c753b..f815ca0c5819 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -342,11 +342,11 @@ static struct page *init_inode_metadata(struct inode *inode,
342 342
343 err = f2fs_init_acl(inode, dir, page); 343 err = f2fs_init_acl(inode, dir, page);
344 if (err) 344 if (err)
345 goto error; 345 goto put_error;
346 346
347 err = f2fs_init_security(inode, dir, name, page); 347 err = f2fs_init_security(inode, dir, name, page);
348 if (err) 348 if (err)
349 goto error; 349 goto put_error;
350 350
351 wait_on_page_writeback(page); 351 wait_on_page_writeback(page);
352 } else { 352 } else {
@@ -370,8 +370,9 @@ static struct page *init_inode_metadata(struct inode *inode,
370 } 370 }
371 return page; 371 return page;
372 372
373error: 373put_error:
374 f2fs_put_page(page, 1); 374 f2fs_put_page(page, 1);
375error:
375 remove_inode_page(inode); 376 remove_inode_page(inode);
376 return ERR_PTR(err); 377 return ERR_PTR(err);
377} 378}
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 2a756e57aed9..688305afbc74 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -81,10 +81,9 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
81 * i_addr[0] is not used for inline data, 81 * i_addr[0] is not used for inline data,
82 * so reserving new block will not destroy inline data 82 * so reserving new block will not destroy inline data
83 */ 83 */
84 set_new_dnode(&dn, inode, ipage, ipage, 0); 84 set_new_dnode(&dn, inode, ipage, NULL, 0);
85 err = f2fs_reserve_block(&dn, 0); 85 err = f2fs_reserve_block(&dn, 0);
86 if (err) { 86 if (err) {
87 f2fs_put_page(ipage, 1);
88 f2fs_unlock_op(sbi); 87 f2fs_unlock_op(sbi);
89 return err; 88 return err;
90 } 89 }
@@ -111,9 +110,8 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
111 stat_dec_inline_inode(inode); 110 stat_dec_inline_inode(inode);
112 111
113 sync_inode_page(&dn); 112 sync_inode_page(&dn);
114 f2fs_put_page(ipage, 1); 113 f2fs_put_dnode(&dn);
115 f2fs_unlock_op(sbi); 114 f2fs_unlock_op(sbi);
116
117 return err; 115 return err;
118} 116}
119 117