OSDN Git Service

Merge 4.20-rc1-4.9 into android-4.9
authorJaegeuk Kim <jaegeuk@google.com>
Sat, 3 Nov 2018 22:04:19 +0000 (15:04 -0700)
committerJaegeuk Kim <jaegeuk@google.com>
Sat, 3 Nov 2018 22:04:19 +0000 (15:04 -0700)
* origin/upstream-f2fs-stable-linux-4.9.y:
  f2fs: guarantee journalled quota data by checkpoint
  f2fs: cleanup dirty pages if recover failed
  f2fs: fix data corruption issue with hardware encryption
  f2fs: fix to recover inode->i_flags of inode block during POR
  f2fs: spread f2fs_set_inode_flags()
  f2fs: fix to spread clear_cold_data()
  Revert "f2fs: fix to clear PG_checked flag in set_page_dirty()"
  f2fs: account read IOs and use IO counts for is_idle
  f2fs: fix to account IO correctly for cgroup writeback
  f2fs: fix to account IO correctly
  f2fs: remove request_list check in is_idle()
  f2fs: allow to mount, if quota is failed
  f2fs: update REQ_TIME in f2fs_cross_rename()
  f2fs: do not update REQ_TIME in case of error conditions
  f2fs: remove unneeded disable_nat_bits()
  f2fs: remove unused sbi->trigger_ssr_threshold
  f2fs: shrink sbi->sb_lock coverage in set_file_temperature()
  f2fs: fix to recover cold bit of inode block during POR
  f2fs: submit cached bio to avoid endless PageWriteback
  f2fs: checkpoint disabling
  f2fs: clear PageError on the read path
  f2fs: allow out-place-update for direct IO in LFS mode
  f2fs: refactor ->page_mkwrite() flow
  Revert: "f2fs: check last page index in cached bio to decide submission"
  f2fs: support superblock checksum
  f2fs: add to account skip count of background GC
  f2fs: add to account meta IO
  f2fs: keep lazytime on remount
  f2fs: fix missing up_read
  f2fs: return correct errno in f2fs_gc
  f2fs: avoid f2fs_bug_on if f2fs_get_meta_page_nofail got EIO
  f2fs: mark inode dirty explicitly in recover_inode()
  f2fs: fix to recover inode's crtime during POR
  f2fs: fix to recover inode's i_gc_failures during POR
  f2fs: fix to recover inode's i_flags during POR
  f2fs: fix to recover inode's project id during POR
  f2fs: update i_size after DIO completion
  f2fs: report ENOENT correctly in f2fs_rename
  f2fs: fix remount problem of option io_bits
  f2fs: fix to recover inode's uid/gid during POR
  f2fs: avoid infinite loop in f2fs_alloc_nid
  f2fs: add new idle interval timing for discard and gc paths
  f2fs: split IO error injection according to RW
  f2fs: add SPDX license identifiers
  f2fs: surround fault_injection related option parsing using CONFIG_F2FS_FAULT_INJECTION
  f2fs: avoid sleeping under spin_lock
  f2fs: plug readahead IO in readdir()
  f2fs: fix to do sanity check with current segment number
  f2fs: fix memory leak of percpu counter in fill_super()
  f2fs: fix memory leak of write_io in fill_super()
  f2fs: cache NULL when both default_acl and acl are NULL
  f2fs: fix to flush all dirty inodes recovered in readonly fs
  f2fs: report error if quota off error during umount
  f2fs: submit bio after shutdown
  f2fs: avoid wrong decrypted data from disk
  Revert "f2fs: use printk_ratelimited for f2fs_msg"
  f2fs: fix unnecessary periodic wakeup of discard thread when dev is busy
  f2fs: fix to avoid NULL pointer dereference on se->discard_map
  f2fs: add additional sanity check in f2fs_acl_from_disk()

Change-Id: Iaf9fc5081065224c87e0987e82f0bb61a6e1b9ac
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
1  2 
fs/f2fs/data.c
fs/f2fs/inline.c
fs/f2fs/namei.c

diff --combined fs/f2fs/data.c
@@@ -1,12 -1,9 +1,9 @@@
+ // SPDX-License-Identifier: GPL-2.0
  /*
   * fs/f2fs/data.c
   *
   * Copyright (c) 2012 Samsung Electronics Co., Ltd.
   *             http://www.samsung.com/
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License version 2 as
-  * published by the Free Software Foundation.
   */
  #include <linux/fs.h>
  #include <linux/f2fs_fs.h>
