f2fs: clean up coding style and redundancy
[cascardo/linux.git] / fs / f2fs / data.c
index 5dafb9c..614154f 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/bio.h>
 #include <linux/prefetch.h>
 #include <linux/uio.h>
+#include <linux/mm.h>
+#include <linux/memcontrol.h>
 #include <linux/cleancache.h>
 
 #include "f2fs.h"
@@ -45,7 +47,8 @@ static void f2fs_read_end_io(struct bio *bio)
                struct page *page = bvec->bv_page;
 
                if (!bio->bi_error) {
-                       SetPageUptodate(page);
+                       if (!PageUptodate(page))
+                               SetPageUptodate(page);
                } else {
                        ClearPageUptodate(page);
                        SetPageError(page);
@@ -68,13 +71,12 @@ static void f2fs_write_end_io(struct bio *bio)
 
                if (unlikely(bio->bi_error)) {
                        set_bit(AS_EIO, &page->mapping->flags);
-                       f2fs_stop_checkpoint(sbi);
+                       f2fs_stop_checkpoint(sbi, true);
                }
                end_page_writeback(page);
-               dec_page_count(sbi, F2FS_WRITEBACK);
        }
-
-       if (!get_pages(sbi, F2FS_WRITEBACK) && wq_has_sleeper(&sbi->cp_wait))
+       if (atomic_dec_and_test(&sbi->nr_wb_bios) &&
+                               wq_has_sleeper(&sbi->cp_wait))
                wake_up(&sbi->cp_wait);
 
        bio_put(bio);
@@ -98,6 +100,18 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
        return bio;
 }
 
+static inline void __submit_bio(struct f2fs_sb_info *sbi, int rw,
+                       struct bio *bio, enum page_type type)
+{
+       if (!is_read_io(rw)) {
+               atomic_inc(&sbi->nr_wb_bios);
+               if (f2fs_sb_mounted_hmsmr(sbi->sb) &&
+                       current->plug && (type == DATA || type == NODE))
+                       blk_finish_plug(current->plug);
+       }
+       submit_bio(rw, bio);
+}
+
 static void __submit_merged_bio(struct f2fs_bio_info *io)
 {
        struct f2fs_io_info *fio = &io->fio;
@@ -110,7 +124,7 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
        else
                trace_f2fs_submit_write_bio(io->sbi->sb, fio, io->bio);
 
-       submit_bio(fio->rw, io->bio);
+       __submit_bio(io->sbi, fio->rw, io->bio, fio->type);
        io->bio = NULL;
 }
 
@@ -228,7 +242,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
                return -EFAULT;
        }
 
-       submit_bio(fio->rw, bio);
+       __submit_bio(fio->sbi, fio->rw, bio, fio->type);
        return 0;
 }
 
@@ -248,9 +262,6 @@ void f2fs_submit_page_mbio(struct f2fs_io_info *fio)
 
        down_write(&io->io_rwsem);
 
-       if (!is_read)
-               inc_page_count(sbi, F2FS_WRITEBACK);
-
        if (io->bio && (io->last_block_in_bio != fio->new_blkaddr - 1 ||
                                                io->fio.rw != fio->rw))
                __submit_merged_bio(io);
@@ -278,6 +289,16 @@ alloc_new:
        trace_f2fs_submit_page_mbio(fio->page, fio);
 }
 
+static void __set_data_blkaddr(struct dnode_of_data *dn)
+{
+       struct f2fs_node *rn = F2FS_NODE(dn->node_page);
+       __le32 *addr_array;
+
+       /* Get physical address of data block */
+       addr_array = blkaddr_in_node(rn);
+       addr_array[dn->ofs_in_node] = cpu_to_le32(dn->data_blkaddr);
+}
+
 /*
  * Lock ordering for the change of data block address:
  * ->data_page
@@ -286,19 +307,9 @@ alloc_new:
  */
 void set_data_blkaddr(struct dnode_of_data *dn)
 {
-       struct f2fs_node *rn;
-       __le32 *addr_array;
-       struct page *node_page = dn->node_page;
-       unsigned int ofs_in_node = dn->ofs_in_node;
-
-       f2fs_wait_on_page_writeback(node_page, NODE, true);
-
-       rn = F2FS_NODE(node_page);
-
-       /* Get physical address of data block */
-       addr_array = blkaddr_in_node(rn);
-       addr_array[ofs_in_node] = cpu_to_le32(dn->data_blkaddr);
-       if (set_page_dirty(node_page))
+       f2fs_wait_on_page_writeback(dn->node_page, NODE, true);
+       __set_data_blkaddr(dn);
+       if (set_page_dirty(dn->node_page))
                dn->node_changed = true;
 }
 
