Use invalidate_lock instead of f2fs' private i_mmap_sem. The intended
purpose is exactly the same. By this conversion we fix a long standing
race between hole punching and read(2) / readahead(2) paths that can
lead to stale page cache contents.

CC: Jaegeuk Kim <jaeg...@kernel.org>
CC: Chao Yu <yuch...@huawei.com>
CC: linux-f2fs-devel@lists.sourceforge.net
Signed-off-by: Jan Kara <j...@suse.cz>
---
 fs/f2fs/data.c  |  4 ++--
 fs/f2fs/f2fs.h  |  1 -
 fs/f2fs/file.c  | 58 ++++++++++++++++++++++++-------------------------
 fs/f2fs/super.c |  1 -
 4 files changed, 30 insertions(+), 34 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 96f1a354f89f..f3177d03c28f 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3165,12 +3165,12 @@ static void f2fs_write_failed(struct address_space 
*mapping, loff_t to)
        /* In the fs-verity case, f2fs_end_enable_verity() does the truncate */
        if (to > i_size && !f2fs_verity_in_progress(inode)) {
                down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-               down_write(&F2FS_I(inode)->i_mmap_sem);
+               down_write(&mapping->invalidate_lock);
 
                truncate_pagecache(inode, i_size);
                f2fs_truncate_blocks(inode, i_size, true);
 
-               up_write(&F2FS_I(inode)->i_mmap_sem);
+               up_write(&mapping->invalidate_lock);
                up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        }
 }
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 044878866ca3..1f887c906aaf 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -748,7 +748,6 @@ struct f2fs_inode_info {
 
        /* avoid racing between foreground op and gc */
        struct rw_semaphore i_gc_rwsem[2];
-       struct rw_semaphore i_mmap_sem;
        struct rw_semaphore i_xattr_sem; /* avoid racing between reading and 
changing EAs */
 
        int i_extra_isize;              /* size of extra space located in 
i_addr */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 44a4650aea7b..6602f3c653c4 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -38,10 +38,7 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
        struct inode *inode = file_inode(vmf->vma->vm_file);
        vm_fault_t ret;
 
-       down_read(&F2FS_I(inode)->i_mmap_sem);
        ret = filemap_fault(vmf);
-       up_read(&F2FS_I(inode)->i_mmap_sem);
-
        if (!ret)
                f2fs_update_iostat(F2FS_I_SB(inode), APP_MAPPED_READ_IO,
                                                        F2FS_BLKSIZE);
@@ -102,7 +99,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
        f2fs_bug_on(sbi, f2fs_has_inline_data(inode));
 
        file_update_time(vmf->vma->vm_file);
-       down_read(&F2FS_I(inode)->i_mmap_sem);
+       down_read(&inode->i_mapping->invalidate_lock);
        lock_page(page);
        if (unlikely(page->mapping != inode->i_mapping ||
                        page_offset(page) > i_size_read(inode) ||
@@ -161,7 +158,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
 
        trace_f2fs_vm_page_mkwrite(page, DATA);
 out_sem:
-       up_read(&F2FS_I(inode)->i_mmap_sem);
+       up_read(&inode->i_mapping->invalidate_lock);
 
        sb_end_pagefault(inode->i_sb);
 err:
@@ -942,7 +939,7 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct 
dentry *dentry,
                }
 
                down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-               down_write(&F2FS_I(inode)->i_mmap_sem);
+               down_write(&inode->i_mapping->invalidate_lock);
 
                truncate_setsize(inode, attr->ia_size);
 
@@ -952,7 +949,7 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct 
dentry *dentry,
                 * do not trim all blocks after i_size if target size is
                 * larger than i_size.
                 */
-               up_write(&F2FS_I(inode)->i_mmap_sem);
+               up_write(&inode->i_mapping->invalidate_lock);
                up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                if (err)
                        return err;
@@ -1097,7 +1094,7 @@ static int punch_hole(struct inode *inode, loff_t offset, 
loff_t len)
                        blk_end = (loff_t)pg_end << PAGE_SHIFT;
 
                        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-                       down_write(&F2FS_I(inode)->i_mmap_sem);
+                       down_write(&mapping->invalidate_lock);
 
                        truncate_inode_pages_range(mapping, blk_start,
                                        blk_end - 1);
@@ -1106,7 +1103,7 @@ static int punch_hole(struct inode *inode, loff_t offset, 
loff_t len)
                        ret = f2fs_truncate_hole(inode, pg_start, pg_end);
                        f2fs_unlock_op(sbi);
 
-                       up_write(&F2FS_I(inode)->i_mmap_sem);
+                       up_write(&mapping->invalidate_lock);
                        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                }
        }
@@ -1341,7 +1338,7 @@ static int f2fs_do_collapse(struct inode *inode, loff_t 
offset, loff_t len)
 
        /* avoid gc operation during block exchange */
        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&inode->i_mapping->invalidate_lock);
 
        f2fs_lock_op(sbi);
        f2fs_drop_extent_tree(inode);
@@ -1349,7 +1346,7 @@ static int f2fs_do_collapse(struct inode *inode, loff_t 
offset, loff_t len)
        ret = __exchange_data_block(inode, inode, end, start, nrpages - end, 
true);
        f2fs_unlock_op(sbi);
 
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&inode->i_mapping->invalidate_lock);
        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        return ret;
 }
