f2fs: do not make dirty any inmemory pages
authorJaegeuk Kim <jaegeuk@kernel.org>
Thu, 9 Oct 2014 20:19:53 +0000 (13:19 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 4 Nov 2014 00:07:29 +0000 (16:07 -0800)
This patch let inmemory pages be clean all the time.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/segment.c
fs/f2fs/super.c

index 8e58c4cc2cb96519359e45d66acd34191972786f..84f20e932499354123c1547b7303bf5627e46d1c 100644 (file)
@@ -1052,10 +1052,7 @@ static int f2fs_write_end(struct file *file,
 
        trace_f2fs_write_end(inode, pos, len, copied);
 
-       if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
-               register_inmem_page(inode, page);
-       else
-               set_page_dirty(page);
+       set_page_dirty(page);
 
        if (pos + copied > i_size_read(inode)) {
                i_size_write(inode, pos + copied);
@@ -1138,6 +1135,12 @@ static int f2fs_set_data_page_dirty(struct page *page)
        trace_f2fs_set_page_dirty(page, DATA);
 
        SetPageUptodate(page);
+
+       if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode)) {
+               register_inmem_page(inode, page);
+               return 1;
+       }
+
        mark_inode_dirty(inode);
 
        if (!PageDirty(page)) {
index 8171e80b2ee9f9709c953b4264ea92bee01011c6..28f24ea13cb2204342eac9b7d07205028882f015 100644 (file)
@@ -269,6 +269,7 @@ struct f2fs_inode_info {
        struct extent_info ext;         /* in-memory extent cache entry */
        struct dir_inode_entry *dirty_dir;      /* the pointer of dirty dir */
 
+       struct radix_tree_root inmem_root;      /* radix tree for inmem pages */
        struct list_head inmem_pages;   /* inmemory pages managed by f2fs */
        struct mutex inmem_lock;        /* lock for inmemory pages */
 };
index 923cb76fdc46e1e9f26b3a5014690e5c58d59fd0..9d4a7ab33b06ba203d19f89091f21312ccbdc092 100644 (file)
@@ -178,7 +178,8 @@ void register_inmem_page(struct inode *inode, struct page *page)
 {
        struct f2fs_inode_info *fi = F2FS_I(inode);
        struct inmem_pages *new;
-
+       int err;
+retry:
        new = f2fs_kmem_cache_alloc(inmem_entry_slab, GFP_NOFS);
 
        /* add atomic page indices to the list */
@@ -187,6 +188,16 @@ void register_inmem_page(struct inode *inode, struct page *page)
 
        /* increase reference count with clean state */
        mutex_lock(&fi->inmem_lock);
+       err = radix_tree_insert(&fi->inmem_root, page->index, new);
+       if (err == -EEXIST) {
+               mutex_unlock(&fi->inmem_lock);
+               kmem_cache_free(inmem_entry_slab, new);
+               return;
+       } else if (err) {
+               mutex_unlock(&fi->inmem_lock);
+               kmem_cache_free(inmem_entry_slab, new);
+               goto retry;
+       }
        get_page(page);
        list_add_tail(&new->list, &fi->inmem_pages);
        mutex_unlock(&fi->inmem_lock);
@@ -216,6 +227,7 @@ void commit_inmem_pages(struct inode *inode, bool abort)
                        do_write_data_page(cur->page, &fio);
                        submit_bio = true;
                }
+               radix_tree_delete(&fi->inmem_root, cur->page->index);
                f2fs_put_page(cur->page, 1);
                list_del(&cur->list);
                kmem_cache_free(inmem_entry_slab, cur);
index 41d6f700f4ee66fc1f3c0f297187a8ef9d4cab11..76b14c8c7e166154d781d6041054eccd11f1c343 100644 (file)
@@ -373,6 +373,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
        fi->i_advise = 0;
        rwlock_init(&fi->ext.ext_lock);
        init_rwsem(&fi->i_sem);
+       INIT_RADIX_TREE(&fi->inmem_root, GFP_NOFS);
        INIT_LIST_HEAD(&fi->inmem_pages);
        mutex_init(&fi->inmem_lock);