@@@ -26,7 -23,6 +23,7 @@@
  #include "segment.h"
  #include "trace.h"
  #include <trace/events/f2fs.h>
 +#include <trace/events/android_fs.h>
  
  #define NUM_PREALLOC_POST_READ_CTXS   128
  
@@@ -49,12 -45,29 +46,29 @@@ static bool __is_cp_guaranteed(struct p
                        inode->i_ino ==  F2FS_NODE_INO(sbi) ||
                        S_ISDIR(inode->i_mode) ||
                        (S_ISREG(inode->i_mode) &&
-                       is_inode_flag_set(inode, FI_ATOMIC_FILE)) ||
+                       (f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) ||
                        is_cold_data(page))
                return true;
        return false;
  }
  
+ static enum count_type __read_io_type(struct page *page)
+ {
+       struct address_space *mapping = page->mapping;
+       if (mapping) {
+               struct inode *inode = mapping->host;
+               struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+               if (inode->i_ino == F2FS_META_INO(sbi))
+                       return F2FS_RD_META;
+               if (inode->i_ino == F2FS_NODE_INO(sbi))
+                       return F2FS_RD_NODE;
+       }
+       return F2FS_RD_DATA;
+ }
  /* postprocessing steps for read bios */
  enum bio_post_read_step {
        STEP_INITIAL = 0,
@@@ -80,10 -93,12 +94,12 @@@ static void __read_end_io(struct bio *b
                /* PG_error was set if any post_read step failed */
                if (bio->bi_error || PageError(page)) {
                        ClearPageUptodate(page);
-                       SetPageError(page);
+                       /* will re-read again later */
+                       ClearPageError(page);
                } else {
                        SetPageUptodate(page);
                }
+               dec_page_count(F2FS_P_SB(page), __read_io_type(page));
                unlock_page(page);
        }
        if (bio->bi_private)
@@@ -126,8 -141,8 +142,8 @@@ static bool f2fs_bio_post_read_required
  
  static void f2fs_read_end_io(struct bio *bio)
  {
-       if (time_to_inject(F2FS_P_SB(bio->bi_io_vec->bv_page), FAULT_IO)) {
-               f2fs_show_injection_info(FAULT_IO);
+       if (time_to_inject(F2FS_P_SB(bio->bi_io_vec->bv_page), FAULT_READ_IO)) {
+               f2fs_show_injection_info(FAULT_READ_IO);
                bio->bi_error = -EIO;
        }
  
@@@ -148,6 -163,11 +164,11 @@@ static void f2fs_write_end_io(struct bi
        struct bio_vec *bvec;
        int i;
  
+       if (time_to_inject(sbi, FAULT_WRITE_IO)) {
+               f2fs_show_injection_info(FAULT_WRITE_IO);
+               bio->bi_error = -EIO;
+       }
        bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
                enum count_type type = WB_DATA_TYPE(page);
@@@ -318,8 -338,8 +339,8 @@@ static void __submit_merged_bio(struct 
        io->bio = NULL;
  }
  
- static bool __has_merged_page(struct f2fs_bio_info *io,
-                               struct inode *inode, nid_t ino, pgoff_t idx)
+ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
+                                               struct page *page, nid_t ino)
  {
        struct bio_vec *bvec;
        struct page *target;
        if (!io->bio)
                return false;
  
-       if (!inode && !ino)
+       if (!inode && !page && !ino)
                return true;
  
        bio_for_each_segment_all(bvec, io->bio, i) {
                else
                        target = fscrypt_control_page(bvec->bv_page);
  
-               if (idx != target->index)
-                       continue;
                if (inode && inode == target->mapping->host)
                        return true;
+               if (page && page == target)
+                       return true;
                if (ino && ino == ino_of_node(target))
                        return true;
        }
  }
  
  static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
-                               nid_t ino, pgoff_t idx, enum page_type type)
+                                               struct page *page, nid_t ino,
+                                               enum page_type type)
  {
        enum page_type btype = PAGE_TYPE_OF_BIO(type);
        enum temp_type temp;
                io = sbi->write_io[btype] + temp;
  
                down_read(&io->io_rwsem);
-               ret = __has_merged_page(io, inode, ino, idx);
+               ret = __has_merged_page(io, inode, page, ino);
                up_read(&io->io_rwsem);
  
                /* TODO: use HOT temp only for meta pages now. */
@@@ -393,12 -413,12 +414,12 @@@ static void __f2fs_submit_merged_write(
  }
  
  static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
-                               struct inode *inode, nid_t ino, pgoff_t idx,
-                               enum page_type type, bool force)
+                               struct inode *inode, struct page *page,
+                               nid_t ino, enum page_type type, bool force)
  {
        enum temp_type temp;
  
-       if (!force && !has_merged_page(sbi, inode, ino, idx, type))
+       if (!force && !has_merged_page(sbi, inode, page, ino, type))
                return;
  
        for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
@@@ -417,10 -437,10 +438,10 @@@ void f2fs_submit_merged_write(struct f2
  }
  
  void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
-                               struct inode *inode, nid_t ino, pgoff_t idx,
-                               enum page_type type)
+                               struct inode *inode, struct page *page,
+                               nid_t ino, enum page_type type)
  {
-       __submit_merged_write_cond(sbi, inode, ino, idx, type, false);
+       __submit_merged_write_cond(sbi, inode, page, ino, type, false);
  }
  
  void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
