[RAMEN9610-8702][COMMON] diskcipher: support f2fs
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / fs / f2fs / data.c
index 36b535207c88906efae946f71195781497be87f5..513e24024a75b58b5dfad85335c4b5bd2f2cf7ff 100644 (file)
@@ -19,8 +19,6 @@
 #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 <linux/sched/signal.h>
 
 #include "segment.h"
 #include "trace.h"
 #include <trace/events/f2fs.h>
+#include <trace/events/android_fs.h>
+
+#define NUM_PREALLOC_POST_READ_CTXS    128
+
+static struct kmem_cache *bio_post_read_ctx_cache;
+static mempool_t *bio_post_read_ctx_pool;
 
 static bool __is_cp_guaranteed(struct page *page)
 {
@@ -50,11 +54,126 @@ static bool __is_cp_guaranteed(struct page *page)
        return false;
 }
 
-static void f2fs_read_end_io(struct bio *bio)
+/* postprocessing steps for read bios */
+enum bio_post_read_step {
+       STEP_INITIAL = 0,
+       STEP_DECRYPT,
+};
+
+struct bio_post_read_ctx {
+       struct bio *bio;
+       struct work_struct work;
+       unsigned int cur_step;
+       unsigned int enabled_steps;
+};
+
+/* device unit number for iv sector */
+#define PG_DUN(i,p)                                            \
+       ((((i)->i_ino & 0xffffffff) << 32) | ((p)->index & 0xffffffff))
+
+static inline bool f2fs_may_encrypt_bio(struct inode *inode,
+               struct f2fs_io_info *fio)
 {
-       struct bio_vec *bvec;
+#ifdef CONFIG_CRYPTO_DISKCIPHER
+       if (fio && (fio->type != DATA || fio->encrypted_page))
+               return false;
+
+       return (f2fs_encrypted_file(inode) &&
+                       fscrypt_disk_encrypted(inode));
+#else
+       return false;
+#endif
+}
+
+static inline bool f2fs_bio_disk_encrypted(unsigned int bi_opf)
+{
+       if (bi_opf & REQ_CRYPT)
+               return true;
+       else
+               return false;
+}
+
+static bool f2fs_mergeable_bio(struct bio *bio, u64 dun, void *ci, bool bio_encrypted)
+{
+#ifdef CONFIG_CRYPTO_DISKCIPHER
+       if (!bio)
+               return true;
+
+       /* if both of them are not encrypted, no further check is needed */
+       if (!f2fs_bio_disk_encrypted(bio->bi_opf) && !bio_encrypted)
+               return true;
+
+#ifdef CONFIG_CRYPTO_DISKCIPHER_DUN
+       if (bio->bi_aux_private == ci)
+               return bio_end_dun(bio) == dun;
+       else
+               return false;
+#else
+       return bio->bi_aux_private == ci;
+#endif
+#else
+       return true;
+#endif
+}
+
+static void __read_end_io(struct bio *bio)
+{
+       struct page *page;
+       struct bio_vec *bv;
        int i;
 
+       bio_for_each_segment_all(bv, bio, i) {
+               page = bv->bv_page;
+
+               /* PG_error was set if any post_read step failed */
+               if (bio->bi_status || PageError(page)) {
+                       ClearPageUptodate(page);
+                       SetPageError(page);
+               } else {
+                       SetPageUptodate(page);
+               }
+               unlock_page(page);
+       }
+       if (bio->bi_private)
+               mempool_free(bio->bi_private, bio_post_read_ctx_pool);
+       bio_put(bio);
+}
+
+static void bio_post_read_processing(struct bio_post_read_ctx *ctx);
+
+static void decrypt_work(struct work_struct *work)
+{
+       struct bio_post_read_ctx *ctx =
+               container_of(work, struct bio_post_read_ctx, work);
+
+       fscrypt_decrypt_bio(ctx->bio);
+
+       bio_post_read_processing(ctx);
+}
+
+static void bio_post_read_processing(struct bio_post_read_ctx *ctx)
+{
+       switch (++ctx->cur_step) {
+       case STEP_DECRYPT:
+               if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
+                       INIT_WORK(&ctx->work, decrypt_work);
+                       fscrypt_enqueue_decrypt_work(&ctx->work);
+                       return;
+               }
+               ctx->cur_step++;
+               /* fall-through */
+       default:
+               __read_end_io(ctx->bio);
+       }
+}
+
+static bool f2fs_bio_post_read_required(struct bio *bio)
+{
+       return bio->bi_private && !bio->bi_status;
+}
+
+static void f2fs_read_end_io(struct bio *bio)
+{
 #ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(F2FS_P_SB(bio->bi_io_vec->bv_page), FAULT_IO)) {
                f2fs_show_injection_info(FAULT_IO);
@@ -62,28 +181,19 @@ static void f2fs_read_end_io(struct bio *bio)
        }
 #endif
 
-       if (f2fs_bio_encrypted(bio)) {
-               if (bio->bi_status) {
-                       fscrypt_release_ctx(bio->bi_private);
-               } else {
-                       fscrypt_decrypt_bio_pages(bio->bi_private, bio);
-                       return;
-               }
-       }
+       if(f2fs_bio_disk_encrypted(bio->bi_opf))
+               goto end_io;
 
-       bio_for_each_segment_all(bvec, bio, i) {
-               struct page *page = bvec->bv_page;
+       if (f2fs_bio_post_read_required(bio)) {
+               struct bio_post_read_ctx *ctx = bio->bi_private;
 
-               if (!bio->bi_status) {
-                       if (!PageUptodate(page))
-                               SetPageUptodate(page);
-               } else {
-                       ClearPageUptodate(page);
-                       SetPageError(page);
-               }
-               unlock_page(page);
+               ctx->cur_step = STEP_INITIAL;
+               bio_post_read_processing(ctx);
+               return;
        }
-       bio_put(bio);
+
+end_io:
+       __read_end_io(bio);
 }
 
 static void f2fs_write_end_io(struct bio *bio)
@@ -111,8 +221,13 @@ static void f2fs_write_end_io(struct bio *bio)
 
                if (unlikely(bio->bi_status)) {
                        mapping_set_error(page->mapping, -EIO);
-                       f2fs_stop_checkpoint(sbi, true);
+                       if (type == F2FS_WB_CP_DATA)
+                               f2fs_stop_checkpoint(sbi, true);
                }
+
+               f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&
+                                       page->index != nid_of_node(page));
+
                dec_page_count(sbi, type);
                clear_cold_data(page);
                end_page_writeback(page);
@@ -169,15 +284,25 @@ static bool __same_bdev(struct f2fs_sb_info *sbi,
  * Low-level block read/write IO operations.
  */
 static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
-                               int npages, bool is_read)
+                               struct writeback_control *wbc,
+                               int npages, bool is_read,
+                               enum page_type type, enum temp_type temp)
 {
        struct bio *bio;
 
-       bio = f2fs_bio_alloc(npages);
+       bio = f2fs_bio_alloc(sbi, npages, true);
 
        f2fs_target_device(sbi, blk_addr, bio);
-       bio->bi_end_io = is_read ? f2fs_read_end_io : f2fs_write_end_io;
-       bio->bi_private = is_read ? NULL : sbi;
+       if (is_read) {
+               bio->bi_end_io = f2fs_read_end_io;
+               bio->bi_private = NULL;
+       } else {
+               bio->bi_end_io = f2fs_write_end_io;
+               bio->bi_private = sbi;
+               bio->bi_write_hint = io_type_to_rw_hint(sbi, type, temp);
+       }
+       if (wbc)
+               wbc_init_bio(wbc, bio);
 
        return bio;
 }
@@ -188,13 +313,12 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
        if (!is_read_io(bio_op(bio))) {
                unsigned int start;
 
-               if (f2fs_sb_mounted_blkzoned(sbi->sb) &&
-                       current->plug && (type == DATA || type == NODE))
-                       blk_finish_plug(current->plug);
-
                if (type != DATA && type != NODE)
                        goto submit_io;
 
+               if (f2fs_sb_has_blkzoned(sbi->sb) && current->plug)
+                       blk_finish_plug(current->plug);
+
                start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS;
                start %= F2FS_IO_SIZE(sbi);
 
@@ -236,7 +360,10 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
        if (!io->bio)
                return;
 
-       bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
+       if (f2fs_bio_disk_encrypted(io->bio->bi_opf))
+               bio_set_op_attrs(io->bio, fio->op, fio->op_flags | REQ_CRYPT);
+       else
+               bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
 
        if (is_read_io(fio->op))
                trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio);
@@ -368,19 +495,26 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
        struct bio *bio;
        struct page *page = fio->encrypted_page ?
                        fio->encrypted_page : fio->page;
+       struct inode *inode = fio->page->mapping->host;
 
+       verify_block_addr(fio, fio->new_blkaddr);
        trace_f2fs_submit_page_bio(page, fio);
        f2fs_trace_ios(fio, 0);
 
        /* Allocate a new bio */
-       bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->op));
+       bio = __bio_alloc(fio->sbi, fio->new_blkaddr, fio->io_wbc,
+                               1, is_read_io(fio->op), fio->type, fio->temp);
 
        if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
                bio_put(bio);
                return -EFAULT;
        }
+       fio->op_flags |= fio->encrypted_page ? REQ_NOENCRYPT : 0;
        bio_set_op_attrs(bio, fio->op, fio->op_flags);
 
+       if (f2fs_may_encrypt_bio(inode, fio))
+               fscrypt_set_bio(inode, bio, PG_DUN(inode, fio->page));
+
        __submit_bio(fio->sbi, bio, fio->type);
 
        if (!is_read_io(fio->op))
