]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
f2fs: fix inconsistency between xattr node blocks and its inode
authorJaegeuk Kim <jaegeuk.kim@samsung.com>
Fri, 9 Aug 2013 05:46:15 +0000 (14:46 +0900)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Fri, 9 Aug 2013 06:25:24 +0000 (15:25 +0900)
Previously xattr node blocks are stored to the COLD_NODE log, which means that
our roll-forward mechanism doesn't recover the xattr node blocks at all.
Only the direct node blocks in the WARM_NODE log can be recovered.

So, let's resolve the issue simply by conducting checkpoint during fsync when a
file has a modified xattr node block.

This approach is able to degrade the performance, but normally the checkpoint
overhead is shown at the initial fsync call after the xattr entry changes.
Once the checkpoint is done, no additional overhead would be occurred.

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/xattr.c

index eb8c45b65fe5e79ccef8a41d8d82a69b2582be2c..c1c9670e642f75789ff5ef45d3c23c29f9579b55 100644 (file)
@@ -181,6 +181,7 @@ struct f2fs_inode_info {
        f2fs_hash_t chash;              /* hash value of given file name */
        unsigned int clevel;            /* maximum level of given file name */
        nid_t i_xattr_nid;              /* node id that contains xattrs */
+       unsigned long long xattr_ver;   /* cp version of xattr modification */
        struct extent_info ext;         /* in-memory extent cache entry */
 };
 
index c2deb27ffb7205c85fa5065fec17979f3260d204..8ef3184b003782a9ad8e01e9386c6bc39135c37c 100644 (file)
@@ -161,10 +161,15 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                need_cp = true;
        else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino))
                need_cp = true;
+       else if (F2FS_I(inode)->xattr_ver ==
+                       le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver))
+               need_cp = true;
 
        if (need_cp) {
                nid_t pino;
 
+               F2FS_I(inode)->xattr_ver = 0;
+
                /* all the dirty node pages should be flushed for POR */
                ret = f2fs_sync_fs(inode->i_sb, 1);
                if (file_wrong_pino(inode) && inode->i_nlink == 1 &&
index 3ab07ecd86ca16b5aaaa4e89792e5fe0db22ffca..0f6d2a1b9a7aa80e3c0e19891b4a3dc5b42a1369 100644 (file)
@@ -486,6 +486,10 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
                inode->i_ctime = CURRENT_TIME;
                clear_inode_flag(fi, FI_ACL_MODE);
        }
+
+       /* store checkpoint version for conducting checkpoint during fsync */
+       fi->xattr_ver = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
+
        if (ipage)
                update_inode(inode, ipage);
        else