f2fs: add info of appended or updated data writes
authorJaegeuk Kim <jaegeuk@kernel.org>
Fri, 25 Jul 2014 14:40:59 +0000 (07:40 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 29 Jul 2014 14:46:11 +0000 (07:46 -0700)
This patch introduces a inode number list in which represents inodes having
appended data writes or updated data writes after last checkpoint.
This will be used at fsync to determine whether the recovery information
should be written or not.

Reviewed-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/inline.c
fs/f2fs/inode.c

index 4bf203756cf84284f87fd626891be66e5c6d11f0..430163d8c806a9d0ceb99a7b8e8058ef9f05bcff 100644 (file)
@@ -326,6 +326,44 @@ static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
        spin_unlock(&sbi->ino_lock[type]);
 }
 
+void add_dirty_inode(struct f2fs_sb_info *sbi, nid_t ino, int type)
+{
+       /* add new dirty ino entry into list */
+       __add_ino_entry(sbi, ino, type);
+}
+
+void remove_dirty_inode(struct f2fs_sb_info *sbi, nid_t ino, int type)
+{
+       /* remove dirty ino entry from list */
+       __remove_ino_entry(sbi, ino, type);
+}
+
+/* mode should be APPEND_INO or UPDATE_INO */
+bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
+{
+       struct ino_entry *e;
+       spin_lock(&sbi->ino_lock[mode]);
+       e = radix_tree_lookup(&sbi->ino_root[mode], ino);
+       spin_unlock(&sbi->ino_lock[mode]);
+       return e ? true : false;
+}
+
+static void release_dirty_inode(struct f2fs_sb_info *sbi)
+{
+       struct ino_entry *e, *tmp;
+       int i;
+
+       for (i = APPEND_INO; i <= UPDATE_INO; i++) {
+               spin_lock(&sbi->ino_lock[i]);
+               list_for_each_entry_safe(e, tmp, &sbi->ino_list[i], list) {
+                       list_del(&e->list);
+                       radix_tree_delete(&sbi->ino_root[i], e->ino);
+                       kmem_cache_free(ino_entry_slab, e);
+               }
+               spin_unlock(&sbi->ino_lock[i]);
+       }
+}
+
 int acquire_orphan_inode(struct f2fs_sb_info *sbi)
 {
        int err = 0;
@@ -897,6 +935,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
        if (unlikely(!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) {
                clear_prefree_segments(sbi);
+               release_dirty_inode(sbi);
                F2FS_RESET_SB_DIRT(sbi);
        }
 }
index 482313dd9e24e88ef3f9e338a1021d78a43d214b..ec3c8860539e205e163cfe975a4c36ee191695af 100644 (file)
@@ -789,9 +789,11 @@ int do_write_data_page(struct page *page, struct f2fs_io_info *fio)
                        !is_cold_data(page) &&
                        need_inplace_update(inode))) {
                rewrite_data_page(page, old_blkaddr, fio);
+               set_inode_flag(F2FS_I(inode), FI_UPDATE_WRITE);
        } else {
                write_data_page(page, &dn, &new_blkaddr, fio);
                update_extent_cache(new_blkaddr, &dn);
+               set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
        }
 out_writepage:
        f2fs_put_dnode(&dn);
index 4454caa8a253d39c6a83dd622111624d7e57837d..ab3602576fb2970ba3e9aad579be7c29d18ed775 100644 (file)
@@ -103,6 +103,8 @@ enum {
 /* for the list of ino */
 enum {
        ORPHAN_INO,             /* for orphan ino list */
+       APPEND_INO,             /* for append ino list */
+       UPDATE_INO,             /* for update ino list */
        MAX_INO_ENTRY,          /* max. list */
 };
 
@@ -994,6 +996,8 @@ enum {
        FI_NO_EXTENT,           /* not to use the extent cache */
        FI_INLINE_XATTR,        /* used for inline xattr */
        FI_INLINE_DATA,         /* used for inline data*/
+       FI_APPEND_WRITE,        /* inode has appended data */
+       FI_UPDATE_WRITE,        /* inode has in-place-update data */
 };
 
 static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
@@ -1252,6 +1256,9 @@ struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
 int ra_meta_pages(struct f2fs_sb_info *, int, int, int);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
+void add_dirty_inode(struct f2fs_sb_info *, nid_t, int type);
+void remove_dirty_inode(struct f2fs_sb_info *, nid_t, int type);
+bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
 int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
 void add_orphan_inode(struct f2fs_sb_info *, nid_t);
index 1bba5228c197443eb3a8ec893ab84d09462525e4..5beeccef9ae1bf968c29f688e4b70664e6f8ce82 100644 (file)
@@ -172,6 +172,7 @@ int f2fs_write_inline_data(struct inode *inode,
                stat_inc_inline_inode(inode);
        }
 
+       set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
        sync_inode_page(&dn);
        f2fs_put_dnode(&dn);
 
index cafba3c9f8d866f25b3a77cc8e224f983f17e0ed..0e69aa90238dc0472700509f9ed5e1873d5b3466 100644 (file)
@@ -296,6 +296,10 @@ void f2fs_evict_inode(struct inode *inode)
        sb_end_intwrite(inode->i_sb);
 no_delete:
        invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino);
+       if (is_inode_flag_set(F2FS_I(inode), FI_APPEND_WRITE))
+               add_dirty_inode(sbi, inode->i_ino, APPEND_INO);
+       if (is_inode_flag_set(F2FS_I(inode), FI_UPDATE_WRITE))
+               add_dirty_inode(sbi, inode->i_ino, UPDATE_INO);
 out_clear:
        clear_inode(inode);
 }