f2fs: call set_buffer_new for get_block
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / fs / f2fs / data.c
index 3e0f5f303c970fc8236771e15be34f4deaeefd72..26e247697e58b51c51bb411756f2962847d0e2a4 100644 (file)
@@ -274,7 +274,7 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
                unsigned int blkbits = inode->i_sb->s_blocksize_bits;
                size_t count;
 
-               clear_buffer_new(bh_result);
+               set_buffer_new(bh_result);
                map_bh(bh_result, inode->i_sb,
                                start_blkaddr + pgofs - start_fofs);
                count = end_fofs - pgofs + 1;
@@ -564,6 +564,7 @@ static int __allocate_data_block(struct dnode_of_data *dn)
        struct f2fs_inode_info *fi = F2FS_I(dn->inode);
        struct f2fs_summary sum;
        struct node_info ni;
+       int seg = CURSEG_WARM_DATA;
        pgoff_t fofs;
 
        if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
@@ -574,8 +575,10 @@ static int __allocate_data_block(struct dnode_of_data *dn)
        get_node_info(sbi, dn->nid, &ni);
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
-       allocate_data_block(sbi, NULL, NULL_ADDR, &dn->data_blkaddr, &sum,
-                                                       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, &dn->data_blkaddr, &sum, seg);
 
        /* direct IO doesn't use extent cache to maximize the performance */
        __set_data_blkaddr(dn);
@@ -631,12 +634,14 @@ static int __get_data_block(struct inode *inode, sector_t iblock,
                goto put_out;
 
        if (dn.data_blkaddr != NULL_ADDR) {
+               set_buffer_new(bh_result);
                map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
        } else if (create) {
                err = __allocate_data_block(&dn);
                if (err)
                        goto put_out;
                allocated = true;
+               set_buffer_new(bh_result);
                map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
        } else {
                goto put_out;
@@ -815,7 +820,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;
@@ -834,7 +839,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;
        }
 
@@ -1113,21 +1117,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;
 }
@@ -1177,8 +1193,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,
 };