From nobody Thu Apr 30 00:40:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=minio.io ARC-Seal: i=1; a=rsa-sha256; t=1776274779; cv=none; d=zohomail.com; s=zohoarc; b=jRae23CLSXvnwm2/Hj8TMlUL9f6Msk5a0NHSGnPA4PX4jbC6xNZrWdKc/FlPNdkO9b/bMfbvvfefgc2WgiKVAUCvU3+wZ/gwxkSoPUAeSW0xtPfdmetZ7hkljAFSqrBBFDFMnFdIEPZmLGIEv+MeR8Wg+/sVPlne6A4cCa56Tv8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776274779; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=czMoe/c8/XX5KWWs2YbJoq4mu8G0tJQUrKnaro6zT2M=; b=CPN43nCuJWbq+/yvxJDGDyNYff5vuaq3K1Bovux0ch5YVSx2+eF8cShxuNpdbNX8qigXZWJ16FoR/1gSl3+YlO0VYR85JfgABuSyO/lNA+D9/0Q56n4xOkoc6YyTNPBXz3JNiWOAH/STSk8DYW0THi1pxPh1JHh9A05MleB099k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776274779848214.47028470231578; Wed, 15 Apr 2026 10:39:39 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wD4Cb-0000Bn-RE; Wed, 15 Apr 2026 13:39:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wD4CZ-0000AQ-7c for qemu-devel@nongnu.org; Wed, 15 Apr 2026 13:38:59 -0400 Received: from mail-wm1-x32c.google.com ([2a00:1450:4864:20::32c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wD4CX-0002kn-FC for qemu-devel@nongnu.org; Wed, 15 Apr 2026 13:38:58 -0400 Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-488a29e6110so75767855e9.3 for ; Wed, 15 Apr 2026 10:38:57 -0700 (PDT) Received: from localhost (2a01cb001411480010f92e9cd3b40a22.ipv6.abo.wanadoo.fr. [2a01:cb00:1411:4800:10f9:2e9c:d3b4:a22]) by smtp.gmail.com with UTF8SMTPSA id 5b1f17b1804b1-488f0edaf47sm24184345e9.35.2026.04.15.10.38.54 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 15 Apr 2026 10:38:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=minio.io; s=minio; t=1776274736; x=1776879536; darn=nongnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=czMoe/c8/XX5KWWs2YbJoq4mu8G0tJQUrKnaro6zT2M=; b=SmyD8BSQ590BU28c9vs6K5UFLRcP9DSeHT1gG6z8Wsp7CYTBaOiOWucmfl3jsRnczd u+OtausaHc9ksIcSXN8Z7EBaNNISZGvMvlz8DgFgyht/wXXfjXtfV77R0XrL9Ne+QyBZ ZP4JB2iiwF6YdTrSxJdgXDG80zGgOYrKoG6rS9ZNH62jykzcMVfh15Dgu7j5CJWA41/r pRDQBisQAo5UX4jrxHLvvpt/HAfu122AANdtBEWHYdjFUp2Q5+EaDeR5NLSFjow8pEnS Wy9FH0GiIfGG/3wCYRmApcRUmt69aA2+y6g0McVb+RSUJhaW8eslQaKpp13sn1wqP4g5 1+pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776274736; x=1776879536; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=czMoe/c8/XX5KWWs2YbJoq4mu8G0tJQUrKnaro6zT2M=; b=FeqXwlWyr/Zn5/wh5vJYYd/NhPjnkxmJcOzAHoKiMns30Ey54IVvxoELFUYXBfEHja IoXSb9IsEVpOSn7zEMH07lCvFSj+KWLzxbsk5eD2/EU9ltuK7lA/K3yeTFo2DarX8gKb gNyqYjldSLdC8jdMZBmUdWaw6kR8AAmF7QZj94ix9Ke+TQAUqj9Sq7uGEXxxr+CcMoP7 fqXYLqfxL31UASUzi2PULY2NsjhMDTKM4lhUZllxn33f+CrHHaRcP5WGwf3s7Awp+Vri /mNC4VsBWGJq8PTnzVKKrHvO2c7VamzHyOdsx+9CbzHJmkFsGbmeiAjpeyYOkVDjVwx3 EeXw== X-Gm-Message-State: AOJu0YxQzR1yRjqBSCUTozJLjSvyMLDkoXqhxIxMmz31T6eaKmAwjzQY wE1uJcbqQ9d7mGH0L7z9/eKiM034zY03ScT91D34loXdavihnTTPANteE/GEMtnEeGdQFASMyow zVjAPPCPgtfkHfCZW+MvmCU0SNmFF6L7+ptfW09ebsSFS+ewtLJ91VctG1cY6AnWk16hRnRz3qk 6CpeVACRTslq/4eilhl8skx1Z6rvq+CWLJNlN9WxQ= X-Gm-Gg: AeBDievMbdFozrg1fBfXXwJFiXpu/FY1APfEvz3/y9rNrJQ+LLXxI1Vx1TELuWX8UCD KOJvZ+dOytOFIRDCHZPeLN/YSp13R2KrQpvGHSkv8VS3nX+GMXHb+3++fXbc4onSWJQLo2I2EdG FbqDyuPXlZGb00TQH9ImE9F9xu2SfTJJ1Ih1ZzIXcEEjsHvGGpyOxgYiaJwLXylyEC0Kx51kYhs MLA8hTJuVg2DZDeuBoccaP89IHV1EGWcNZ+Wrtw291au+mhlK9yG0q8NDvECuiCSXsJhdLaMgP6 lx47J07HnMQfiF2DwbDt+N0KagbBeL4bTJiG/oxRATwEB1DBTaaXfK/I41peCRJaV6PUkV/aDKl z4LlVdQmzjzn9HM8tFCSc75/zbt+XEsL7fgyr2jGLocA8sOPGEcZ8wPzgW2aOVmOzKcUafvjKSM TbN80ecC+cWZCyBtPtqvOKnW/TcwQucUegEWGD8j8xrZiBkflVwKSdA2KVffLGIbOlNoa0bruyh ChGN0I6tSTmdN9fOYrN43KXhlDK/M7xoGnfZP6Vx6/ebqJKJIaTY0skpPklqGLu7IoKfEhH6RGX ZkdZTQ== X-Received: by 2002:a05:600c:a305:b0:488:ab37:b442 with SMTP id 5b1f17b1804b1-488d68c7f92mr216679995e9.28.1776274735540; Wed, 15 Apr 2026 10:38:55 -0700 (PDT) From: mr-083 X-Google-Original-From: mr-083 To: qemu-devel@nongnu.org, qemu-block@nongnu.org Cc: its@irrelevant.dk, kbusch@kernel.org, stefanha@redhat.com, berrange@redhat.com, mr-083 Subject: [PATCH] block: add blockdev-attach QMP command Date: Wed, 15 Apr 2026 19:39:05 +0200 Message-ID: <20260415173905.71224-1-matthieu@min.io> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32c; envelope-from=matthieu@minio.io; helo=mail-wm1-x32c.google.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HK_NAME_MR_MRS=0.998, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @minio.io) X-ZM-MESSAGEID: 1776274781974158500 Content-Type: text/plain; charset="utf-8" Add a blockdev-attach QMP command that attaches a block driver state tree to a device's block backend. Unlike blockdev-insert-medium, this works for non-removable devices such as NVMe namespaces. After drive_del removes a device's backing store, the BlockBackend remains attached to the guest device but has no BlockDriverState. blockdev-attach reconnects a block node (previously created with blockdev-add) to the device's BlockBackend via blk_insert_bs(). This separates the two concerns as recommended: blockdev-add creates the block node, blockdev-attach associates it with the device. Example usage with NVMe namespace hot-swap: drive_del drv0 blockdev-add node-name=3Dnode0 driver=3Dqcow2 file.driver=3Dfile \ file.filename=3Ddisk.qcow2 blockdev-attach id=3Dns0 node-name=3Dnode0 An HMP wrapper is included for convenience. Signed-off-by: Matthieu --- block/monitor/block-hmp-cmds.c | 10 ++++++++++ block/qapi-system.c | 36 ++++++++++++++++++++++++++++++++++ hmp-commands.hx | 16 +++++++++++++++ include/block/block-hmp-cmds.h | 1 + qapi/block.json | 33 +++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+) diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c index 1fd28d59eb..8a3d821e01 100644 --- a/block/monitor/block-hmp-cmds.c +++ b/block/monitor/block-hmp-cmds.c @@ -195,6 +195,16 @@ unlock: hmp_handle_error(mon, err); } =20 +void hmp_blockdev_attach(Monitor *mon, const QDict *qdict) +{ + const char *id =3D qdict_get_str(qdict, "id"); + const char *node_name =3D qdict_get_str(qdict, "node-name"); + Error *err =3D NULL; + + qmp_blockdev_attach(id, node_name, &err); + hmp_handle_error(mon, err); +} + void hmp_commit(Monitor *mon, const QDict *qdict) { const char *device =3D qdict_get_str(qdict, "device"); diff --git a/block/qapi-system.c b/block/qapi-system.c index 54b7409b2b..ec89645bc1 100644 --- a/block/qapi-system.c +++ b/block/qapi-system.c @@ -304,6 +304,42 @@ void qmp_blockdev_insert_medium(const char *id, const = char *node_name, blockdev_insert_medium(NULL, id, node_name, errp); } =20 +void qmp_blockdev_attach(const char *id, const char *node_name, + Error **errp) +{ + BlockBackend *blk; + BlockDriverState *bs; + int ret; + + GRAPH_RDLOCK_GUARD_MAINLOOP(); + + blk =3D qmp_get_blk(NULL, id, errp); + if (!blk) { + return; + } + + if (blk_bs(blk)) { + error_setg(errp, "Device already has a medium inserted"); + return; + } + + bs =3D bdrv_find_node(node_name); + if (!bs) { + error_setg(errp, "Node '%s' not found", node_name); + return; + } + + if (bdrv_has_blk(bs)) { + error_setg(errp, "Node '%s' is already in use", node_name); + return; + } + + ret =3D blk_insert_bs(blk, bs, errp); + if (ret < 0) { + return; + } +} + void qmp_blockdev_change_medium(const char *device, const char *id, const char *filename, diff --git a/hmp-commands.hx b/hmp-commands.hx index 5cc4788f12..ce32ed33ab 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -207,6 +207,22 @@ SRST actions (drive options rerror, werror). ERST =20 + { + .name =3D "blockdev-attach", + .args_type =3D "id:s,node-name:s", + .params =3D "id node-name", + .help =3D "attach a block node to a device (non-removable)", + .cmd =3D hmp_blockdev_attach, + }, + +SRST +``blockdev-attach`` *id* *node-name* + Attach a block driver state tree (created with ``blockdev-add``) to a + device's block backend. Unlike ``blockdev-insert-medium``, this works + for non-removable devices such as NVMe namespaces. The device must + have no medium inserted (e.g. after ``drive_del``). +ERST + { .name =3D "change", .args_type =3D "device:B,force:-f,target:F,arg:s?,read-only-mode:= s?", diff --git a/include/block/block-hmp-cmds.h b/include/block/block-hmp-cmds.h index 71113cd7ef..34d30915fc 100644 --- a/include/block/block-hmp-cmds.h +++ b/include/block/block-hmp-cmds.h @@ -21,6 +21,7 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict); =20 void hmp_commit(Monitor *mon, const QDict *qdict); void hmp_drive_del(Monitor *mon, const QDict *qdict); +void hmp_blockdev_attach(Monitor *mon, const QDict *qdict); =20 void hmp_drive_mirror(Monitor *mon, const QDict *qdict); void hmp_drive_backup(Monitor *mon, const QDict *qdict); diff --git a/qapi/block.json b/qapi/block.json index 46955bbb3e..c05d3b5ac1 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -295,6 +295,39 @@ 'data': { 'id': 'str', 'node-name': 'str'} } =20 +## +# @blockdev-attach: +# +# Attach a block driver state tree to a device's block backend. +# Unlike blockdev-insert-medium, this works for non-removable +# devices such as NVMe namespaces. The device must currently have +# no medium inserted (e.g. after drive_del removed the backing). +# +# @id: The name or QOM path of the guest device +# +# @node-name: name of a node in the block driver state graph +# +# Since: 11.1 +# +# .. qmp-example:: +# +# -> { "execute": "blockdev-add", +# "arguments": { +# "node-name": "node0", +# "driver": "qcow2", +# "file": { "driver": "file", +# "filename": "disk.qcow2" } } } +# <- { "return": {} } +# +# -> { "execute": "blockdev-attach", +# "arguments": { "id": "ns0", +# "node-name": "node0" } } +# <- { "return": {} } +## +{ 'command': 'blockdev-attach', + 'data': { 'id': 'str', + 'node-name': 'str'} } + ## # @BlockdevChangeReadOnlyMode: # --=20 2.53.0