@@@ -455,12 -475,16 +476,16 @@@ int f2fs_submit_page_bio(struct f2fs_io
                bio_put(bio);
                return -EFAULT;
        }
+       if (fio->io_wbc && !is_read_io(fio->op))
+               wbc_account_io(fio->io_wbc, page, PAGE_SIZE);
        bio_set_op_attrs(bio, fio->op, fio->op_flags);
  
-       __submit_bio(fio->sbi, bio, fio->type);
+       inc_page_count(fio->sbi, is_read_io(fio->op) ?
+                       __read_io_type(page): WB_DATA_TYPE(fio->page));
  
-       if (!is_read_io(fio->op))
-               inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page));
+       __submit_bio(fio->sbi, bio, fio->type);
        return 0;
  }
  
@@@ -532,6 -556,9 +557,9 @@@ skip
        if (fio->in_list)
                goto next;
  out:
+       if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) ||
+                               f2fs_is_checkpoint_ready(sbi))
+               __submit_merged_bio(io);
        up_write(&io->io_rwsem);
  }
  
@@@ -564,9 -591,6 +592,6 @@@ static struct bio *f2fs_grab_read_bio(s
                ctx->bio = bio;
                ctx->enabled_steps = post_read_steps;
                bio->bi_private = ctx;
-               /* wait the page to be moved by cleaning */
-               f2fs_wait_on_block_writeback(sbi, blkaddr);
        }
  
        return bio;
@@@ -581,10 -605,15 +606,15 @@@ static int f2fs_submit_page_read(struc
        if (IS_ERR(bio))
                return PTR_ERR(bio);
  
+       /* wait for GCed page writeback via META_MAPPING */
+       f2fs_wait_on_block_writeback(inode, blkaddr);
        if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
                bio_put(bio);
                return -EFAULT;
        }
+       ClearPageError(page);
+       inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
        __submit_bio(F2FS_I_SB(inode), bio, DATA);
        return 0;
  }
@@@ -875,7 -904,6 +905,6 @@@ static int __allocate_data_block(struc
        struct f2fs_summary sum;
        struct node_info ni;
        block_t old_blkaddr;
-       pgoff_t fofs;
        blkcnt_t count = 1;
        int err;
  
  
        dn->data_blkaddr = datablock_addr(dn->inode,
                                dn->node_page, dn->ofs_in_node);
-       if (dn->data_blkaddr == NEW_ADDR)
+       if (dn->data_blkaddr != NULL_ADDR)
                goto alloc;
  
        if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count))))
@@@ -904,12 -932,10 +933,10 @@@ alloc
                                        old_blkaddr, old_blkaddr);
        f2fs_set_data_blkaddr(dn);
  
-       /* update i_size */
-       fofs = f2fs_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))
-               f2fs_i_size_write(dn->inode,
-                               ((loff_t)(fofs + 1) << PAGE_SHIFT));
+       /*
+        * i_size will be updated by direct_IO. Otherwise, we'll get stale
+        * data from unwritten block via dio_read.
+        */
        return 0;
  }
  
@@@ -944,7 -970,7 +971,7 @@@ int f2fs_preallocate_blocks(struct kioc
  
        if (direct_io) {
                map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint);
-               flag = f2fs_force_buffered_io(inode, WRITE) ?
+               flag = f2fs_force_buffered_io(inode, iocb, from) ?
                                        F2FS_GET_BLOCK_PRE_AIO :
                                        F2FS_GET_BLOCK_PRE_DIO;
                goto map_blocks;
@@@ -969,7 -995,7 +996,7 @@@ map_blocks
        return err;
  }
  