@@ -309,24 +320,50 @@ void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr)
        f2fs_update_extent_cache(dn);
 }
 
-int reserve_new_block(struct dnode_of_data *dn)
+/* dn->ofs_in_node will be returned with up-to-date last block pointer */
+int reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
 
-       if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
+       if (!count)
+               return 0;
+
+       if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
                return -EPERM;
-       if (unlikely(!inc_valid_block_count(sbi, dn->inode, 1)))
+       if (unlikely(!inc_valid_block_count(sbi, dn->inode, &count)))
                return -ENOSPC;
 
-       trace_f2fs_reserve_new_block(dn->inode, dn->nid, dn->ofs_in_node);
+       trace_f2fs_reserve_new_blocks(dn->inode, dn->nid,
+                                               dn->ofs_in_node, count);
 
-       dn->data_blkaddr = NEW_ADDR;
-       set_data_blkaddr(dn);
-       mark_inode_dirty(dn->inode);
-       sync_inode_page(dn);
+       f2fs_wait_on_page_writeback(dn->node_page, NODE, true);
+
+       for (; count > 0; dn->ofs_in_node++) {
+               block_t blkaddr =
+                       datablock_addr(dn->node_page, dn->ofs_in_node);
+               if (blkaddr == NULL_ADDR) {
+                       dn->data_blkaddr = NEW_ADDR;
+                       __set_data_blkaddr(dn);
+                       count--;
+               }
+       }
+
+       if (set_page_dirty(dn->node_page))
+               dn->node_changed = true;
        return 0;
 }
 
+/* Should keep dn->ofs_in_node unchanged */
+int reserve_new_block(struct dnode_of_data *dn)
+{
+       unsigned int ofs_in_node = dn->ofs_in_node;
+       int ret;
+
+       ret = reserve_new_blocks(dn, 1);
+       dn->ofs_in_node = ofs_in_node;
+       return ret;
+}
+
 int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index)
 {
        bool need_put = dn->inode_page ? false : true;
@@ -407,7 +444,8 @@ got_it:
         */
        if (dn.data_blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_SIZE);
-               SetPageUptodate(page);
+               if (!PageUptodate(page))
+                       SetPageUptodate(page);
                unlock_page(page);
                return page;
        }
@@ -466,14 +504,14 @@ repeat:
 
        /* wait for read completion */
        lock_page(page);
-       if (unlikely(!PageUptodate(page))) {
-               f2fs_put_page(page, 1);
-               return ERR_PTR(-EIO);
-       }
        if (unlikely(page->mapping != mapping)) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
+       if (unlikely(!PageUptodate(page))) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(-EIO);
+       }
        return page;
 }
 
@@ -518,7 +556,8 @@ struct page *get_new_data_page(struct inode *inode,
 
        if (dn.data_blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_SIZE);
-               SetPageUptodate(page);
+               if (!PageUptodate(page))
+                       SetPageUptodate(page);
        } else {
                f2fs_put_page(page, 1);
 
@@ -530,11 +569,8 @@ struct page *get_new_data_page(struct inode *inode,
        }
 got_it:
        if (new_i_size && i_size_read(inode) <
-                               ((loff_t)(index + 1) << PAGE_SHIFT)) {
-               i_size_write(inode, ((loff_t)(index + 1) << PAGE_SHIFT));
-               /* Only the directory inode sets new_i_size */
-               set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR);
-       }
+                               ((loff_t)(index + 1) << PAGE_SHIFT))
+               f2fs_i_size_write(inode, ((loff_t)(index + 1) << PAGE_SHIFT));
        return page;
 }
 
