memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
memset(&root->root_kobj, 0, sizeof(root->root_kobj));
init_completion(&root->kobj_unregister);
+ init_rwsem(&root->snap_sem);
root->defrag_running = 0;
root->defrag_level = 0;
root->root_key.objectid = objectid;
num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >>
inode->i_blkbits;
+ down_read(&BTRFS_I(inode)->root->snap_sem);
end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1;
lock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS);
mutex_lock(&root->fs_info->fs_mutex);
mutex_unlock(&root->fs_info->fs_mutex);
unlock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS);
free_extent_map(em);
+ up_read(&BTRFS_I(inode)->root->snap_sem);
return err;
}
if ((offset & (blocksize - 1)) == 0)
goto out;
+ down_read(&BTRFS_I(inode)->root->snap_sem);
ret = -ENOMEM;
page = grab_cache_page(mapping, index);
if (!page)
unlock_page(page);
page_cache_release(page);
+ up_read(&BTRFS_I(inode)->root->snap_sem);
out:
return ret;
}
int ret = -EINVAL;
u64 page_start;
+ down_read(&BTRFS_I(inode)->root->snap_sem);
lock_page(page);
wait_on_page_writeback(page);
size = i_size_read(inode);
ret = btrfs_cow_one_page(inode, page, end);
out_unlock:
+ up_read(&BTRFS_I(inode)->root->snap_sem);
unlock_page(page);
return ret;
}
if (!root->ref_cows)
return -EINVAL;
+ down_write(&root->snap_sem);
+ freeze_bdev(root->fs_info->sb->s_bdev);
+ thaw_bdev(root->fs_info->sb->s_bdev, root->fs_info->sb);
+
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1);
BUG_ON(!trans);
ret = btrfs_inc_root_ref(trans, root);
if (ret)
goto fail;
-
fail:
err = btrfs_commit_transaction(trans, root);
if (err && !ret)
ret = err;
mutex_unlock(&root->fs_info->fs_mutex);
+ up_write(&root->snap_sem);
btrfs_btree_balance_dirty(root);
return ret;
}