static inline void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock)
+ void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock)
  {
        if (flag == F2FS_GET_BLOCK_PRE_AIO) {
                if (lock)
@@@ -1024,6 -1050,11 +1051,11 @@@ int f2fs_map_blocks(struct inode *inode
                map->m_flags = F2FS_MAP_MAPPED;
                if (map->m_next_extent)
                        *map->m_next_extent = pgofs + map->m_len;
+               /* for hardware encryption, but to avoid potential issue in future */
+               if (flag == F2FS_GET_BLOCK_DIO)
+                       f2fs_wait_on_block_writeback_range(inode,
+                                               map->m_pblk, map->m_len);
                goto out;
        }
  
@@@ -1063,7 -1094,15 +1095,15 @@@ next_block
                goto sync_out;
        }
  
-       if (!is_valid_data_blkaddr(sbi, blkaddr)) {
+       if (is_valid_data_blkaddr(sbi, blkaddr)) {
+               /* use out-place-update for driect IO under LFS mode */
+               if (test_opt(sbi, LFS) && create &&
+                               flag == F2FS_GET_BLOCK_DIO) {
+                       err = __allocate_data_block(&dn, map->m_seg_type);
+                       if (!err)
+                               set_inode_flag(inode, FI_APPEND_WRITE);
+               }
+       } else {
                if (create) {
                        if (unlikely(f2fs_cp_error(sbi))) {
                                err = -EIO;
                                        last_ofs_in_node = dn.ofs_in_node;
                                }
                        } else {
+                               WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO &&
+                                       flag != F2FS_GET_BLOCK_DIO);
                                err = __allocate_data_block(&dn,
                                                        map->m_seg_type);
                                if (!err)
@@@ -1172,6 -1213,12 +1214,12 @@@ skip
        goto next_dnode;
  
  sync_out:
+       /* for hardware encryption, but to avoid potential issue in future */
+       if (flag == F2FS_GET_BLOCK_DIO && map->m_flags & F2FS_MAP_MAPPED)
+               f2fs_wait_on_block_writeback_range(inode,
+                                               map->m_pblk, map->m_len);
        if (flag == F2FS_GET_BLOCK_PRECACHE) {
                if (map->m_flags & F2FS_MAP_MAPPED) {
                        unsigned int ofs = start_pgofs - map->m_lblk;
@@@ -1254,7 -1301,7 +1302,7 @@@ static int get_data_block_dio(struct in
                        struct buffer_head *bh_result, int create)
  {
        return __get_data_block(inode, iblock, bh_result, create,
-                                               F2FS_GET_BLOCK_DEFAULT, NULL,
+                                               F2FS_GET_BLOCK_DIO, NULL,
                                                f2fs_rw_hint_to_seg_type(
                                                        inode->i_write_hint));
  }
@@@ -1557,9 -1604,17 +1605,17 @@@ submit_and_realloc
                        }
                }
  
+               /*
+                * If the page is under writeback, we need to wait for
+                * its completion to see the correct decrypted data.
+                */
+               f2fs_wait_on_block_writeback(inode, block_nr);
                if (bio_add_page(bio, page, blocksize, 0) < blocksize)
                        goto submit_and_realloc;
  
+               inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
+               ClearPageError(page);
                last_block_in_bio = block_nr;
                goto next_page;
  set_error_page:
@@@ -1624,7 -1679,7 +1680,7 @@@ static int encrypt_one_page(struct f2fs
                return 0;
  
        /* wait for GCed page writeback via META_MAPPING */
-       f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr);
+       f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
  
  retry_encrypt:
        fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
@@@ -1681,6 -1736,10 +1737,10 @@@ static inline bool check_inplace_update
                        is_inode_flag_set(inode, FI_NEED_IPU))
                return true;
  
+       if (unlikely(fio && is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
+                       !f2fs_is_checkpointed_data(sbi, fio->old_blkaddr)))
+               return true;
        return false;
  }
  
@@@ -1704,6 -1763,8 +1764,8 @@@ bool f2fs_should_update_outplace(struc
                return true;
        if (S_ISDIR(inode->i_mode))
                return true;
+       if (IS_NOQUOTA(inode))
+               return true;
        if (f2fs_is_atomic_file(inode))
                return true;
        if (fio) {
                        return true;
                if (IS_ATOMIC_WRITTEN_PAGE(fio->page))
                        return true;
+               if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
+                       f2fs_is_checkpointed_data(sbi, fio->old_blkaddr)))
+                       return true;
        }
        return false;
  }