@@ -1380,13 +1377,13 @@ static int f2fs_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
                return ret;
 
        /* write out all moved pages, if possible */
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&inode->i_mapping->invalidate_lock);
        filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        truncate_pagecache(inode, offset);
 
        new_size = i_size_read(inode) - len;
        ret = f2fs_truncate_blocks(inode, new_size, true);
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&inode->i_mapping->invalidate_lock);
        if (!ret)
                f2fs_i_size_write(inode, new_size);
        return ret;
@@ -1486,7 +1483,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t 
offset, loff_t len,
                        pgoff_t end;
 
                        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-                       down_write(&F2FS_I(inode)->i_mmap_sem);
+                       down_write(&mapping->invalidate_lock);
 
                        truncate_pagecache_range(inode,
                                (loff_t)index << PAGE_SHIFT,
@@ -1498,7 +1495,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t 
offset, loff_t len,
                        ret = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE);
                        if (ret) {
                                f2fs_unlock_op(sbi);
-                               up_write(&F2FS_I(inode)->i_mmap_sem);
+                               up_write(&mapping->invalidate_lock);
                                up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                                goto out;
                        }
@@ -1510,7 +1507,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t 
offset, loff_t len,
                        f2fs_put_dnode(&dn);
 
                        f2fs_unlock_op(sbi);
-                       up_write(&F2FS_I(inode)->i_mmap_sem);
+                       up_write(&mapping->invalidate_lock);
                        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 
                        f2fs_balance_fs(sbi, dn.node_changed);
@@ -1545,6 +1542,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t 
offset, loff_t len,
 static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct address_space *mapping = inode->i_mapping;
        pgoff_t nr, pg_start, pg_end, delta, idx;
        loff_t new_size;
        int ret = 0;
@@ -1567,14 +1565,14 @@ static int f2fs_insert_range(struct inode *inode, 
loff_t offset, loff_t len)
 
        f2fs_balance_fs(sbi, true);
 
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&mapping->invalidate_lock);
        ret = f2fs_truncate_blocks(inode, i_size_read(inode), true);
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&mapping->invalidate_lock);
        if (ret)
                return ret;
 
        /* write out all dirty pages from offset */
-       ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
+       ret = filemap_write_and_wait_range(mapping, offset, LLONG_MAX);
        if (ret)
                return ret;
 
@@ -1585,7 +1583,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t 
offset, loff_t len)
 
        /* avoid gc operation during block exchange */
        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&mapping->invalidate_lock);
        truncate_pagecache(inode, offset);
 
        while (!ret && idx > pg_start) {
@@ -1601,14 +1599,14 @@ static int f2fs_insert_range(struct inode *inode, 
loff_t offset, loff_t len)
                                        idx + delta, nr, false);
                f2fs_unlock_op(sbi);
        }
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&mapping->invalidate_lock);
        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 
        /* write out all moved pages, if possible */
-       down_write(&F2FS_I(inode)->i_mmap_sem);
-       filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
+       down_write(&mapping->invalidate_lock);
+       filemap_write_and_wait_range(mapping, offset, LLONG_MAX);
        truncate_pagecache(inode, offset);
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&mapping->invalidate_lock);
 
        if (!ret)
                f2fs_i_size_write(inode, new_size);
@@ -3442,7 +3440,7 @@ static int f2fs_release_compress_blocks(struct file 
*filp, unsigned long arg)
                goto out;
 
        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&inode->i_mapping->invalidate_lock);
 
        last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
 
@@ -3478,7 +3476,7 @@ static int f2fs_release_compress_blocks(struct file 
*filp, unsigned long arg)
        }
 
        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&inode->i_mapping->invalidate_lock);
 out:
        inode_unlock(inode);
 
@@ -3595,7 +3593,7 @@ static int f2fs_reserve_compress_blocks(struct file 
*filp, unsigned long arg)
        }
 
        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&inode->i_mapping->invalidate_lock);
 
        last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
 
@@ -3631,7 +3629,7 @@ static int f2fs_reserve_compress_blocks(struct file 
*filp, unsigned long arg)
        }
 
        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&inode->i_mapping->invalidate_lock);
 
        if (ret >= 0) {
                F2FS_I(inode)->i_flags &= ~F2FS_IMMUTABLE_FL;
@@ -3751,7 +3749,7 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned 
long arg)
                goto err;
 
        down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-       down_write(&F2FS_I(inode)->i_mmap_sem);
+       down_write(&mapping->invalidate_lock);
 
        ret = filemap_write_and_wait_range(mapping, range.start,
                        to_end ? LLONG_MAX : end_addr - 1);
@@ -3838,7 +3836,7 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned 
long arg)
                ret = f2fs_secure_erase(prev_bdev, inode, prev_index,
                                prev_block, len, range.flags);
 out:
-       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&mapping->invalidate_lock);
        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 err:
        inode_unlock(inode);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 7d325bfaf65a..22e942aac7ad 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1187,7 +1187,6 @@ static struct inode *f2fs_alloc_inode(struct super_block 
*sb)
        mutex_init(&fi->inmem_lock);
        init_rwsem(&fi->i_gc_rwsem[READ]);
        init_rwsem(&fi->i_gc_rwsem[WRITE]);
-       init_rwsem(&fi->i_mmap_sem);
        init_rwsem(&fi->i_xattr_sem);
 
        /* Will be used by directory only */
-- 
2.26.2



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to