xarray: add the xa_lock to the radix_tree_root
[linux-2.6-microblaze.git] / fs / f2fs / node.c
index 177c438..9a99243 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);
@@ -1076,7 +1097,7 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
 
        f2fs_wait_on_page_writeback(page, NODE, true);
        fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
-       set_cold_node(dn->inode, page);
+       set_cold_node(page, S_ISDIR(dn->inode->i_mode));
        if (!PageUptodate(page))
                SetPageUptodate(page);
        if (set_page_dirty(page))
@@ -2291,6 +2312,7 @@ retry:
        if (!PageUptodate(ipage))
                SetPageUptodate(ipage);
        fill_node_footer(ipage, ino, ino, 0, true);
+       set_cold_node(page, false);
 
        src = F2FS_INODE(page);
        dst = F2FS_INODE(ipage);
@@ -2580,8 +2602,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
        if (!enabled_nat_bits(sbi, NULL))
                return 0;
 
-       nm_i->nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 8 +
-                                               F2FS_BLKSIZE - 1);
+       nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
        nm_i->nat_bits = f2fs_kzalloc(sbi,
                        nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL);
        if (!nm_i->nat_bits)
@@ -2707,12 +2728,20 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
 static int init_free_nid_cache(struct f2fs_sb_info *sbi)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
+       int i;
 
-       nm_i->free_nid_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks *
-                                       NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL);
+       nm_i->free_nid_bitmap = f2fs_kzalloc(sbi, nm_i->nat_blocks *
+                               sizeof(unsigned char *), GFP_KERNEL);
        if (!nm_i->free_nid_bitmap)
                return -ENOMEM;
 
+       for (i = 0; i < nm_i->nat_blocks; i++) {
+               nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi,
+                               NAT_ENTRY_BITMAP_SIZE_ALIGNED, GFP_KERNEL);
+               if (!nm_i->free_nid_bitmap)
+                       return -ENOMEM;
+       }
+
        nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8,
                                                                GFP_KERNEL);
        if (!nm_i->nat_block_bitmap)
@@ -2803,7 +2832,13 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
        up_write(&nm_i->nat_tree_lock);
 
        kvfree(nm_i->nat_block_bitmap);
-       kvfree(nm_i->free_nid_bitmap);
+       if (nm_i->free_nid_bitmap) {
+               int i;
+
+               for (i = 0; i < nm_i->nat_blocks; i++)
+                       kvfree(nm_i->free_nid_bitmap[i]);
+               kfree(nm_i->free_nid_bitmap);
+       }
        kvfree(nm_i->free_nid_count);
 
        kfree(nm_i->nat_bitmap);