@@ -36,5 +36,6 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
BlockCopyState **bcs,
Error **errp);
void bdrv_cbw_drop(BlockDriverState *bs);
+bool bdrv_is_fleecing_node(BlockDriverState *bs);
#endif /* COPY_BEFORE_WRITE_H */
@@ -50,6 +50,7 @@
#include "qemu/cutils.h"
#include "qemu/id.h"
#include "block/coroutines.h"
+#include "block/copy-before-write.h"
#ifdef CONFIG_BSD
#include <sys/ioctl.h>
@@ -2502,7 +2503,7 @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
* writable and resizable backing file.
* TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too?
*/
- if (shared & BLK_PERM_WRITE) {
+ if (shared & BLK_PERM_WRITE || bdrv_is_fleecing_node(bs)) {
shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
} else {
shared = 0;
@@ -269,6 +269,43 @@ void bdrv_cbw_drop(BlockDriverState *bs)
bdrv_unref(bs);
}
+/*
+ * Detect is bs a fleecing node in some fleecing sceheme like:
+ *
+ * copy-before-write -- target --> fleecing-node
+ * | |
+ * | file | backing
+ * active-node <---------------------
+ *
+ * In this case, fleecing-node can (and should) safely share writes on its
+ * backing child.
+ */
+bool bdrv_is_fleecing_node(BlockDriverState *bs)
+{
+ BdrvChild *parent;
+ BlockDriverState *parent_bs;
+ BDRVCopyBeforeWriteState *s;
+
+ QLIST_FOREACH(parent, &bs->parents, next_parent) {
+ if (parent->klass != &child_of_bds) {
+ continue;
+ }
+
+ parent_bs = parent->opaque;
+ if (parent_bs->drv != &bdrv_cbw_filter) {
+ continue;
+ }
+
+ s = parent_bs->opaque;
+
+ if (s->target->bs == bs && cbw_is_fleecing(parent_bs)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void cbw_init(void)
{
bdrv_register(&bdrv_cbw_filter);
By default, we share writes on backing child only if our parents share write permission on us. Still, with fleecing scheme we want to be able to unshare writes on fleecing node, which is a kind of immutable snapshot (copy-before-write operations are write-unchanged). So, let's detect fleecing node and share writes on its backing child. (we should share them, otherwise copy-before-write filter can't write to its file child). With fleecing scheme we are sure, that writes to backing child goes through copy-before-write filter, so we are safe to share them. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- block/copy-before-write.h | 1 + block.c | 3 ++- block/copy-before-write.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-)