|
@@ -61,6 +61,7 @@ struct BlockBackend {
|
|
|
|
|
|
uint64_t perm;
|
|
uint64_t perm;
|
|
uint64_t shared_perm;
|
|
uint64_t shared_perm;
|
|
|
|
+ bool disable_perm;
|
|
|
|
|
|
bool allow_write_beyond_eof;
|
|
bool allow_write_beyond_eof;
|
|
|
|
|
|
@@ -578,7 +579,7 @@ int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- if (blk->root) {
|
|
|
|
|
|
+ if (blk->root && !blk->disable_perm) {
|
|
ret = bdrv_child_try_set_perm(blk->root, perm, shared_perm, errp);
|
|
ret = bdrv_child_try_set_perm(blk->root, perm, shared_perm, errp);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
return ret;
|
|
return ret;
|
|
@@ -597,15 +598,52 @@ void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
|
|
*shared_perm = blk->shared_perm;
|
|
*shared_perm = blk->shared_perm;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Notifies the user of all BlockBackends that migration has completed. qdev
|
|
|
|
+ * devices can tighten their permissions in response (specifically revoke
|
|
|
|
+ * shared write permissions that we needed for storage migration).
|
|
|
|
+ *
|
|
|
|
+ * If an error is returned, the VM cannot be allowed to be resumed.
|
|
|
|
+ */
|
|
|
|
+void blk_resume_after_migration(Error **errp)
|
|
|
|
+{
|
|
|
|
+ BlockBackend *blk;
|
|
|
|
+ Error *local_err = NULL;
|
|
|
|
+
|
|
|
|
+ for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
|
|
|
|
+ if (!blk->disable_perm) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ blk->disable_perm = false;
|
|
|
|
+
|
|
|
|
+ blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
|
|
|
|
+ if (local_err) {
|
|
|
|
+ error_propagate(errp, local_err);
|
|
|
|
+ blk->disable_perm = true;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static int blk_do_attach_dev(BlockBackend *blk, void *dev)
|
|
static int blk_do_attach_dev(BlockBackend *blk, void *dev)
|
|
{
|
|
{
|
|
if (blk->dev) {
|
|
if (blk->dev) {
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* While migration is still incoming, we don't need to apply the
|
|
|
|
+ * permissions of guest device BlockBackends. We might still have a block
|
|
|
|
+ * job or NBD server writing to the image for storage migration. */
|
|
|
|
+ if (runstate_check(RUN_STATE_INMIGRATE)) {
|
|
|
|
+ blk->disable_perm = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
blk_ref(blk);
|
|
blk_ref(blk);
|
|
blk->dev = dev;
|
|
blk->dev = dev;
|
|
blk->legacy_dev = false;
|
|
blk->legacy_dev = false;
|
|
blk_iostatus_reset(blk);
|
|
blk_iostatus_reset(blk);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|