f2fs: checkpoint disabling
[sfrench/cifs-2.6.git] / fs / f2fs / data.c
index 382c1ef9a9e4d6e9df05e39031ce0f5958e51663..9ef6f1f01eda821a1632b03a5e995d571ccc2797 100644 (file)
@@ -1,12 +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>
@@ -80,7 +77,8 @@ static void __read_end_io(struct bio *bio)
                /* PG_error was set if any post_read step failed */
                if (bio->bi_status || PageError(page)) {
                        ClearPageUptodate(page);
-                       SetPageError(page);
+                       /* will re-read again later */
+                       ClearPageError(page);
                } else {
                        SetPageUptodate(page);
                }
@@ -126,8 +124,9 @@ static bool f2fs_bio_post_read_required(struct bio *bio)
 
 static void f2fs_read_end_io(struct bio *bio)
 {
-       if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)), FAULT_IO)) {
-               f2fs_show_injection_info(FAULT_IO);
+       if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)),
+                                               FAULT_READ_IO)) {
+               f2fs_show_injection_info(FAULT_READ_IO);
                bio->bi_status = BLK_STS_IOERR;
        }
 
@@ -148,6 +147,11 @@ static void f2fs_write_end_io(struct bio *bio)
        struct bio_vec *bvec;
        int i;
 
+       if (time_to_inject(sbi, FAULT_WRITE_IO)) {
+               f2fs_show_injection_info(FAULT_WRITE_IO);
+               bio->bi_status = BLK_STS_IOERR;
+       }
+
        bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
                enum count_type type = WB_DATA_TYPE(page);
@@ -319,8 +323,8 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
        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;
@@ -329,7 +333,7 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
        if (!io->bio)
                return false;
 
-       if (!inode && !ino)
+       if (!inode && !page && !ino)
                return true;
 
        bio_for_each_segment_all(bvec, io->bio, i) {
@@ -339,11 +343,10 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
                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;
        }
@@ -352,7 +355,8 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
 }
 
 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;
@@ -363,7 +367,7 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
                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. */
@@ -394,12 +398,12 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
 }
 
 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++) {
@@ -418,10 +422,10 @@ void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
 }
 
 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)
@@ -533,6 +537,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);
 }
 
@@ -565,9 +572,6 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
                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;
@@ -582,10 +586,14 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
        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);
        __submit_bio(F2FS_I_SB(inode), bio, DATA);
        return 0;
 }
@@ -876,7 +884,6 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
        struct f2fs_summary sum;
        struct node_info ni;
        block_t old_blkaddr;
-       pgoff_t fofs;
        blkcnt_t count = 1;
        int err;
 
@@ -889,7 +896,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
 
        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))))
@@ -905,12 +912,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;
 }
 
@@ -945,7 +950,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
 
        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;
@@ -970,7 +975,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)
@@ -1064,7 +1069,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;
@@ -1076,6 +1089,8 @@ next_block:
                                        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)
@@ -1255,7 +1270,7 @@ 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_DIO, NULL,
                                                f2fs_rw_hint_to_seg_type(
                                                        inode->i_write_hint));
 }
@@ -1558,9 +1573,16 @@ 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;
 
+               ClearPageError(page);
                last_block_in_bio = block_nr;
                goto next_page;
 set_error_page:
@@ -1625,7 +1647,7 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
                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,
@@ -1682,6 +1704,10 @@ static inline bool check_inplace_update_policy(struct inode *inode,
                        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;
 }
 
@@ -1712,6 +1738,9 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *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;
 }
@@ -1942,7 +1971,7 @@ out:
                ClearPageUptodate(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;
@@ -2000,10 +2029,10 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
        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);
 
@@ -2106,7 +2135,7 @@ continue_unlock:
                                done = 1;
                                break;
                        } else if (submitted) {
-                               last_idx = page->index;
+                               nwritten++;
                        }
 
                        if (--wbc->nr_to_write <= 0 &&
@@ -2128,9 +2157,9 @@ continue_unlock:
        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;
 }
@@ -2332,6 +2361,10 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 
        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)) {
@@ -2382,10 +2415,6 @@ repeat:
 
        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;
 
@@ -2480,36 +2509,53 @@ 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);
+       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 (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)
@@ -2517,7 +2563,8 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                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);
                }