@@ -545,15 +581,16 @@ static int __allocate_data_block(struct dnode_of_data *dn)
        struct node_info ni;
        int seg = CURSEG_WARM_DATA;
        pgoff_t fofs;
+       blkcnt_t count = 1;
 
-       if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
+       if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
                return -EPERM;
 
        dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
        if (dn->data_blkaddr == NEW_ADDR)
                goto alloc;
 
-       if (unlikely(!inc_valid_block_count(sbi, dn->inode, 1)))
+       if (unlikely(!inc_valid_block_count(sbi, dn->inode, &count)))
                return -ENOSPC;
 
 alloc:
@@ -571,7 +608,7 @@ alloc:
        fofs = start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
                                                        dn->ofs_in_node;
        if (i_size_read(dn->inode) < ((loff_t)(fofs + 1) << PAGE_SHIFT))
-               i_size_write(dn->inode,
+               f2fs_i_size_write(dn->inode,
                                ((loff_t)(fofs + 1) << PAGE_SHIFT));
        return 0;
 }
@@ -582,8 +619,8 @@ ssize_t f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
        struct f2fs_map_blocks map;
        ssize_t ret = 0;
 
-       map.m_lblk = F2FS_BYTES_TO_BLK(iocb->ki_pos);
-       map.m_len = F2FS_BLK_ALIGN(iov_iter_count(from));
+       map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos);
+       map.m_len = F2FS_BYTES_TO_BLK(iov_iter_count(from));
        map.m_next_pgofs = NULL;
 
        if (f2fs_encrypted_inode(inode))
@@ -620,9 +657,11 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
        unsigned int maxblocks = map->m_len;
        struct dnode_of_data dn;
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       int mode = create ? ALLOC_NODE : LOOKUP_NODE_RA;
-       pgoff_t pgofs, end_offset;
+       int mode = create ? ALLOC_NODE : LOOKUP_NODE;
+       pgoff_t pgofs, end_offset, end;
        int err = 0, ofs = 1;
+       unsigned int ofs_in_node, last_ofs_in_node;
+       blkcnt_t prealloc;
        struct extent_info ei;
        bool allocated = false;
        block_t blkaddr;
@@ -632,6 +671,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
 
        /* it only supports block size == page size */
        pgofs = (pgoff_t)map->m_lblk;
+       end = pgofs + maxblocks;
 
        if (!create && f2fs_lookup_extent_cache(inode, pgofs, &ei)) {
                map->m_pblk = ei.blk + pgofs - ei.fofs;
@@ -648,6 +688,8 @@ next_dnode:
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = get_dnode_of_data(&dn, pgofs, mode);
        if (err) {
+               if (flag == F2FS_GET_BLOCK_BMAP)
+                       map->m_pblk = 0;
                if (err == -ENOENT) {
                        err = 0;
                        if (map->m_next_pgofs)
@@ -657,6 +699,8 @@ next_dnode:
                goto unlock_out;
        }
 
+       prealloc = 0;
+       ofs_in_node = dn.ofs_in_node;
        end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
 
 next_block:
@@ -669,31 +713,40 @@ next_block:
                                goto sync_out;
                        }
                        if (flag == F2FS_GET_BLOCK_PRE_AIO) {
-                               if (blkaddr == NULL_ADDR)
-                                       err = reserve_new_block(&dn);
+                               if (blkaddr == NULL_ADDR) {
+                                       prealloc++;
+                                       last_ofs_in_node = dn.ofs_in_node;
+                               }
                        } else {
                                err = __allocate_data_block(&dn);
+                               if (!err) {
+                                       set_inode_flag(inode, FI_APPEND_WRITE);
+                                       allocated = true;
+                               }
                        }
                        if (err)
                                goto sync_out;
-                       allocated = true;
                        map->m_flags = F2FS_MAP_NEW;
                        blkaddr = dn.data_blkaddr;
                } else {
+                       if (flag == F2FS_GET_BLOCK_BMAP) {
+                               map->m_pblk = 0;
+                               goto sync_out;
+                       }
                        if (flag == F2FS_GET_BLOCK_FIEMAP &&
                                                blkaddr == NULL_ADDR) {
                                if (map->m_next_pgofs)
                                        *map->m_next_pgofs = pgofs + 1;
                        }
                        if (flag != F2FS_GET_BLOCK_FIEMAP ||
-                                               blkaddr != NEW_ADDR) {
-                               if (flag == F2FS_GET_BLOCK_BMAP)
-                                       err = -ENOENT;
+                                               blkaddr != NEW_ADDR)
                                goto sync_out;
-                       }
                }
        }
 