@@ -395,6 +529,9 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
        struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
        struct page *bio_page;
        int err = 0;
+       struct inode *inode;
+       bool bio_encrypted;
+       u64 dun;
 
        f2fs_bug_on(sbi, is_read_io(fio->op));
 
@@ -413,13 +550,17 @@ next:
        }
 
        if (fio->old_blkaddr != NEW_ADDR)
-               verify_block_addr(sbi, fio->old_blkaddr);
-       verify_block_addr(sbi, fio->new_blkaddr);
+               verify_block_addr(fio, fio->old_blkaddr);
+       verify_block_addr(fio, fio->new_blkaddr);
 
        bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
+       inode = fio->page->mapping->host;
+       dun = PG_DUN(inode, fio->page);
+       bio_encrypted = f2fs_may_encrypt_bio(inode, fio);
+       fio->op_flags |= fio->encrypted_page ? REQ_NOENCRYPT : 0;
 
-       /* set submitted = 1 as a return value */
-       fio->submitted = 1;
+       /* set submitted = true as a return value */
+       fio->submitted = true;
 
        inc_page_count(sbi, WB_DATA_TYPE(bio_page));
 
@@ -427,6 +568,10 @@ next:
            (io->fio.op != fio->op || io->fio.op_flags != fio->op_flags) ||
                        !__same_bdev(sbi, fio->new_blkaddr, io->bio)))
                __submit_merged_bio(io);
+
+       if (!f2fs_mergeable_bio(io->bio, dun, fscrypt_get_diskcipher(inode), bio_encrypted))
+               __submit_merged_bio(io);
+
 alloc_new:
        if (io->bio == NULL) {
                if ((fio->type == DATA || fio->type == NODE) &&
@@ -435,8 +580,12 @@ alloc_new:
                        dec_page_count(sbi, WB_DATA_TYPE(bio_page));
                        goto out_fail;
                }
-               io->bio = __bio_alloc(sbi, fio->new_blkaddr,
-                                               BIO_MAX_PAGES, false);
+               io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc,
+                                               BIO_MAX_PAGES, false,
+                                               fio->type, fio->temp);
+               if (bio_encrypted)
+                       fscrypt_set_bio(inode, io->bio, dun);
+
                io->fio = *fio;
        }
 
@@ -445,6 +594,9 @@ alloc_new:
                goto alloc_new;
        }
 
+       if (fio->io_wbc)
+               wbc_account_io(fio->io_wbc, bio_page, PAGE_SIZE);
+
        io->last_block_in_bio = fio->new_blkaddr;
        f2fs_trace_ios(fio, 0);
 
@@ -461,29 +613,37 @@ static struct bio *f2fs_grab_read_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 bio *bio;
+       struct bio_post_read_ctx *ctx;
+       unsigned int post_read_steps = 0;
 
-       if (f2fs_encrypted_file(inode)) {
-               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_block_writeback(sbi, blkaddr);
-       }
-
-       bio = bio_alloc(GFP_KERNEL, min_t(int, nr_pages, BIO_MAX_PAGES));
-       if (!bio) {
-               if (ctx)
-                       fscrypt_release_ctx(ctx);
+       bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false);
+       if (!bio)
                return ERR_PTR(-ENOMEM);
-       }
        f2fs_target_device(sbi, blkaddr, bio);
        bio->bi_end_io = f2fs_read_end_io;
-       bio->bi_private = ctx;
        bio_set_op_attrs(bio, REQ_OP_READ, 0);
 
+       if (f2fs_encrypted_file(inode) && !fscrypt_disk_encrypted(inode))
+               post_read_steps |= 1 << STEP_DECRYPT;
+       if (post_read_steps) {
+               ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
+               if (!ctx) {
+                       bio_put(bio);
+                       return ERR_PTR(-ENOMEM);
+               }
+               ctx->bio = bio;
+               ctx->enabled_steps = post_read_steps;
+               bio->bi_private = ctx;
+               bio_set_op_attrs(bio, REQ_OP_READ,
+                       (f2fs_encrypted_inode(inode) ?
+                        REQ_NOENCRYPT :
+                        0));
+
+               /* wait the page to be moved by cleaning */
+               f2fs_wait_on_block_writeback(sbi, blkaddr);
+       }
+
        return bio;
 }
 
@@ -500,6 +660,10 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
                bio_put(bio);
                return -EFAULT;
        }
+
+       if (f2fs_may_encrypt_bio(inode, NULL))
+               fscrypt_set_bio(inode, bio, PG_DUN(inode, page));
+
        __submit_bio(F2FS_I_SB(inode), bio, DATA);
        return 0;
 }
@@ -783,7 +947,7 @@ got_it:
        return page;
 }
 
-static int __allocate_data_block(struct dnode_of_data *dn)
+static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        struct f2fs_summary sum;
@@ -808,7 +972,7 @@ alloc:
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
        allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
