]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/f2fs/data.c
f2fs: merge {invalidate,release}page for meta/node/data pages
[karo-tx-linux.git] / fs / f2fs / data.c
index 155885bf714cecaef20861ebd17ff289c73ce1e6..d166557ca8673917c66c95657d4c670c0e3c1849 100644 (file)
@@ -563,31 +563,25 @@ static int __allocate_data_block(struct dnode_of_data *dn)
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        struct f2fs_inode_info *fi = F2FS_I(dn->inode);
        struct f2fs_summary sum;
-       block_t new_blkaddr;
        struct node_info ni;
+       int seg = CURSEG_WARM_DATA;
        pgoff_t fofs;
-       int type;
 
        if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
                return -EPERM;
        if (unlikely(!inc_valid_block_count(sbi, dn->inode, 1)))
                return -ENOSPC;
 
-       dn->data_blkaddr = NEW_ADDR;
-       __set_data_blkaddr(dn);
-
        get_node_info(sbi, dn->nid, &ni);
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
-       type = CURSEG_WARM_DATA;
+       if (dn->ofs_in_node == 0 && dn->inode_page == dn->node_page)
+               seg = CURSEG_DIRECT_IO;
 
-       allocate_data_block(sbi, NULL, NULL_ADDR, &new_blkaddr, &sum, type);
+       allocate_data_block(sbi, NULL, NULL_ADDR, &dn->data_blkaddr, &sum, seg);
 
        /* direct IO doesn't use extent cache to maximize the performance */
-       set_inode_flag(F2FS_I(dn->inode), FI_NO_EXTENT);
-       dn->data_blkaddr = new_blkaddr;
-       update_extent_cache(dn);
-       clear_inode_flag(F2FS_I(dn->inode), FI_NO_EXTENT);
+       __set_data_blkaddr(dn);
 
        /* update i_size */
        fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
@@ -595,7 +589,6 @@ static int __allocate_data_block(struct dnode_of_data *dn)
        if (i_size_read(dn->inode) < ((fofs + 1) << PAGE_CACHE_SHIFT))
                i_size_write(dn->inode, ((fofs + 1) << PAGE_CACHE_SHIFT));
 
-       dn->data_blkaddr = new_blkaddr;
        return 0;
 }
 
@@ -825,7 +818,7 @@ static int f2fs_write_data_page(struct page *page,
 
        zero_user_segment(page, offset, PAGE_CACHE_SIZE);
 write:
-       if (unlikely(sbi->por_doing))
+       if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                goto redirty_out;
        if (f2fs_is_drop_cache(inode))
                goto out;
@@ -844,7 +837,6 @@ write:
        /* we should bypass data pages to proceed the kworkder jobs */
        if (unlikely(f2fs_cp_error(sbi))) {
                SetPageError(page);
-               unlock_page(page);
                goto out;
        }
 
@@ -1123,21 +1115,33 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
        return err;
 }
 
-static void f2fs_invalidate_data_page(struct page *page, unsigned int offset,
-                                     unsigned int length)
+void f2fs_invalidate_page(struct page *page, unsigned int offset,
+                                                       unsigned int length)
 {
        struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 
-       if (offset % PAGE_CACHE_SIZE || length != PAGE_CACHE_SIZE)
+       if (inode->i_ino >= F2FS_ROOT_INO(sbi) &&
+               (offset % PAGE_CACHE_SIZE || length != PAGE_CACHE_SIZE))
                return;
 
-       if (PageDirty(page))
-               inode_dec_dirty_pages(inode);
+       if (PageDirty(page)) {
+               if (inode->i_ino == F2FS_META_INO(sbi))
+                       dec_page_count(sbi, F2FS_DIRTY_META);
+               else if (inode->i_ino == F2FS_NODE_INO(sbi))
+                       dec_page_count(sbi, F2FS_DIRTY_NODES);
+               else
+                       inode_dec_dirty_pages(inode);
+       }
        ClearPagePrivate(page);
 }
 
-static int f2fs_release_data_page(struct page *page, gfp_t wait)
+int f2fs_release_page(struct page *page, gfp_t wait)
 {
+       /* If this is dirty page, keep PagePrivate */
+       if (PageDirty(page))
+               return 0;
+
        ClearPagePrivate(page);
        return 1;
 }
@@ -1187,8 +1191,8 @@ const struct address_space_operations f2fs_dblock_aops = {
        .write_begin    = f2fs_write_begin,
        .write_end      = f2fs_write_end,
        .set_page_dirty = f2fs_set_data_page_dirty,
-       .invalidatepage = f2fs_invalidate_data_page,
-       .releasepage    = f2fs_release_data_page,
+       .invalidatepage = f2fs_invalidate_page,
+       .releasepage    = f2fs_release_page,
        .direct_IO      = f2fs_direct_IO,
        .bmap           = f2fs_bmap,
 };