[{"id":3681572,"web_url":"http://patchwork.ozlabs.org/comment/3681572/","msgid":"<20260423162927.GA529033@fedora>","list_archive_url":null,"date":"2026-04-23T16:29:27","subject":"Re: [PATCH] block: add blockdev-attach QMP command","submitter":{"id":17227,"url":"http://patchwork.ozlabs.org/api/people/17227/","name":"Stefan Hajnoczi","email":"stefanha@redhat.com"},"content":"On Wed, Apr 15, 2026 at 07:39:05PM +0200, mr-083 wrote:\n> Add a blockdev-attach QMP command that attaches a block driver state\n> tree to a device's block backend.  Unlike blockdev-insert-medium, this\n> works for non-removable devices such as NVMe namespaces.\n> \n> After drive_del removes a device's backing store, the BlockBackend\n> remains attached to the guest device but has no BlockDriverState.\n> blockdev-attach reconnects a block node (previously created with\n> blockdev-add) to the device's BlockBackend via blk_insert_bs().\n> \n> This separates the two concerns as recommended: blockdev-add creates\n> the block node, blockdev-attach associates it with the device.\n> \n> Example usage with NVMe namespace hot-swap:\n>   drive_del drv0\n>   blockdev-add node-name=node0 driver=qcow2 file.driver=file \\\n>                file.filename=disk.qcow2\n>   blockdev-attach id=ns0 node-name=node0\n\nHi Matthieu,\nI came across a quirk here:\n\n  $ qemu-system-x86_64 \\\n      --blockdev file,filename=my-lun.img,node-name=drive1 \\\n      --device nvme,serial=nvme0 \\\n      --device nvme-ns,id=nvme-ns0,drive=drive1\n  (qemu) drive_del drive1\n  Error: drive drive1 is in use\n\nBut when I change --blockdev to --drive, it succeeds. I think this\nsecond scenario is the one that you have been testing.\n\nI also tried the QMP blockdev-del command together with --blockdev, and\nit fails:\n\n  $ qemu-system-x86_64 ... \\\n      -qmp unix:/tmp/qmp.sock,server=on,wait=off\n  $ qmp-shell /tmp/qmp.sock\n  (QEMU) blockdev-del node-name=drive1\n  {\"error\": {\"class\": \"GenericError\", \"desc\": \"Node drive1 is in use\"}}\n\nIt seems logical that a disk image that's in use by NVMe emulation\ncannot be removed. So now I'm wondering if there is a bug or a\nhistorical reason why drive_del allows drives to the removed at runtime\neven when media change is not supported.\n\nCCing Kevin Wolf and Markus Amrbruster as they may know the answer.\n\nDepending on the answer this may influence the test workflow in this\npatch. It's unclear to me what is being tested here since this does not\nsimulate a real error that a physical NVMe drive could raise?\n\nI think the intention is to fail I/O so a test can simulate a period\nwhere the drive is down. QEMU has the blkdebug driver which could be\ninserted into the block graph to fail I/O requests - maybe that is\nappropriate for your test and may not require new monitor commands (see\nblkdebug examples in tests/)?\n\nStefan\n\n> \n> An HMP wrapper is included for convenience.\n> \n> Signed-off-by: Matthieu <matthieu@min.io>\n> ---\n>  block/monitor/block-hmp-cmds.c | 10 ++++++++++\n>  block/qapi-system.c            | 36 ++++++++++++++++++++++++++++++++++\n>  hmp-commands.hx                | 16 +++++++++++++++\n>  include/block/block-hmp-cmds.h |  1 +\n>  qapi/block.json                | 33 +++++++++++++++++++++++++++++++\n>  5 files changed, 96 insertions(+)\n> \n> diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c\n> index 1fd28d59eb..8a3d821e01 100644\n> --- a/block/monitor/block-hmp-cmds.c\n> +++ b/block/monitor/block-hmp-cmds.c\n> @@ -195,6 +195,16 @@ unlock:\n>      hmp_handle_error(mon, err);\n>  }\n>  \n> +void hmp_blockdev_attach(Monitor *mon, const QDict *qdict)\n> +{\n> +    const char *id = qdict_get_str(qdict, \"id\");\n> +    const char *node_name = qdict_get_str(qdict, \"node-name\");\n> +    Error *err = NULL;\n> +\n> +    qmp_blockdev_attach(id, node_name, &err);\n> +    hmp_handle_error(mon, err);\n> +}\n> +\n>  void hmp_commit(Monitor *mon, const QDict *qdict)\n>  {\n>      const char *device = qdict_get_str(qdict, \"device\");\n> diff --git a/block/qapi-system.c b/block/qapi-system.c\n> index 54b7409b2b..ec89645bc1 100644\n> --- a/block/qapi-system.c\n> +++ b/block/qapi-system.c\n> @@ -304,6 +304,42 @@ void qmp_blockdev_insert_medium(const char *id, const char *node_name,\n>      blockdev_insert_medium(NULL, id, node_name, errp);\n>  }\n>  \n> +void qmp_blockdev_attach(const char *id, const char *node_name,\n> +                         Error **errp)\n> +{\n> +    BlockBackend *blk;\n> +    BlockDriverState *bs;\n> +    int ret;\n> +\n> +    GRAPH_RDLOCK_GUARD_MAINLOOP();\n> +\n> +    blk = qmp_get_blk(NULL, id, errp);\n> +    if (!blk) {\n> +        return;\n> +    }\n> +\n> +    if (blk_bs(blk)) {\n> +        error_setg(errp, \"Device already has a medium inserted\");\n> +        return;\n> +    }\n> +\n> +    bs = bdrv_find_node(node_name);\n> +    if (!bs) {\n> +        error_setg(errp, \"Node '%s' not found\", node_name);\n> +        return;\n> +    }\n> +\n> +    if (bdrv_has_blk(bs)) {\n> +        error_setg(errp, \"Node '%s' is already in use\", node_name);\n> +        return;\n> +    }\n> +\n> +    ret = blk_insert_bs(blk, bs, errp);\n> +    if (ret < 0) {\n> +        return;\n> +    }\n> +}\n> +\n>  void qmp_blockdev_change_medium(const char *device,\n>                                  const char *id,\n>                                  const char *filename,\n> diff --git a/hmp-commands.hx b/hmp-commands.hx\n> index 5cc4788f12..ce32ed33ab 100644\n> --- a/hmp-commands.hx\n> +++ b/hmp-commands.hx\n> @@ -207,6 +207,22 @@ SRST\n>    actions (drive options rerror, werror).\n>  ERST\n>  \n> +    {\n> +        .name       = \"blockdev-attach\",\n> +        .args_type  = \"id:s,node-name:s\",\n> +        .params     = \"id node-name\",\n> +        .help       = \"attach a block node to a device (non-removable)\",\n> +        .cmd        = hmp_blockdev_attach,\n> +    },\n> +\n> +SRST\n> +``blockdev-attach`` *id* *node-name*\n> +  Attach a block driver state tree (created with ``blockdev-add``) to a\n> +  device's block backend. Unlike ``blockdev-insert-medium``, this works\n> +  for non-removable devices such as NVMe namespaces. The device must\n> +  have no medium inserted (e.g. after ``drive_del``).\n> +ERST\n> +\n>      {\n>          .name       = \"change\",\n>          .args_type  = \"device:B,force:-f,target:F,arg:s?,read-only-mode:s?\",\n> diff --git a/include/block/block-hmp-cmds.h b/include/block/block-hmp-cmds.h\n> index 71113cd7ef..34d30915fc 100644\n> --- a/include/block/block-hmp-cmds.h\n> +++ b/include/block/block-hmp-cmds.h\n> @@ -21,6 +21,7 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict);\n>  \n>  void hmp_commit(Monitor *mon, const QDict *qdict);\n>  void hmp_drive_del(Monitor *mon, const QDict *qdict);\n> +void hmp_blockdev_attach(Monitor *mon, const QDict *qdict);\n>  \n>  void hmp_drive_mirror(Monitor *mon, const QDict *qdict);\n>  void hmp_drive_backup(Monitor *mon, const QDict *qdict);\n> diff --git a/qapi/block.json b/qapi/block.json\n> index 46955bbb3e..c05d3b5ac1 100644\n> --- a/qapi/block.json\n> +++ b/qapi/block.json\n> @@ -295,6 +295,39 @@\n>    'data': { 'id': 'str',\n>              'node-name': 'str'} }\n>  \n> +##\n> +# @blockdev-attach:\n> +#\n> +# Attach a block driver state tree to a device's block backend.\n> +# Unlike blockdev-insert-medium, this works for non-removable\n> +# devices such as NVMe namespaces.  The device must currently have\n> +# no medium inserted (e.g. after drive_del removed the backing).\n> +#\n> +# @id: The name or QOM path of the guest device\n> +#\n> +# @node-name: name of a node in the block driver state graph\n> +#\n> +# Since: 11.1\n> +#\n> +# .. qmp-example::\n> +#\n> +#     -> { \"execute\": \"blockdev-add\",\n> +#          \"arguments\": {\n> +#              \"node-name\": \"node0\",\n> +#              \"driver\": \"qcow2\",\n> +#              \"file\": { \"driver\": \"file\",\n> +#                        \"filename\": \"disk.qcow2\" } } }\n> +#     <- { \"return\": {} }\n> +#\n> +#     -> { \"execute\": \"blockdev-attach\",\n> +#          \"arguments\": { \"id\": \"ns0\",\n> +#                         \"node-name\": \"node0\" } }\n> +#     <- { \"return\": {} }\n> +##\n> +{ 'command': 'blockdev-attach',\n> +  'data': { 'id': 'str',\n> +            'node-name': 'str'} }\n> +\n>  ##\n>  # @BlockdevChangeReadOnlyMode:\n>  #\n> -- \n> 2.53.0\n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=NPkSGzd0;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1j4H2Gd1z1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 24 Apr 2026 02:59:25 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wFxNO-0007ai-3L; Thu, 23 Apr 2026 12:58:06 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <stefanha@redhat.com>)\n id 1wFxNL-0007aU-MH\n for qemu-devel@nongnu.org; Thu, 23 Apr 2026 12:58:03 -0400","from us-smtp-delivery-124.mimecast.com ([170.10.133.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <stefanha@redhat.com>)\n id 1wFxNJ-0001sv-Sw\n for qemu-devel@nongnu.org; Thu, 23 Apr 2026 12:58:03 -0400","from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-138-KI6gDEZ6P3-fwdrom__Z3Q-1; Thu,\n 23 Apr 2026 12:57:51 -0400","from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 435831956048; Thu, 23 Apr 2026 16:57:50 +0000 (UTC)","from localhost (unknown [10.44.32.119])\n by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id E1FF9300070A; Thu, 23 Apr 2026 16:57:48 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776963481;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=U12YSLBM/S2r/iw3/rkp71u5Yn5c3NGuWbtdRd56dPo=;\n b=NPkSGzd0eNQrpMZiahLyCz/YvlqQy52luiwhk/aND7qwuDwbjPrte9qOE0WamCA7RiCLlW\n GLknpj6WUsanfSW68gaBUgR4BJ3GYOH+Dq9IB9q9RezECK1h2quzqzlZ2D+vCS25aV3jul\n x4TbrWnqA/5f6kLXDX/6kOsqNEkjXck=","X-MC-Unique":"KI6gDEZ6P3-fwdrom__Z3Q-1","X-Mimecast-MFC-AGG-ID":"KI6gDEZ6P3-fwdrom__Z3Q_1776963470","Date":"Thu, 23 Apr 2026 12:29:27 -0400","From":"Stefan Hajnoczi <stefanha@redhat.com>","To":"mr-083 <matthieu@minio.io>","Cc":"qemu-devel@nongnu.org, qemu-block@nongnu.org, its@irrelevant.dk,\n kbusch@kernel.org, berrange@redhat.com, mr-083 <matthieu@min.io>,\n Kevin Wolf <kwolf@redhat.com>, armbru@redhat.com","Subject":"Re: [PATCH] block: add blockdev-attach QMP command","Message-ID":"<20260423162927.GA529033@fedora>","References":"<20260415173905.71224-1-matthieu@min.io>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha512;\n protocol=\"application/pgp-signature\"; boundary=\"9ffV7S53+P2LmfPw\"","Content-Disposition":"inline","In-Reply-To":"<20260415173905.71224-1-matthieu@min.io>","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.4","Received-SPF":"pass client-ip=170.10.133.124;\n envelope-from=stefanha@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"12","X-Spam_score":"1.2","X-Spam_bar":"+","X-Spam_report":"(1.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001,\n 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 <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3682141,"web_url":"http://patchwork.ozlabs.org/comment/3682141/","msgid":"<aeujDmRSu39026wD@redhat.com>","list_archive_url":null,"date":"2026-04-24T17:06:22","subject":"Re: [PATCH] block: add blockdev-attach QMP command","submitter":{"id":2714,"url":"http://patchwork.ozlabs.org/api/people/2714/","name":"Kevin Wolf","email":"kwolf@redhat.com"},"content":"Am 15.04.2026 um 19:39 hat mr-083 geschrieben:\n> Add a blockdev-attach QMP command that attaches a block driver state\n> tree to a device's block backend.  Unlike blockdev-insert-medium, this\n> works for non-removable devices such as NVMe namespaces.\n> \n> After drive_del removes a device's backing store, the BlockBackend\n> remains attached to the guest device but has no BlockDriverState.\n> blockdev-attach reconnects a block node (previously created with\n> blockdev-add) to the device's BlockBackend via blk_insert_bs().\n> \n> This separates the two concerns as recommended: blockdev-add creates\n> the block node, blockdev-attach associates it with the device.\n> \n> Example usage with NVMe namespace hot-swap:\n>   drive_del drv0\n>   blockdev-add node-name=node0 driver=qcow2 file.driver=file \\\n>                file.filename=disk.qcow2\n>   blockdev-attach id=ns0 node-name=node0\n\nIs the intended functionality the same as the following?\n\n   blockdev-add node-name=node0 driver=qcow2 file.driver=file \\\n                file.filename=disk.qcow2\n   qom-set path=ns0 property=drive value=node0\n   drive-del drv0 / blockdev-del node-name=old-node\n\nThis seems cleaner because there is no window where the namespace\nisn't backed by any block node.\n\nIf this does what you want, it's unclear to me if we want a separate QMP\ncommand to do the same in a maybe more discoverable way. Markus, do we\nhave precedence for this?\n\n> An HMP wrapper is included for convenience.\n\nAn HMP convenience command mapping to qom-set should still be possible\neither way.\n\nKevin","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=d9UyNR8t;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g2KBs218Hz1yDD\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 25 Apr 2026 03:07:17 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wGJzF-0001TZ-9s; Fri, 24 Apr 2026 13:06:41 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <kwolf@redhat.com>) id 1wGJzC-0001Si-UI\n for qemu-devel@nongnu.org; Fri, 24 Apr 2026 13:06:38 -0400","from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <kwolf@redhat.com>) id 1wGJzB-0003Dt-Aj\n for qemu-devel@nongnu.org; Fri, 24 Apr 2026 13:06:38 -0400","from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-373--9Sz5lIqMuiz4KJsicRvjA-1; Fri,\n 24 Apr 2026 13:06:29 -0400","from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id CE03619560BB; Fri, 24 Apr 2026 17:06:27 +0000 (UTC)","from redhat.com (unknown [10.44.32.216])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id 9EF4C180047F; Fri, 24 Apr 2026 17:06:24 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777050394;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=lOKgE8jFCSmFpf4dCp7U1NP42j4qCfmEM5uH1z39tq4=;\n b=d9UyNR8t991RKfKiP3OBbu1uCIyHgRL6TjgqNUZWFW68tVntDcde0qj1rZEwACkXsXrXgq\n UX0omroSnKKdxTSuxoEArgihzrgk4ag9H/W1ke/g27zMUKcobGzJal7YxS4DbAueZLq2n0\n t/OB1IXYRLK/wswA7tLoHRo6X1VfGfk=","X-MC-Unique":"-9Sz5lIqMuiz4KJsicRvjA-1","X-Mimecast-MFC-AGG-ID":"-9Sz5lIqMuiz4KJsicRvjA_1777050388","Date":"Fri, 24 Apr 2026 19:06:22 +0200","From":"Kevin Wolf <kwolf@redhat.com>","To":"mr-083 <matthieu@minio.io>","Cc":"qemu-devel@nongnu.org, qemu-block@nongnu.org, its@irrelevant.dk,\n kbusch@kernel.org, stefanha@redhat.com, berrange@redhat.com,\n mr-083 <matthieu@min.io>, armbru@redhat.com","Subject":"Re: [PATCH] block: add blockdev-attach QMP command","Message-ID":"<aeujDmRSu39026wD@redhat.com>","References":"<20260415173905.71224-1-matthieu@min.io>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20260415173905.71224-1-matthieu@min.io>","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.111","Received-SPF":"pass client-ip=170.10.129.124; envelope-from=kwolf@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"12","X-Spam_score":"1.2","X-Spam_bar":"+","X-Spam_report":"(1.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001,\n 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 <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3686833,"web_url":"http://patchwork.ozlabs.org/comment/3686833/","msgid":"<877bphf4qg.fsf@pond.sub.org>","list_archive_url":null,"date":"2026-05-06T06:10:15","subject":"Re: [PATCH] block: add blockdev-attach QMP command","submitter":{"id":2645,"url":"http://patchwork.ozlabs.org/api/people/2645/","name":"Markus Armbruster","email":"armbru@redhat.com"},"content":"Stefan Hajnoczi <stefanha@redhat.com> writes:\n\n> On Wed, Apr 15, 2026 at 07:39:05PM +0200, mr-083 wrote:\n>> Add a blockdev-attach QMP command that attaches a block driver state\n>> tree to a device's block backend.  Unlike blockdev-insert-medium, this\n>> works for non-removable devices such as NVMe namespaces.\n>> \n>> After drive_del removes a device's backing store, the BlockBackend\n>> remains attached to the guest device but has no BlockDriverState.\n>> blockdev-attach reconnects a block node (previously created with\n>> blockdev-add) to the device's BlockBackend via blk_insert_bs().\n>> \n>> This separates the two concerns as recommended: blockdev-add creates\n>> the block node, blockdev-attach associates it with the device.\n>> \n>> Example usage with NVMe namespace hot-swap:\n>>   drive_del drv0\n>>   blockdev-add node-name=node0 driver=qcow2 file.driver=file \\\n>>                file.filename=disk.qcow2\n>>   blockdev-attach id=ns0 node-name=node0\n>\n> Hi Matthieu,\n> I came across a quirk here:\n>\n>   $ qemu-system-x86_64 \\\n>       --blockdev file,filename=my-lun.img,node-name=drive1 \\\n>       --device nvme,serial=nvme0 \\\n>       --device nvme-ns,id=nvme-ns0,drive=drive1\n>   (qemu) drive_del drive1\n>   Error: drive drive1 is in use\n\nI see \"Error: Node drive1 is in use\".\n\nIt's from qmp_blockdev_del():\n\n    bs = bdrv_find_node(node_name);\n    if (!bs) {\n        error_setg(errp, \"Failed to find node with node-name='%s'\", node_name);\n        return;\n    }\n    if (bdrv_has_blk(bs)) {\n        error_setg(errp, \"Node %s is in use\", node_name);\n        return;\n    }\n\nCalled from hmp_drive_del():\n\n    bs = bdrv_find_node(id);\n    if (bs) {\n        qmp_blockdev_del(id, &err);\n        goto unlock;\n    }\n\n> But when I change --blockdev to --drive, it succeeds. I think this\n> second scenario is the one that you have been testing.\n\nI *guess* you changed it to something like\n\n    -drive if=none,file=test.img,id=drive1\n\nhmp_drive_del()'s call of bdrv_find_node() then fails, and we take a\ncompletely different path, which succeeds:\n\n    (qemu) info block\n    drive1 (#block195): test.img (raw)\n        Attached to:      nvme-ns0\n        Cache mode:       writeback\n    (qemu) drive_del drive1\n    (qemu) info block\n    nvme-ns0: [not inserted]\n        Attached to:      nvme-ns0\n\nThis rips nvme-ns0's drive right off.  Feels *unsafe*: the frontend\n(here: nvme-ns) may reasonably assume that a non-removable medium stays\nput, use it without checking it's still there, and crash.\n\n> I also tried the QMP blockdev-del command together with --blockdev, and\n> it fails:\n>\n>   $ qemu-system-x86_64 ... \\\n>       -qmp unix:/tmp/qmp.sock,server=on,wait=off\n>   $ qmp-shell /tmp/qmp.sock\n>   (QEMU) blockdev-del node-name=drive1\n>   {\"error\": {\"class\": \"GenericError\", \"desc\": \"Node drive1 is in use\"}}\n>\n> It seems logical that a disk image that's in use by NVMe emulation\n> cannot be removed. So now I'm wondering if there is a bug or a\n> historical reason why drive_del allows drives to the removed at runtime\n> even when media change is not supported.\n>\n> CCing Kevin Wolf and Markus Amrbruster as they may know the answer.\n\nI suspect this is simply a bug, and likely a regression.  Can you find\nout?\n\n> Depending on the answer this may influence the test workflow in this\n> patch. It's unclear to me what is being tested here since this does not\n> simulate a real error that a physical NVMe drive could raise?\n>\n> I think the intention is to fail I/O so a test can simulate a period\n> where the drive is down. QEMU has the blkdebug driver which could be\n> inserted into the block graph to fail I/O requests - maybe that is\n> appropriate for your test and may not require new monitor commands (see\n> blkdebug examples in tests/)?\n>\n> Stefan\n>\n>> \n>> An HMP wrapper is included for convenience.\n>> \n>> Signed-off-by: Matthieu <matthieu@min.io>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=hzvq5Y25;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g9Q4D1JQDz1yJx\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 06 May 2026 16:11:06 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wKVSm-0001fM-P3; Wed, 06 May 2026 02:10:28 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <armbru@redhat.com>) id 1wKVSl-0001db-2i\n for qemu-devel@nongnu.org; Wed, 06 May 2026 02:10:27 -0400","from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <armbru@redhat.com>) id 1wKVSi-00085x-Cn\n for qemu-devel@nongnu.org; Wed, 06 May 2026 02:10:26 -0400","from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-653-OhAB2KUxPxy0gQzKsHINOg-1; Wed,\n 06 May 2026 02:10:20 -0400","from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id CB8B2195606F; Wed,  6 May 2026 06:10:18 +0000 (UTC)","from blackfin.pond.sub.org (unknown [10.44.22.2])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id 3D038180034E; Wed,  6 May 2026 06:10:17 +0000 (UTC)","by blackfin.pond.sub.org (Postfix, from userid 1000)\n id 78C0D21E6A01; Wed, 06 May 2026 08:10:15 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1778047822;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=RPAQKg3vLviuOPJzBae8eTiC8sPPcl1KUgt7wPaiqh4=;\n b=hzvq5Y25mA8DstYwpGElj/BG36AXQhN880z3ttOZ0XtHDgL9AAocqW/JwnKdyNGAJSH9b8\n UbhSKs+c2e9MJLl+rqLcHbJh6qpjYNE95YHDy+pBxFvNWTax12bYZJiVhPHKGKulPuQLyc\n FtGH/eOWKNpvt4GTc21QHAgnXzDkpt8=","X-MC-Unique":"OhAB2KUxPxy0gQzKsHINOg-1","X-Mimecast-MFC-AGG-ID":"OhAB2KUxPxy0gQzKsHINOg_1778047819","From":"Markus Armbruster <armbru@redhat.com>","To":"Stefan Hajnoczi <stefanha@redhat.com>","Cc":"mr-083 <matthieu@minio.io>,  qemu-devel@nongnu.org,\n qemu-block@nongnu.org,  its@irrelevant.dk,  kbusch@kernel.org,\n berrange@redhat.com,  mr-083 <matthieu@min.io>,  Kevin Wolf\n <kwolf@redhat.com>","Subject":"Re: [PATCH] block: add blockdev-attach QMP command","In-Reply-To":"<20260423162927.GA529033@fedora> (Stefan Hajnoczi's message of\n \"Thu, 23 Apr 2026 12:29:27 -0400\")","References":"<20260415173905.71224-1-matthieu@min.io>\n <20260423162927.GA529033@fedora>","Date":"Wed, 06 May 2026 08:10:15 +0200","Message-ID":"<877bphf4qg.fsf@pond.sub.org>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","Content-Type":"text/plain","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.111","Received-SPF":"pass client-ip=170.10.129.124; envelope-from=armbru@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"8","X-Spam_score":"0.8","X-Spam_bar":"/","X-Spam_report":"(0.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.443,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001,\n 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 <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}}]