|
@@ -474,7 +474,8 @@ static inline bool need_reserve_reloc_root(struct btrfs_root *root)
|
|
|
|
|
|
static struct btrfs_trans_handle *
|
|
|
start_transaction(struct btrfs_root *root, unsigned int num_items,
|
|
|
- unsigned int type, enum btrfs_reserve_flush_enum flush)
|
|
|
+ unsigned int type, enum btrfs_reserve_flush_enum flush,
|
|
|
+ bool enforce_qgroups)
|
|
|
{
|
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
|
|
|
@@ -505,9 +506,10 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
|
|
|
* Do the reservation before we join the transaction so we can do all
|
|
|
* the appropriate flushing if need be.
|
|
|
*/
|
|
|
- if (num_items > 0 && root != fs_info->chunk_root) {
|
|
|
+ if (num_items && root != fs_info->chunk_root) {
|
|
|
qgroup_reserved = num_items * fs_info->nodesize;
|
|
|
- ret = btrfs_qgroup_reserve_meta(root, qgroup_reserved);
|
|
|
+ ret = btrfs_qgroup_reserve_meta(root, qgroup_reserved,
|
|
|
+ enforce_qgroups);
|
|
|
if (ret)
|
|
|
return ERR_PTR(ret);
|
|
|
|
|
@@ -613,8 +615,9 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
|
|
|
unsigned int num_items)
|
|
|
{
|
|
|
return start_transaction(root, num_items, TRANS_START,
|
|
|
- BTRFS_RESERVE_FLUSH_ALL);
|
|
|
+ BTRFS_RESERVE_FLUSH_ALL, true);
|
|
|
}
|
|
|
+
|
|
|
struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
|
|
|
struct btrfs_root *root,
|
|
|
unsigned int num_items,
|
|
@@ -625,7 +628,14 @@ struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
|
|
|
u64 num_bytes;
|
|
|
int ret;
|
|
|
|
|
|
- trans = btrfs_start_transaction(root, num_items);
|
|
|
+ /*
|
|
|
+ * We have two callers: unlink and block group removal. The
|
|
|
+ * former should succeed even if we will temporarily exceed
|
|
|
+ * quota and the latter operates on the extent root so
|
|
|
+ * qgroup enforcement is ignored anyway.
|
|
|
+ */
|
|
|
+ trans = start_transaction(root, num_items, TRANS_START,
|
|
|
+ BTRFS_RESERVE_FLUSH_ALL, false);
|
|
|
if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
|
|
|
return trans;
|
|
|
|
|
@@ -654,25 +664,25 @@ struct btrfs_trans_handle *btrfs_start_transaction_lflush(
|
|
|
unsigned int num_items)
|
|
|
{
|
|
|
return start_transaction(root, num_items, TRANS_START,
|
|
|
- BTRFS_RESERVE_FLUSH_LIMIT);
|
|
|
+ BTRFS_RESERVE_FLUSH_LIMIT, true);
|
|
|
}
|
|
|
|
|
|
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)
|
|
|
{
|
|
|
- return start_transaction(root, 0, TRANS_JOIN,
|
|
|
- BTRFS_RESERVE_NO_FLUSH);
|
|
|
+ return start_transaction(root, 0, TRANS_JOIN, BTRFS_RESERVE_NO_FLUSH,
|
|
|
+ true);
|
|
|
}
|
|
|
|
|
|
struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root)
|
|
|
{
|
|
|
return start_transaction(root, 0, TRANS_JOIN_NOLOCK,
|
|
|
- BTRFS_RESERVE_NO_FLUSH);
|
|
|
+ BTRFS_RESERVE_NO_FLUSH, true);
|
|
|
}
|
|
|
|
|
|
struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root)
|
|
|
{
|
|
|
return start_transaction(root, 0, TRANS_USERSPACE,
|
|
|
- BTRFS_RESERVE_NO_FLUSH);
|
|
|
+ BTRFS_RESERVE_NO_FLUSH, true);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -691,7 +701,7 @@ struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root
|
|
|
struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root)
|
|
|
{
|
|
|
return start_transaction(root, 0, TRANS_ATTACH,
|
|
|
- BTRFS_RESERVE_NO_FLUSH);
|
|
|
+ BTRFS_RESERVE_NO_FLUSH, true);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -707,7 +717,7 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
|
|
|
struct btrfs_trans_handle *trans;
|
|
|
|
|
|
trans = start_transaction(root, 0, TRANS_ATTACH,
|
|
|
- BTRFS_RESERVE_NO_FLUSH);
|
|
|
+ BTRFS_RESERVE_NO_FLUSH, true);
|
|
|
if (IS_ERR(trans) && PTR_ERR(trans) == -ENOENT)
|
|
|
btrfs_wait_for_commit(root->fs_info, 0);
|
|
|
|