@@ -307,7 +307,7 @@ struct btrfs_root {
*/
int dedupe_in_progress;
/* For exclusion of snapshot creation and nocow writes */
- struct btrfs_drew_lock snapshot_lock;
+ struct btrfs_drew_lock *snapshot_lock;
atomic_t snapshot_force_cow;
@@ -1546,12 +1546,17 @@ static int btrfs_init_fs_root(struct btrfs_root *root,
int ret;
unsigned int nofs_flag;
+ root->snapshot_lock = kzalloc(sizeof(*root->snapshot_lock), GFP_NOFS);
+ if (!root->snapshot_lock) {
+ ret = -ENOMEM;
+ goto fail;
+ }
/*
* We might be called under a transaction (e.g. indirect backref
* resolution) which could deadlock if it triggers memory reclaim
*/
nofs_flag = memalloc_nofs_save();
- ret = btrfs_drew_lock_init(&root->snapshot_lock);
+ ret = btrfs_drew_lock_init(root->snapshot_lock);
memalloc_nofs_restore(nofs_flag);
if (ret)
goto fail;
@@ -2260,7 +2265,10 @@ void btrfs_put_root(struct btrfs_root *root)
WARN_ON(test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state));
if (root->anon_dev)
free_anon_bdev(root->anon_dev);
- btrfs_drew_lock_destroy(&root->snapshot_lock);
+ if (root->snapshot_lock) {
+ btrfs_drew_lock_destroy(root->snapshot_lock);
+ kfree(root->snapshot_lock);
+ }
free_root_extent_buffers(root);
#ifdef CONFIG_BTRFS_DEBUG
spin_lock(&root->fs_info->fs_roots_radix_lock);
@@ -1071,7 +1071,7 @@ int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
if (!(inode->flags & (BTRFS_INODE_NODATACOW | BTRFS_INODE_PREALLOC)))
return 0;
- if (!btrfs_drew_try_write_lock(&root->snapshot_lock))
+ if (!btrfs_drew_try_write_lock(root->snapshot_lock))
return -EAGAIN;
lockstart = round_down(pos, fs_info->sectorsize);
@@ -1082,7 +1082,7 @@ int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
if (nowait) {
if (!btrfs_try_lock_ordered_range(inode, lockstart, lockend,
&cached_state)) {
- btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_drew_write_unlock(root->snapshot_lock);
return -EAGAIN;
}
} else {
@@ -1092,7 +1092,7 @@ int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
ret = can_nocow_extent(&inode->vfs_inode, lockstart, &num_bytes,
NULL, NULL, NULL, nowait, false);
if (ret <= 0)
- btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_drew_write_unlock(root->snapshot_lock);
else
*write_bytes = min_t(size_t, *write_bytes ,
num_bytes - pos + lockstart);
@@ -1103,7 +1103,7 @@ int btrfs_check_nocow_lock(struct btrfs_inode *inode, loff_t pos,
void btrfs_check_nocow_unlock(struct btrfs_inode *inode)
{
- btrfs_drew_write_unlock(&inode->root->snapshot_lock);
+ btrfs_drew_write_unlock(inode->root->snapshot_lock);
}
static void update_time_for_write(struct inode *inode)
@@ -5218,16 +5218,16 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
* truncation, it must capture all writes that happened before
* this truncation.
*/
- btrfs_drew_write_lock(&root->snapshot_lock);
+ btrfs_drew_write_lock(root->snapshot_lock);
ret = btrfs_cont_expand(BTRFS_I(inode), oldsize, newsize);
if (ret) {
- btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_drew_write_unlock(root->snapshot_lock);
return ret;
}
trans = btrfs_start_transaction(root, 1);
if (IS_ERR(trans)) {
- btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_drew_write_unlock(root->snapshot_lock);
return PTR_ERR(trans);
}
@@ -5235,7 +5235,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
btrfs_inode_safe_disk_i_size_write(BTRFS_I(inode), 0);
pagecache_isize_extended(inode, oldsize, newsize);
ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
- btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_drew_write_unlock(root->snapshot_lock);
btrfs_end_transaction(trans);
} else {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
@@ -11090,7 +11090,7 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
* completes before the first write into the swap file after it is
* activated, than that write would fallback to COW.
*/
- if (!btrfs_drew_try_write_lock(&root->snapshot_lock)) {
+ if (!btrfs_drew_try_write_lock(root->snapshot_lock)) {
btrfs_exclop_finish(fs_info);
btrfs_warn(fs_info,
"cannot activate swapfile because snapshot creation is in progress");
@@ -11263,7 +11263,7 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
if (ret)
btrfs_swap_deactivate(file);
- btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_drew_write_unlock(root->snapshot_lock);
btrfs_exclop_finish(fs_info);
@@ -1019,7 +1019,7 @@ static noinline int btrfs_mksnapshot(const struct path *parent,
* possible. This is to avoid later writeback (running dealloc) to
* fallback to COW mode and unexpectedly fail with ENOSPC.
*/
- btrfs_drew_read_lock(&root->snapshot_lock);
+ btrfs_drew_read_lock(root->snapshot_lock);
ret = btrfs_start_delalloc_snapshot(root, false);
if (ret)
@@ -1040,7 +1040,7 @@ static noinline int btrfs_mksnapshot(const struct path *parent,
out:
if (snapshot_force_cow)
atomic_dec(&root->snapshot_force_cow);
- btrfs_drew_read_unlock(&root->snapshot_lock);
+ btrfs_drew_read_unlock(root->snapshot_lock);
return ret;
}