]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
f2fs: reconstruct code to write a data page
authorHou Pengyang <houpengyang@huawei.com>
Tue, 25 Apr 2017 12:45:12 +0000 (12:45 +0000)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 3 May 2017 04:19:46 +0000 (21:19 -0700)
This patch introduces encrypt_one_page which encrypts one data page before
submit_bio, and change the use of need_inplace_update.

Signed-off-by: Hou Pengyang <houpengyang@huawei.com>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/file.c
fs/f2fs/segment.h

index b8dcd1e224e855edaf4bd0899a7799924c70acf3..dfc974c95dd28dc1daddf8678498701c02079f36 100644 (file)
@@ -1302,6 +1302,49 @@ static int f2fs_read_data_pages(struct file *file,
        return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages);
 }
 
+static int encrypt_one_page(struct f2fs_io_info *fio)
+{
+       struct inode *inode = fio->page->mapping->host;
+       gfp_t gfp_flags = GFP_NOFS;
+
+       if (!f2fs_encrypted_inode(inode) || !S_ISREG(inode->i_mode))
+               return 0;
+
+       /* wait for GCed encrypted page writeback */
+       f2fs_wait_on_encrypted_page_writeback(fio->sbi, fio->old_blkaddr);
+
+retry_encrypt:
+       fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
+                       PAGE_SIZE, 0, fio->page->index, gfp_flags);
+       if (!IS_ERR(fio->encrypted_page))
+               return 0;
+
+       /* flush pending IOs and wait for a while in the ENOMEM case */
+       if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
+               f2fs_flush_merged_bios(fio->sbi);
+               congestion_wait(BLK_RW_ASYNC, HZ/50);
+               gfp_flags |= __GFP_NOFAIL;
+               goto retry_encrypt;
+       }
+       return PTR_ERR(fio->encrypted_page);
+}
+
+static inline bool need_inplace_update(struct f2fs_io_info *fio)
+{
+       struct inode *inode = fio->page->mapping->host;
+
+       if (fio->old_blkaddr == NEW_ADDR)
+               return false;
+       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))
+               return false;
+
+       return need_inplace_update_policy(inode, fio);
+}
+
 int do_write_data_page(struct f2fs_io_info *fio)
 {
        struct page *page = fio->page;
@@ -1322,30 +1365,9 @@ int do_write_data_page(struct f2fs_io_info *fio)
                goto out_writepage;
        }
 
-       if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
-               gfp_t gfp_flags = GFP_NOFS;
-
-               /* wait for GCed encrypted page writeback */
-               f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode),
-                                                       fio->old_blkaddr);
-retry_encrypt:
-               fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
-                                                       PAGE_SIZE, 0,
-                                                       fio->page->index,
-                                                       gfp_flags);
-               if (IS_ERR(fio->encrypted_page)) {
-                       err = PTR_ERR(fio->encrypted_page);
-                       if (err == -ENOMEM) {
-                               /* flush pending ios and wait for a while */
-                               f2fs_flush_merged_bios(F2FS_I_SB(inode));
-                               congestion_wait(BLK_RW_ASYNC, HZ/50);
-                               gfp_flags |= __GFP_NOFAIL;
-                               err = 0;
-                               goto retry_encrypt;
-                       }
-                       goto out_writepage;
-               }
-       }
+       err = encrypt_one_page(fio);
+       if (err)
+               goto out_writepage;
 
        set_page_writeback(page);
 
@@ -1353,15 +1375,14 @@ int do_write_data_page(struct f2fs_io_info *fio)
         * If current allocation needs SSR,
         * it had better in-place writes for updated data.
         */
-       if (unlikely(fio->old_blkaddr != NEW_ADDR &&
-                       !is_cold_data(page) &&
-                       !IS_ATOMIC_WRITTEN_PAGE(page) &&
-                       need_inplace_update(inode, fio))) {
-               f2fs_unlock_op(F2FS_I_SB(inode));
+       if (need_inplace_update(fio)) {
+               f2fs_bug_on(fio->sbi, !fio->cp_rwsem_locked);
+               f2fs_unlock_op(fio->sbi);
                fio->cp_rwsem_locked = false;
+
                err = rewrite_data_page(fio);
+               trace_f2fs_do_write_data_page(fio->page, IPU);
                set_inode_flag(inode, FI_UPDATE_WRITE);
-               trace_f2fs_do_write_data_page(page, IPU);
        } else {
                write_data_page(&dn, fio);
                trace_f2fs_do_write_data_page(page, OPU);
index 32050f4c3592c308bc72486be679461186ba9541..cdbf1add2a11794ca749ea77c369526bb9f454cf 100644 (file)
@@ -1898,7 +1898,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
        int err;
 
        /* if in-place-update policy is enabled, don't waste time here */
-       if (need_inplace_update(inode, NULL))
+       if (need_inplace_update_policy(inode, NULL))
                return -EINVAL;
 
        pg_start = range->start >> PAGE_SHIFT;
@@ -2033,7 +2033,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!S_ISREG(inode->i_mode))
+       if (!S_ISREG(inode->i_mode) || f2fs_is_atomic_file(inode))
                return -EINVAL;
 
        if (f2fs_readonly(sbi->sb))
index 8ad22b8cbba70005d1be8f33ffa2577a9739d646..10bf05d4cff49be8152a8e6aa434ec0ccb0827d4 100644 (file)
@@ -564,16 +564,12 @@ enum {
        F2FS_IPU_ASYNC,
 };
 
-static inline bool need_inplace_update(struct inode *inode,
+static inline bool need_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;
 
-       /* IPU can be done only for the user data */
-       if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
-               return false;
-
        if (test_opt(sbi, LFS))
                return false;