+       if (flag == F2FS_GET_BLOCK_PRE_AIO)
+               goto skip;
+
        if (map->m_len == 0) {
                /* preallocated unwritten block should be mapped for fiemap. */
                if (blkaddr == NEW_ADDR)
@@ -705,36 +758,49 @@ next_block:
        } else if ((map->m_pblk != NEW_ADDR &&
                        blkaddr == (map->m_pblk + ofs)) ||
                        (map->m_pblk == NEW_ADDR && blkaddr == NEW_ADDR) ||
-                       flag == F2FS_GET_BLOCK_PRE_DIO ||
-                       flag == F2FS_GET_BLOCK_PRE_AIO) {
+                       flag == F2FS_GET_BLOCK_PRE_DIO) {
                ofs++;
                map->m_len++;
        } else {
                goto sync_out;
        }
 
+skip:
        dn.ofs_in_node++;
        pgofs++;
 
-       if (map->m_len < maxblocks) {
-               if (dn.ofs_in_node < end_offset)
-                       goto next_block;
+       /* preallocate blocks in batch for one dnode page */
+       if (flag == F2FS_GET_BLOCK_PRE_AIO &&
+                       (pgofs == end || dn.ofs_in_node == end_offset)) {
 
-               if (allocated)
-                       sync_inode_page(&dn);
-               f2fs_put_dnode(&dn);
+               dn.ofs_in_node = ofs_in_node;
+               err = reserve_new_blocks(&dn, prealloc);
+               if (err)
+                       goto sync_out;
 
-               if (create) {
-                       f2fs_unlock_op(sbi);
-                       f2fs_balance_fs(sbi, allocated);
+               map->m_len += dn.ofs_in_node - ofs_in_node;
+               if (prealloc && dn.ofs_in_node != last_ofs_in_node + 1) {
+                       err = -ENOSPC;
+                       goto sync_out;
                }
-               allocated = false;
-               goto next_dnode;
+               dn.ofs_in_node = end_offset;
+       }
+
+       if (pgofs >= end)
+               goto sync_out;
+       else if (dn.ofs_in_node < end_offset)
+               goto next_block;
+
+       f2fs_put_dnode(&dn);
+
+       if (create) {
+               f2fs_unlock_op(sbi);
+               f2fs_balance_fs(sbi, allocated);
        }
+       allocated = false;
+       goto next_dnode;
 
 sync_out:
-       if (allocated)
-               sync_inode_page(&dn);
        f2fs_put_dnode(&dn);
 unlock_out:
        if (create) {
@@ -894,6 +960,37 @@ out:
        return ret;
 }
 
+struct bio *f2fs_grab_bio(struct inode *inode, block_t blkaddr,
+                                                       unsigned nr_pages)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct fscrypt_ctx *ctx = NULL;
+       struct block_device *bdev = sbi->sb->s_bdev;
+       struct bio *bio;
+
+       if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
+               ctx = fscrypt_get_ctx(inode, GFP_NOFS);
+               if (IS_ERR(ctx))
+                       return ERR_CAST(ctx);
+
+               /* wait the page to be moved by cleaning */
+               f2fs_wait_on_encrypted_page_writeback(sbi, blkaddr);
+       }
+
+       bio = bio_alloc(GFP_KERNEL, min_t(int, nr_pages, BIO_MAX_PAGES));
+       if (!bio) {
+               if (ctx)
+                       fscrypt_release_ctx(ctx);
+               return ERR_PTR(-ENOMEM);
+       }
+       bio->bi_bdev = bdev;
+       bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(blkaddr);
+       bio->bi_end_io = f2fs_read_end_io;
+       bio->bi_private = ctx;
+
+       return bio;
+}
+
 /*
  * This function was originally taken from fs/mpage.c, and customized for f2fs.
  * Major change was from block_size == page_size in f2fs by default.
@@ -912,7 +1009,6 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
        sector_t last_block;
        sector_t last_block_in_file;
        sector_t block_nr;
-       struct block_device *bdev = inode->i_sb->s_bdev;
        struct f2fs_map_blocks map;
 
        map.m_pblk = 0;
@@ -972,7 +1068,8 @@ got_it:
                        }
                } else {
                        zero_user_segment(page, 0, PAGE_SIZE);
-                       SetPageUptodate(page);
+                       if (!PageUptodate(page))
+                               SetPageUptodate(page);
                        unlock_page(page);
                        goto next_page;
                }
@@ -983,35 +1080,15 @@ got_it:
                 */
                if (bio && (last_block_in_bio != block_nr - 1)) {
 submit_and_realloc:
-                       submit_bio(READ, bio);
+                       __submit_bio(F2FS_I_SB(inode), READ, bio, DATA);
                        bio = NULL;
                }
                if (bio == NULL) {
-                       struct fscrypt_ctx *ctx = NULL;
-
-                       if (f2fs_encrypted_inode(inode) &&
-                                       S_ISREG(inode->i_mode)) {
-
-                               ctx = fscrypt_get_ctx(inode, GFP_NOFS);
-                               if (IS_ERR(ctx))
-                                       goto set_error_page;
-
-                               /* wait the page to be moved by cleaning */
-                               f2fs_wait_on_encrypted_page_writeback(
-                                               F2FS_I_SB(inode), block_nr);
-                       }
-
-                       bio = bio_alloc(GFP_KERNEL,
-                               min_t(int, nr_pages, BIO_MAX_PAGES));
-                       if (!bio) {
-                               if (ctx)
-                                       fscrypt_release_ctx(ctx);
+                       bio = f2fs_grab_bio(inode, block_nr, nr_pages);
+                       if (IS_ERR(bio)) {
+                               bio = NULL;
                                goto set_error_page;
                        }
-                       bio->bi_bdev = bdev;
-                       bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(block_nr);
-                       bio->bi_end_io = f2fs_read_end_io;
-                       bio->bi_private = ctx;
                }
 
                if (bio_add_page(bio, page, blocksize, 0) < blocksize)
@@ -1026,7 +1103,7 @@ set_error_page:
                goto next_page;
 confused:
                if (bio) {
-                       submit_bio(READ, bio);
+                       __submit_bio(F2FS_I_SB(inode), READ, bio, DATA);
                        bio = NULL;
                }
                unlock_page(page);
@@ -1036,7 +1113,7 @@ next_page:
        }
        BUG_ON(pages && !list_empty(pages));
        if (bio)