-                                       &sum, CURSEG_WARM_DATA, NULL, false);
+                                       &sum, seg_type, NULL, false);
        set_data_blkaddr(dn);
 
        /* update i_size */
@@ -820,18 +984,20 @@ alloc:
        return 0;
 }
 
-static inline bool __force_buffered_io(struct inode *inode, int rw)
-{
-       return (f2fs_encrypted_file(inode) ||
-                       (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) ||
-                       F2FS_I_SB(inode)->s_ndevs);
-}
-
 int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
 {
        struct inode *inode = file_inode(iocb->ki_filp);
        struct f2fs_map_blocks map;
+       int flag;
        int err = 0;
+       bool direct_io = iocb->ki_flags & IOCB_DIRECT;
+
+       /* convert inline data for Direct I/O*/
+       if (direct_io) {
+               err = f2fs_convert_inline_inode(inode);
+               if (err)
+                       return err;
+       }
 
        if (is_inode_flag_set(inode, FI_NO_PREALLOC))
                return 0;
@@ -844,23 +1010,33 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
                map.m_len = 0;
 
        map.m_next_pgofs = NULL;
+       map.m_next_extent = NULL;
+       map.m_seg_type = NO_CHECK_TYPE;
 
-       if (iocb->ki_flags & IOCB_DIRECT) {
-               err = f2fs_convert_inline_inode(inode);
-               if (err)
-                       return err;
-               return f2fs_map_blocks(inode, &map, 1,
-                       __force_buffered_io(inode, WRITE) ?
-                               F2FS_GET_BLOCK_PRE_AIO :
-                               F2FS_GET_BLOCK_PRE_DIO);
+       if (direct_io) {
+               map.m_seg_type = rw_hint_to_seg_type(iocb->ki_hint);
+               flag = f2fs_force_buffered_io(inode, WRITE) ?
+                                       F2FS_GET_BLOCK_PRE_AIO :
+                                       F2FS_GET_BLOCK_PRE_DIO;
+               goto map_blocks;
        }
        if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) {
                err = f2fs_convert_inline_inode(inode);
                if (err)
                        return err;
        }
-       if (!f2fs_has_inline_data(inode))
-               return f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO);
+       if (f2fs_has_inline_data(inode))
+               return err;
+
+       flag = F2FS_GET_BLOCK_PRE_AIO;
+
+map_blocks:
+       err = f2fs_map_blocks(inode, &map, 1, flag);
+       if (map.m_len > 0 && err == -ENOSPC) {
+               if (!direct_io)
+                       set_inode_flag(inode, FI_NO_PREALLOC);
+               err = 0;
+       }
        return err;
 }
 
@@ -901,6 +1077,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
        blkcnt_t prealloc;
        struct extent_info ei = {0,0,0};
        block_t blkaddr;
+       unsigned int start_pgofs;
 
        if (!maxblocks)
                return 0;
@@ -916,6 +1093,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
                map->m_pblk = ei.blk + pgofs - ei.fofs;
                map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs);
                map->m_flags = F2FS_MAP_MAPPED;
+               if (map->m_next_extent)
+                       *map->m_next_extent = pgofs + map->m_len;
                goto out;
        }
 
@@ -934,10 +1113,14 @@ next_dnode:
                        if (map->m_next_pgofs)
                                *map->m_next_pgofs =
                                        get_next_page_offset(&dn, pgofs);
+                       if (map->m_next_extent)
+                               *map->m_next_extent =
+                                       get_next_page_offset(&dn, pgofs);
                }
                goto unlock_out;
        }
 
+       start_pgofs = pgofs;
        prealloc = 0;
        last_ofs_in_node = ofs_in_node = dn.ofs_in_node;
        end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
@@ -957,7 +1140,8 @@ next_block:
                                        last_ofs_in_node = dn.ofs_in_node;
                                }
                        } else {
-                               err = __allocate_data_block(&dn);
+                               err = __allocate_data_block(&dn,
+                                                       map->m_seg_type);
                                if (!err)
                                        set_inode_flag(inode, FI_APPEND_WRITE);
                        }
@@ -970,14 +1154,20 @@ next_block:
                                map->m_pblk = 0;
                                goto sync_out;
                        }
+                       if (flag == F2FS_GET_BLOCK_PRECACHE)
+                               goto sync_out;
                        if (flag == F2FS_GET_BLOCK_FIEMAP &&
                                                blkaddr == NULL_ADDR) {
                                if (map->m_next_pgofs)
                                        *map->m_next_pgofs = pgofs + 1;
+                               goto sync_out;
                        }
-                       if (flag != F2FS_GET_BLOCK_FIEMAP ||
-                                               blkaddr != NEW_ADDR)
+                       if (flag != F2FS_GET_BLOCK_FIEMAP) {
+                               /* for defragment case */
+                               if (map->m_next_pgofs)
+                                       *map->m_next_pgofs = pgofs + 1;
                                goto sync_out;
+                       }
                }
        }
 