@@@ -1762,6 -1826,7 +1827,7 @@@ int f2fs_do_write_data_page(struct f2fs
        /* This page is already truncated */
        if (fio->old_blkaddr == NULL_ADDR) {
                ClearPageUptodate(page);
+               clear_cold_data(page);
                goto out_writepage;
        }
  got_it:
@@@ -1937,18 -2002,20 +2003,20 @@@ done
  
  out:
        inode_dec_dirty_pages(inode);
-       if (err)
+       if (err) {
                ClearPageUptodate(page);
+               clear_cold_data(page);
+       }
  
        if (wbc->for_reclaim) {
-               f2fs_submit_merged_write_cond(sbi, inode, 0, page->index, DATA);
+               f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA);
                clear_inode_flag(inode, FI_HOT_DATA);
                f2fs_remove_dirty_inode(inode);
                submitted = NULL;
        }
  
        unlock_page(page);
-       if (!S_ISDIR(inode->i_mode))
+       if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode))
                f2fs_balance_fs(sbi, need_balance_fs);
  
        if (unlikely(f2fs_cp_error(sbi))) {
@@@ -1999,10 -2066,10 +2067,10 @@@ static int f2fs_write_cache_pages(struc
        pgoff_t index;
        pgoff_t end;            /* Inclusive */
        pgoff_t done_index;
-       pgoff_t last_idx = ULONG_MAX;
        int cycled;
        int range_whole = 0;
        int tag;
+       int nwritten = 0;
  
        pagevec_init(&pvec, 0);
  
@@@ -2105,7 -2172,7 +2173,7 @@@ continue_unlock
                                done = 1;
                                break;
                        } else if (submitted) {
-                               last_idx = page->index;
+                               nwritten++;
                        }
  
                        if (--wbc->nr_to_write <= 0 &&
        if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
                mapping->writeback_index = done_index;
  
-       if (last_idx != ULONG_MAX)
+       if (nwritten)
                f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host,
-                                               0, last_idx, DATA);
+                                                               NULL, 0, DATA);
  
        return ret;
  }
@@@ -2139,6 -2206,8 +2207,8 @@@ static inline bool __should_serialize_i
  {
        if (!S_ISREG(inode->i_mode))
                return false;
+       if (IS_NOQUOTA(inode))
+               return false;
        if (wbc->sync_mode != WB_SYNC_ALL)
                return true;
        if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks)
@@@ -2168,7 -2237,8 +2238,8 @@@ static int __f2fs_write_data_pages(stru
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                goto skip_write;
  
-       if (S_ISDIR(inode->i_mode) && wbc->sync_mode == WB_SYNC_NONE &&
+       if ((S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) &&
+                       wbc->sync_mode == WB_SYNC_NONE &&
                        get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) &&
                        f2fs_available_free_memory(sbi, DIRTY_DENTS))
                goto skip_write;
@@@ -2233,7 -2303,7 +2304,7 @@@ static void f2fs_write_failed(struct ad
                down_write(&F2FS_I(inode)->i_mmap_sem);
  
                truncate_pagecache(inode, i_size);
-               f2fs_truncate_blocks(inode, i_size, true);
+               f2fs_truncate_blocks(inode, i_size, true, true);
  
                up_write(&F2FS_I(inode)->i_mmap_sem);
                up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@@@ -2329,18 -2399,12 +2400,22 @@@ static int f2fs_write_begin(struct fil
        block_t blkaddr = NULL_ADDR;
        int err = 0;
  
 +      if (trace_android_fs_datawrite_start_enabled()) {
 +              char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 +
 +              path = android_fstrace_get_pathname(pathbuf,
 +                                                  MAX_TRACE_PATHBUF_LEN,
 +                                                  inode);
 +              trace_android_fs_datawrite_start(inode, pos, len,
 +                                               current->pid, path,
 +                                               current->comm);
 +      }
        trace_f2fs_write_begin(inode, pos, len, flags);
  
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               goto fail;
        if ((f2fs_is_atomic_file(inode) &&
                        !f2fs_available_free_memory(sbi, INMEM_PAGES)) ||
                        is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) {
@@@ -2378,7 -2442,8 +2453,8 @@@ repeat
        if (err)
                goto fail;
  
-       if (need_balance && has_not_enough_free_secs(sbi, 0, 0)) {
+       if (need_balance && !IS_NOQUOTA(inode) &&
+                       has_not_enough_free_secs(sbi, 0, 0)) {
                unlock_page(page);
                f2fs_balance_fs(sbi, true);
                lock_page(page);
  
        f2fs_wait_on_page_writeback(page, DATA, false);
  
-       /* wait for GCed page writeback via META_MAPPING */
-       if (f2fs_post_read_required(inode))
-               f2fs_wait_on_block_writeback(sbi, blkaddr);
        if (len == PAGE_SIZE || PageUptodate(page))
                return 0;
  
@@@ -2438,7 -2499,6 +2510,7 @@@ static int f2fs_write_end(struct file *
  {
        struct inode *inode = page->mapping->host;
  
 +      trace_android_fs_datawrite_end(inode, pos, len);
        trace_f2fs_write_end(inode, pos, len, copied);
  
        /*
@@@ -2490,58 -2550,53 +2562,75 @@@ static ssize_t f2fs_direct_IO(struct ki
        struct address_space *mapping = iocb->ki_filp->f_mapping;
        struct inode *inode = mapping->host;
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
        size_t count = iov_iter_count(iter);
        loff_t offset = iocb->ki_pos;
        int rw = iov_iter_rw(iter);
        int err;
        enum rw_hint hint = iocb->ki_hint;
        int whint_mode = F2FS_OPTION(sbi).whint_mode;
+       bool do_opu;
  
        err = check_direct_IO(inode, iter, offset);
        if (err)
                return err < 0 ? err : 0;
  
-       if (f2fs_force_buffered_io(inode, rw))
+       if (f2fs_force_buffered_io(inode, iocb, iter))
                return 0;
  
+       do_opu = allow_outplace_dio(inode, iocb, iter);
        trace_f2fs_direct_IO_enter(inode, offset, count, rw);
  
 +      if (trace_android_fs_dataread_start_enabled() &&
 +          (rw == READ)) {
 +              char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 +
 +              path = android_fstrace_get_pathname(pathbuf,
 +                                                  MAX_TRACE_PATHBUF_LEN,
 +                                                  inode);
 +              trace_android_fs_dataread_start(inode, offset,
 +                                              count, current->pid, path,
 +                                              current->comm);
 +      }
 +      if (trace_android_fs_datawrite_start_enabled() &&
 +          (rw == WRITE)) {
 +              char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 +
 +              path = android_fstrace_get_pathname(pathbuf,
 +                                                  MAX_TRACE_PATHBUF_LEN,
 +                                                  inode);
 +              trace_android_fs_datawrite_start(inode, offset, count,
 +                                               current->pid, path,
 +                                               current->comm);
 +      }
        if (rw == WRITE && whint_mode == WHINT_MODE_OFF)
                iocb->ki_hint = WRITE_LIFE_NOT_SET;
  
-       if (!down_read_trylock(&F2FS_I(inode)->i_gc_rwsem[rw])) {
-               if (iocb->ki_flags & IOCB_NOWAIT) {
+       if (iocb->ki_flags & IOCB_NOWAIT) {
+               if (!down_read_trylock(&fi->i_gc_rwsem[rw])) {
                        iocb->ki_hint = hint;
                        err = -EAGAIN;
                        goto out;
                }
-               down_read(&F2FS_I(inode)->i_gc_rwsem[rw]);
+               if (do_opu && !down_read_trylock(&fi->i_gc_rwsem[READ])) {
+                       up_read(&fi->i_gc_rwsem[rw]);
+                       iocb->ki_hint = hint;
+                       err = -EAGAIN;
+                       goto out;
+               }
+       } else {
+               down_read(&fi->i_gc_rwsem[rw]);
+               if (do_opu)
+                       down_read(&fi->i_gc_rwsem[READ]);
        }
  
        err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
-       up_read(&F2FS_I(inode)->i_gc_rwsem[rw]);
+       if (do_opu)
+               up_read(&fi->i_gc_rwsem[READ]);
+       up_read(&fi->i_gc_rwsem[rw]);
  
        if (rw == WRITE) {
                if (whint_mode == WHINT_MODE_OFF)
                if (err > 0) {
                        f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO,
                                                                        err);
-                       set_inode_flag(inode, FI_UPDATE_WRITE);
+                       if (!do_opu)
+                               set_inode_flag(inode, FI_UPDATE_WRITE);
                } else if (err < 0) {
                        f2fs_write_failed(mapping, offset + count);
                }
        }
 -
  out:
 +      if (trace_android_fs_dataread_start_enabled() &&
 +          (rw == READ))
 +              trace_android_fs_dataread_end(inode, offset, count);
 +      if (trace_android_fs_datawrite_start_enabled() &&
 +          (rw == WRITE))
 +              trace_android_fs_datawrite_end(inode, offset, count);
 +
        trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
  
        return err;
@@@ -2588,6 -2638,8 +2678,8 @@@ void f2fs_invalidate_page(struct page *
                }
        }
  
+       clear_cold_data(page);
        /* This is atomic written page, keep Private */
        if (IS_ATOMIC_WRITTEN_PAGE(page))
                return f2fs_drop_inmem_page(inode, page);
@@@ -2606,6 -2658,7 +2698,7 @@@ int f2fs_release_page(struct page *page
        if (IS_ATOMIC_WRITTEN_PAGE(page))
                return 0;
  
+       clear_cold_data(page);
        set_page_private(page, 0);
        ClearPagePrivate(page);
        return 1;
@@@ -2621,10 -2674,6 +2714,6 @@@ static int f2fs_set_data_page_dirty(str
        if (!PageUptodate(page))
                SetPageUptodate(page);
  
-       /* don't remain PG_checked flag which was set during GC */
-       if (is_cold_data(page))
-               clear_cold_data(page);
        if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
                if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
                        f2fs_register_inmem_page(inode, page);
diff --combined fs/f2fs/inline.c
@@@ -1,11 -1,9 +1,9 @@@
+ // SPDX-License-Identifier: GPL-2.0
  /*
   * fs/f2fs/inline.c
   * Copyright (c) 2013, Intel Corporation
   * Authors: Huajun Li <huajun.li@intel.com>
   *          Haicheng Li <haicheng.li@intel.com>
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License version 2 as
-  * published by the Free Software Foundation.
   */
  
  #include <linux/fs.h>
@@@ -13,7 -11,6 +11,7 @@@
  
  #include "f2fs.h"
  #include "node.h"
 +#include <trace/events/android_fs.h>
  
  bool f2fs_may_inline_data(struct inode *inode)
  {
@@@ -87,29 -84,14 +85,29 @@@ int f2fs_read_inline_data(struct inode 
  {
        struct page *ipage;
  
 +      if (trace_android_fs_dataread_start_enabled()) {
 +              char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
 +
 +              path = android_fstrace_get_pathname(pathbuf,
 +                                                  MAX_TRACE_PATHBUF_LEN,
 +                                                  inode);
 +              trace_android_fs_dataread_start(inode, page_offset(page),
 +                                              PAGE_SIZE, current->pid,
 +                                              path, current->comm);
 +      }
 +
        ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
        if (IS_ERR(ipage)) {
 +              trace_android_fs_dataread_end(inode, page_offset(page),
 +                                            PAGE_SIZE);
                unlock_page(page);
                return PTR_ERR(ipage);
        }
  
        if (!f2fs_has_inline_data(inode)) {
                f2fs_put_page(ipage, 1);
 +              trace_android_fs_dataread_end(inode, page_offset(page),
 +                                            PAGE_SIZE);
                return -EAGAIN;
        }
  
        if (!PageUptodate(page))
                SetPageUptodate(page);
        f2fs_put_page(ipage, 1);
 +      trace_android_fs_dataread_end(inode, page_offset(page),
 +                                    PAGE_SIZE);
        unlock_page(page);
        return 0;
  }
@@@ -318,7 -298,7 +316,7 @@@ process_inline
                clear_inode_flag(inode, FI_INLINE_DATA);
                f2fs_put_page(ipage, 1);
        } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
-               if (f2fs_truncate_blocks(inode, 0, false))
+               if (f2fs_truncate_blocks(inode, 0, false, false))
                        return false;
                goto process_inline;
        }
@@@ -490,7 -470,7 +488,7 @@@ static int f2fs_add_inline_entries(stru
        return 0;
  punch_dentry_pages:
        truncate_inode_pages(&dir->i_data, 0);
-       f2fs_truncate_blocks(dir, 0, false);
+       f2fs_truncate_blocks(dir, 0, false, false);
        f2fs_remove_dirty_inode(dir);
        return err;
  }
diff --combined fs/f2fs/namei.c
@@@ -1,12 -1,9 +1,9 @@@
+ // SPDX-License-Identifier: GPL-2.0
  /*
   * fs/f2fs/namei.c
   *
   * Copyright (c) 2012 Samsung Electronics Co., Ltd.
   *             http://www.samsung.com/
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License version 2 as
-  * published by the Free Software Foundation.
   */
  #include <linux/fs.h>
  #include <linux/f2fs_fs.h>
@@@ -19,6 -16,7 +16,7 @@@
  
  #include "f2fs.h"
  #include "node.h"
+ #include "segment.h"
  #include "xattr.h"
  #include "acl.h"
  #include <trace/events/f2fs.h>
@@@ -74,10 -72,6 +72,6 @@@ static struct inode *f2fs_new_inode(str
        if (err)
                goto fail_drop;
  
-       err = dquot_alloc_inode(inode);
-       if (err)
-               goto fail_drop;
        set_inode_flag(inode, FI_NEW_INODE);
  
        /* If the directory encrypted, then we should encrypt the inode. */
        if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL)
                set_inode_flag(inode, FI_PROJ_INHERIT);
  
+       f2fs_set_inode_flags(inode);
        trace_f2fs_new_inode(inode, 0);
        return inode;
  
@@@ -184,16 -180,19 +180,19 @@@ static inline void set_file_temperature
        hot_count = sbi->raw_super->hot_ext_count;
  
        for (i = 0; i < cold_count + hot_count; i++) {
-               if (!is_extension_exist(name, extlist[i]))
-                       continue;
-               if (i < cold_count)
-                       file_set_cold(inode);
-               else
-                       file_set_hot(inode);
-               break;
+               if (is_extension_exist(name, extlist[i]))
+                       break;
        }
  
        up_read(&sbi->sb_lock);
+       if (i == cold_count + hot_count)
+               return;
+       if (i < cold_count)
+               file_set_cold(inode);
+       else
+               file_set_hot(inode);
  }
  
  int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
@@@ -272,6 -271,9 +271,9 @@@ static int f2fs_create(struct inode *di
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               return err;
  
        err = dquot_initialize(dir);
        if (err)
  
        f2fs_alloc_nid_done(sbi, ino);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
  
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
@@@ -318,6 -321,9 +320,9 @@@ static int f2fs_link(struct dentry *old
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               return err;
  
        err = fscrypt_prepare_link(old_dentry, dir, dentry);
        if (err)
@@@ -564,6 -570,9 +569,9 @@@ static int f2fs_symlink(struct inode *d
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               return err;
  
        err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
                                      &disk_link);
        err = page_symlink(inode, disk_link.name, disk_link.len);
  
  err_out:
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
  
        /*
         * Let's flush symlink data in order to avoid broken symlink as much as
@@@ -662,7 -672,8 +670,7 @@@ static int f2fs_mkdir(struct inode *dir
  
        f2fs_alloc_nid_done(sbi, inode->i_ino);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
  
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
@@@ -693,6 -704,9 +701,9 @@@ static int f2fs_mknod(struct inode *dir
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               return err;
  
        err = dquot_initialize(dir);
        if (err)
  
        f2fs_alloc_nid_done(sbi, inode->i_ino);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
  
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
@@@ -823,10 -838,13 +834,13 @@@ static int f2fs_rename(struct inode *ol
        struct f2fs_dir_entry *old_entry;
        struct f2fs_dir_entry *new_entry;
        bool is_old_inline = f2fs_has_inline_dentry(old_dir);
-       int err = -ENOENT;
+       int err;
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               return err;
  
        if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
                        (!projid_eq(F2FS_I(new_dir)->i_projid,
                        goto out;
        }
  
+       err = -ENOENT;
        old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
        if (!old_entry) {
                if (IS_ERR(old_page))
  
        if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
                f2fs_sync_fs(sbi->sb, 1);
+       f2fs_update_time(sbi, REQ_TIME);
        return 0;
  
  put_out_dir:
@@@ -1012,10 -1033,13 +1029,13 @@@ static int f2fs_cross_rename(struct ino
        struct f2fs_dir_entry *old_dir_entry = NULL, *new_dir_entry = NULL;
        struct f2fs_dir_entry *old_entry, *new_entry;
        int old_nlink = 0, new_nlink = 0;
-       int err = -ENOENT;
+       int err;
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
+       err = f2fs_is_checkpoint_ready(sbi);
+       if (err)
+               return err;
  
        if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
                        !projid_eq(F2FS_I(new_dir)->i_projid,
        if (err)
                goto out;
  
+       err = -ENOENT;
        old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
        if (!old_entry) {
                if (IS_ERR(old_page))
  
        if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
                f2fs_sync_fs(sbi->sb, 1);
+       f2fs_update_time(sbi, REQ_TIME);
        return 0;
  out_new_dir:
        if (new_dir_entry) {