mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
btrfs: add a i_mmap_lock to our inode
We need to be able to exclude page_mkwrite from happening concurrently with certain operations. To facilitate this, add a i_mmap_lock to our inode, down_read() it in our mkwrite, and add a new ILOCK flag to indicate that we want to take the i_mmap_lock as well. I used pahole to check the size of the btrfs_inode, the sizes are as follows no lockdep: before: 1120 (3 per 4k page) after: 1160 (3 per 4k page) lockdep: before: 2072 (1 per 4k page) after: 2224 (1 per 4k page) We're slightly larger but it doesn't change how many objects we can fit per page. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
5e295768a0
commit
8318ba79ee
@ -220,6 +220,7 @@ struct btrfs_inode {
|
||||
/* Hook into fs_info->delayed_iputs */
|
||||
struct list_head delayed_iput;
|
||||
|
||||
struct rw_semaphore i_mmap_lock;
|
||||
struct inode vfs_inode;
|
||||
};
|
||||
|
||||
|
@ -3178,6 +3178,7 @@ extern const struct iomap_dio_ops btrfs_dio_ops;
|
||||
/* Inode locking type flags, by default the exclusive lock is taken */
|
||||
#define BTRFS_ILOCK_SHARED (1U << 0)
|
||||
#define BTRFS_ILOCK_TRY (1U << 1)
|
||||
#define BTRFS_ILOCK_MMAP (1U << 2)
|
||||
|
||||
int btrfs_inode_lock(struct inode *inode, unsigned int ilock_flags);
|
||||
void btrfs_inode_unlock(struct inode *inode, unsigned int ilock_flags);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user