@@ -1028,6 +1218,16 @@ skip:
        else if (dn.ofs_in_node < end_offset)
                goto next_block;
 
+       if (flag == F2FS_GET_BLOCK_PRECACHE) {
+               if (map->m_flags & F2FS_MAP_MAPPED) {
+                       unsigned int ofs = start_pgofs - map->m_lblk;
+
+                       f2fs_update_extent_cache_range(&dn,
+                               start_pgofs, map->m_pblk + ofs,
+                               map->m_len - ofs);
+               }
+       }
+
        f2fs_put_dnode(&dn);
 
        if (create) {
@@ -1037,6 +1237,17 @@ skip:
        goto next_dnode;
 
 sync_out:
+       if (flag == F2FS_GET_BLOCK_PRECACHE) {
+               if (map->m_flags & F2FS_MAP_MAPPED) {
+                       unsigned int ofs = start_pgofs - map->m_lblk;
+
+                       f2fs_update_extent_cache_range(&dn,
+                               start_pgofs, map->m_pblk + ofs,
+                               map->m_len - ofs);
+               }
+               if (map->m_next_extent)
+                       *map->m_next_extent = pgofs + 1;
+       }
        f2fs_put_dnode(&dn);
 unlock_out:
        if (create) {
@@ -1048,9 +1259,34 @@ out:
        return err;
 }
 
+bool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len)
+{
+       struct f2fs_map_blocks map;
+       block_t last_lblk;
+       int err;
+
+       if (pos + len > i_size_read(inode))
+               return false;
+
+       map.m_lblk = F2FS_BYTES_TO_BLK(pos);
+       map.m_next_pgofs = NULL;
+       map.m_next_extent = NULL;
+       map.m_seg_type = NO_CHECK_TYPE;
+       last_lblk = F2FS_BLK_ALIGN(pos + len);
+
+       while (map.m_lblk < last_lblk) {
+               map.m_len = last_lblk - map.m_lblk;
+               err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT);
+               if (err || map.m_len == 0)
+                       return false;
+               map.m_lblk += map.m_len;
+       }
+       return true;
+}
+
 static int __get_data_block(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh, int create, int flag,
-                       pgoff_t *next_pgofs)
+                       pgoff_t *next_pgofs, int seg_type)
 {
        struct f2fs_map_blocks map;
        int err;
@@ -1058,6 +1294,8 @@ static int __get_data_block(struct inode *inode, sector_t iblock,
        map.m_lblk = iblock;
        map.m_len = bh->b_size >> inode->i_blkbits;
        map.m_next_pgofs = next_pgofs;
+       map.m_next_extent = NULL;
+       map.m_seg_type = seg_type;
 
        err = f2fs_map_blocks(inode, &map, create, flag);
        if (!err) {
@@ -1073,14 +1311,17 @@ static int get_data_block(struct inode *inode, sector_t iblock,
                        pgoff_t *next_pgofs)
 {
        return __get_data_block(inode, iblock, bh_result, create,
-                                                       flag, next_pgofs);
+                                                       flag, next_pgofs,
+                                                       NO_CHECK_TYPE);
 }
 
 static int get_data_block_dio(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh_result, int create)
 {
        return __get_data_block(inode, iblock, bh_result, create,
-                                               F2FS_GET_BLOCK_DEFAULT, NULL);
+                                               F2FS_GET_BLOCK_DEFAULT, NULL,
+                                               rw_hint_to_seg_type(
+                                                       inode->i_write_hint));
 }
 
 static int get_data_block_bmap(struct inode *inode, sector_t iblock,
@@ -1091,7 +1332,8 @@ static int get_data_block_bmap(struct inode *inode, sector_t iblock,
                return -EFBIG;
 
        return __get_data_block(inode, iblock, bh_result, create,
-                                               F2FS_GET_BLOCK_BMAP, NULL);
+                                               F2FS_GET_BLOCK_BMAP, NULL,
+                                               NO_CHECK_TYPE);
 }
 
 static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
@@ -1104,6 +1346,68 @@ static inline loff_t blk_to_logical(struct inode *inode, sector_t blk)
        return (blk << inode->i_blkbits);
 }
 
+static int f2fs_xattr_fiemap(struct inode *inode,
+                               struct fiemap_extent_info *fieinfo)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct page *page;
+       struct node_info ni;
+       __u64 phys = 0, len;
+       __u32 flags;
+       nid_t xnid = F2FS_I(inode)->i_xattr_nid;
+       int err = 0;
+
+       if (f2fs_has_inline_xattr(inode)) {
+               int offset;
+
+               page = f2fs_grab_cache_page(NODE_MAPPING(sbi),
+                                               inode->i_ino, false);
+               if (!page)
+                       return -ENOMEM;
+
+               get_node_info(sbi, inode->i_ino, &ni);
+
+               phys = (__u64)blk_to_logical(inode, ni.blk_addr);
+               offset = offsetof(struct f2fs_inode, i_addr) +
+                                       sizeof(__le32) * (DEF_ADDRS_PER_INODE -
+                                       get_inline_xattr_addrs(inode));
+
+               phys += offset;
+               len = inline_xattr_size(inode);
+
+               f2fs_put_page(page, 1);
+
+               flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED;
+
+               if (!xnid)
+                       flags |= FIEMAP_EXTENT_LAST;
+
+               err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags);
+               if (err || err == 1)
+                       return err;
+       }
+
+       if (xnid) {
+               page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false);
+               if (!page)
+                       return -ENOMEM;
+
+               get_node_info(sbi, xnid, &ni);
+
+               phys = (__u64)blk_to_logical(inode, ni.blk_addr);
+               len = inode->i_sb->s_blocksize;
+
+               f2fs_put_page(page, 1);
+
+               flags = FIEMAP_EXTENT_LAST;
+       }
+
+       if (phys)
+               err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags);
+
+       return (err < 0 ? err : 0);
+}
+
 int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                u64 start, u64 len)
 {
@@ -1114,18 +1418,29 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        u32 flags = 0;
        int ret = 0;
 
-       ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
+       if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
+               ret = f2fs_precache_extents(inode);
+               if (ret)
+                       return ret;
+       }
+
+       ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR);
        if (ret)
                return ret;
 
+       inode_lock(inode);
+
+       if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
+               ret = f2fs_xattr_fiemap(inode, fieinfo);
+               goto out;
+       }
+
        if (f2fs_has_inline_data(inode)) {
                ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
                if (ret != -EAGAIN)
-                       return ret;
+                       goto out;
        }
 
-       inode_lock(inode);
-
        if (logical_to_blk(inode, len) == 0)
                len = blk_to_logical(inode, 1);
 
@@ -1195,7 +1510,6 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
                        unsigned nr_pages)
 {
        struct bio *bio = NULL;
-       unsigned page_idx;
        sector_t last_block_in_bio = 0;
        struct inode *inode = mapping->host;
        const unsigned blkbits = inode->i_blkbits;
@@ -1205,15 +1519,18 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
        sector_t last_block_in_file;
        sector_t block_nr;
        struct f2fs_map_blocks map;
+       bool bio_encrypted;
+       u64 dun;
 
        map.m_pblk = 0;
        map.m_lblk = 0;
        map.m_len = 0;
        map.m_flags = 0;
        map.m_next_pgofs = NULL;
+       map.m_next_extent = NULL;
+       map.m_seg_type = NO_CHECK_TYPE;
 
-       for (page_idx = 0; nr_pages; page_idx++, nr_pages--) {
-
+       for (; nr_pages; nr_pages--) {
                if (pages) {
                        page = list_last_entry(pages, struct page, lru);
 
@@ -1281,12 +1598,22 @@ submit_and_realloc:
                        __submit_bio(F2FS_I_SB(inode), bio, DATA);
                        bio = NULL;
                }
+
+               dun = PG_DUN(inode, page);
+               bio_encrypted = f2fs_may_encrypt_bio(inode, NULL);
+               if (!f2fs_mergeable_bio(bio, dun, fscrypt_get_diskcipher(inode), bio_encrypted)) {
+                       __submit_bio(F2FS_I_SB(inode), bio, DATA);
+                       bio = NULL;
+               }
+
                if (bio == NULL) {
                        bio = f2fs_grab_read_bio(inode, block_nr, nr_pages);
                        if (IS_ERR(bio)) {
                                bio = NULL;
                                goto set_error_page;
                        }
+                       if (f2fs_may_encrypt_bio(inode, NULL))
+                               fscrypt_set_bio(inode, bio, dun);
                }
 
                if (bio_add_page(bio, page, blocksize, 0) < blocksize)
@@ -1334,7 +1661,7 @@ static int f2fs_read_data_pages(struct file *file,
                        struct address_space *mapping,
                        struct list_head *pages, unsigned nr_pages)
 {
-       struct inode *inode = file->f_mapping->host;
+       struct inode *inode = mapping->host;
        struct page *page = list_last_entry(pages, struct page, lru);
 
        trace_f2fs_readpages(inode, page, nr_pages);
@@ -1354,10 +1681,13 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
        if (!f2fs_encrypted_file(inode))
                return 0;
 
-       /* wait for GCed encrypted page writeback */
+       /* wait for GCed page writeback via META_MAPPING */
        f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr);
 
 retry_encrypt:
+       if (fscrypt_disk_encrypted(inode))
+               return 0;
+
        fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
                        PAGE_SIZE, 0, fio->page->index, gfp_flags);
        if (!IS_ERR(fio->encrypted_page))
@@ -1373,18 +1703,79 @@ retry_encrypt:
        return PTR_ERR(fio->encrypted_page);
 }
 
+static inline bool check_inplace_update_policy(struct inode *inode,
+                               struct f2fs_io_info *fio)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       unsigned int policy = SM_I(sbi)->ipu_policy;
+
+       if (policy & (0x1 << F2FS_IPU_FORCE))
+               return true;
+       if (policy & (0x1 << F2FS_IPU_SSR) && need_SSR(sbi))
+               return true;
+       if (policy & (0x1 << F2FS_IPU_UTIL) &&
+                       utilization(sbi) > SM_I(sbi)->min_ipu_util)
+               return true;
+       if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && need_SSR(sbi) &&
+                       utilization(sbi) > SM_I(sbi)->min_ipu_util)
+               return true;
+
+       /*
+        * IPU for rewrite async pages
+        */
+       if (policy & (0x1 << F2FS_IPU_ASYNC) &&
+                       fio && fio->op == REQ_OP_WRITE &&
+                       !(fio->op_flags & REQ_SYNC) &&
+                       !f2fs_encrypted_inode(inode))
+               return true;
+
+       /* this is only set during fdatasync */
+       if (policy & (0x1 << F2FS_IPU_FSYNC) &&
+                       is_inode_flag_set(inode, FI_NEED_IPU))
+               return true;
+
+       return false;
+}
+
+bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio)
+{
+       if (f2fs_is_pinned_file(inode))
+               return true;
+
+       /* if this is cold file, we should overwrite to avoid fragmentation */
+       if (file_is_cold(inode))
+               return true;
+
+       return check_inplace_update_policy(inode, fio);
+}
+
+bool should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+
+       if (test_opt(sbi, LFS))
+               return true;
+       if (S_ISDIR(inode->i_mode))
+               return true;
+       if (f2fs_is_atomic_file(inode))
+               return true;
+       if (fio) {
+               if (is_cold_data(fio->page))
+                       return true;
+               if (IS_ATOMIC_WRITTEN_PAGE(fio->page))
+                       return true;
+       }
+       return false;
+}
+
 static inline bool need_inplace_update(struct f2fs_io_info *fio)
 {
        struct inode *inode = fio->page->mapping->host;
 
-       if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
-               return false;
-       if (is_cold_data(fio->page))
-               return false;
-       if (IS_ATOMIC_WRITTEN_PAGE(fio->page))
+       if (should_update_outplace(inode, fio))
                return false;
 
-       return need_inplace_update_policy(inode, fio);
+       return should_update_inplace(inode, fio);
 }
 
 static inline bool valid_ipu_blkaddr(struct f2fs_io_info *fio)
@@ -1443,6 +1834,7 @@ got_it:
                        goto out_writepage;
 
                set_page_writeback(page);
+               ClearPageError(page);
                f2fs_put_dnode(&dn);
                if (fio->need_lock == LOCK_REQ)
                        f2fs_unlock_op(fio->sbi);
@@ -1465,6 +1857,7 @@ got_it:
                goto out_writepage;
 
        set_page_writeback(page);
+       ClearPageError(page);
 
        /* LFS mode write path */
        write_data_page(&dn, fio);
@@ -1495,6 +1888,7 @@ static int __write_data_page(struct page *page, bool *submitted,
        int err = 0;
        struct f2fs_io_info fio = {
                .sbi = sbi,
+               .ino = inode->i_ino,
                .type = DATA,
                .op = REQ_OP_WRITE,
                .op_flags = wbc_to_write_flags(wbc),
@@ -1504,10 +1898,17 @@ static int __write_data_page(struct page *page, bool *submitted,
                .submitted = false,
                .need_lock = LOCK_RETRY,
                .io_type = io_type,
+               .io_wbc = wbc,
        };
 
        trace_f2fs_writepage(page, DATA);
 
+       /* we should bypass data pages to proceed the kworkder jobs */
+       if (unlikely(f2fs_cp_error(sbi))) {
+               mapping_set_error(page->mapping, -EIO);
+               goto out;
+       }
+
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                goto redirty_out;
 
@@ -1532,12 +1933,6 @@ 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)) {
                fio.need_lock = LOCK_DONE;
@@ -1566,8 +1961,15 @@ write:
                        err = do_write_data_page(&fio);
                }
        }
-       if (F2FS_I(inode)->last_disk_size < psize)
-               F2FS_I(inode)->last_disk_size = psize;
+
+       if (err) {
+               file_set_keep_isize(inode);
+       } else {
+               down_write(&F2FS_I(inode)->i_sem);
+               if (F2FS_I(inode)->last_disk_size < psize)
+                       F2FS_I(inode)->last_disk_size = psize;
+               up_write(&F2FS_I(inode)->i_sem);
+       }
 
 done:
        if (err && err != -ENOENT)
