f2fs: separate out iostat feature
[linux-2.6-microblaze.git] / fs / f2fs / checkpoint.c
index f795049..3962cfe 100644 (file)
@@ -18,6 +18,7 @@
 #include "f2fs.h"
 #include "node.h"
 #include "segment.h"
+#include "iostat.h"
 #include <trace/events/f2fs.h>
 
 #define DEFAULT_CHECKPOINT_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
@@ -444,7 +445,7 @@ static int f2fs_set_meta_page_dirty(struct page *page)
        if (!PageDirty(page)) {
                __set_page_dirty_nobuffers(page);
                inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
-               f2fs_set_page_private(page, 0);
+               set_page_private_reference(page);
                return 1;
        }
        return 0;
@@ -465,16 +466,29 @@ static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
                                                unsigned int devidx, int type)
 {
        struct inode_management *im = &sbi->im[type];
-       struct ino_entry *e, *tmp;
+       struct ino_entry *e = NULL, *new = NULL;
+
+       if (type == FLUSH_INO) {
+               rcu_read_lock();
+               e = radix_tree_lookup(&im->ino_root, ino);
+               rcu_read_unlock();
+       }
 
-       tmp = f2fs_kmem_cache_alloc(ino_entry_slab, GFP_NOFS);
+retry:
+       if (!e)
+               new = f2fs_kmem_cache_alloc(ino_entry_slab,
+                                               GFP_NOFS, true, NULL);
 
        radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
 
        spin_lock(&im->ino_lock);
        e = radix_tree_lookup(&im->ino_root, ino);
        if (!e) {
-               e = tmp;
+               if (!new) {
+                       spin_unlock(&im->ino_lock);
+                       goto retry;
+               }
+               e = new;
                if (unlikely(radix_tree_insert(&im->ino_root, ino, e)))
                        f2fs_bug_on(sbi, 1);
 
@@ -492,8 +506,8 @@ static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
        spin_unlock(&im->ino_lock);
        radix_tree_preload_end();
 
-       if (e != tmp)
-               kmem_cache_free(ino_entry_slab, tmp);
+       if (new && e != new)
+               kmem_cache_free(ino_entry_slab, new);
 }
 
 static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
@@ -1018,7 +1032,7 @@ void f2fs_update_dirty_page(struct inode *inode, struct page *page)
        inode_inc_dirty_pages(inode);
        spin_unlock(&sbi->inode_lock[type]);
 
-       f2fs_set_page_private(page, 0);
+       set_page_private_reference(page);
 }
 
 void f2fs_remove_dirty_inode(struct inode *inode)
@@ -1639,8 +1653,11 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 
        /* write cached NAT/SIT entries to NAT/SIT area */
        err = f2fs_flush_nat_entries(sbi, cpc);
-       if (err)
+       if (err) {
+               f2fs_err(sbi, "f2fs_flush_nat_entries failed err:%d, stop checkpoint", err);
+               f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
                goto stop;
+       }
 
        f2fs_flush_sit_entries(sbi, cpc);
 
@@ -1648,10 +1665,13 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        f2fs_save_inmem_curseg(sbi);
 
        err = do_checkpoint(sbi, cpc);
-       if (err)
+       if (err) {
+               f2fs_err(sbi, "do_checkpoint failed err:%d, stop checkpoint", err);
+               f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
                f2fs_release_discard_addrs(sbi);
-       else
+       } else {
                f2fs_clear_prefree_segments(sbi, cpc);
+       }
 
        f2fs_restore_inmem_curseg(sbi);
 stop: