Merge tag 'for-f2fs-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2016 17:36:31 +0000 (10:36 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2016 17:36:31 +0000 (10:36 -0700)
Pull f2fs updates from Jaegeuk Kim:
 "The major change in this version is mitigating cpu overheads on write
  paths by replacing redundant inode page updates with mark_inode_dirty
  calls.  And we tried to reduce lock contentions as well to improve
  filesystem scalability.  Other feature is setting F2FS automatically
  when detecting host-managed SMR.

  Enhancements:
   - ioctl to move a range of data between files
   - inject orphan inode errors
   - avoid flush commands congestion
   - support lazytime

  Bug fixes:
   - return proper results for some dentry operations
   - fix deadlock in add_link failure
   - disable extent_cache for fcollapse/finsert"

* tag 'for-f2fs-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (68 commits)
  f2fs: clean up coding style and redundancy
  f2fs: get victim segment again after new cp
  f2fs: handle error case with f2fs_bug_on
  f2fs: avoid data race when deciding checkpoin in f2fs_sync_file
  f2fs: support an ioctl to move a range of data blocks
  f2fs: fix to report error number of f2fs_find_entry
  f2fs: avoid memory allocation failure due to a long length
  f2fs: reset default idle interval value
  f2fs: use blk_plug in all the possible paths
  f2fs: fix to avoid data update racing between GC and DIO
  f2fs: add maximum prefree segments
  f2fs: disable extent_cache for fcollapse/finsert inodes
  f2fs: refactor __exchange_data_block for speed up
  f2fs: fix ERR_PTR returned by bio
  f2fs: avoid mark_inode_dirty
  f2fs: move i_size_write in f2fs_write_end
  f2fs: fix to avoid redundant discard during fstrim
  f2fs: avoid mismatching block range for discard
  f2fs: fix incorrect f_bfree calculation in ->statfs
  f2fs: use percpu_rw_semaphore
  ...

1  2 
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/gc.c
fs/f2fs/inline.c
fs/f2fs/node.c
fs/f2fs/segment.c

diff --combined fs/f2fs/checkpoint.c
index 124b4a3017b537efd3df41002ad069f0f4badb6d,be1c54b62388cf143da8b373c103d76b996f5f81..f94d01e7d001f3181dd9cdae25b50eed3593f44f
@@@ -48,7 -48,8 +48,8 @@@ repeat
                goto repeat;
        }
        f2fs_wait_on_page_writeback(page, META, true);
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        return page;
  }
  
@@@ -63,15 -64,14 +64,15 @@@ static struct page *__get_meta_page(str
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = META,
 -              .rw = READ_SYNC | REQ_META | REQ_PRIO,
 +              .op = REQ_OP_READ,
 +              .op_flags = READ_SYNC | REQ_META | REQ_PRIO,
                .old_blkaddr = index,
                .new_blkaddr = index,
                .encrypted_page = NULL,
        };
  
        if (unlikely(!is_meta))
 -              fio.rw &= ~REQ_META;
 +              fio.op_flags &= ~REQ_META;
  repeat:
        page = f2fs_grab_cache_page(mapping, index, false);
        if (!page) {
@@@ -158,14 -158,13 +159,14 @@@ int ra_meta_pages(struct f2fs_sb_info *
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = META,
 -              .rw = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : READA,
 +              .op = REQ_OP_READ,
 +              .op_flags = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : REQ_RAHEAD,
                .encrypted_page = NULL,
        };
        struct blk_plug plug;
  
        if (unlikely(type == META_POR))
 -              fio.rw &= ~REQ_META;
 +              fio.op_flags &= ~REQ_META;
  
        blk_start_plug(&plug);
        for (; nrpages-- > 0; blkno++) {
@@@ -266,6 -265,7 +267,7 @@@ static int f2fs_write_meta_pages(struc
                                struct writeback_control *wbc)
  {
        struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
+       struct blk_plug plug;
        long diff, written;
  
        /* collect a number of dirty meta pages and write together */
        /* if mounting is failed, skip writing node pages */
        mutex_lock(&sbi->cp_mutex);
        diff = nr_pages_to_write(sbi, META, wbc);
+       blk_start_plug(&plug);
        written = sync_meta_pages(sbi, META, wbc->nr_to_write);
+       blk_finish_plug(&plug);
        mutex_unlock(&sbi->cp_mutex);
        wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
        return 0;
@@@ -366,9 -368,10 +370,10 @@@ static int f2fs_set_meta_page_dirty(str
  {
        trace_f2fs_set_page_dirty(page, META);
  
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        if (!PageDirty(page)) {
-               __set_page_dirty_nobuffers(page);
+               f2fs_set_page_dirty_nobuffers(page);
                inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
                SetPagePrivate(page);
                f2fs_trace_pid(page);
@@@ -510,10 -513,11 +515,11 @@@ void release_orphan_inode(struct f2fs_s
        spin_unlock(&im->ino_lock);
  }
  
- void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+ void add_orphan_inode(struct inode *inode)
  {
        /* add new orphan ino entry into list */
-       __add_ino_entry(sbi, ino, ORPHAN_INO);
+       __add_ino_entry(F2FS_I_SB(inode), inode->i_ino, ORPHAN_INO);
+       update_inode_page(inode);
  }
  
  void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
@@@ -761,28 -765,25 +767,25 @@@ fail_no_cp
  static void __add_dirty_inode(struct inode *inode, enum inode_type type)
  {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       struct f2fs_inode_info *fi = F2FS_I(inode);
        int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
  
-       if (is_inode_flag_set(fi, flag))
+       if (is_inode_flag_set(inode, flag))
                return;
  
-       set_inode_flag(fi, flag);
-       list_add_tail(&fi->dirty_list, &sbi->inode_list[type]);
+       set_inode_flag(inode, flag);
+       list_add_tail(&F2FS_I(inode)->dirty_list, &sbi->inode_list[type]);
        stat_inc_dirty_inode(sbi, type);
  }
  
  static void __remove_dirty_inode(struct inode *inode, enum inode_type type)
  {
-       struct f2fs_inode_info *fi = F2FS_I(inode);
        int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
  
-       if (get_dirty_pages(inode) ||
-                       !is_inode_flag_set(F2FS_I(inode), flag))
+       if (get_dirty_pages(inode) || !is_inode_flag_set(inode, flag))
                return;
  
-       list_del_init(&fi->dirty_list);
-       clear_inode_flag(fi, flag);
+       list_del_init(&F2FS_I(inode)->dirty_list);
+       clear_inode_flag(inode, flag);
        stat_dec_dirty_inode(F2FS_I_SB(inode), type);
  }
  
@@@ -795,13 -796,12 +798,12 @@@ void update_dirty_page(struct inode *in
                        !S_ISLNK(inode->i_mode))
                return;
  
-       if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH)) {
-               spin_lock(&sbi->inode_lock[type]);
+       spin_lock(&sbi->inode_lock[type]);
+       if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH))
                __add_dirty_inode(inode, type);
-               spin_unlock(&sbi->inode_lock[type]);
-       }
        inode_inc_dirty_pages(inode);
+       spin_unlock(&sbi->inode_lock[type]);
        SetPagePrivate(page);
        f2fs_trace_pid(page);
  }
@@@ -864,6 -864,34 +866,34 @@@ retry
        goto retry;
  }
  
+ int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
+ {
+       struct list_head *head = &sbi->inode_list[DIRTY_META];
+       struct inode *inode;
+       struct f2fs_inode_info *fi;
+       s64 total = get_pages(sbi, F2FS_DIRTY_IMETA);
+       while (total--) {
+               if (unlikely(f2fs_cp_error(sbi)))
+                       return -EIO;
+               spin_lock(&sbi->inode_lock[DIRTY_META]);
+               if (list_empty(head)) {
+                       spin_unlock(&sbi->inode_lock[DIRTY_META]);
+                       return 0;
+               }
+               fi = list_entry(head->next, struct f2fs_inode_info,
+                                                       gdirty_list);
+               inode = igrab(&fi->vfs_inode);
+               spin_unlock(&sbi->inode_lock[DIRTY_META]);
+               if (inode) {
+                       update_inode_page(inode);
+                       iput(inode);
+               }
+       };
+       return 0;
+ }
  /*
   * Freeze all the FS-operations for checkpoint.
   */
@@@ -890,6 -918,14 +920,14 @@@ retry_flush_dents
                goto retry_flush_dents;
        }
  
+       if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
+               f2fs_unlock_all(sbi);
+               err = f2fs_sync_inode_meta(sbi);
+               if (err)
+                       goto out;
+               goto retry_flush_dents;
+       }
        /*
         * POR: we should ensure that there are no dirty node pages
         * until finishing nat/sit flush.
@@@ -914,6 -950,8 +952,8 @@@ out
  static void unblock_operations(struct f2fs_sb_info *sbi)
  {
        up_write(&sbi->node_write);
+       build_free_nids(sbi);
        f2fs_unlock_all(sbi);
  }
  
@@@ -954,7 -992,7 +994,7 @@@ static int do_checkpoint(struct f2fs_sb
         * This avoids to conduct wrong roll-forward operations and uses
         * metapages, so should be called prior to sync_meta_pages below.
         */
-       if (discard_next_dnode(sbi, discard_blk))
+       if (!test_opt(sbi, LFS) && discard_next_dnode(sbi, discard_blk))
                invalidate = true;
  
        /* Flush all the NAT/SIT pages */
diff --combined fs/f2fs/data.c
index ded224518978355821c2345d07c88d71b885aa74,614154f9bb3533f60f935e2d57426391d08895b4..e2624275d828c5d65885948e6426e8906e305a90
@@@ -19,6 -19,8 +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 +47,8 @@@ static void f2fs_read_end_io(struct bi
                struct page *page = bvec->bv_page;
  
                if (!bio->bi_error) {
-                       SetPageUptodate(page);
+                       if (!PageUptodate(page))
+                               SetPageUptodate(page);
                } else {
                        ClearPageUptodate(page);
                        SetPageError(page);
@@@ -97,11 -100,16 +100,16 @@@ static struct bio *__bio_alloc(struct f
        return bio;
  }
  
- static inline void __submit_bio(struct f2fs_sb_info *sbi, struct bio *bio)
 -static inline void __submit_bio(struct f2fs_sb_info *sbi, int rw,
 -                      struct bio *bio, enum page_type type)
++static inline void __submit_bio(struct f2fs_sb_info *sbi,
++                              struct bio *bio, enum page_type type)
  {
-       if (!is_read_io(bio_op(bio)))
 -      if (!is_read_io(rw)) {
++      if (!is_read_io(bio_op(bio))) {
                atomic_inc(&sbi->nr_wb_bios);
 -      submit_bio(rw, bio);
+               if (f2fs_sb_mounted_hmsmr(sbi->sb) &&
+                       current->plug && (type == DATA || type == NODE))
+                       blk_finish_plug(current->plug);
+       }
 +      submit_bio(bio);
  }
  
  static void __submit_merged_bio(struct f2fs_bio_info *io)
        if (!io->bio)
                return;
  
 -      if (is_read_io(fio->rw))
 +      if (is_read_io(fio->op))
                trace_f2fs_submit_read_bio(io->sbi->sb, fio, io->bio);
        else
                trace_f2fs_submit_write_bio(io->sbi->sb, fio, io->bio);
  
 -      __submit_bio(io->sbi, fio->rw, io->bio, fio->type);
 +      bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
 +
-       __submit_bio(io->sbi, io->bio);
++      __submit_bio(io->sbi, io->bio, fio->type);
        io->bio = NULL;
  }
  
@@@ -184,12 -190,10 +192,12 @@@ static void __f2fs_submit_merged_bio(st
        /* change META to META_FLUSH in the checkpoint procedure */
        if (type >= META_FLUSH) {
                io->fio.type = META_FLUSH;
 +              io->fio.op = REQ_OP_WRITE;
                if (test_opt(sbi, NOBARRIER))
 -                      io->fio.rw = WRITE_FLUSH | REQ_META | REQ_PRIO;
 +                      io->fio.op_flags = WRITE_FLUSH | REQ_META | REQ_PRIO;
                else
 -                      io->fio.rw = WRITE_FLUSH_FUA | REQ_META | REQ_PRIO;
 +                      io->fio.op_flags = WRITE_FLUSH_FUA | REQ_META |
 +                                                              REQ_PRIO;
        }
        __submit_merged_bio(io);
  out:
@@@ -231,16 -235,14 +239,16 @@@ int f2fs_submit_page_bio(struct f2fs_io
        f2fs_trace_ios(fio, 0);
  
        /* Allocate a new bio */
 -      bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->rw));
 +      bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->op));
  
        if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
                bio_put(bio);
                return -EFAULT;
        }
 +      bio->bi_rw = fio->op_flags;
 +      bio_set_op_attrs(bio, fio->op, fio->op_flags);
  
-       __submit_bio(fio->sbi, bio);
 -      __submit_bio(fio->sbi, fio->rw, bio, fio->type);
++      __submit_bio(fio->sbi, bio, fio->type);
        return 0;
  }
  
@@@ -249,7 -251,7 +257,7 @@@ void f2fs_submit_page_mbio(struct f2fs_
        struct f2fs_sb_info *sbi = fio->sbi;
        enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
        struct f2fs_bio_info *io;
 -      bool is_read = is_read_io(fio->rw);
 +      bool is_read = is_read_io(fio->op);
        struct page *bio_page;
  
        io = is_read ? &sbi->read_io : &sbi->write_io[btype];
        down_write(&io->io_rwsem);
  
        if (io->bio && (io->last_block_in_bio != fio->new_blkaddr - 1 ||
 -                                              io->fio.rw != fio->rw))
 +          (io->fio.op != fio->op || io->fio.op_flags != fio->op_flags)))
                __submit_merged_bio(io);
  alloc_new:
        if (io->bio == NULL) {
@@@ -326,7 -328,7 +334,7 @@@ int reserve_new_blocks(struct dnode_of_
        if (!count)
                return 0;
  
-       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;
        if (unlikely(!inc_valid_block_count(sbi, dn->inode, &count)))
                return -ENOSPC;
  
        if (set_page_dirty(dn->node_page))
                dn->node_changed = true;
-       mark_inode_dirty(dn->inode);
-       sync_inode_page(dn);
        return 0;
  }
  
@@@ -395,7 -394,7 +400,7 @@@ int f2fs_get_block(struct dnode_of_dat
  }
  
  struct page *get_read_data_page(struct inode *inode, pgoff_t index,
 -                                              int rw, bool for_write)
 +                                              int op_flags, bool for_write)
  {
        struct address_space *mapping = inode->i_mapping;
        struct dnode_of_data dn;
        struct f2fs_io_info fio = {
                .sbi = F2FS_I_SB(inode),
                .type = DATA,
 -              .rw = rw,
 +              .op = REQ_OP_READ,
 +              .op_flags = op_flags,
                .encrypted_page = NULL,
        };
  
@@@ -446,7 -444,8 +451,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;
        }
@@@ -505,14 -504,14 +511,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;
  }
  
@@@ -557,7 -556,8 +563,8 @@@ struct page *get_new_data_page(struct i
  
        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);
  
        }
  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;
  }
  
@@@ -586,7 -583,7 +590,7 @@@ static int __allocate_data_block(struc
        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);
@@@ -611,7 -608,7 +615,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;
  }
@@@ -660,7 -657,7 +664,7 @@@ int f2fs_map_blocks(struct inode *inode
        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;
+       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;
@@@ -723,8 -720,7 +727,7 @@@ next_block
                        } else {
                                err = __allocate_data_block(&dn);
                                if (!err) {
-                                       set_inode_flag(F2FS_I(inode),
-                                                       FI_APPEND_WRITE);
+                                       set_inode_flag(inode, FI_APPEND_WRITE);
                                        allocated = true;
                                }
                        }
@@@ -795,8 -791,6 +798,6 @@@ skip
        else if (dn.ofs_in_node < end_offset)
                goto next_block;
  
-       if (allocated)
-               sync_inode_page(&dn);
        f2fs_put_dnode(&dn);
  
        if (create) {
        goto next_dnode;
  
  sync_out:
-       if (allocated)
-               sync_inode_page(&dn);
        f2fs_put_dnode(&dn);
  unlock_out:
        if (create) {
@@@ -968,6 -960,37 +967,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.
@@@ -986,7 -1009,6 +1016,6 @@@ static int f2fs_mpage_readpages(struct 
        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;
                        page = list_entry(pages->prev, struct page, lru);
                        list_del(&page->lru);
                        if (add_to_page_cache_lru(page, mapping,
 -                                                page->index, GFP_KERNEL))
 +                                                page->index,
 +                                                readahead_gfp_mask(mapping)))
                                goto next_page;
                }
  
@@@ -1047,7 -1068,8 +1076,8 @@@ got_it
                        }
                } else {
                        zero_user_segment(page, 0, PAGE_SIZE);
-                       SetPageUptodate(page);
+                       if (!PageUptodate(page))
+                               SetPageUptodate(page);
                        unlock_page(page);
                        goto next_page;
                }
                 */
                if (bio && (last_block_in_bio != block_nr - 1)) {
  submit_and_realloc:
-                       __submit_bio(F2FS_I_SB(inode), bio);
 -                      __submit_bio(F2FS_I_SB(inode), READ, bio, DATA);
++                      __submit_bio(F2FS_I_SB(inode), 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;
 +                      bio_set_op_attrs(bio, REQ_OP_READ, 0);
                }
  
                if (bio_add_page(bio, page, blocksize, 0) < blocksize)
@@@ -1102,7 -1103,7 +1112,7 @@@ set_error_page
                goto next_page;
  confused:
                if (bio) {
-                       __submit_bio(F2FS_I_SB(inode), bio);
 -                      __submit_bio(F2FS_I_SB(inode), READ, bio, DATA);
++                      __submit_bio(F2FS_I_SB(inode), bio, DATA);
                        bio = NULL;
                }
                unlock_page(page);
@@@ -1112,7 -1113,7 +1122,7 @@@ next_page
        }
        BUG_ON(pages && !list_empty(pages));
        if (bio)
-               __submit_bio(F2FS_I_SB(inode), bio);
 -              __submit_bio(F2FS_I_SB(inode), READ, bio, DATA);
++              __submit_bio(F2FS_I_SB(inode), bio, DATA);
        return 0;
  }
  
@@@ -1201,14 -1202,14 +1211,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);
@@@ -1223,14 -1224,14 +1233,15 @@@ static int f2fs_write_data_page(struct 
        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;
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = DATA,
 -              .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE,
 +              .op = REQ_OP_WRITE,
 +              .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
                .page = page,
                .encrypted_page = NULL,
        };
@@@ -1260,20 -1261,18 +1271,18 @@@ write
                        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))
                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)
@@@ -1311,16 -1312,8 +1322,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;
  }
  
  /*
   * 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;
        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;
@@@ -1401,9 -1392,6 +1402,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,
                        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 &&
                cond_resched();
        }
  
-       if (step < 1) {
-               step++;
-               goto next;
-       }
        if (!cycled && !done) {
                cycled = 1;
                index = 0;
@@@ -1460,9 -1438,8 +1448,8 @@@ static int f2fs_write_data_pages(struc
  {
        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)
                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. */
  
        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:
@@@ -1558,7 -1531,7 +1541,7 @@@ 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_inode_flag(inode, FI_DATA_EXIST);
                        if (inode->i_nlink)
                                set_inline_node(ipage);
                } else {
@@@ -1668,39 -1641,35 +1651,35 @@@ repeat
        if (blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_SIZE);
        } else {
-               struct f2fs_io_info fio = {
-                       .sbi = sbi,
-                       .type = DATA,
-                       .op = REQ_OP_READ,
-                       .op_flags = READ_SYNC,
-                       .old_blkaddr = blkaddr,
-                       .new_blkaddr = blkaddr,
-                       .page = page,
-                       .encrypted_page = NULL,
-               };
-               err = f2fs_submit_page_bio(&fio);
-               if (err)
-                       goto fail;
+               struct bio *bio;
  
-               lock_page(page);
-               if (unlikely(!PageUptodate(page))) {
-                       err = -EIO;
+               bio = f2fs_grab_bio(inode, blkaddr, 1);
+               if (IS_ERR(bio)) {
+                       err = PTR_ERR(bio);
                        goto fail;
                }
 -
++              bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC);
+               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);
++              __submit_bio(sbi, 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;
@@@ -1721,13 -1690,11 +1700,11 @@@ static int f2fs_write_end(struct 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;
  }
@@@ -1752,6 -1719,7 +1729,7 @@@ static ssize_t f2fs_direct_IO(struct ki
        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);
  
        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);
  
+       down_read(&F2FS_I(inode)->dio_rwsem[rw]);
        err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
-       if (iov_iter_rw(iter) == WRITE) {
+       up_read(&F2FS_I(inode)->dio_rwsem[rw]);
+       if (rw == WRITE) {
                if (err > 0)
-                       set_inode_flag(F2FS_I(inode), FI_UPDATE_WRITE);
+                       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;
  }
@@@ -1818,6 -1791,35 +1801,35 @@@ int f2fs_release_page(struct page *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;
  
        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)) {
        }
  
        if (!PageDirty(page)) {
-               __set_page_dirty_nobuffers(page);
+               f2fs_set_page_dirty_nobuffers(page);
                update_dirty_page(inode, page);
                return 1;
        }
diff --combined fs/f2fs/f2fs.h
index 23ae6a81ccd6c4f0ba419d9b735eb08f1bcab7df,30981094dff84ee1d8f57016d0d8ea8423bfad3b..7890e9071499cbf6e3337daa875e721b147fefe9
@@@ -45,6 -45,7 +45,7 @@@ enum 
        FAULT_ORPHAN,
        FAULT_BLOCK,
        FAULT_DIR_DEPTH,
+       FAULT_EVICT_INODE,
        FAULT_MAX,
  };
  
@@@ -74,6 -75,8 +75,8 @@@ static inline bool time_to_inject(int t
                return false;
        else if (type == FAULT_DIR_DEPTH && !IS_FAULT_SET(type))
                return false;
+       else if (type == FAULT_EVICT_INODE && !IS_FAULT_SET(type))
+               return false;
  
        atomic_inc(&f2fs_fault.inject_ops);
        if (atomic_read(&f2fs_fault.inject_ops) >= f2fs_fault.inject_rate) {
  #define F2FS_MOUNT_FORCE_FG_GC                0x00004000
  #define F2FS_MOUNT_DATA_FLUSH         0x00008000
  #define F2FS_MOUNT_FAULT_INJECTION    0x00010000
+ #define F2FS_MOUNT_ADAPTIVE           0x00020000
+ #define F2FS_MOUNT_LFS                        0x00040000
  
  #define clear_opt(sbi, option)        (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
  #define set_opt(sbi, option)  (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
@@@ -128,6 -133,7 +133,7 @@@ struct f2fs_mount_info 
  };
  
  #define F2FS_FEATURE_ENCRYPT  0x0001
+ #define F2FS_FEATURE_HMSMR    0x0002
  
  #define F2FS_HAS_FEATURE(sb, mask)                                    \
        ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@@ -158,7 -164,7 +164,7 @@@ enum 
  #define BATCHED_TRIM_BLOCKS(sbi)      \
                (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
  #define DEF_CP_INTERVAL                       60      /* 60 secs */
- #define DEF_IDLE_INTERVAL             120     /* 2 mins */
+ #define DEF_IDLE_INTERVAL             5       /* 5 secs */
  
  struct cp_control {
        int reason;
@@@ -262,6 -268,8 +268,8 @@@ static inline bool __has_cursum_space(s
  #define F2FS_IOC_GARBAGE_COLLECT      _IO(F2FS_IOCTL_MAGIC, 6)
  #define F2FS_IOC_WRITE_CHECKPOINT     _IO(F2FS_IOCTL_MAGIC, 7)
  #define F2FS_IOC_DEFRAGMENT           _IO(F2FS_IOCTL_MAGIC, 8)
+ #define F2FS_IOC_MOVE_RANGE           _IOWR(F2FS_IOCTL_MAGIC, 9,      \
+                                               struct f2fs_move_range)
  
  #define F2FS_IOC_SET_ENCRYPTION_POLICY        FS_IOC_SET_ENCRYPTION_POLICY
  #define F2FS_IOC_GET_ENCRYPTION_POLICY        FS_IOC_GET_ENCRYPTION_POLICY
@@@ -291,6 -299,13 +299,13 @@@ struct f2fs_defragment 
        u64 len;
  };
  
+ struct f2fs_move_range {
+       u32 dst_fd;             /* destination fd */
+       u64 pos_in;             /* start position in src_fd */
+       u64 pos_out;            /* start position in dst_fd */
+       u64 len;                /* size to move */
+ };
  /*
   * For INODE and NODE manager
   */
@@@ -441,11 -456,14 +456,14 @@@ struct f2fs_inode_info 
        unsigned int clevel;            /* maximum level of given file name */
        nid_t i_xattr_nid;              /* node id that contains xattrs */
        unsigned long long xattr_ver;   /* cp version of xattr modification */
+       loff_t  last_disk_size;         /* lastly written file size */
  
-       struct list_head dirty_list;    /* linked in global dirty list */
+       struct list_head dirty_list;    /* dirty list for dirs and files */
+       struct list_head gdirty_list;   /* linked in global dirty list */
        struct list_head inmem_pages;   /* inmemory pages managed by f2fs */
        struct mutex inmem_lock;        /* lock for inmemory pages */
        struct extent_tree *extent_tree;        /* cached extent_tree entry */
+       struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
  };
  
  static inline void get_extent_info(struct extent_info *ext,
@@@ -498,11 -516,14 +516,14 @@@ static inline bool __is_front_mergeable
        return __is_extent_mergeable(cur, front);
  }
  
- static inline void __try_update_largest_extent(struct extent_tree *et,
-                                               struct extent_node *en)
+ extern void f2fs_mark_inode_dirty_sync(struct inode *);
+ static inline void __try_update_largest_extent(struct inode *inode,
+                       struct extent_tree *et, struct extent_node *en)
  {
-       if (en->ei.len > et->largest.len)
+       if (en->ei.len > et->largest.len) {
                et->largest = en->ei;
+               f2fs_mark_inode_dirty_sync(inode);
+       }
  }
  
  struct f2fs_nm_info {
        /* NAT cache management */
        struct radix_tree_root nat_root;/* root of the nat entry cache */
        struct radix_tree_root nat_set_root;/* root of the nat set cache */
-       struct rw_semaphore nat_tree_lock;      /* protect nat_tree_lock */
+       struct percpu_rw_semaphore nat_tree_lock;       /* protect nat_tree_lock */
        struct list_head nat_entries;   /* cached nat entry list (clean) */
        unsigned int nat_cnt;           /* the # of cached nat entries */
        unsigned int dirty_nat_cnt;     /* total num of nat entries in set */
@@@ -599,6 -620,7 +620,7 @@@ struct flush_cmd 
  struct flush_cmd_control {
        struct task_struct *f2fs_issue_flush;   /* flush thread */
        wait_queue_head_t flush_wait_queue;     /* waiting queue for wake-up */
+       atomic_t submit_flush;                  /* # of issued flushes */
        struct llist_head issue_list;           /* list for command issue */
        struct llist_node *dispatch_list;       /* list for command dispatch */
  };
@@@ -655,6 -677,7 +677,7 @@@ enum count_type 
        F2FS_DIRTY_NODES,
        F2FS_DIRTY_META,
        F2FS_INMEM_PAGES,
+       F2FS_DIRTY_IMETA,
        NR_COUNT_TYPE,
  };
  
@@@ -686,15 -709,14 +709,15 @@@ enum page_type 
  struct f2fs_io_info {
        struct f2fs_sb_info *sbi;       /* f2fs_sb_info pointer */
        enum page_type type;    /* contains DATA/NODE/META/META_FLUSH */
 -      int rw;                 /* contains R/RS/W/WS with REQ_META/REQ_PRIO */
 +      int op;                 /* contains REQ_OP_ */
 +      int op_flags;           /* rq_flag_bits */
        block_t new_blkaddr;    /* new block address to be written */
        block_t old_blkaddr;    /* old block address before Cow */
        struct page *page;      /* page to be written */
        struct page *encrypted_page;    /* encrypted page */
  };
  
 -#define is_read_io(rw)        (((rw) & 1) == READ)
 +#define is_read_io(rw) (rw == READ)
  struct f2fs_bio_info {
        struct f2fs_sb_info *sbi;       /* f2fs superblock */
        struct bio *bio;                /* bios to merge */
  enum inode_type {
        DIR_INODE,                      /* for dirty dir inode */
        FILE_INODE,                     /* for dirty regular/symlink inode */
+       DIRTY_META,                     /* for all dirtied inode metadata */
        NR_INODE_TYPE,
  };
  
@@@ -757,14 -780,14 +781,14 @@@ struct f2fs_sb_info 
        /* for bio operations */
        struct f2fs_bio_info read_io;                   /* for read bios */
        struct f2fs_bio_info write_io[NR_PAGE_TYPE];    /* for write bios */
+       struct mutex wio_mutex[NODE + 1];       /* bio ordering for NODE/DATA */
  
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
        struct inode *meta_inode;               /* cache meta blocks */
        struct mutex cp_mutex;                  /* checkpoint procedure lock */
-       struct rw_semaphore cp_rwsem;           /* blocking FS operations */
+       struct percpu_rw_semaphore cp_rwsem;            /* blocking FS operations */
        struct rw_semaphore node_write;         /* locking node writes */
-       struct mutex writepages;                /* mutex for writepages() */
        wait_queue_head_t cp_wait;
        unsigned long last_time[MAX_TIME];      /* to store time in jiffies */
        long interval_time[MAX_TIME];           /* to store thresholds */
@@@ -1050,22 -1073,22 +1074,22 @@@ static inline void clear_ckpt_flags(str
  
  static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
  {
-       down_read(&sbi->cp_rwsem);
+       percpu_down_read(&sbi->cp_rwsem);
  }
  
  static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi)
  {
-       up_read(&sbi->cp_rwsem);
+       percpu_up_read(&sbi->cp_rwsem);
  }
  
  static inline void f2fs_lock_all(struct f2fs_sb_info *sbi)
  {
-       down_write(&sbi->cp_rwsem);
+       percpu_down_write(&sbi->cp_rwsem);
  }
  
  static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
  {
-       up_write(&sbi->cp_rwsem);
+       percpu_up_write(&sbi->cp_rwsem);
  }
  
  static inline int __get_cp_reason(struct f2fs_sb_info *sbi)
@@@ -1120,34 -1143,37 +1144,37 @@@ static inline bool f2fs_has_xattr_block
        return ofs == XATTR_NODE_OFFSET;
  }
  
+ static inline void f2fs_i_blocks_write(struct inode *, blkcnt_t, bool);
  static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
                                 struct inode *inode, blkcnt_t *count)
  {
-       block_t valid_block_count;
+       blkcnt_t diff;
  
-       spin_lock(&sbi->stat_lock);
  #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (time_to_inject(FAULT_BLOCK)) {
-               spin_unlock(&sbi->stat_lock);
+       if (time_to_inject(FAULT_BLOCK))
                return false;
-       }
  #endif
-       valid_block_count =
-               sbi->total_valid_block_count + (block_t)(*count);
-       if (unlikely(valid_block_count > sbi->user_block_count)) {
-               *count = sbi->user_block_count - sbi->total_valid_block_count;
+       /*
+        * let's increase this in prior to actual block count change in order
+        * for f2fs_sync_file to avoid data races when deciding checkpoint.
+        */
+       percpu_counter_add(&sbi->alloc_valid_block_count, (*count));
+       spin_lock(&sbi->stat_lock);
+       sbi->total_valid_block_count += (block_t)(*count);
+       if (unlikely(sbi->total_valid_block_count > sbi->user_block_count)) {
+               diff = sbi->total_valid_block_count - sbi->user_block_count;
+               *count -= diff;
+               sbi->total_valid_block_count = sbi->user_block_count;
                if (!*count) {
                        spin_unlock(&sbi->stat_lock);
+                       percpu_counter_sub(&sbi->alloc_valid_block_count, diff);
                        return false;
                }
        }
-       /* *count can be recalculated */
-       inode->i_blocks += *count;
-       sbi->total_valid_block_count =
-               sbi->total_valid_block_count + (block_t)(*count);
        spin_unlock(&sbi->stat_lock);
  
-       percpu_counter_add(&sbi->alloc_valid_block_count, (*count));
+       f2fs_i_blocks_write(inode, *count, true);
        return true;
  }
  
@@@ -1158,9 -1184,9 +1185,9 @@@ static inline void dec_valid_block_coun
        spin_lock(&sbi->stat_lock);
        f2fs_bug_on(sbi, sbi->total_valid_block_count < (block_t) count);
        f2fs_bug_on(sbi, inode->i_blocks < count);
-       inode->i_blocks -= count;
        sbi->total_valid_block_count -= (block_t)count;
        spin_unlock(&sbi->stat_lock);
+       f2fs_i_blocks_write(inode, count, false);
  }
  
  static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
@@@ -1295,7 -1321,7 +1322,7 @@@ static inline bool inc_valid_node_count
        }
  
        if (inode)
-               inode->i_blocks++;
+               f2fs_i_blocks_write(inode, 1, true);
  
        sbi->total_valid_node_count++;
        sbi->total_valid_block_count++;
@@@ -1314,7 -1340,7 +1341,7 @@@ static inline void dec_valid_node_count
        f2fs_bug_on(sbi, !sbi->total_valid_node_count);
        f2fs_bug_on(sbi, !inode->i_blocks);
  
-       inode->i_blocks--;
+       f2fs_i_blocks_write(inode, 1, false);
        sbi->total_valid_node_count--;
        sbi->total_valid_block_count--;
  
@@@ -1511,12 -1537,12 +1538,12 @@@ static inline void f2fs_change_bit(unsi
  enum {
        FI_NEW_INODE,           /* indicate newly allocated inode */
        FI_DIRTY_INODE,         /* indicate inode is dirty or not */
+       FI_AUTO_RECOVER,        /* indicate inode is recoverable */
        FI_DIRTY_DIR,           /* indicate directory has dirty pages */
        FI_INC_LINK,            /* need to increment i_nlink */
        FI_ACL_MODE,            /* indicate acl mode */
        FI_NO_ALLOC,            /* should not allocate any blocks */
        FI_FREE_NID,            /* free allocated nide */
-       FI_UPDATE_DIR,          /* should update inode block for consistency */
        FI_NO_EXTENT,           /* not to use the extent cache */
        FI_INLINE_XATTR,        /* used for inline xattr */
        FI_INLINE_DATA,         /* used for inline data*/
        FI_DIRTY_FILE,          /* indicate regular/symlink has dirty pages */
  };
  
- static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
+ static inline void __mark_inode_dirty_flag(struct inode *inode,
+                                               int flag, bool set)
+ {
+       switch (flag) {
+       case FI_INLINE_XATTR:
+       case FI_INLINE_DATA:
+       case FI_INLINE_DENTRY:
+               if (set)
+                       return;
+       case FI_DATA_EXIST:
+       case FI_INLINE_DOTS:
+               f2fs_mark_inode_dirty_sync(inode);
+       }
+ }
+ static inline void set_inode_flag(struct inode *inode, int flag)
+ {
+       if (!test_bit(flag, &F2FS_I(inode)->flags))
+               set_bit(flag, &F2FS_I(inode)->flags);
+       __mark_inode_dirty_flag(inode, flag, true);
+ }
+ static inline int is_inode_flag_set(struct inode *inode, int flag)
+ {
+       return test_bit(flag, &F2FS_I(inode)->flags);
+ }
+ static inline void clear_inode_flag(struct inode *inode, int flag)
+ {
+       if (test_bit(flag, &F2FS_I(inode)->flags))
+               clear_bit(flag, &F2FS_I(inode)->flags);
+       __mark_inode_dirty_flag(inode, flag, false);
+ }
+ static inline void set_acl_inode(struct inode *inode, umode_t mode)
  {
-       if (!test_bit(flag, &fi->flags))
-               set_bit(flag, &fi->flags);
+       F2FS_I(inode)->i_acl_mode = mode;
+       set_inode_flag(inode, FI_ACL_MODE);
+       f2fs_mark_inode_dirty_sync(inode);
  }
  
- static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
+ static inline void f2fs_i_links_write(struct inode *inode, bool inc)
  {
-       return test_bit(flag, &fi->flags);
+       if (inc)
+               inc_nlink(inode);
+       else
+               drop_nlink(inode);
+       f2fs_mark_inode_dirty_sync(inode);
+ }
+ static inline void f2fs_i_blocks_write(struct inode *inode,
+                                       blkcnt_t diff, bool add)
+ {
+       bool clean = !is_inode_flag_set(inode, FI_DIRTY_INODE);
+       bool recover = is_inode_flag_set(inode, FI_AUTO_RECOVER);
+       inode->i_blocks = add ? inode->i_blocks + diff :
+                               inode->i_blocks - diff;
+       f2fs_mark_inode_dirty_sync(inode);
+       if (clean || recover)
+               set_inode_flag(inode, FI_AUTO_RECOVER);
+ }
+ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
+ {
+       bool clean = !is_inode_flag_set(inode, FI_DIRTY_INODE);
+       bool recover = is_inode_flag_set(inode, FI_AUTO_RECOVER);
+       if (i_size_read(inode) == i_size)
+               return;
+       i_size_write(inode, i_size);
+       f2fs_mark_inode_dirty_sync(inode);
+       if (clean || recover)
+               set_inode_flag(inode, FI_AUTO_RECOVER);
  }
  
- static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
+ static inline bool f2fs_skip_inode_update(struct inode *inode)
  {
-       if (test_bit(flag, &fi->flags))
-               clear_bit(flag, &fi->flags);
+       if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
+               return false;
+       return F2FS_I(inode)->last_disk_size == i_size_read(inode);
  }
  
- static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
+ static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
  {
-       fi->i_acl_mode = mode;
-       set_inode_flag(fi, FI_ACL_MODE);
+       F2FS_I(inode)->i_current_depth = depth;
+       f2fs_mark_inode_dirty_sync(inode);
  }
  
- static inline void get_inline_info(struct f2fs_inode_info *fi,
-                                       struct f2fs_inode *ri)
+ static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
  {
+       F2FS_I(inode)->i_xattr_nid = xnid;
+       f2fs_mark_inode_dirty_sync(inode);
+ }
+ static inline void f2fs_i_pino_write(struct inode *inode, nid_t pino)
+ {
+       F2FS_I(inode)->i_pino = pino;
+       f2fs_mark_inode_dirty_sync(inode);
+ }
+ static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri)
+ {
+       struct f2fs_inode_info *fi = F2FS_I(inode);
        if (ri->i_inline & F2FS_INLINE_XATTR)
-               set_inode_flag(fi, FI_INLINE_XATTR);
+               set_bit(FI_INLINE_XATTR, &fi->flags);
        if (ri->i_inline & F2FS_INLINE_DATA)
-               set_inode_flag(fi, FI_INLINE_DATA);
+               set_bit(FI_INLINE_DATA, &fi->flags);
        if (ri->i_inline & F2FS_INLINE_DENTRY)
-               set_inode_flag(fi, FI_INLINE_DENTRY);
+               set_bit(FI_INLINE_DENTRY, &fi->flags);
        if (ri->i_inline & F2FS_DATA_EXIST)
-               set_inode_flag(fi, FI_DATA_EXIST);
+               set_bit(FI_DATA_EXIST, &fi->flags);
        if (ri->i_inline & F2FS_INLINE_DOTS)
-               set_inode_flag(fi, FI_INLINE_DOTS);
+               set_bit(FI_INLINE_DOTS, &fi->flags);
  }
  
- static inline void set_raw_inline(struct f2fs_inode_info *fi,
-                                       struct f2fs_inode *ri)
+ static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri)
  {
        ri->i_inline = 0;
  
-       if (is_inode_flag_set(fi, FI_INLINE_XATTR))
+       if (is_inode_flag_set(inode, FI_INLINE_XATTR))
                ri->i_inline |= F2FS_INLINE_XATTR;
-       if (is_inode_flag_set(fi, FI_INLINE_DATA))
+       if (is_inode_flag_set(inode, FI_INLINE_DATA))
                ri->i_inline |= F2FS_INLINE_DATA;
-       if (is_inode_flag_set(fi, FI_INLINE_DENTRY))
+       if (is_inode_flag_set(inode, FI_INLINE_DENTRY))
                ri->i_inline |= F2FS_INLINE_DENTRY;
-       if (is_inode_flag_set(fi, FI_DATA_EXIST))
+       if (is_inode_flag_set(inode, FI_DATA_EXIST))
                ri->i_inline |= F2FS_DATA_EXIST;
-       if (is_inode_flag_set(fi, FI_INLINE_DOTS))
+       if (is_inode_flag_set(inode, FI_INLINE_DOTS))
                ri->i_inline |= F2FS_INLINE_DOTS;
  }
  
  static inline int f2fs_has_inline_xattr(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_XATTR);
+       return is_inode_flag_set(inode, FI_INLINE_XATTR);
  }
  
  static inline unsigned int addrs_per_inode(struct inode *inode)
@@@ -1618,43 -1723,43 +1724,43 @@@ static inline int inline_xattr_size(str
  
  static inline int f2fs_has_inline_data(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
+       return is_inode_flag_set(inode, FI_INLINE_DATA);
  }
  
  static inline void f2fs_clear_inline_inode(struct inode *inode)
  {
-       clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
-       clear_inode_flag(F2FS_I(inode), FI_DATA_EXIST);
+       clear_inode_flag(inode, FI_INLINE_DATA);
+       clear_inode_flag(inode, FI_DATA_EXIST);
  }
  
  static inline int f2fs_exist_data(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_DATA_EXIST);
+       return is_inode_flag_set(inode, FI_DATA_EXIST);
  }
  
  static inline int f2fs_has_inline_dots(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DOTS);
+       return is_inode_flag_set(inode, FI_INLINE_DOTS);
  }
  
  static inline bool f2fs_is_atomic_file(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_ATOMIC_FILE);
+       return is_inode_flag_set(inode, FI_ATOMIC_FILE);
  }
  
  static inline bool f2fs_is_volatile_file(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_VOLATILE_FILE);
+       return is_inode_flag_set(inode, FI_VOLATILE_FILE);
  }
  
  static inline bool f2fs_is_first_block_written(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_FIRST_BLOCK_WRITTEN);
+       return is_inode_flag_set(inode, FI_FIRST_BLOCK_WRITTEN);
  }
  
  static inline bool f2fs_is_drop_cache(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_DROP_CACHE);
+       return is_inode_flag_set(inode, FI_DROP_CACHE);
  }
  
  static inline void *inline_data_addr(struct page *page)
  
  static inline int f2fs_has_inline_dentry(struct inode *inode)
  {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DENTRY);
+       return is_inode_flag_set(inode, FI_INLINE_DENTRY);
  }
  
  static inline void f2fs_dentry_kunmap(struct inode *dir, struct page *page)
@@@ -1682,11 -1787,13 +1788,13 @@@ static inline int is_file(struct inode 
  static inline void set_file(struct inode *inode, int type)
  {
        F2FS_I(inode)->i_advise |= type;
+       f2fs_mark_inode_dirty_sync(inode);
  }
  
  static inline void clear_file(struct inode *inode, int type)
  {
        F2FS_I(inode)->i_advise &= ~type;
+       f2fs_mark_inode_dirty_sync(inode);
  }
  
  static inline int f2fs_readonly(struct super_block *sb)
@@@ -1713,7 -1820,7 +1821,7 @@@ static inline bool is_dot_dotdot(const 
  static inline bool f2fs_may_extent_tree(struct inode *inode)
  {
        if (!test_opt(F2FS_I_SB(inode), EXTENT_CACHE) ||
-                       is_inode_flag_set(F2FS_I(inode), FI_NO_EXTENT))
+                       is_inode_flag_set(inode, FI_NO_EXTENT))
                return false;
  
        return S_ISREG(inode->i_mode);
@@@ -1749,7 -1856,7 +1857,7 @@@ static inline void *f2fs_kvzalloc(size_
  }
  
  #define get_inode_mode(i) \
-       ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
+       ((is_inode_flag_set(i, FI_ACL_MODE)) ? \
         (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
  
  /* get offset of first page in next direct node */
  int f2fs_sync_file(struct file *, loff_t, loff_t, int);
  void truncate_data_blocks(struct dnode_of_data *);
  int truncate_blocks(struct inode *, u64, bool);
- int f2fs_truncate(struct inode *, bool);
+ int f2fs_truncate(struct inode *);
  int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
  int f2fs_setattr(struct dentry *, struct iattr *);
  int truncate_hole(struct inode *, pgoff_t, pgoff_t);
@@@ -1805,11 -1912,11 +1913,11 @@@ struct page *init_inode_metadata(struc
                        const struct qstr *, struct page *);
  void update_parent_metadata(struct inode *, struct inode *, unsigned int);
  int room_for_filename(const void *, int, int);
- void f2fs_drop_nlink(struct inode *, struct inode *, struct page *);
+ void f2fs_drop_nlink(struct inode *, struct inode *);
  struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
                                                        struct page **);
  struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
- ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
+ ino_t f2fs_inode_by_name(struct inode *, struct qstr *, struct page **);
  void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
                                struct page *, struct inode *);
  int update_dent_inode(struct inode *, struct inode *, const struct qstr *);
@@@ -1833,6 -1940,8 +1941,8 @@@ static inline int f2fs_add_link(struct 
  /*
   * super.c
   */
+ int f2fs_inode_dirtied(struct inode *);
+ void f2fs_inode_synced(struct inode *);
  int f2fs_commit_super(struct f2fs_sb_info *, bool);
  int f2fs_sync_fs(struct super_block *, int);
  extern __printf(3, 4)
@@@ -1866,11 -1975,11 +1976,11 @@@ struct page *new_node_page(struct dnode
  void ra_node_page(struct f2fs_sb_info *, nid_t);
  struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
  struct page *get_node_page_ra(struct page *, int);
- void sync_inode_page(struct dnode_of_data *);
  void move_node_page(struct page *, int);
- int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *,
-                                                               bool);
+ int fsync_node_pages(struct f2fs_sb_info *, struct inode *,
+                       struct writeback_control *, bool);
  int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *);
+ void build_free_nids(struct f2fs_sb_info *);
  bool alloc_nid(struct f2fs_sb_info *, nid_t *);
  void alloc_nid_done(struct f2fs_sb_info *, nid_t);
  void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
@@@ -1944,9 -2053,10 +2054,10 @@@ void add_ino_entry(struct f2fs_sb_info 
  void remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
  void release_ino_entry(struct f2fs_sb_info *, bool);
  bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
+ int f2fs_sync_inode_meta(struct f2fs_sb_info *);
  int acquire_orphan_inode(struct f2fs_sb_info *);
  void release_orphan_inode(struct f2fs_sb_info *);
- void add_orphan_inode(struct f2fs_sb_info *, nid_t);
+ void add_orphan_inode(struct inode *);
  void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
  int recover_orphan_inodes(struct f2fs_sb_info *);
  int get_valid_checkpoint(struct f2fs_sb_info *);
@@@ -1981,6 -2091,7 +2092,7 @@@ struct page *get_new_data_page(struct i
  int do_write_data_page(struct f2fs_io_info *);
  int f2fs_map_blocks(struct inode *, struct f2fs_map_blocks *, int, int);
  int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *, u64, u64);
+ void f2fs_set_page_dirty_nobuffers(struct page *);
  void f2fs_invalidate_page(struct page *, unsigned int, unsigned int);
  int f2fs_release_page(struct page *, gfp_t);
  
@@@ -2012,7 -2123,7 +2124,7 @@@ struct f2fs_stat_info 
        unsigned long long hit_total, total_ext;
        int ext_tree, zombie_tree, ext_node;
        s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
-       unsigned int ndirty_dirs, ndirty_files;
+       unsigned int ndirty_dirs, ndirty_files, ndirty_all;
        int nats, dirty_nats, sits, dirty_sits, fnids;
        int total_count, utilization;
        int bg_gc, wb_bios;
@@@ -2181,7 -2292,6 +2293,6 @@@ int f2fs_write_inline_data(struct inod
  bool recover_inline_data(struct inode *, struct page *);
  struct f2fs_dir_entry *find_in_inline_dir(struct inode *,
                                struct fscrypt_name *, struct page **);
- struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *, struct page **);
  int make_empty_inline_dir(struct inode *inode, struct inode *, struct page *);
  int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
                                                nid_t, umode_t);
@@@ -2206,6 -2316,7 +2317,7 @@@ void f2fs_leave_shrinker(struct f2fs_sb
   */
  unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
  bool f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
+ void f2fs_drop_extent_tree(struct inode *);
  unsigned int f2fs_destroy_extent_node(struct inode *);
  void f2fs_destroy_extent_tree(struct inode *);
  bool f2fs_lookup_extent_cache(struct inode *, pgoff_t, struct extent_info *);
@@@ -2241,6 -2352,26 +2353,26 @@@ static inline int f2fs_sb_has_crypto(st
        return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_ENCRYPT);
  }
  
+ static inline int f2fs_sb_mounted_hmsmr(struct super_block *sb)
+ {
+       return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_HMSMR);
+ }
+ static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
+ {
+       clear_opt(sbi, ADAPTIVE);
+       clear_opt(sbi, LFS);
+       switch (mt) {
+       case F2FS_MOUNT_ADAPTIVE:
+               set_opt(sbi, ADAPTIVE);
+               break;
+       case F2FS_MOUNT_LFS:
+               set_opt(sbi, LFS);
+               break;
+       }
+ }
  static inline bool f2fs_may_encrypt(struct inode *inode)
  {
  #ifdef CONFIG_F2FS_FS_ENCRYPTION
diff --combined fs/f2fs/gc.c
index f06ed73adf99602dcedd63ab75366f049d226213,06cfb94cc3db22a142c0b3c2346911d4cb7a001c..8f7fa326ce95b169e74d3ac0fcb205648a7fae90
@@@ -538,8 -538,7 +538,8 @@@ static void move_encrypted_block(struc
        struct f2fs_io_info fio = {
                .sbi = F2FS_I_SB(inode),
                .type = DATA,
 -              .rw = READ_SYNC,
 +              .op = REQ_OP_READ,
 +              .op_flags = READ_SYNC,
                .encrypted_page = NULL,
        };
        struct dnode_of_data dn;
        /* write page */
        lock_page(fio.encrypted_page);
  
-       if (unlikely(!PageUptodate(fio.encrypted_page))) {
+       if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
                err = -EIO;
                goto put_page_out;
        }
-       if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
+       if (unlikely(!PageUptodate(fio.encrypted_page))) {
                err = -EIO;
                goto put_page_out;
        }
        /* allocate block address */
        f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
  
 -      fio.rw = WRITE_SYNC;
 +      fio.op = REQ_OP_WRITE;
 +      fio.op_flags = WRITE_SYNC;
        fio.new_blkaddr = newaddr;
        f2fs_submit_page_mbio(&fio);
  
        f2fs_update_data_blkaddr(&dn, newaddr);
-       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);
  put_page_out:
        f2fs_put_page(fio.encrypted_page, 1);
  recover_block:
@@@ -651,17 -649,27 +651,28 @@@ static void move_data_page(struct inod
                struct f2fs_io_info fio = {
                        .sbi = F2FS_I_SB(inode),
                        .type = DATA,
 -                      .rw = WRITE_SYNC,
 +                      .op = REQ_OP_WRITE,
 +                      .op_flags = WRITE_SYNC,
                        .page = page,
                        .encrypted_page = NULL,
                };
+               bool is_dirty = PageDirty(page);
+               int err;
+ retry:
                set_page_dirty(page);
                f2fs_wait_on_page_writeback(page, DATA, true);
                if (clear_page_dirty_for_io(page))
                        inode_dec_dirty_pages(inode);
                set_cold_data(page);
-               do_write_data_page(&fio);
+               err = do_write_data_page(&fio);
+               if (err == -ENOMEM && is_dirty) {
+                       congestion_wait(BLK_RW_ASYNC, HZ/50);
+                       goto retry;
+               }
                clear_cold_data(page);
        }
  out:
@@@ -733,8 -741,7 +744,8 @@@ next_step
  
                        start_bidx = start_bidx_of_node(nofs, inode);
                        data_page = get_read_data_page(inode,
 -                                      start_bidx + ofs_in_node, READA, true);
 +                                      start_bidx + ofs_in_node, REQ_RAHEAD,
 +                                      true);
                        if (IS_ERR(data_page)) {
                                iput(inode);
                                continue;
                /* phase 3 */
                inode = find_gc_inode(gc_list, dni.ino);
                if (inode) {
+                       struct f2fs_inode_info *fi = F2FS_I(inode);
+                       bool locked = false;
+                       if (S_ISREG(inode->i_mode)) {
+                               if (!down_write_trylock(&fi->dio_rwsem[READ]))
+                                       continue;
+                               if (!down_write_trylock(
+                                               &fi->dio_rwsem[WRITE])) {
+                                       up_write(&fi->dio_rwsem[READ]);
+                                       continue;
+                               }
+                               locked = true;
+                       }
                        start_bidx = start_bidx_of_node(nofs, inode)
                                                                + ofs_in_node;
                        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
                                move_encrypted_block(inode, start_bidx);
                        else
                                move_data_page(inode, start_bidx, gc_type);
+                       if (locked) {
+                               up_write(&fi->dio_rwsem[WRITE]);
+                               up_write(&fi->dio_rwsem[READ]);
+                       }
                        stat_inc_data_blk_count(sbi, 1, gc_type);
                }
        }
@@@ -802,6 -829,10 +833,10 @@@ static int do_garbage_collect(struct f2
        blk_start_plug(&plug);
  
        for (segno = start_segno; segno < end_segno; segno++) {
+               if (get_valid_blocks(sbi, segno, 1) == 0)
+                       continue;
                /* find segment summary of victim */
                sum_page = find_get_page(META_MAPPING(sbi),
                                        GET_SUM_BLOCK(sbi, segno));
@@@ -877,10 -908,13 +912,13 @@@ gc_more
                 * enough free sections, we should flush dent/node blocks and do
                 * garbage collections.
                 */
-               if (__get_victim(sbi, &segno, gc_type) || prefree_segments(sbi))
+               if (__get_victim(sbi, &segno, gc_type) ||
+                                               prefree_segments(sbi)) {
                        write_checkpoint(sbi, &cpc);
-               else if (has_not_enough_free_secs(sbi, 0))
+                       segno = NULL_SEGNO;
+               } else if (has_not_enough_free_secs(sbi, 0)) {
                        write_checkpoint(sbi, &cpc);
+               }
        }
  
        if (segno == NULL_SEGNO && !__get_victim(sbi, &segno, gc_type))
diff --combined fs/f2fs/inline.c
index c15e53c1d794c482faab4626f089af531e91fc5b,d411ab6c74832ec232b87618edc985c83779559b..ccea8735de593cdeb015e1b9c138bf437414a92d
@@@ -59,7 -59,8 +59,8 @@@ void read_inline_data(struct page *page
        memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
        flush_dcache_page(page);
        kunmap_atomic(dst_addr);
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
  }
  
  bool truncate_inline_inode(struct page *ipage, u64 from)
@@@ -73,7 -74,7 +74,7 @@@
  
        f2fs_wait_on_page_writeback(ipage, NODE, true);
        memset(addr + from, 0, MAX_INLINE_DATA - from);
+       set_page_dirty(ipage);
        return true;
  }
  
@@@ -97,7 -98,8 +98,8 @@@ int f2fs_read_inline_data(struct inode 
        else
                read_inline_data(page, ipage);
  
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        f2fs_put_page(ipage, 1);
        unlock_page(page);
        return 0;
@@@ -108,8 -110,7 +110,8 @@@ int f2fs_convert_inline_page(struct dno
        struct f2fs_io_info fio = {
                .sbi = F2FS_I_SB(dn->inode),
                .type = DATA,
 -              .rw = WRITE_SYNC | REQ_PRIO,
 +              .op = REQ_OP_WRITE,
 +              .op_flags = WRITE_SYNC | REQ_PRIO,
                .page = page,
                .encrypted_page = NULL,
        };
                inode_dec_dirty_pages(dn->inode);
  
        /* this converted inline_data should be recovered. */
-       set_inode_flag(F2FS_I(dn->inode), FI_APPEND_WRITE);
+       set_inode_flag(dn->inode, FI_APPEND_WRITE);
  
        /* clear inline data and flag after data writeback */
        truncate_inline_inode(dn->inode_page, 0);
  clear_out:
        stat_dec_inline_inode(dn->inode);
        f2fs_clear_inline_inode(dn->inode);
-       sync_inode_page(dn);
        f2fs_put_dnode(dn);
        return 0;
  }
@@@ -213,11 -213,11 +214,11 @@@ int f2fs_write_inline_data(struct inod
        dst_addr = inline_data_addr(dn.inode_page);
        memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
        kunmap_atomic(src_addr);
+       set_page_dirty(dn.inode_page);
  
-       set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
-       set_inode_flag(F2FS_I(inode), FI_DATA_EXIST);
+       set_inode_flag(inode, FI_APPEND_WRITE);
+       set_inode_flag(inode, FI_DATA_EXIST);
  
-       sync_inode_page(&dn);
        clear_inline_node(dn.inode_page);
        f2fs_put_dnode(&dn);
        return 0;
@@@ -253,10 -253,10 +254,10 @@@ process_inline
                dst_addr = inline_data_addr(ipage);
                memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
  
-               set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
-               set_inode_flag(F2FS_I(inode), FI_DATA_EXIST);
+               set_inode_flag(inode, FI_INLINE_DATA);
+               set_inode_flag(inode, FI_DATA_EXIST);
  
-               update_inode(inode, ipage);
+               set_page_dirty(ipage);
                f2fs_put_page(ipage, 1);
                return true;
        }
                if (!truncate_inline_inode(ipage, 0))
                        return false;
                f2fs_clear_inline_inode(inode);
-               update_inode(inode, ipage);
                f2fs_put_page(ipage, 1);
        } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
                if (truncate_blocks(inode, 0, false))
@@@ -289,8 -288,10 +289,10 @@@ struct f2fs_dir_entry *find_in_inline_d
        f2fs_hash_t namehash;
  
        ipage = get_node_page(sbi, dir->i_ino);
-       if (IS_ERR(ipage))
+       if (IS_ERR(ipage)) {
+               *res_page = ipage;
                return NULL;
+       }
  
        namehash = f2fs_dentry_hash(&name);
  
        return de;
  }
  
- struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *dir,
-                                                       struct page **p)
- {
-       struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
-       struct page *ipage;
-       struct f2fs_dir_entry *de;
-       struct f2fs_inline_dentry *dentry_blk;
-       ipage = get_node_page(sbi, dir->i_ino);
-       if (IS_ERR(ipage))
-               return NULL;
-       dentry_blk = inline_data_addr(ipage);
-       de = &dentry_blk->dentry[1];
-       *p = ipage;
-       unlock_page(ipage);
-       return de;
- }
  int make_empty_inline_dir(struct inode *inode, struct inode *parent,
                                                        struct page *ipage)
  {
        set_page_dirty(ipage);
  
        /* update i_size to MAX_INLINE_DATA */
-       if (i_size_read(inode) < MAX_INLINE_DATA) {
-               i_size_write(inode, MAX_INLINE_DATA);
-               set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR);
-       }
+       if (i_size_read(inode) < MAX_INLINE_DATA)
+               f2fs_i_size_write(inode, MAX_INLINE_DATA);
        return 0;
  }
  
@@@ -392,22 -372,19 +373,19 @@@ static int f2fs_move_inline_dirents(str
                                        NR_INLINE_DENTRY * F2FS_SLOT_LEN);
  
        kunmap_atomic(dentry_blk);
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        set_page_dirty(page);
  
        /* clear inline dir and flag after data writeback */
        truncate_inline_inode(ipage, 0);
  
        stat_dec_inline_dir(dir);
-       clear_inode_flag(F2FS_I(dir), FI_INLINE_DENTRY);
+       clear_inode_flag(dir, FI_INLINE_DENTRY);
  
-       F2FS_I(dir)->i_current_depth = 1;
-       if (i_size_read(dir) < PAGE_SIZE) {
-               i_size_write(dir, PAGE_SIZE);
-               set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
-       }
-       sync_inode_page(&dn);
+       f2fs_i_depth_write(dir, 1);
+       if (i_size_read(dir) < PAGE_SIZE)
+               f2fs_i_size_write(dir, PAGE_SIZE);
  out:
        f2fs_put_page(page, 1);
        return err;
@@@ -465,7 -442,6 +443,6 @@@ static int f2fs_move_rehashed_dirents(s
                                struct f2fs_inline_dentry *inline_dentry)
  {
        struct f2fs_inline_dentry *backup_dentry;
-       struct f2fs_inode_info *fi = F2FS_I(dir);
        int err;
  
        backup_dentry = f2fs_kmalloc(sizeof(struct f2fs_inline_dentry),
        lock_page(ipage);
  
        stat_dec_inline_dir(dir);
-       clear_inode_flag(fi, FI_INLINE_DENTRY);
-       update_inode(dir, ipage);
+       clear_inode_flag(dir, FI_INLINE_DENTRY);
        kfree(backup_dentry);
        return 0;
  recover:
        lock_page(ipage);
        memcpy(inline_dentry, backup_dentry, MAX_INLINE_DATA);
-       fi->i_current_depth = 0;
-       i_size_write(dir, MAX_INLINE_DATA);
-       update_inode(dir, ipage);
+       f2fs_i_depth_write(dir, 0);
+       f2fs_i_size_write(dir, MAX_INLINE_DATA);
+       set_page_dirty(ipage);
        f2fs_put_page(ipage, 1);
  
        kfree(backup_dentry);
@@@ -560,8 -535,7 +536,7 @@@ int f2fs_add_inline_entry(struct inode 
  
        /* we don't need to mark_inode_dirty now */
        if (inode) {
-               F2FS_I(inode)->i_pino = dir->i_ino;
-               update_inode(inode, page);
+               f2fs_i_pino_write(inode, dir->i_ino);
                f2fs_put_page(page, 1);
        }
  
  fail:
        if (inode)
                up_write(&F2FS_I(inode)->i_sem);
-       if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
-               update_inode(dir, ipage);
-               clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR);
-       }
  out:
        f2fs_put_page(ipage, 1);
        return err;
@@@ -597,13 -566,13 +567,13 @@@ void f2fs_delete_inline_entry(struct f2
                                &inline_dentry->dentry_bitmap);
  
        set_page_dirty(page);
+       f2fs_put_page(page, 1);
  
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       f2fs_mark_inode_dirty_sync(dir);
  
        if (inode)
-               f2fs_drop_nlink(dir, inode, page);
-       f2fs_put_page(page, 1);
+               f2fs_drop_nlink(dir, inode);
  }
  
  bool f2fs_empty_inline_dir(struct inode *dir)
diff --combined fs/f2fs/node.c
index d1867698e6012ca263a04babc4502e1916cc16ad,79a93c6e632fe0edd24a3b046c8b27cdb01f5f57..b2fa4b615925b894a92377b215780edb33354571
@@@ -52,6 -52,10 +52,10 @@@ bool available_free_memory(struct f2fs_
                mem_size = (nm_i->nat_cnt * sizeof(struct nat_entry)) >>
                                                        PAGE_SHIFT;
                res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2);
+               if (excess_cached_nats(sbi))
+                       res = false;
+               if (nm_i->nat_cnt > DEF_NAT_CACHE_THRESHOLD)
+                       res = false;
        } else if (type == DIRTY_DENTS) {
                if (sbi->sb->s_bdi->wb.dirty_exceeded)
                        return false;
@@@ -202,14 -206,14 +206,14 @@@ int need_dentry_mark(struct f2fs_sb_inf
        struct nat_entry *e;
        bool need = false;
  
-       down_read(&nm_i->nat_tree_lock);
+       percpu_down_read(&nm_i->nat_tree_lock);
        e = __lookup_nat_cache(nm_i, nid);
        if (e) {
                if (!get_nat_flag(e, IS_CHECKPOINTED) &&
                                !get_nat_flag(e, HAS_FSYNCED_INODE))
                        need = true;
        }
-       up_read(&nm_i->nat_tree_lock);
+       percpu_up_read(&nm_i->nat_tree_lock);
        return need;
  }
  
@@@ -219,11 -223,11 +223,11 @@@ bool is_checkpointed_node(struct f2fs_s
        struct nat_entry *e;
        bool is_cp = true;
  
-       down_read(&nm_i->nat_tree_lock);
+       percpu_down_read(&nm_i->nat_tree_lock);
        e = __lookup_nat_cache(nm_i, nid);
        if (e && !get_nat_flag(e, IS_CHECKPOINTED))
                is_cp = false;
-       up_read(&nm_i->nat_tree_lock);
+       percpu_up_read(&nm_i->nat_tree_lock);
        return is_cp;
  }
  
@@@ -233,13 -237,13 +237,13 @@@ bool need_inode_block_update(struct f2f
        struct nat_entry *e;
        bool need_update = true;
  
-       down_read(&nm_i->nat_tree_lock);
+       percpu_down_read(&nm_i->nat_tree_lock);
        e = __lookup_nat_cache(nm_i, ino);
        if (e && get_nat_flag(e, HAS_LAST_FSYNC) &&
                        (get_nat_flag(e, IS_CHECKPOINTED) ||
                         get_nat_flag(e, HAS_FSYNCED_INODE)))
                need_update = false;
-       up_read(&nm_i->nat_tree_lock);
+       percpu_up_read(&nm_i->nat_tree_lock);
        return need_update;
  }
  
@@@ -280,7 -284,7 +284,7 @@@ static void set_node_addr(struct f2fs_s
        struct f2fs_nm_info *nm_i = NM_I(sbi);
        struct nat_entry *e;
  
-       down_write(&nm_i->nat_tree_lock);
+       percpu_down_write(&nm_i->nat_tree_lock);
        e = __lookup_nat_cache(nm_i, ni->nid);
        if (!e) {
                e = grab_nat_entry(nm_i, ni->nid);
                        set_nat_flag(e, HAS_FSYNCED_INODE, true);
                set_nat_flag(e, HAS_LAST_FSYNC, fsync_done);
        }
-       up_write(&nm_i->nat_tree_lock);
+       percpu_up_write(&nm_i->nat_tree_lock);
  }
  
  int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
        struct f2fs_nm_info *nm_i = NM_I(sbi);
        int nr = nr_shrink;
  
-       if (!down_write_trylock(&nm_i->nat_tree_lock))
-               return 0;
+       percpu_down_write(&nm_i->nat_tree_lock);
  
        while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
                struct nat_entry *ne;
                __del_from_nat_cache(nm_i, ne);
                nr_shrink--;
        }
-       up_write(&nm_i->nat_tree_lock);
+       percpu_up_write(&nm_i->nat_tree_lock);
        return nr - nr_shrink;
  }
  
@@@ -370,13 -373,13 +373,13 @@@ void get_node_info(struct f2fs_sb_info 
        ni->nid = nid;
  
        /* Check nat cache */
-       down_read(&nm_i->nat_tree_lock);
+       percpu_down_read(&nm_i->nat_tree_lock);
        e = __lookup_nat_cache(nm_i, nid);
        if (e) {
                ni->ino = nat_get_ino(e);
                ni->blk_addr = nat_get_blkaddr(e);
                ni->version = nat_get_version(e);
-               up_read(&nm_i->nat_tree_lock);
+               percpu_up_read(&nm_i->nat_tree_lock);
                return;
        }
  
        node_info_from_raw_nat(ni, &ne);
        f2fs_put_page(page, 1);
  cache:
-       up_read(&nm_i->nat_tree_lock);
+       percpu_up_read(&nm_i->nat_tree_lock);
        /* cache nat entry */
-       down_write(&nm_i->nat_tree_lock);
+       percpu_down_write(&nm_i->nat_tree_lock);
        cache_nat_entry(sbi, nid, &ne);
-       up_write(&nm_i->nat_tree_lock);
+       percpu_up_write(&nm_i->nat_tree_lock);
  }
  
  /*
@@@ -646,6 -649,7 +649,7 @@@ release_out
        if (err == -ENOENT) {
                dn->cur_level = i;
                dn->max_level = level;
+               dn->ofs_in_node = offset[level];
        }
        return err;
  }
@@@ -670,8 -674,7 +674,7 @@@ static void truncate_node(struct dnode_
        if (dn->nid == dn->inode->i_ino) {
                remove_orphan_inode(sbi, dn->nid);
                dec_valid_inode_count(sbi);
-       } else {
-               sync_inode_page(dn);
+               f2fs_inode_synced(dn->inode);
        }
  invalidate:
        clear_node_page_dirty(dn->node_page);
@@@ -953,7 -956,7 +956,7 @@@ int truncate_xattr_node(struct inode *i
        if (IS_ERR(npage))
                return PTR_ERR(npage);
  
-       F2FS_I(inode)->i_xattr_nid = 0;
+       f2fs_i_xnid_write(inode, 0);
  
        /* need to do checkpoint during fsync */
        F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi));
@@@ -1019,7 -1022,7 +1022,7 @@@ struct page *new_node_page(struct dnode
        struct page *page;
        int err;
  
-       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 ERR_PTR(-EPERM);
  
        page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false);
        f2fs_wait_on_page_writeback(page, NODE, true);
        fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
        set_cold_node(dn->inode, page);
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        if (set_page_dirty(page))
                dn->node_changed = true;
  
        if (f2fs_has_xattr_block(ofs))
-               F2FS_I(dn->inode)->i_xattr_nid = dn->nid;
+               f2fs_i_xnid_write(dn->inode, dn->nid);
  
-       dn->node_page = page;
-       if (ipage)
-               update_inode(dn->inode, ipage);
-       else
-               sync_inode_page(dn);
        if (ofs == 0)
                inc_valid_inode_count(sbi);
        return page;
  
  fail:
   * 0: f2fs_put_page(page, 0)
   * LOCKED_PAGE or error: f2fs_put_page(page, 1)
   */
 -static int read_node_page(struct page *page, int rw)
 +static int read_node_page(struct page *page, int op_flags)
  {
        struct f2fs_sb_info *sbi = F2FS_P_SB(page);
        struct node_info ni;
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = NODE,
 -              .rw = rw,
 +              .op = REQ_OP_READ,
 +              .op_flags = op_flags,
                .page = page,
                .encrypted_page = NULL,
        };
  
+       if (PageUptodate(page))
+               return LOCKED_PAGE;
        get_node_info(sbi, page->index, &ni);
  
        if (unlikely(ni.blk_addr == NULL_ADDR)) {
                return -ENOENT;
        }
  
-       if (PageUptodate(page))
-               return LOCKED_PAGE;
        fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr;
        return f2fs_submit_page_bio(&fio);
  }
@@@ -1119,7 -1116,7 +1117,7 @@@ void ra_node_page(struct f2fs_sb_info *
        if (!apage)
                return;
  
 -      err = read_node_page(apage, READA);
 +      err = read_node_page(apage, REQ_RAHEAD);
        f2fs_put_page(apage, err ? 1 : 0);
  }
  
@@@ -1150,16 -1147,21 +1148,21 @@@ repeat
  
        lock_page(page);
  
-       if (unlikely(!PageUptodate(page))) {
-               f2fs_put_page(page, 1);
-               return ERR_PTR(-EIO);
-       }
        if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
+       if (unlikely(!PageUptodate(page)))
+               goto out_err;
  page_hit:
-       f2fs_bug_on(sbi, nid != nid_of_node(page));
+       if(unlikely(nid != nid_of_node(page))) {
+               f2fs_bug_on(sbi, 1);
+               ClearPageUptodate(page);
+ out_err:
+               f2fs_put_page(page, 1);
+               return ERR_PTR(-EIO);
+       }
        return page;
  }
  
@@@ -1176,24 -1178,6 +1179,6 @@@ struct page *get_node_page_ra(struct pa
        return __get_node_page(sbi, nid, parent, start);
  }
  
- void sync_inode_page(struct dnode_of_data *dn)
- {
-       int ret = 0;
-       if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) {
-               ret = update_inode(dn->inode, dn->node_page);
-       } else if (dn->inode_page) {
-               if (!dn->inode_page_locked)
-                       lock_page(dn->inode_page);
-               ret = update_inode(dn->inode, dn->inode_page);
-               if (!dn->inode_page_locked)
-                       unlock_page(dn->inode_page);
-       } else {
-               ret = update_inode_page(dn->inode);
-       }
-       dn->node_changed = ret ? true: false;
- }
  static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino)
  {
        struct inode *inode;
@@@ -1319,7 -1303,7 +1304,7 @@@ continue_unlock
        return last_page;
  }
  
- int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino,
+ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
                        struct writeback_control *wbc, bool atomic)
  {
        pgoff_t index, end;
        int ret = 0;
        struct page *last_page = NULL;
        bool marked = false;
+       nid_t ino = inode->i_ino;
  
        if (atomic) {
                last_page = last_fsync_dnode(sbi, ino);
@@@ -1380,9 -1365,13 +1366,13 @@@ continue_unlock
  
                        if (!atomic || page == last_page) {
                                set_fsync_mark(page, 1);
-                               if (IS_INODE(page))
+                               if (IS_INODE(page)) {
+                                       if (is_inode_flag_set(inode,
+                                                               FI_DIRTY_INODE))
+                                               update_inode(inode, page);
                                        set_dentry_mark(page,
                                                need_dentry_mark(sbi, ino));
+                               }
                                /*  may be written by other thread */
                                if (!PageDirty(page))
                                        set_page_dirty(page);
@@@ -1569,8 -1558,7 +1559,8 @@@ static int f2fs_write_node_page(struct 
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = NODE,
 -              .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE,
 +              .op = REQ_OP_WRITE,
 +              .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
                .page = page,
                .encrypted_page = NULL,
        };
@@@ -1630,6 -1618,7 +1620,7 @@@ static int f2fs_write_node_pages(struc
                            struct writeback_control *wbc)
  {
        struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
+       struct blk_plug plug;
        long diff;
  
        /* balancing f2fs's metadata in background */
  
        diff = nr_pages_to_write(sbi, NODE, wbc);
        wbc->sync_mode = WB_SYNC_NONE;
+       blk_start_plug(&plug);
        sync_node_pages(sbi, wbc);
+       blk_finish_plug(&plug);
        wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
        return 0;
  
@@@ -1657,9 -1648,10 +1650,10 @@@ static int f2fs_set_node_page_dirty(str
  {
        trace_f2fs_set_page_dirty(page, NODE);
  
-       SetPageUptodate(page);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        if (!PageDirty(page)) {
-               __set_page_dirty_nobuffers(page);
+               f2fs_set_page_dirty_nobuffers(page);
                inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
                SetPagePrivate(page);
                f2fs_trace_pid(page);
@@@ -1778,7 -1770,7 +1772,7 @@@ static void scan_nat_page(struct f2fs_s
        }
  }
  
static void build_free_nids(struct f2fs_sb_info *sbi)
+ void build_free_nids(struct f2fs_sb_info *sbi)
  {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
        struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
        nid_t nid = nm_i->next_scan_nid;
  
        /* Enough entries */
-       if (nm_i->fcnt > NAT_ENTRY_PER_BLOCK)
+       if (nm_i->fcnt >= NAT_ENTRY_PER_BLOCK)
                return;
  
        /* readahead nat pages to be scanned */
        ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
                                                        META_NAT, true);
  
-       down_read(&nm_i->nat_tree_lock);
+       percpu_down_read(&nm_i->nat_tree_lock);
  
        while (1) {
                struct page *page = get_current_nat_page(sbi, nid);
                        remove_free_nid(nm_i, nid);
        }
        up_read(&curseg->journal_rwsem);
-       up_read(&nm_i->nat_tree_lock);
+       percpu_up_read(&nm_i->nat_tree_lock);
  
        ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
                                        nm_i->ra_nid_pages, META_NAT, false);
@@@ -1925,12 -1917,15 +1919,15 @@@ int try_to_free_nids(struct f2fs_sb_inf
        struct free_nid *i, *next;
        int nr = nr_shrink;
  
+       if (nm_i->fcnt <= MAX_FREE_NIDS)
+               return 0;
        if (!mutex_trylock(&nm_i->build_lock))
                return 0;
  
        spin_lock(&nm_i->free_nid_list_lock);
        list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) {
-               if (nr_shrink <= 0 || nm_i->fcnt <= NAT_ENTRY_PER_BLOCK)
+               if (nr_shrink <= 0 || nm_i->fcnt <= MAX_FREE_NIDS)
                        break;
                if (i->state == NID_ALLOC)
                        continue;
@@@ -1957,7 -1952,7 +1954,7 @@@ void recover_inline_xattr(struct inode 
  
        ri = F2FS_INODE(page);
        if (!(ri->i_inline & F2FS_INLINE_XATTR)) {
-               clear_inode_flag(F2FS_I(inode), FI_INLINE_XATTR);
+               clear_inode_flag(inode, FI_INLINE_XATTR);
                goto update_inode;
        }
  
@@@ -1999,13 -1994,11 +1996,11 @@@ recover_xnid
        get_node_info(sbi, new_xnid, &ni);
        ni.ino = inode->i_ino;
        set_node_addr(sbi, &ni, NEW_ADDR, false);
-       F2FS_I(inode)->i_xattr_nid = new_xnid;
+       f2fs_i_xnid_write(inode, new_xnid);
  
        /* 3: update xattr blkaddr */
        refresh_sit_entry(sbi, NEW_ADDR, blkaddr);
        set_node_addr(sbi, &ni, blkaddr, false);
-       update_inode_page(inode);
  }
  
  int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        /* Should not use this inode from free nid list */
        remove_free_nid(NM_I(sbi), ino);
  
-       SetPageUptodate(ipage);
+       if (!PageUptodate(ipage))
+               SetPageUptodate(ipage);
        fill_node_footer(ipage, ino, ino, 0, true);
  
        src = F2FS_INODE(page);
@@@ -2213,7 -2207,7 +2209,7 @@@ void flush_nat_entries(struct f2fs_sb_i
        if (!nm_i->dirty_nat_cnt)
                return;
  
-       down_write(&nm_i->nat_tree_lock);
+       percpu_down_write(&nm_i->nat_tree_lock);
  
        /*
         * if there are no enough space in journal to store dirty nat
        list_for_each_entry_safe(set, tmp, &sets, set_list)
                __flush_nat_entry_set(sbi, set);
  
-       up_write(&nm_i->nat_tree_lock);
+       percpu_up_write(&nm_i->nat_tree_lock);
  
        f2fs_bug_on(sbi, nm_i->dirty_nat_cnt);
  }
@@@ -2272,7 -2266,8 +2268,8 @@@ static int init_node_manager(struct f2f
  
        mutex_init(&nm_i->build_lock);
        spin_lock_init(&nm_i->free_nid_list_lock);
-       init_rwsem(&nm_i->nat_tree_lock);
+       if (percpu_init_rwsem(&nm_i->nat_tree_lock))
+               return -ENOMEM;
  
        nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
        nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
@@@ -2329,7 -2324,7 +2326,7 @@@ void destroy_node_manager(struct f2fs_s
        spin_unlock(&nm_i->free_nid_list_lock);
  
        /* destroy nat cache */
-       down_write(&nm_i->nat_tree_lock);
+       percpu_down_write(&nm_i->nat_tree_lock);
        while ((found = __gang_lookup_nat_cache(nm_i,
                                        nid, NATVEC_SIZE, natvec))) {
                unsigned idx;
                        kmem_cache_free(nat_entry_set_slab, setvec[idx]);
                }
        }
-       up_write(&nm_i->nat_tree_lock);
+       percpu_up_write(&nm_i->nat_tree_lock);
  
+       percpu_free_rwsem(&nm_i->nat_tree_lock);
        kfree(nm_i->nat_bitmap);
        sbi->nm_info = NULL;
        kfree(nm_i);
diff --combined fs/f2fs/segment.c
index 4c2d1fa1e0e2e9e581b09397da28e0e8a54e4d32,d45e6bbf84934332e1f975a95868137017844a17..a46296f57b026e650f2a82950ae7f63a02fd2fb0
@@@ -241,7 -241,7 +241,7 @@@ void drop_inmem_pages(struct inode *ino
  {
        struct f2fs_inode_info *fi = F2FS_I(inode);
  
-       clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
+       clear_inode_flag(inode, FI_ATOMIC_FILE);
  
        mutex_lock(&fi->inmem_lock);
        __revoke_inmem_pages(inode, &fi->inmem_pages, true, false);
@@@ -257,8 -257,7 +257,8 @@@ static int __commit_inmem_pages(struct 
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = DATA,
 -              .rw = WRITE_SYNC | REQ_PRIO,
 +              .op = REQ_OP_WRITE,
 +              .op_flags = WRITE_SYNC | REQ_PRIO,
                .encrypted_page = NULL,
        };
        bool submit_bio = false;
@@@ -346,6 -345,11 +346,11 @@@ void f2fs_balance_fs(struct f2fs_sb_inf
  {
        if (!need)
                return;
+       /* balance_fs_bg is able to be pending */
+       if (excess_cached_nats(sbi))
+               f2fs_balance_fs_bg(sbi);
        /*
         * We should do GC or end up with checkpoint, if there are so many dirty
         * dir/node pages without enough free segments.
@@@ -367,7 -371,9 +372,9 @@@ void f2fs_balance_fs_bg(struct f2fs_sb_
                try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK);
  
        if (!available_free_memory(sbi, FREE_NIDS))
-               try_to_free_nids(sbi, NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES);
+               try_to_free_nids(sbi, MAX_FREE_NIDS);
+       else
+               build_free_nids(sbi);
  
        /* checkpoint is the only way to shrink partial cached entries */
        if (!available_free_memory(sbi, NAT_ENTRIES) ||
@@@ -407,8 -413,7 +414,8 @@@ repeat
                fcc->dispatch_list = llist_reverse_order(fcc->dispatch_list);
  
                bio->bi_bdev = sbi->sb->s_bdev;
 -              ret = submit_bio_wait(WRITE_FLUSH, bio);
 +              bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
 +              ret = submit_bio_wait(bio);
  
                llist_for_each_entry_safe(cmd, next,
                                          fcc->dispatch_list, llnode) {
@@@ -435,25 -440,28 +442,29 @@@ int f2fs_issue_flush(struct f2fs_sb_inf
        if (test_opt(sbi, NOBARRIER))
                return 0;
  
-       if (!test_opt(sbi, FLUSH_MERGE)) {
+       if (!test_opt(sbi, FLUSH_MERGE) || !atomic_read(&fcc->submit_flush)) {
                struct bio *bio = f2fs_bio_alloc(0);
                int ret;
  
+               atomic_inc(&fcc->submit_flush);
                bio->bi_bdev = sbi->sb->s_bdev;
 -              ret = submit_bio_wait(WRITE_FLUSH, bio);
 +              bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
 +              ret = submit_bio_wait(bio);
+               atomic_dec(&fcc->submit_flush);
                bio_put(bio);
                return ret;
        }
  
        init_completion(&cmd.wait);
  
+       atomic_inc(&fcc->submit_flush);
        llist_add(&cmd.llnode, &fcc->issue_list);
  
        if (!fcc->dispatch_list)
                wake_up(&fcc->flush_wait_queue);
  
        wait_for_completion(&cmd.wait);
+       atomic_dec(&fcc->submit_flush);
  
        return cmd.ret;
  }
@@@ -467,6 -475,7 +478,7 @@@ int create_flush_cmd_control(struct f2f
        fcc = kzalloc(sizeof(struct flush_cmd_control), GFP_KERNEL);
        if (!fcc)
                return -ENOMEM;
+       atomic_set(&fcc->submit_flush, 0);
        init_waitqueue_head(&fcc->flush_wait_queue);
        init_llist_head(&fcc->issue_list);
        SM_I(sbi)->cmd_control_info = fcc;
@@@ -668,6 -677,10 +680,10 @@@ static void add_discard_addrs(struct f2
                        break;
  
                end = __find_rev_next_zero_bit(dmap, max_blocks, start + 1);
+               if (force && start && end != max_blocks
+                                       && (end - start) < cpc->trim_minlen)
+                       continue;
                __add_discard_entry(sbi, cpc, se, start, end);
        }
  }
@@@ -705,6 -718,8 +721,8 @@@ void clear_prefree_segments(struct f2fs
        struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
        unsigned long *prefree_map = dirty_i->dirty_segmap[PRE];
        unsigned int start = 0, end = -1;
+       unsigned int secno, start_segno;
+       bool force = (cpc->reason == CP_DISCARD);
  
        mutex_lock(&dirty_i->seglist_lock);
  
  
                dirty_i->nr_dirty[PRE] -= end - start;
  
-               if (!test_opt(sbi, DISCARD))
+               if (force || !test_opt(sbi, DISCARD))
                        continue;
  
-               f2fs_issue_discard(sbi, START_BLOCK(sbi, start),
+               if (!test_opt(sbi, LFS) || sbi->segs_per_sec == 1) {
+                       f2fs_issue_discard(sbi, START_BLOCK(sbi, start),
                                (end - start) << sbi->log_blocks_per_seg);
+                       continue;
+               }
+ next:
+               secno = GET_SECNO(sbi, start);
+               start_segno = secno * sbi->segs_per_sec;
+               if (!IS_CURSEC(sbi, secno) &&
+                       !get_valid_blocks(sbi, start, sbi->segs_per_sec))
+                       f2fs_issue_discard(sbi, START_BLOCK(sbi, start_segno),
+                               sbi->segs_per_sec << sbi->log_blocks_per_seg);
+               start = start_segno + sbi->segs_per_sec;
+               if (start < end)
+                       goto next;
        }
        mutex_unlock(&dirty_i->seglist_lock);
  
        /* send small discards */
        list_for_each_entry_safe(entry, this, head, list) {
-               if (cpc->reason == CP_DISCARD && entry->len < cpc->trim_minlen)
+               if (force && entry->len < cpc->trim_minlen)
                        goto skip;
                f2fs_issue_discard(sbi, entry->blkaddr, entry->len);
                cpc->trimmed += entry->len;
@@@ -1219,6 -1248,9 +1251,9 @@@ void allocate_new_segments(struct f2fs_
  {
        int i;
  
+       if (test_opt(sbi, LFS))
+               return;
        for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++)
                __allocate_new_segments(sbi, i);
  }
@@@ -1392,11 -1424,17 +1427,17 @@@ static void do_write_page(struct f2fs_s
  {
        int type = __get_segment_type(fio->page, fio->type);
  
+       if (fio->type == NODE || fio->type == DATA)
+               mutex_lock(&fio->sbi->wio_mutex[fio->type]);
        allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
                                        &fio->new_blkaddr, sum, type);
  
        /* writeout dirty page into bdev */
        f2fs_submit_page_mbio(fio);
+       if (fio->type == NODE || fio->type == DATA)
+               mutex_unlock(&fio->sbi->wio_mutex[fio->type]);
  }
  
  void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
        struct f2fs_io_info fio = {
                .sbi = sbi,
                .type = META,
 -              .rw = WRITE_SYNC | REQ_META | REQ_PRIO,
 +              .op = REQ_OP_WRITE,
 +              .op_flags = WRITE_SYNC | REQ_META | REQ_PRIO,
                .old_blkaddr = page->index,
                .new_blkaddr = page->index,
                .page = page,
        };
  
        if (unlikely(page->index >= MAIN_BLKADDR(sbi)))
 -              fio.rw &= ~REQ_META;
 +              fio.op_flags &= ~REQ_META;
  
        set_page_writeback(page);
        f2fs_submit_page_mbio(&fio);
@@@ -2377,7 -2414,11 +2418,11 @@@ int build_segment_manager(struct f2fs_s
        sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
        sm_info->rec_prefree_segments = sm_info->main_segments *
                                        DEF_RECLAIM_PREFREE_SEGMENTS / 100;
-       sm_info->ipu_policy = 1 << F2FS_IPU_FSYNC;
+       if (sm_info->rec_prefree_segments > DEF_MAX_RECLAIM_PREFREE_SEGMENTS)
+               sm_info->rec_prefree_segments = DEF_MAX_RECLAIM_PREFREE_SEGMENTS;
+       if (!test_opt(sbi, LFS))
+               sm_info->ipu_policy = 1 << F2FS_IPU_FSYNC;
        sm_info->min_ipu_util = DEF_MIN_IPU_UTIL;
        sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS;