f2fs: don't track new nat entry in nat set
authorChao Yu <yuchao0@huawei.com>
Tue, 20 Mar 2018 15:08:30 +0000 (23:08 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Sun, 8 Apr 2018 11:14:37 +0000 (04:14 -0700)
Nat entry set is used only in checkpoint(), and during checkpoint() we
won't flush new nat entry with unallocated address, so we don't need to
add new nat entry into nat set, then nat_entry_set::entry_cnt can
indicate actual entry count we need to flush in checkpoint().

Signed-off-by: Yunlei He <heyunlei@huawei.com>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/node.c
fs/f2fs/node.h

index 9bdefe4a5cd9e799a120e8ff8297cc4933b7c3ff..199170e2e22127f7c74e7fada80b65e072ed61fb 100644 (file)
@@ -193,8 +193,8 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
        __free_nat_entry(e);
 }
 
-static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
-                                               struct nat_entry *ne)
+static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
+                                                       struct nat_entry *ne)
 {
        nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid);
        struct nat_entry_set *head;
@@ -209,15 +209,36 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
                head->entry_cnt = 0;
                f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head);
        }
+       return head;
+}
+
+static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
+                                               struct nat_entry *ne)
+{
+       struct nat_entry_set *head;
+       bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
+
+       if (!new_ne)
+               head = __grab_nat_entry_set(nm_i, ne);
+
+       /*
+        * update entry_cnt in below condition:
+        * 1. update NEW_ADDR to valid block address;
+        * 2. update old block address to new one;
+        */
+       if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) ||
+                               !get_nat_flag(ne, IS_DIRTY)))
+               head->entry_cnt++;
+
+       set_nat_flag(ne, IS_PREALLOC, new_ne);
 
        if (get_nat_flag(ne, IS_DIRTY))
                goto refresh_list;
 
        nm_i->dirty_nat_cnt++;
-       head->entry_cnt++;
        set_nat_flag(ne, IS_DIRTY, true);
 refresh_list:
-       if (nat_get_blkaddr(ne) == NEW_ADDR)
+       if (new_ne)
                list_del_init(&ne->list);
        else
                list_move_tail(&ne->list, &head->entry_list);
index e593b4d78be22851a154803c911b57587bd89e7b..b95e49e4a928a77c421f53175a8b8cde36c2ef6b 100644 (file)
@@ -44,6 +44,7 @@ enum {
        HAS_FSYNCED_INODE,      /* is the inode fsynced before? */
        HAS_LAST_FSYNC,         /* has the latest node fsync mark? */
        IS_DIRTY,               /* this nat entry is dirty? */
+       IS_PREALLOC,            /* nat entry is preallocated */
 };
 
 /*