@@ -1601,7 +2003,13 @@ out:
 
 redirty_out:
        redirty_page_for_writepage(wbc, page);
-       if (!err)
+       /*
+        * pageout() in MM traslates EAGAIN, so calls handle_write_error()
+        * -> mapping_set_error() -> set_bit(AS_EIO, ...).
+        * file_write_and_wait_range() will see EIO error, which is critical
+        * to return value of fsync() followed by atomic_write failure to user.
+        */
+       if (!err || wbc->for_reclaim)
                return AOP_WRITEPAGE_ACTIVATE;
        unlock_page(page);
        return err;
@@ -1931,12 +2339,29 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct page *page = NULL;
        pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT;
-       bool need_balance = false;
+       bool need_balance = false, drop_atomic = false;
        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);
 
+       if (f2fs_is_atomic_file(inode) &&
+                       !available_free_memory(sbi, INMEM_PAGES)) {
+               err = -ENOMEM;
+               drop_atomic = true;
+               goto fail;
+       }
+
        /*
         * We should check this at this moment to avoid deadlock on inode page
         * and #0 page. The locking rule for inline_data conversion should be:
@@ -1952,7 +2377,7 @@ repeat:
         * Do not use grab_cache_page_write_begin() to avoid deadlock due to
         * wait_for_stable_page. Will wait that below with our IO control.
         */
-       page = pagecache_get_page(mapping, index,
+       page = f2fs_pagecache_get_page(mapping, index,
                                FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS);
        if (!page) {
                err = -ENOMEM;
@@ -1979,8 +2404,8 @@ repeat:
 
        f2fs_wait_on_page_writeback(page, DATA, false);
 
-       /* wait for GCed encrypted page writeback */
-       if (f2fs_encrypted_file(inode))
+       /* 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))
@@ -2014,6 +2439,8 @@ repeat:
 fail:
        f2fs_put_page(page, 1);
        f2fs_write_failed(mapping, pos + len);
+       if (drop_atomic)
+               drop_inmem_pages_all(sbi);
        return err;
 }
 
@@ -2024,6 +2451,7 @@ static int f2fs_write_end(struct file *file,
 {
        struct inode *inode = page->mapping->host;
 
+       trace_android_fs_datawrite_end(inode, pos, len);
        trace_f2fs_write_end(inode, pos, len, copied);
 
        /*
@@ -2068,25 +2496,63 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 {
        struct address_space *mapping = iocb->ki_filp->f_mapping;
        struct inode *inode = mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_I_SB(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;
 
        err = check_direct_IO(inode, iter, offset);
        if (err)
                return err;
 
-       if (__force_buffered_io(inode, rw))
+       if (f2fs_force_buffered_io(inode, rw))
                return 0;
 
        trace_f2fs_direct_IO_enter(inode, offset, count, rw);
 
-       down_read(&F2FS_I(inode)->dio_rwsem[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)->dio_rwsem[rw])) {
+               if (iocb->ki_flags & IOCB_NOWAIT) {
+                       iocb->ki_hint = hint;
+                       err = -EAGAIN;
+                       goto out;
+               }
+               down_read(&F2FS_I(inode)->dio_rwsem[rw]);
+       }
+
        err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
        up_read(&F2FS_I(inode)->dio_rwsem[rw]);
 
        if (rw == WRITE) {
+               if (whint_mode == WHINT_MODE_OFF)
+                       iocb->ki_hint = hint;
                if (err > 0) {
                        f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO,
                                                                        err);
@@ -2095,6 +2561,13 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                        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);
 
@@ -2145,35 +2618,6 @@ int f2fs_release_page(struct page *page, gfp_t wait)
        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;
@@ -2197,7 +2641,7 @@ static int f2fs_set_data_page_dirty(struct page *page)
        }
 
        if (!PageDirty(page)) {
-               f2fs_set_page_dirty_nobuffers(page);
+               __set_page_dirty_nobuffers(page);
                update_dirty_page(inode, page);
                return 1;
        }
@@ -2293,3 +2737,27 @@ const struct address_space_operations f2fs_dblock_aops = {
        .migratepage    = f2fs_migrate_page,
 #endif
 };
+
+int __init f2fs_init_post_read_processing(void)
+{
+       bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0);
+       if (!bio_post_read_ctx_cache)
+               goto fail;
+       bio_post_read_ctx_pool =
+               mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,
+                                        bio_post_read_ctx_cache);
+       if (!bio_post_read_ctx_pool)
+               goto fail_free_cache;
+       return 0;
+
+fail_free_cache:
+       kmem_cache_destroy(bio_post_read_ctx_cache);
+fail:
+       return -ENOMEM;
+}
+
+void __exit f2fs_destroy_post_read_processing(void)
+{
+       mempool_destroy(bio_post_read_ctx_pool);
+       kmem_cache_destroy(bio_post_read_ctx_cache);
+}