BTRFS_RESERVE_NO_FLUSH);
if (!ret)
return block_rsv;
+
+ /*
+ * If we are being used for updating a log tree, fail immediately, which
+ * makes the fsync fallback to a transaction commit.
+ *
+ * We don't want to consume from the global block reserve, as that is
+ * precious space that may be needed to do updates to some trees for
+ * which we don't reserve space during a transaction commit (update root
+ * items in the root tree, device stat items in the device tree and
+ * quota tree updates, see btrfs_init_root_block_rsv()), or to fallback
+ * to in case we did not reserve enough space to run delayed items,
+ * delayed references, or anything else we need in order to avoid a
+ * transaction abort.
+ *
+ * We also don't want to do a reservation in flush emergency mode, as
+ * we end up using metadata that could be critical to allow a
+ * transaction to complete successfully and therefore increase the
+ * chances for a transaction abort.
+ *
+ * Log trees are an optimization and should never consume from the
+ * global reserve or be allowed overcommitting metadata.
+ */
+ if (btrfs_root_id(root) == BTRFS_TREE_LOG_OBJECTID)
+ return ERR_PTR(ret);
+
/*
* If we couldn't reserve metadata bytes try and use some from
* the global reserve if its space type is the same as the global