From: Christian Brauner Date: Fri, 1 May 2026 11:34:06 +0000 (+0200) Subject: vmspawn: track removability as a QmpDriveFlags bit and expose add_block_device X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0e911e41649d46ff529522ba2ed036e779c13098;p=thirdparty%2Fsystemd.git vmspawn: track removability as a QmpDriveFlags bit and expose add_block_device Drives attached at boot via the existing CLI options (--image, --extra-drive) must not be detachable at runtime via the upcoming RemoveStorage Varlink method, while drives added at runtime via AddStorage must be. Track this distinction with a new QMP_DRIVE_REMOVABLE property flag — placed alongside QMP_DRIVE_BLOCK_DEVICE, not in the transient BlockDeviceStateFlags state-machine, since "may be removed" is a permanent property of the drive. vmspawn_qmp_remove_block_device() now early-rejects unknown ids with io.systemd.MachineInstance.NoSuchStorage and immutable drives with io.systemd.MachineInstance.StorageImmutable. vmspawn_qmp_add_block_device() loses its 'static' qualifier and gets a declaration in the header, so the runtime hotplug path (vmspawn-bind-volume.c, next) can dispatch into it directly. Signed-off-by: Christian Brauner (Amutable) --- diff --git a/src/vmspawn/vmspawn-qmp.c b/src/vmspawn/vmspawn-qmp.c index d09576213a1..52d9e11b9f8 100644 --- a/src/vmspawn/vmspawn-qmp.c +++ b/src/vmspawn/vmspawn-qmp.c @@ -826,7 +826,7 @@ static int on_add_device_add_complete( return 0; if (d->link) { - (void) sd_varlink_replybo(d->link, SD_JSON_BUILD_PAIR_STRING("id", d->id)); + (void) sd_varlink_reply(d->link, NULL); d->link = sd_varlink_unref(d->link); } @@ -882,7 +882,7 @@ static int qmp_setup_scsi_controller(VmspawnQmpBridge *bridge, const char *pcie_ return 0; } -static int vmspawn_qmp_add_block_device(VmspawnQmpBridge *bridge, DriveInfo *drive) { +int vmspawn_qmp_add_block_device(VmspawnQmpBridge *bridge, DriveInfo *drive) { int r; assert(bridge); @@ -989,7 +989,6 @@ static int qmp_setup_regular_drive(VmspawnQmpBridge *bridge, DriveInfo *drive) { assert(bridge); assert(drive); assert(drive->fd >= 0); - assert(!drive->id); return vmspawn_qmp_add_block_device(bridge, drive); } @@ -1028,7 +1027,9 @@ int vmspawn_qmp_remove_block_device(VmspawnQmpBridge *bridge, sd_varlink *link, DriveInfo *drive = hashmap_get(bridge->block_devices, id); if (!drive) - return reply_qmp_error(link, "Unknown block device id", -ENOENT); + return sd_varlink_error(link, "io.systemd.MachineInstance.NoSuchStorage", NULL); + if (!FLAGS_SET(drive->flags, QMP_DRIVE_REMOVABLE)) + return sd_varlink_error(link, "io.systemd.MachineInstance.StorageImmutable", NULL); if (!FLAGS_SET(drive->state, BLOCK_DEVICE_STATE_BLOCKDEV_ADDED)) return reply_qmp_error(link, "Block device add pending", -EBUSY); if (FLAGS_SET(drive->state, BLOCK_DEVICE_STATE_REMOVE_PENDING)) diff --git a/src/vmspawn/vmspawn-qmp.h b/src/vmspawn/vmspawn-qmp.h index d8403520c9a..a2f92973208 100644 --- a/src/vmspawn/vmspawn-qmp.h +++ b/src/vmspawn/vmspawn-qmp.h @@ -72,6 +72,7 @@ typedef enum QmpDriveFlags { QMP_DRIVE_BOOT = 1u << 4, QMP_DRIVE_IO_URING = 1u << 5, QMP_DRIVE_DISCARD_NO_UNREF = 1u << 6, /* qcow2 only */ + QMP_DRIVE_REMOVABLE = 1u << 7, /* may be detached at runtime via RemoveStorage */ } QmpDriveFlags; typedef enum BlockDeviceStateFlags { @@ -177,5 +178,6 @@ int vmspawn_qmp_setup_drives(VmspawnQmpBridge *bridge, DriveInfos *drives); int vmspawn_qmp_setup_network(VmspawnQmpBridge *bridge, NetworkInfo *network); int vmspawn_qmp_setup_virtiofs(VmspawnQmpBridge *bridge, const VirtiofsInfos *virtiofs); int vmspawn_qmp_setup_vsock(VmspawnQmpBridge *bridge, VsockInfo *vsock); +int vmspawn_qmp_add_block_device(VmspawnQmpBridge *bridge, DriveInfo *drive); int vmspawn_qmp_remove_block_device(VmspawnQmpBridge *bridge, sd_varlink *link, const char *id); int vmspawn_qmp_dispatch_device_deleted(VmspawnQmpBridge *bridge, sd_json_variant *data);