aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-05-19 21:10:29 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-05-28 02:03:02 -0400
commit44a83ff6a81d84ab83bcb43a49ff1ba6c7e17cd1 (patch)
tree8b7c8b192d237ee774c0f1ab59f3a0007e463655 /fs/f2fs
parent64aa7ed98db489d1c41ef140876ada38498678ab (diff)
f2fs: update inode page after creation
I found a bug when testing power-off-recovery as follows. [Bug Scenario] 1. create a file 2. fsync the file 3. reboot w/o any sync 4. try to recover the file - found its fsync mark - found its dentry mark : try to recover its dentry - get its file name - get its parent inode number : here we got zero value The reason why we get the wrong parent inode number is that we didn't synchronize the inode page with its newly created inode information perfectly. Especially, previous f2fs stores fi->i_pino and writes it to the cached node page in a wrong order, which incurs the zero-valued i_pino during the recovery. So, this patch modifies the creation flow to fix the synchronization order of inode page with its inode. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/data.c1
-rw-r--r--fs/f2fs/dir.c85
-rw-r--r--fs/f2fs/f2fs.h3
-rw-r--r--fs/f2fs/node.c12
4 files changed, 51 insertions, 50 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index af7454939362..c320f7f31327 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -279,6 +279,7 @@ repeat:
279 * 279 *
280 * Also, caller should grab and release a mutex by calling mutex_lock_op() and 280 * Also, caller should grab and release a mutex by calling mutex_lock_op() and
281 * mutex_unlock_op(). 281 * mutex_unlock_op().
282 * Note that, npage is set only by make_empty_dir.
282 */ 283 */
283struct page *get_new_data_page(struct inode *inode, 284struct page *get_new_data_page(struct inode *inode,
284 struct page *npage, pgoff_t index, bool new_i_size) 285 struct page *npage, pgoff_t index, bool new_i_size)
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 7db6e58622d9..fc1dacf55b3a 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -264,15 +264,10 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
264 f2fs_put_page(page, 1); 264 f2fs_put_page(page, 1);
265} 265}
266 266
267void init_dent_inode(const struct qstr *name, struct page *ipage) 267static void init_dent_inode(const struct qstr *name, struct page *ipage)
268{ 268{
269 struct f2fs_node *rn; 269 struct f2fs_node *rn;
270 270
271 if (IS_ERR(ipage))
272 return;
273
274 wait_on_page_writeback(ipage);
275
276 /* copy name info. to this inode page */ 271 /* copy name info. to this inode page */
277 rn = (struct f2fs_node *)page_address(ipage); 272 rn = (struct f2fs_node *)page_address(ipage);
278 rn->i.i_namelen = cpu_to_le32(name->len); 273 rn->i.i_namelen = cpu_to_le32(name->len);
@@ -280,14 +275,15 @@ void init_dent_inode(const struct qstr *name, struct page *ipage)
280 set_page_dirty(ipage); 275 set_page_dirty(ipage);
281} 276}
282 277
283static int make_empty_dir(struct inode *inode, struct inode *parent) 278static int make_empty_dir(struct inode *inode,
279 struct inode *parent, struct page *page)
284{ 280{
285 struct page *dentry_page; 281 struct page *dentry_page;
286 struct f2fs_dentry_block *dentry_blk; 282 struct f2fs_dentry_block *dentry_blk;
287 struct f2fs_dir_entry *de; 283 struct f2fs_dir_entry *de;
288 void *kaddr; 284 void *kaddr;
289 285
290 dentry_page = get_new_data_page(inode, NULL, 0, true); 286 dentry_page = get_new_data_page(inode, page, 0, true);
291 if (IS_ERR(dentry_page)) 287 if (IS_ERR(dentry_page))
292 return PTR_ERR(dentry_page); 288 return PTR_ERR(dentry_page);
293 289
@@ -317,42 +313,47 @@ static int make_empty_dir(struct inode *inode, struct inode *parent)
317 return 0; 313 return 0;
318} 314}
319 315
320static int init_inode_metadata(struct inode *inode, 316static struct page *init_inode_metadata(struct inode *inode,
321 struct inode *dir, const struct qstr *name) 317 struct inode *dir, const struct qstr *name)
322{ 318{
319 struct page *page;
320 int err;
321
323 if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { 322 if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
324 int err; 323 page = new_inode_page(inode, name);
325 err = new_inode_page(inode, name); 324 if (IS_ERR(page))
326 if (err) 325 return page;
327 return err;
328 326
329 if (S_ISDIR(inode->i_mode)) { 327 if (S_ISDIR(inode->i_mode)) {
330 err = make_empty_dir(inode, dir); 328 err = make_empty_dir(inode, dir, page);
331 if (err) { 329 if (err)
332 remove_inode_page(inode); 330 goto error;
333 return err;
334 }
335 } 331 }
336 332
337 err = f2fs_init_acl(inode, dir); 333 err = f2fs_init_acl(inode, dir);
338 if (err) { 334 if (err)
339 remove_inode_page(inode); 335 goto error;
340 return err; 336
341 } 337 wait_on_page_writeback(page);
342 } else { 338 } else {
343 struct page *ipage; 339 page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
344 ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); 340 if (IS_ERR(page))
345 if (IS_ERR(ipage)) 341 return page;
346 return PTR_ERR(ipage); 342
347 set_cold_node(inode, ipage); 343 wait_on_page_writeback(page);
348 init_dent_inode(name, ipage); 344 set_cold_node(inode, page);
349 f2fs_put_page(ipage, 1);
350 } 345 }
351 if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { 346
347 init_dent_inode(name, page);
348
349 if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK))
352 inc_nlink(inode); 350 inc_nlink(inode);
353 update_inode_page(inode); 351 return page;
354 } 352
355 return 0; 353error:
354 f2fs_put_page(page, 1);
355 remove_inode_page(inode);
356 return ERR_PTR(err);
356} 357}
357 358
358static void update_parent_metadata(struct inode *dir, struct inode *inode, 359static void update_parent_metadata(struct inode *dir, struct inode *inode,
@@ -423,6 +424,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, struct inode *in
423 struct page *dentry_page = NULL; 424 struct page *dentry_page = NULL;
424 struct f2fs_dentry_block *dentry_blk = NULL; 425 struct f2fs_dentry_block *dentry_blk = NULL;
425 int slots = GET_DENTRY_SLOTS(namelen); 426 int slots = GET_DENTRY_SLOTS(namelen);
427 struct page *page;
426 int err = 0; 428 int err = 0;
427 int i; 429 int i;
428 430
@@ -465,12 +467,13 @@ start:
465 ++level; 467 ++level;
466 goto start; 468 goto start;
467add_dentry: 469add_dentry:
468 err = init_inode_metadata(inode, dir, name);
469 if (err)
470 goto fail;
471
472 wait_on_page_writeback(dentry_page); 470 wait_on_page_writeback(dentry_page);
473 471
472 page = init_inode_metadata(inode, dir, name);
473 if (IS_ERR(page)) {
474 err = PTR_ERR(page);
475 goto fail;
476 }
474 de = &dentry_blk->dentry[bit_pos]; 477 de = &dentry_blk->dentry[bit_pos];
475 de->hash_code = dentry_hash; 478 de->hash_code = dentry_hash;
476 de->name_len = cpu_to_le16(namelen); 479 de->name_len = cpu_to_le16(namelen);
@@ -481,10 +484,12 @@ add_dentry:
481 test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); 484 test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
482 set_page_dirty(dentry_page); 485 set_page_dirty(dentry_page);
483 486
484 update_parent_metadata(dir, inode, current_depth); 487 /* we don't need to mark_inode_dirty now */
485
486 /* update parent inode number before releasing dentry page */
487 F2FS_I(inode)->i_pino = dir->i_ino; 488 F2FS_I(inode)->i_pino = dir->i_ino;
489 update_inode(inode, page);
490 f2fs_put_page(page, 1);
491
492 update_parent_metadata(dir, inode, current_depth);
488fail: 493fail:
489 kunmap(dentry_page); 494 kunmap(dentry_page);
490 f2fs_put_page(dentry_page, 1); 495 f2fs_put_page(dentry_page, 1);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index cbae2b663eba..9360a03fcc96 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -914,7 +914,6 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
914ino_t f2fs_inode_by_name(struct inode *, struct qstr *); 914ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
915void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, 915void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
916 struct page *, struct inode *); 916 struct page *, struct inode *);
917void init_dent_inode(const struct qstr *, struct page *);
918int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *); 917int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *);
919void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *); 918void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
920int f2fs_make_empty(struct inode *, struct inode *); 919int f2fs_make_empty(struct inode *, struct inode *);
@@ -949,7 +948,7 @@ void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
949int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); 948int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
950int truncate_inode_blocks(struct inode *, pgoff_t); 949int truncate_inode_blocks(struct inode *, pgoff_t);
951int remove_inode_page(struct inode *); 950int remove_inode_page(struct inode *);
952int new_inode_page(struct inode *, const struct qstr *); 951struct page *new_inode_page(struct inode *, const struct qstr *);
953struct page *new_node_page(struct dnode_of_data *, unsigned int); 952struct page *new_node_page(struct dnode_of_data *, unsigned int);
954void ra_node_page(struct f2fs_sb_info *, nid_t); 953void ra_node_page(struct f2fs_sb_info *, nid_t);
955struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); 954struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index f63f0a4046c6..b41482de492f 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -806,19 +806,15 @@ int remove_inode_page(struct inode *inode)
806 return 0; 806 return 0;
807} 807}
808 808
809int new_inode_page(struct inode *inode, const struct qstr *name) 809struct page *new_inode_page(struct inode *inode, const struct qstr *name)
810{ 810{
811 struct page *page;
812 struct dnode_of_data dn; 811 struct dnode_of_data dn;
813 812
814 /* allocate inode page for new inode */ 813 /* allocate inode page for new inode */
815 set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); 814 set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
816 page = new_node_page(&dn, 0); 815
817 init_dent_inode(name, page); 816 /* caller should f2fs_put_page(page, 1); */
818 if (IS_ERR(page)) 817 return new_node_page(&dn, 0);
819 return PTR_ERR(page);
820 f2fs_put_page(page, 1);
821 return 0;
822} 818}
823 819
824struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) 820struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)