]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - fs/btrfs/inode.c
btrfs: add a i_mmap_lock to our inode
[mirror_ubuntu-jammy-kernel.git] / fs / btrfs / inode.c
index df38540d7550425274614683637527c1cba2911f..93f735ca96cf6fa176b81ba09ccbb2babfde118b 100644 (file)
@@ -102,6 +102,7 @@ static void __endio_write_update_ordered(struct btrfs_inode *inode,
  * BTRFS_ILOCK_SHARED - acquire a shared lock on the inode
  * BTRFS_ILOCK_TRY - try to acquire the lock, if fails on first attempt
  *                  return -EAGAIN
+ * BTRFS_ILOCK_MMAP - acquire a write lock on the i_mmap_lock
  */
 int btrfs_inode_lock(struct inode *inode, unsigned int ilock_flags)
 {
@@ -122,6 +123,8 @@ int btrfs_inode_lock(struct inode *inode, unsigned int ilock_flags)
                }
                inode_lock(inode);
        }
+       if (ilock_flags & BTRFS_ILOCK_MMAP)
+               down_write(&BTRFS_I(inode)->i_mmap_lock);
        return 0;
 }
 
@@ -133,6 +136,8 @@ int btrfs_inode_lock(struct inode *inode, unsigned int ilock_flags)
  */
 void btrfs_inode_unlock(struct inode *inode, unsigned int ilock_flags)
 {
+       if (ilock_flags & BTRFS_ILOCK_MMAP)
+               up_write(&BTRFS_I(inode)->i_mmap_lock);
        if (ilock_flags & BTRFS_ILOCK_SHARED)
                inode_unlock_shared(inode);
        else
@@ -8540,6 +8545,7 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
 
        ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
 again:
+       down_read(&BTRFS_I(inode)->i_mmap_lock);
        lock_page(page);
        size = i_size_read(inode);
 
@@ -8568,6 +8574,7 @@ again:
                unlock_extent_cached(io_tree, page_start, page_end,
                                     &cached_state);
                unlock_page(page);
+               up_read(&BTRFS_I(inode)->i_mmap_lock);
                btrfs_start_ordered_extent(ordered, 1);
                btrfs_put_ordered_extent(ordered);
                goto again;
@@ -8625,6 +8632,7 @@ again:
        BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->root->last_log_commit;
 
        unlock_extent_cached(io_tree, page_start, page_end, &cached_state);
+       up_read(&BTRFS_I(inode)->i_mmap_lock);
 
        btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
        sb_end_pagefault(inode->i_sb);
@@ -8633,6 +8641,7 @@ again:
 
 out_unlock:
        unlock_page(page);
+       up_read(&BTRFS_I(inode)->i_mmap_lock);
 out:
        btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
        btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved, page_start,
@@ -8884,6 +8893,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        INIT_LIST_HEAD(&ei->delalloc_inodes);
        INIT_LIST_HEAD(&ei->delayed_iput);
        RB_CLEAR_NODE(&ei->rb_node);
+       init_rwsem(&ei->i_mmap_lock);
 
        return inode;
 }