@@ -885,6 +885,9 @@ struct BlockDriverState {
/* Only read/written by whoever has set active_flush_req to true. */
unsigned int flushed_gen; /* Flushed write generation */
+
+ /* BdrvChild links to this node may never be frozen */
+ bool never_freeze;
};
struct BlockBackendRootState {
@@ -4416,6 +4416,14 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
return -EPERM;
}
+ for (i = bs; i != base; i = backing_bs(i)) {
+ if (i->backing && backing_bs(i)->never_freeze) {
+ error_setg(errp, "Cannot freeze '%s' link to '%s'",
+ i->backing->name, backing_bs(i)->node_name);
+ return -EPERM;
+ }
+ }
+
for (i = bs; i != base; i = backing_bs(i)) {
if (i->backing) {
i->backing->frozen = true;
@@ -298,6 +298,10 @@ void commit_start(const char *job_id, BlockDriverState *bs,
if (!filter_node_name) {
commit_top_bs->implicit = true;
}
+
+ /* So that we can always drop this node */
+ commit_top_bs->never_freeze = true;
+
commit_top_bs->total_sectors = top->total_sectors;
bdrv_append(commit_top_bs, top, &local_err);
@@ -1551,6 +1551,10 @@ static BlockJob *mirror_start_job(
if (!filter_node_name) {
mirror_top_bs->implicit = true;
}
+
+ /* So that we can always drop this node */
+ mirror_top_bs->never_freeze = true;
+
mirror_top_bs->total_sectors = bs->total_sectors;
mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |