aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-08-12 03:04:53 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-08-12 03:04:53 -0400
commit479bd73ac425ff117efeea051077b4277baab52e (patch)
treea078a20d6d657f4b77140392be5a6316c96110a3
parent9c02740c0174932162531a28ba8593e82884a9d7 (diff)
f2fs: should cover i_xattr_nid with its xattr node page lock
Previously, f2fs_setxattr assigns i_xattr_nid in the inode page inconsistently. The scenario is: = Thread 1 = = Thread 2 = = fi->i_xattr_nid = = on-disk nid = f2fs_setxattr 0 0 new_node_page X 0 sync_inode_page X X checkpoint X X -. grab_cache_page X X | --> allocate a new xattr node block or -ENOSPC <----------------' At this moment, the checkpoint stores inconsistent data where the inode has i_xattr_nid but actual xattr node block is not allocated yet. So, we should assign the real i_xattr_nid only after its xattr node block is allocated. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
-rw-r--r--fs/f2fs/node.c3
-rw-r--r--fs/f2fs/xattr.c10
2 files changed, 8 insertions, 5 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 858a333f6ab9..1c21344fba30 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -851,6 +851,9 @@ struct page *new_node_page(struct dnode_of_data *dn,
851 SetPageUptodate(page); 851 SetPageUptodate(page);
852 set_page_dirty(page); 852 set_page_dirty(page);
853 853
854 if (ofs == XATTR_NODE_OFFSET)
855 F2FS_I(dn->inode)->i_xattr_nid = dn->nid;
856
854 dn->node_page = page; 857 dn->node_page = page;
855 if (ipage) 858 if (ipage)
856 update_inode(dn->inode, ipage); 859 update_inode(dn->inode, ipage);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index fb16f71e4c23..3bc307c22b70 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -378,23 +378,23 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
378 if (!fi->i_xattr_nid) { 378 if (!fi->i_xattr_nid) {
379 /* Allocate new attribute block */ 379 /* Allocate new attribute block */
380 struct dnode_of_data dn; 380 struct dnode_of_data dn;
381 nid_t new_nid;
381 382
382 if (!alloc_nid(sbi, &fi->i_xattr_nid)) { 383 if (!alloc_nid(sbi, &new_nid)) {
383 error = -ENOSPC; 384 error = -ENOSPC;
384 goto exit; 385 goto exit;
385 } 386 }
386 set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); 387 set_new_dnode(&dn, inode, NULL, NULL, new_nid);
387 mark_inode_dirty(inode); 388 mark_inode_dirty(inode);
388 389
389 page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); 390 page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage);
390 if (IS_ERR(page)) { 391 if (IS_ERR(page)) {
391 alloc_nid_failed(sbi, fi->i_xattr_nid); 392 alloc_nid_failed(sbi, new_nid);
392 fi->i_xattr_nid = 0;
393 error = PTR_ERR(page); 393 error = PTR_ERR(page);
394 goto exit; 394 goto exit;
395 } 395 }
396 396
397 alloc_nid_done(sbi, fi->i_xattr_nid); 397 alloc_nid_done(sbi, new_nid);
398 base_addr = page_address(page); 398 base_addr = page_address(page);
399 header = XATTR_HDR(base_addr); 399 header = XATTR_HDR(base_addr);
400 header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC); 400 header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);