-               submit_bio(READ, bio);
+               __submit_bio(F2FS_I_SB(inode), READ, bio, DATA);
        return 0;
 }
 
@@ -1125,14 +1202,14 @@ retry_encrypt:
                        !IS_ATOMIC_WRITTEN_PAGE(page) &&
                        need_inplace_update(inode))) {
                rewrite_data_page(fio);
-               set_inode_flag(F2FS_I(inode), FI_UPDATE_WRITE);
+               set_inode_flag(inode, FI_UPDATE_WRITE);
                trace_f2fs_do_write_data_page(page, IPU);
        } else {
                write_data_page(&dn, fio);
                trace_f2fs_do_write_data_page(page, OPU);
-               set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
+               set_inode_flag(inode, FI_APPEND_WRITE);
                if (page->index == 0)
-                       set_inode_flag(F2FS_I(inode), FI_FIRST_BLOCK_WRITTEN);
+                       set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
        }
 out_writepage:
        f2fs_put_dnode(&dn);
@@ -1147,6 +1224,7 @@ static int f2fs_write_data_page(struct page *page,
        loff_t i_size = i_size_read(inode);
        const pgoff_t end_index = ((unsigned long long) i_size)
                                                        >> PAGE_SHIFT;
+       loff_t psize = (page->index + 1) << PAGE_SHIFT;
        unsigned offset = 0;
        bool need_balance_fs = false;
        int err = 0;
@@ -1177,24 +1255,24 @@ write:
                goto redirty_out;
        if (f2fs_is_drop_cache(inode))
                goto out;
-       if (f2fs_is_volatile_file(inode) && !wbc->for_reclaim &&
-                       available_free_memory(sbi, BASE_CHECK))
+       /* we should not write 0'th page having journal header */
+       if (f2fs_is_volatile_file(inode) && (!page->index ||
+                       (!wbc->for_reclaim &&
+                       available_free_memory(sbi, BASE_CHECK))))
                goto redirty_out;
 
+       /* we should bypass data pages to proceed the kworkder jobs */
+       if (unlikely(f2fs_cp_error(sbi))) {
+               mapping_set_error(page->mapping, -EIO);
+               goto out;
+       }
+
        /* Dentry blocks are controlled by checkpoint */
        if (S_ISDIR(inode->i_mode)) {
-               if (unlikely(f2fs_cp_error(sbi)))
-                       goto redirty_out;
                err = do_write_data_page(&fio);
                goto done;
        }
 
-       /* we should bypass data pages to proceed the kworkder jobs */
-       if (unlikely(f2fs_cp_error(sbi))) {
-               SetPageError(page);
-               goto out;
-       }
-
        if (!wbc->for_reclaim)
                need_balance_fs = true;
        else if (has_not_enough_free_secs(sbi, 0))
@@ -1206,6 +1284,8 @@ write:
                err = f2fs_write_inline_data(inode, page);
        if (err == -EAGAIN)
                err = do_write_data_page(&fio);
+       if (F2FS_I(inode)->last_disk_size < psize)
+               F2FS_I(inode)->last_disk_size = psize;
        f2fs_unlock_op(sbi);
 done:
        if (err && err != -ENOENT)
@@ -1232,16 +1312,8 @@ out:
 
 redirty_out:
        redirty_page_for_writepage(wbc, page);
-       return AOP_WRITEPAGE_ACTIVATE;
-}
-
-static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
-                       void *data)
-{
-       struct address_space *mapping = data;
-       int ret = mapping->a_ops->writepage(page, wbc);
-       mapping_set_error(mapping, ret);
-       return ret;
+       unlock_page(page);
+       return err;
 }
 
 /*
@@ -1250,8 +1322,7 @@ static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
  * warm/hot data page.
  */
 static int f2fs_write_cache_pages(struct address_space *mapping,
-                       struct writeback_control *wbc, writepage_t writepage,
-                       void *data)
+                                       struct writeback_control *wbc)
 {
        int ret = 0;
        int done = 0;
@@ -1264,10 +1335,9 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
        int cycled;
        int range_whole = 0;
        int tag;
-       int step = 0;
 
        pagevec_init(&pvec, 0);
-next:
+
        if (wbc->range_cyclic) {
                writeback_index = mapping->writeback_index; /* prev offset */
                index = writeback_index;
@@ -1322,9 +1392,6 @@ continue_unlock:
                                goto continue_unlock;
                        }
 
-                       if (step == is_cold_data(page))
-                               goto continue_unlock;
-
                        if (PageWriteback(page)) {
                                if (wbc->sync_mode != WB_SYNC_NONE)
                                        f2fs_wait_on_page_writeback(page,
@@ -1337,16 +1404,11 @@ continue_unlock:
                        if (!clear_page_dirty_for_io(page))
                                goto continue_unlock;
 
-                       ret = (*writepage)(page, wbc, data);
+                       ret = mapping->a_ops->writepage(page, wbc);
                        if (unlikely(ret)) {
-                               if (ret == AOP_WRITEPAGE_ACTIVATE) {
-                                       unlock_page(page);
-                                       ret = 0;
-                               } else {
-                                       done_index = page->index + 1;
-                                       done = 1;
-                                       break;
-                               }
+                               done_index = page->index + 1;
+                               done = 1;
+                               break;
                        }
 
                        if (--wbc->nr_to_write <= 0 &&
@@ -1359,11 +1421,6 @@ continue_unlock:
                cond_resched();
        }
 
-       if (step < 1) {
-               step++;
-               goto next;
-       }
-
        if (!cycled && !done) {
                cycled = 1;
                index = 0;
@@ -1381,9 +1438,8 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 {
        struct inode *inode = mapping->host;
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       bool locked = false;
+       struct blk_plug plug;
        int ret;
-       long diff;
 
        /* deal with chardevs and other special file */
        if (!mapping->a_ops->writepage)
@@ -1399,7 +1455,7 @@ static int f2fs_write_data_pages(struct address_space *mapping,
                goto skip_write;
 
        /* skip writing during file defragment */
-       if (is_inode_flag_set(F2FS_I(inode), FI_DO_DEFRAG))
+       if (is_inode_flag_set(inode, FI_DO_DEFRAG))
                goto skip_write;
 
        /* during POR, we don't need to trigger writepage at all. */
@@ -1408,20 +1464,16 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 
        trace_f2fs_writepages(mapping->host, wbc, DATA);
 
-       diff = nr_pages_to_write(sbi, DATA, wbc);
-
-       if (!S_ISDIR(inode->i_mode) && wbc->sync_mode == WB_SYNC_ALL) {
-               mutex_lock(&sbi->writepages);
-               locked = true;
-       }
-       ret = f2fs_write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
-       f2fs_submit_merged_bio_cond(sbi, inode, NULL, 0, DATA, WRITE);
-       if (locked)
-               mutex_unlock(&sbi->writepages);
+       blk_start_plug(&plug);
+       ret = f2fs_write_cache_pages(mapping, wbc);
+       blk_finish_plug(&plug);
+       /*
+        * if some pages were truncated, we cannot guarantee its mapping->host
+        * to detect pending bios.
+        */
+       f2fs_submit_merged_bio(sbi, DATA, WRITE);
 
        remove_dirty_inode(inode);
-
-       wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
        return ret;
 
 skip_write:
@@ -1479,8 +1531,9 @@ restart:
        if (f2fs_has_inline_data(inode)) {
                if (pos + len <= MAX_INLINE_DATA) {
                        read_inline_data(page, ipage);
-                       set_inode_flag(F2FS_I(inode), FI_DATA_EXIST);
-                       set_inline_node(ipage);
+                       set_inode_flag(inode, FI_DATA_EXIST);
+                       if (inode->i_nlink)
+                               set_inline_node(ipage);
                } else {
                        err = f2fs_convert_inline_page(&dn, page);
                        if (err)
@@ -1496,7 +1549,7 @@ restart:
                } else {
                        /* hole case */
                        err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
-                       if (err || (!err && dn.data_blkaddr == NULL_ADDR)) {
+                       if (err || dn.data_blkaddr == NULL_ADDR) {
                                f2fs_put_dnode(&dn);
                                f2fs_lock_op(sbi);
                                locked = true;
@@ -1588,38 +1641,35 @@ repeat:
        if (blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_SIZE);
        } else {
-               struct f2fs_io_info fio = {
-                       .sbi = sbi,
-                       .type = DATA,
-                       .rw = READ_SYNC,
-                       .old_blkaddr = blkaddr,
-                       .new_blkaddr = blkaddr,
-                       .page = page,
-                       .encrypted_page = NULL,
-               };
-               err = f2fs_submit_page_bio(&fio);
-               if (err)
+               struct bio *bio;
+
+               bio = f2fs_grab_bio(inode, blkaddr, 1);
+               if (IS_ERR(bio)) {
+                       err = PTR_ERR(bio);
                        goto fail;
+               }
 
-               lock_page(page);
-               if (unlikely(!PageUptodate(page))) {
-                       err = -EIO;
+               if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
+                       bio_put(bio);
+                       err = -EFAULT;
                        goto fail;
                }
+
+               __submit_bio(sbi, READ_SYNC, bio, DATA);
+
+               lock_page(page);
                if (unlikely(page->mapping != mapping)) {
                        f2fs_put_page(page, 1);
                        goto repeat;
                }
-
-               /* avoid symlink page */
-               if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
-                       err = fscrypt_decrypt_page(page);
-                       if (err)
-                               goto fail;
+               if (unlikely(!PageUptodate(page))) {
+                       err = -EIO;
+                       goto fail;
                }
        }
 out_update:
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
 out_clear:
        clear_cold_data(page);
        return 0;
@@ -1640,13 +1690,11 @@ static int f2fs_write_end(struct file *file,
        trace_f2fs_write_end(inode, pos, len, copied);
 
        set_page_dirty(page);
+       f2fs_put_page(page, 1);
 
-       if (pos + copied > i_size_read(inode)) {
-               i_size_write(inode, pos + copied);
-               mark_inode_dirty(inode);
-       }
+       if (pos + copied > i_size_read(inode))
+               f2fs_i_size_write(inode, pos + copied);
 
-       f2fs_put_page(page, 1);
        f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
        return copied;
 }
@@ -1665,12 +1713,13 @@ static int check_direct_IO(struct inode *inode, struct iov_iter *iter,
        return 0;
 }
 
-static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
-                             loff_t offset)
+static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 {
        struct address_space *mapping = iocb->ki_filp->f_mapping;
        struct inode *inode = mapping->host;
        size_t count = iov_iter_count(iter);
+       loff_t offset = iocb->ki_pos;
+       int rw = iov_iter_rw(iter);
        int err;
 
        err = check_direct_IO(inode, iter, offset);
@@ -1679,14 +1728,23 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
                return 0;
+       if (test_opt(F2FS_I_SB(inode), LFS))
+               return 0;
 
-       trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
+       trace_f2fs_direct_IO_enter(inode, offset, count, rw);
 
-       err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
-       if (err < 0 && iov_iter_rw(iter) == WRITE)
-               f2fs_write_failed(mapping, offset + count);
+       down_read(&F2FS_I(inode)->dio_rwsem[rw]);
+       err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
+       up_read(&F2FS_I(inode)->dio_rwsem[rw]);
+
+       if (rw == WRITE) {
+               if (err > 0)
+                       set_inode_flag(inode, FI_UPDATE_WRITE);
+               else if (err < 0)
+                       f2fs_write_failed(mapping, offset + count);
+       }
 
-       trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
+       trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
 
        return err;
 }
@@ -1714,6 +1772,7 @@ void f2fs_invalidate_page(struct page *page, unsigned int offset,
        if (IS_ATOMIC_WRITTEN_PAGE(page))
                return;
 
+       set_page_private(page, 0);
        ClearPagePrivate(page);
 }
 
@@ -1727,10 +1786,40 @@ int f2fs_release_page(struct page *page, gfp_t wait)
        if (IS_ATOMIC_WRITTEN_PAGE(page))
                return 0;
 
+       set_page_private(page, 0);
        ClearPagePrivate(page);
        return 1;
 }
 
+/*
+ * This was copied from __set_page_dirty_buffers which gives higher performance
+ * in very high speed storages. (e.g., pmem)
+ */
+void f2fs_set_page_dirty_nobuffers(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       unsigned long flags;
+
+       if (unlikely(!mapping))
+               return;
+
+       spin_lock(&mapping->private_lock);
+       lock_page_memcg(page);
+       SetPageDirty(page);
+       spin_unlock(&mapping->private_lock);
+
+       spin_lock_irqsave(&mapping->tree_lock, flags);
+       WARN_ON_ONCE(!PageUptodate(page));
+       account_page_dirtied(page, mapping);
+       radix_tree_tag_set(&mapping->page_tree,
+                       page_index(page), PAGECACHE_TAG_DIRTY);
+       spin_unlock_irqrestore(&mapping->tree_lock, flags);
+       unlock_page_memcg(page);
+
+       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+       return;
+}
+
 static int f2fs_set_data_page_dirty(struct page *page)
 {
        struct address_space *mapping = page->mapping;
@@ -1738,7 +1827,8 @@ static int f2fs_set_data_page_dirty(struct page *page)
 
        trace_f2fs_set_page_dirty(page, DATA);
 
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
 
        if (f2fs_is_atomic_file(inode)) {
                if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
@@ -1753,7 +1843,7 @@ static int f2fs_set_data_page_dirty(struct page *page)
        }
 
        if (!PageDirty(page)) {
-               __set_page_dirty_nobuffers(page);
+               f2fs_set_page_dirty_nobuffers(page);
                update_dirty_page(inode, page);
                return 1;
        }