From nobody Sat Feb 7 05:53:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1769721703; cv=none; d=zohomail.com; s=zohoarc; b=ex5d84A4alKRiKJgVYlvtXTu8+SVWexqJuJ5IdDJzyulIHSAzj7aumzD8zW9roc0rtHdFRskJ+rEDqFshW+nGlZ9tGR7JKLPus5ts+t7zFKJ/03pAjlRXOk3cBvMzhIh4f1nT3PhnwGSbsTx5Us0oRvGWjSqzmfpOFufZDXSIoM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769721703; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TkILmiJQdkYLAtvznkxkJeL7qB7WKa4fKOqLfIQTCdU=; b=hsDqFErxEvHDIGzUu5slznUJkIu+YwpX1YX2Qp3/LJ99tmzBCuHB9+F0eLNUjh+Soej6B7/V7wQ6WeRAB8SLbNqPImVwjN4smcFdKwvnLhfFcWpg/C/pLTOrgjRECDWZV+HT2SDiH9jaUAnWfLIP6jUR1OnV61BT3k2532Nbtgs= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176972170347544.50232261087615; Thu, 29 Jan 2026 13:21:43 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vlZRa-0005Q1-Nb; Thu, 29 Jan 2026 16:20:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRZ-0005Pa-LG for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:49 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRY-00063Q-3E for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:49 -0500 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-630-vCvVtDD1NuiKK4IecyL_nA-1; Thu, 29 Jan 2026 16:20:43 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 97F3718005A7; Thu, 29 Jan 2026 21:20:41 +0000 (UTC) Received: from localhost (unknown [10.2.16.153]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4A7EA3000218; Thu, 29 Jan 2026 21:20:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769721647; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TkILmiJQdkYLAtvznkxkJeL7qB7WKa4fKOqLfIQTCdU=; b=BmL+VWGhJVYCCTkh+T6TQiJ88DGLaKXCZL0JhBJzj4rk4J3PM5Q+FfljzpSJWAEu0i3bUN 3WpR52fMnRKYJyAZjyPUgCg1KwRP/MHjVOy13uxOh6TUNylglM0pMo1+mwfI7EJruiOhyA DvT1nCUDXDn3wbas2ZWibgzoJOO/XE8= X-MC-Unique: vCvVtDD1NuiKK4IecyL_nA-1 X-Mimecast-MFC-AGG-ID: vCvVtDD1NuiKK4IecyL_nA_1769721642 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Paolo Bonzini , Yanan Wang , Zhao Liu , Qing Wang , Kevin Wolf , Fam Zheng , Marcel Apfelbaum , Hannes Reinecke , pkrempa@redhat.com, Eduardo Habkost , Alberto Faria , Stefan Hajnoczi Subject: [PATCH v3 1/5] scsi: generalize scsi_SG_IO_FROM_DEV() to scsi_SG_IO() Date: Thu, 29 Jan 2026 16:20:31 -0500 Message-ID: <20260129212035.219676-2-stefanha@redhat.com> In-Reply-To: <20260129212035.219676-1-stefanha@redhat.com> References: <20260129212035.219676-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1769721706143154100 Content-Type: text/plain; charset="utf-8" Add a direction argument so that scsi_SG_IO() can be used for SG_DXFER_FROM_DEV and SG_DXFER_TO_DEV transfers. Signed-off-by: Stefan Hajnoczi --- include/hw/scsi/scsi.h | 4 ++-- hw/scsi/scsi-disk.c | 4 ++-- hw/scsi/scsi-generic.c | 18 ++++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index d26f1127bb..670c477e38 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -236,8 +236,8 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISen= se sense); void scsi_device_unit_attention_reported(SCSIDevice *dev); void scsi_generic_read_device_inquiry(SCSIDevice *dev); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fix= ed); -int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, - uint8_t *buf, uint8_t buf_size, uint32_t timeout); +int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, uint8_t cmd= _size, + uint8_t *buf, uint8_t buf_size, uint32_t timeout); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lu= n); SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun= ); =20 diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 0f896c27f4..97ae535a27 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2748,8 +2748,8 @@ static int get_device_type(SCSIDiskState *s) cmd[0] =3D INQUIRY; cmd[4] =3D sizeof(buf); =20 - ret =3D scsi_SG_IO_FROM_DEV(s->qdev.conf.blk, cmd, sizeof(cmd), - buf, sizeof(buf), s->qdev.io_timeout); + ret =3D scsi_SG_IO(s->qdev.conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cm= d), + buf, sizeof(buf), s->qdev.io_timeout); if (ret < 0) { return -1; } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 6acaf8831a..61511cf945 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -525,8 +525,9 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_ww= n) return -EINVAL; } =20 -int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, - uint8_t *buf, uint8_t buf_size, uint32_t timeout) +int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, + uint8_t cmd_size, uint8_t *buf, uint8_t buf_size, + uint32_t timeout) { sg_io_hdr_t io_header; uint8_t sensebuf[8]; @@ -534,7 +535,7 @@ int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd= , uint8_t cmd_size, =20 memset(&io_header, 0, sizeof(io_header)); io_header.interface_id =3D 'S'; - io_header.dxfer_direction =3D SG_DXFER_FROM_DEV; + io_header.dxfer_direction =3D direction; io_header.dxfer_len =3D buf_size; io_header.dxferp =3D buf; io_header.cmdp =3D cmd; @@ -574,8 +575,8 @@ static void scsi_generic_set_vpd_bl_emulation(SCSIDevic= e *s) cmd[2] =3D 0x00; cmd[4] =3D sizeof(buf); =20 - ret =3D scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd), - buf, sizeof(buf), s->io_timeout); + ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), + buf, sizeof(buf), s->io_timeout); if (ret < 0) { /* * Do not assume anything if we can't retrieve the @@ -610,8 +611,8 @@ static void scsi_generic_read_device_identification(SCS= IDevice *s) cmd[2] =3D 0x83; cmd[4] =3D sizeof(buf); =20 - ret =3D scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd), - buf, sizeof(buf), s->io_timeout); + ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), + buf, sizeof(buf), s->io_timeout); if (ret < 0) { return; } @@ -662,7 +663,8 @@ static int get_stream_blocksize(BlockBackend *blk) cmd[0] =3D MODE_SENSE; cmd[4] =3D sizeof(buf); =20 - ret =3D scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 6= ); + ret =3D scsi_SG_IO(blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), + buf, sizeof(buf), 6); if (ret < 0) { return -1; } --=20 2.52.0 From nobody Sat Feb 7 05:53:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1769721693; cv=none; d=zohomail.com; s=zohoarc; b=fYX37OvGkMk+6tDgsFufRJ52TMeC7KganI51lQu3i2jH1MGv4IumvgodETttyBEq6ChZN9uxfUmNfq4Ax4BMSEj5Ky8bluKlAbnX7hQJ1a2/Fu/LzlKqy9DR+BA1HYO/EwDNSsqVn9TOL2gio3PKBhrPA5lHrxr5dU3ojH8BhOU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769721693; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ZQeN0oLuz7ZITpfuBoB9Wcsm9rE+tTtG3SJ0pKFnHeE=; b=JNr2XZH14APJcXI2Rvuhf4Z2huIaWusT9NE3xq3tqyQorMp4KmOKzJ0ZsCE2cjUuCQp/jj34N2eK1pzSW3KORhQsgYl8Igds5Npw67kd884yrX4q1icJFxPmaqtbWjOrLMH4p7l5d2gZSptWNs2kxBgV4EicJhJTa1UAoXgjh3w= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769721693054340.5286727227618; Thu, 29 Jan 2026 13:21:33 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vlZRe-0005Qm-4Q; Thu, 29 Jan 2026 16:20:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRc-0005QJ-7o for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:52 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRa-000641-1l for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:51 -0500 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-657-0ell5hJwOVSNTLKjIwuBow-1; Thu, 29 Jan 2026 16:20:45 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BD74B1800378; Thu, 29 Jan 2026 21:20:43 +0000 (UTC) Received: from localhost (unknown [10.2.16.153]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C9ADB3000218; Thu, 29 Jan 2026 21:20:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769721649; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZQeN0oLuz7ZITpfuBoB9Wcsm9rE+tTtG3SJ0pKFnHeE=; b=dI4Yh81IdKvmQ+7KDJD8DyJ20+tk4BxjCa/iAEBXmxzTIvx8hNkcYVjm2ty97bczUNSBqt 52XwJinpj+CjaIRptzVmK1BUnDjG5VuD5fyu8cZwWs0uDhErPqelsgCORCJ4B+5CE2iURf RM/Czjv6MdAP5K/Se6FYHc6CuKyAhmQ= X-MC-Unique: 0ell5hJwOVSNTLKjIwuBow-1 X-Mimecast-MFC-AGG-ID: 0ell5hJwOVSNTLKjIwuBow_1769721644 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Paolo Bonzini , Yanan Wang , Zhao Liu , Qing Wang , Kevin Wolf , Fam Zheng , Marcel Apfelbaum , Hannes Reinecke , pkrempa@redhat.com, Eduardo Habkost , Alberto Faria , Stefan Hajnoczi Subject: [PATCH v3 2/5] scsi: add error reporting to scsi_SG_IO() Date: Thu, 29 Jan 2026 16:20:32 -0500 Message-ID: <20260129212035.219676-3-stefanha@redhat.com> In-Reply-To: <20260129212035.219676-1-stefanha@redhat.com> References: <20260129212035.219676-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham 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 @redhat.com) X-ZM-MESSAGEID: 1769721695640158500 Content-Type: text/plain; charset="utf-8" Report the details of the SG_IO ioctl failure if an Error pointer is provided. This information aids troubleshooting and will be used by the SCSI Persistent Reservations migration code. Signed-off-by: Stefan Hajnoczi --- include/hw/scsi/scsi.h | 2 +- hw/scsi/scsi-disk.c | 2 +- hw/scsi/scsi-generic.c | 33 ++++++++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 670c477e38..89b1ed6258 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -237,7 +237,7 @@ void scsi_device_unit_attention_reported(SCSIDevice *de= v); void scsi_generic_read_device_inquiry(SCSIDevice *dev); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fix= ed); int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, uint8_t cmd= _size, - uint8_t *buf, uint8_t buf_size, uint32_t timeout); + uint8_t *buf, uint8_t buf_size, uint32_t timeout, Error **e= rrp); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lu= n); SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun= ); =20 diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 97ae535a27..76fe5f085b 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2749,7 +2749,7 @@ static int get_device_type(SCSIDiskState *s) cmd[4] =3D sizeof(buf); =20 ret =3D scsi_SG_IO(s->qdev.conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cm= d), - buf, sizeof(buf), s->qdev.io_timeout); + buf, sizeof(buf), s->qdev.io_timeout, NULL); if (ret < 0) { return -1; } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 61511cf945..2af8803644 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -527,10 +527,10 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_= wwn) =20 int scsi_SG_IO(BlockBackend *blk, int direction, uint8_t *cmd, uint8_t cmd_size, uint8_t *buf, uint8_t buf_size, - uint32_t timeout) + uint32_t timeout, Error **errp) { sg_io_hdr_t io_header; - uint8_t sensebuf[8]; + uint8_t sensebuf[8] =3D {}; int ret; =20 memset(&io_header, 0, sizeof(io_header)); @@ -550,6 +550,29 @@ int scsi_SG_IO(BlockBackend *blk, int direction, uint8= _t *cmd, io_header.driver_status || io_header.host_status) { trace_scsi_generic_ioctl_sgio_done(cmd[0], ret, io_header.status, io_header.host_status); + if (ret < 0) { + error_setg_errno(errp, -ret, "SG_IO ioctl failed"); + } else { + g_autofree char *sensebuf_hex =3D + g_strdup_printf("%02x%02x%02x%02x%02x%02x%02x%02x", + sensebuf[0], + sensebuf[1], + sensebuf[2], + sensebuf[3], + sensebuf[4], + sensebuf[5], + sensebuf[6], + sensebuf[7]); + + error_setg(errp, "SG_IO SCSI command failed with status=3D0x%x= " + "driver_status=3D0x%x host_status=3D0x%x sensebuf=3D%s= " + "sb_len_wr=3D%u", + io_header.status, + io_header.driver_status, + io_header.host_status, + sensebuf_hex, + io_header.sb_len_wr); + } return -1; } return 0; @@ -576,7 +599,7 @@ static void scsi_generic_set_vpd_bl_emulation(SCSIDevic= e *s) cmd[4] =3D sizeof(buf); =20 ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), s->io_timeout); + buf, sizeof(buf), s->io_timeout, NULL); if (ret < 0) { /* * Do not assume anything if we can't retrieve the @@ -612,7 +635,7 @@ static void scsi_generic_read_device_identification(SCS= IDevice *s) cmd[4] =3D sizeof(buf); =20 ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), s->io_timeout); + buf, sizeof(buf), s->io_timeout, NULL); if (ret < 0) { return; } @@ -664,7 +687,7 @@ static int get_stream_blocksize(BlockBackend *blk) cmd[4] =3D sizeof(buf); =20 ret =3D scsi_SG_IO(blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), - buf, sizeof(buf), 6); + buf, sizeof(buf), 6, NULL); if (ret < 0) { return -1; } --=20 2.52.0 From nobody Sat Feb 7 05:53:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1769721692; cv=none; d=zohomail.com; s=zohoarc; b=ft4fwDjELH/MLxp8caYga8U2XCge10YpyFanW35SThfvfclS0Hw7ylIIzS5aWG0S9+ZRk4JTUq8uPvGmRsB1AHcSuiduP/EaPsU/HxkhAKtdsiZz936WYvaEnb0ul4Xvzt/0ZliChGWXb94fXEe7by3iD1BIa9c5xyjEqbrR6wc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769721692; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=0ieS5FLWOdnQKY8wvcntnnzGFC81nxXr1CQ4An0scW0=; b=bKmsesKKyLR65sFwD6+M+24wbIS447sn9gJoVzBFC/X3aqPHI3tviuynVw6R76MM1lfwTfnGFYRPrc7Jq9VPV9ytY3JL5rj+Wu67R6OaZabWWe7LLO64TBcECrvWz/lR6o0tTlH/7cqTRPU997IIqtdkkmnFsBjAMWj0JO5wWhs= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769721692581558.415805433228; Thu, 29 Jan 2026 13:21:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vlZRf-0005Rw-S3; Thu, 29 Jan 2026 16:20:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRe-0005Qy-61 for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:54 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRc-00066H-5h for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:53 -0500 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-685-Ruz1bJcHN0y_DLQINK55NA-1; Thu, 29 Jan 2026 16:20:47 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C720918005A7; Thu, 29 Jan 2026 21:20:45 +0000 (UTC) Received: from localhost (unknown [10.2.16.153]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EE0EF1800980; Thu, 29 Jan 2026 21:20:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769721651; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0ieS5FLWOdnQKY8wvcntnnzGFC81nxXr1CQ4An0scW0=; b=W0r6lDSJ7DgcsskOmLnsFg3hZeulObN46qocjCIgKZMDESSnyHPEOfmU5gFi1yqFOu0tP+ 7w84ILpvDgoQfZKM6xe04Q7OWETHdfTnKVwklqKWPd5NXW2YQ1sVet+83YdKuf5DCbZECE s6+1NQHtE8xPFJbS2n6rOYXHrt/bXO4= X-MC-Unique: Ruz1bJcHN0y_DLQINK55NA-1 X-Mimecast-MFC-AGG-ID: Ruz1bJcHN0y_DLQINK55NA_1769721646 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Paolo Bonzini , Yanan Wang , Zhao Liu , Qing Wang , Kevin Wolf , Fam Zheng , Marcel Apfelbaum , Hannes Reinecke , pkrempa@redhat.com, Eduardo Habkost , Alberto Faria , Stefan Hajnoczi Subject: [PATCH v3 3/5] scsi: track SCSI reservation state for live migration Date: Thu, 29 Jan 2026 16:20:33 -0500 Message-ID: <20260129212035.219676-4-stefanha@redhat.com> In-Reply-To: <20260129212035.219676-1-stefanha@redhat.com> References: <20260129212035.219676-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1769721694545154100 Content-Type: text/plain; charset="utf-8" SCSI Persistent Reservations are stateful and external to the guest. In order to transparently move reservations to the destination host during live migration, it is necessary to track the state built up on the source host before migration. Only then can the destination host ensure an equivalent state is restored upon migration. Snoop on successful PERSISTENT RESERVE OUT commands and save the reservation key and reservation type. This will allow registered keys and reservations to be migrated. Also patch PERSISTENT RESERVE IN replies with the REPORT CAPABILITIES service action since features that involve the physical SCSI bus target ports must not be exposed to the guest (it sees a virtual SCSI bus). Usually this plays out as follows: 1. The guest invokes the REGISTER service action to register a reservation key on its I_T nexus. 2. The guest invokes the RESERVE service action to create a reservation using the previously-registered key. This commit implements the snooping and stores the reservation key and type (if any) for each LUN. The snooped PR state and the migrate_pr flag to enable PR migration will be used in later commits. Signed-off-by: Stefan Hajnoczi --- include/hw/scsi/scsi.h | 10 +++ include/scsi/constants.h | 21 +++++ hw/scsi/scsi-bus.c | 3 + hw/scsi/scsi-generic.c | 165 +++++++++++++++++++++++++++++++++++++++ hw/scsi/trace-events | 1 + 5 files changed, 200 insertions(+) diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 89b1ed6258..c5ec58089b 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -57,6 +57,13 @@ struct SCSIRequest { QTAILQ_ENTRY(SCSIRequest) next; }; =20 +/* Per-SCSIDevice Persistent Reservation state */ +typedef struct { + QemuMutex mutex; /* protects all fields (e.g. from multiple IOThread= s) */ + uint64_t key; /* 0 if no registered key */ + uint8_t resv_type; /* 0 if no reservation */ +} SCSIPRState; + #define TYPE_SCSI_DEVICE "scsi-device" OBJECT_DECLARE_TYPE(SCSIDevice, SCSIDeviceClass, SCSI_DEVICE) =20 @@ -97,6 +104,9 @@ struct SCSIDevice uint32_t io_timeout; bool needs_vpd_bl_emulation; bool hba_supports_iothread; + + bool migrate_pr; + SCSIPRState pr_state; }; =20 extern const VMStateDescription vmstate_scsi_device; diff --git a/include/scsi/constants.h b/include/scsi/constants.h index 9b98451912..cb97bdb636 100644 --- a/include/scsi/constants.h +++ b/include/scsi/constants.h @@ -319,4 +319,25 @@ #define IDENT_DESCR_TGT_DESCR_SIZE 32 #define XCOPY_BLK2BLK_SEG_DESC_SIZE 28 =20 +/* + * PERSISTENT RESERVATION IN service action codes + */ +#define PRI_READ_KEYS 0x00 +#define PRI_READ_RESERVATION 0x01 +#define PRI_REPORT_CAPABILITIES 0x02 +#define PRI_READ_FULL_STATUS 0x03 + +/* + * PERSISTENT RESERVATION OUT service action codes + */ +#define PRO_REGISTER 0x00 +#define PRO_RESERVE 0x01 +#define PRO_RELEASE 0x02 +#define PRO_CLEAR 0x03 +#define PRO_PREEMPT 0x04 +#define PRO_PREEMPT_AND_ABORT 0x05 +#define PRO_REGISTER_AND_IGNORE_EXISTING_KEY 0x06 +#define PRO_REGISTER_AND_MOVE 0x07 +#define PRO_REPLACE_LOST_RESERVATION 0x08 + #endif diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index f310ddafb9..9b8656dd83 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -393,6 +393,7 @@ static void scsi_qdev_realize(DeviceState *qdev, Error = **errp) } =20 qemu_mutex_init(&dev->requests_lock); + qemu_mutex_init(&dev->pr_state.mutex); QTAILQ_INIT(&dev->requests); scsi_device_realize(dev, &local_err); if (local_err) { @@ -417,6 +418,8 @@ static void scsi_qdev_unrealize(DeviceState *qdev) =20 scsi_device_unrealize(dev); =20 + qemu_mutex_destroy(&dev->pr_state.mutex); + blockdev_mark_auto_del(dev->conf.blk); } =20 diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 2af8803644..0b3cf8f77b 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -265,6 +265,165 @@ static int scsi_generic_emulate_block_limits(SCSIGene= ricReq *r, SCSIDevice *s) return r->buflen; } =20 +/* + * Patch persistent reservation capabilities that are not emulated. + */ +static void scsi_handle_persistent_reserve_in_reply(SCSIGenericReq *r, + SCSIDevice *s) +{ + uint8_t service_action =3D r->req.cmd.buf[1] & 0x1f; + + if (!s->migrate_pr) { + return; /* when migration is disabled there is no need for patchin= g */ + } + + if (service_action =3D=3D PRI_REPORT_CAPABILITIES) { + assert(r->buflen >=3D 3); + + /* + * Clear specify initiator ports capable (SIP_C) and all target po= rts + * capable (ATC_C). + * + * SPEC_I_PT is not supported because the guest sees an emulated S= CSI + * bus and does not have the underlying transport IDs needed to use + * SPEC_I_PT. + * + * ALL_TG_PT is not supported because we only track the state of t= his + * emulated I_T nexus, not the underlying device's target ports. + */ + r->buf[2] &=3D ~0xc; + } +} + +static int scsi_generic_read_reservation(SCSIDevice *s, uint64_t *key, + uint8_t *resv_type, Error **errp) +{ + uint8_t cmd[10] =3D {}; + uint8_t buf[24] =3D {}; + uint32_t additional_length; + int ret; + + *key =3D 0; + *resv_type =3D 0; + + cmd[0] =3D PERSISTENT_RESERVE_IN; + cmd[1] =3D PRI_READ_RESERVATION; + cmd[8] =3D sizeof(buf); + + ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_FROM_DEV, cmd, sizeof(cmd), + buf, sizeof(buf), s->io_timeout, errp); + if (ret < 0) { + return ret; + } + + memcpy(&additional_length, &buf[4], sizeof(additional_length)); + be32_to_cpus(&additional_length); + + if (additional_length >=3D 0x10) { + memcpy(key, &buf[8], sizeof(*key)); + be64_to_cpus(key); + + *resv_type =3D buf[21] & 0xf; + } + return 0; +} + +/* + * Snoop changes to registered keys and reservations so that this informat= ion + * can be transferred during live migration. + */ +static void scsi_handle_persistent_reserve_out_reply( + SCSIGenericReq *r, + SCSIDevice *s) +{ + SCSIPRState *pr_state =3D &s->pr_state; + uint8_t service_action =3D r->req.cmd.buf[1] & 0x1f; + uint8_t resv_type =3D r->req.cmd.buf[2] & 0xf; + uint64_t old_key; + uint64_t new_key; + + assert(r->buflen >=3D 16); + memcpy(&old_key, &r->buf[0], sizeof(old_key)); + memcpy(&new_key, &r->buf[8], sizeof(new_key)); + be64_to_cpus(&old_key); + be64_to_cpus(&new_key); + + trace_scsi_generic_persistent_reserve_out_reply(service_action, resv_t= ype, + old_key, new_key); + + switch (service_action) { + case PRO_REGISTER: /* fallthrough */ + case PRO_REGISTER_AND_IGNORE_EXISTING_KEY: + if (service_action =3D=3D PRO_REGISTER && old_key =3D=3D 0 && new_= key =3D=3D 0) { + /* Do nothing */ + } else { + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + pr_state->key =3D new_key; + if (new_key =3D=3D 0) { + pr_state->resv_type =3D 0; /* release reservation */ + } + } + } + break; + + case PRO_RESERVE: + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + pr_state->resv_type =3D resv_type; + } + break; + + case PRO_RELEASE: + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + pr_state->resv_type =3D 0; + } + break; + + case PRO_CLEAR: + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + pr_state->key =3D 0; + pr_state->resv_type =3D 0; + } + break; + + case PRO_REPLACE_LOST_RESERVATION: + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + pr_state->key =3D new_key; + pr_state->resv_type =3D resv_type; + } + break; + + case PRO_PREEMPT: /* fallthrough */ + case PRO_PREEMPT_AND_ABORT: { + uint64_t dev_key; + uint8_t dev_resv_type; + Error *local_err =3D NULL; + + /* Not enough information to know actual state, ask the device */ + if (!scsi_generic_read_reservation(s, &dev_key, &dev_resv_type, + &local_err)) { + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + if (pr_state->key =3D=3D dev_key) { + pr_state->resv_type =3D dev_resv_type; + } else { + pr_state->resv_type =3D 0; + } + } + } + if (local_err) { + warn_report_err(local_err); + } + break; + } + + /* + * PRO_REGISTER_AND_MOVE cannot be implemented since it involves the + * physical SCSI bus target ports. + */ + default: + break; /* do nothing */ + } +} + static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r =3D (SCSIGenericReq *)opaque; @@ -347,6 +506,9 @@ static void scsi_read_complete(void * opaque, int ret) if (r->req.cmd.buf[0] =3D=3D INQUIRY) { len =3D scsi_handle_inquiry_reply(r, s, len); } + if (r->req.cmd.buf[0] =3D=3D PERSISTENT_RESERVE_IN) { + scsi_handle_persistent_reserve_in_reply(r, s); + } =20 req_complete: scsi_req_data(&r->req, len); @@ -396,6 +558,9 @@ static void scsi_write_complete(void * opaque, int ret) s->blocksize =3D (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11= ]; trace_scsi_generic_write_complete_blocksize(s->blocksize); } + if (r->req.cmd.buf[0] =3D=3D PERSISTENT_RESERVE_OUT) { + scsi_handle_persistent_reserve_out_reply(r, s); + } =20 scsi_command_complete_noio(r, ret); } diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index 3e81f44dad..ff92fff7c5 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -390,3 +390,4 @@ scsi_generic_realize_blocksize(int blocksize) "block si= ze %d" scsi_generic_aio_sgio_command(uint32_t tag, uint8_t cmd, uint32_t timeout)= "generic aio sgio: tag=3D0x%x cmd=3D0x%x timeout=3D%u" scsi_generic_ioctl_sgio_command(uint8_t cmd, uint32_t timeout) "generic io= ctl sgio: cmd=3D0x%x timeout=3D%u" scsi_generic_ioctl_sgio_done(uint8_t cmd, int ret, uint8_t status, uint8_t= host_status) "generic ioctl sgio: cmd=3D0x%x ret=3D%d status=3D0x%x host_s= tatus=3D0x%x" +scsi_generic_persistent_reserve_out_reply(uint8_t service_action, uint8_t = resv_type, uint64_t old_key, uint64_t new_key) "persistent reserve out repl= y service_action=3D%u resv_type=3D%u old_key=3D0x%" PRIx64 " new_key=3D0x%"= PRIx64 --=20 2.52.0 From nobody Sat Feb 7 05:53:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1769721721; cv=none; d=zohomail.com; s=zohoarc; b=nD1esbtwyeyA3QODT9uA8iBHfdo0h4ptnffRxyQ9CngmHAUnGcpH5HOQNj79vWN135kLtOOWC3YNenf9OQHlVgz72X7RgPE96CskYU6wp/a9Y6Yql2BwBxZrKdnkVJ5fZnYAU/kj2Pjw9mv2TFIYeyXHw7Ivt5lYhtx+S+GrFx4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769721721; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=f7sTa/7B2GMJ/8vFM1+B7FbBAKelt643031z+eV1q68=; b=UeKF6H50oJQZEbNiByOaZkCd57zgS8adRPlTLsULaV15wtVnalw3XaUQvgamvITaqkqgpRNLQ+IxZ0Wb6dY4G82dqyjZ1yocNqOFFM1YtHdJ5kDiTcO0SpYcKd51u3DttAmVuKdM0Xzl55PGy2wUnjhJElQKLwqEO1ro/CVJse0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769721721886185.03141275883183; Thu, 29 Jan 2026 13:22:01 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vlZRi-0005SV-5e; Thu, 29 Jan 2026 16:20:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRh-0005SE-55 for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:57 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRf-000696-4X for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:20:56 -0500 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-172-Sp68cNjoOdK0t4IuMp_1Hg-1; Thu, 29 Jan 2026 16:20:50 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 668EE1954B0C; Thu, 29 Jan 2026 21:20:48 +0000 (UTC) Received: from localhost (unknown [10.2.16.153]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6ABE71956056; Thu, 29 Jan 2026 21:20:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769721654; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=f7sTa/7B2GMJ/8vFM1+B7FbBAKelt643031z+eV1q68=; b=KiKSLo4hpnUh13Azwawgfu0GhKrbVNeVgeGBphSeYIn2VdbsNHlEIf+Z/QuDJDR+iwcHgL unC92avU3qUwwBAVWNvMQT6CJTGcv8Uj3ONlS4Uoo3KWaKT92aFe8aDHgXKSHpzToqY8N+ r0SJuYhJxJjM7kfSYWOG6vXd8ul/3Zo= X-MC-Unique: Sp68cNjoOdK0t4IuMp_1Hg-1 X-Mimecast-MFC-AGG-ID: Sp68cNjoOdK0t4IuMp_1Hg_1769721648 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Paolo Bonzini , Yanan Wang , Zhao Liu , Qing Wang , Kevin Wolf , Fam Zheng , Marcel Apfelbaum , Hannes Reinecke , pkrempa@redhat.com, Eduardo Habkost , Alberto Faria , Stefan Hajnoczi Subject: [PATCH v3 4/5] scsi: save/load SCSI reservation state Date: Thu, 29 Jan 2026 16:20:34 -0500 Message-ID: <20260129212035.219676-5-stefanha@redhat.com> In-Reply-To: <20260129212035.219676-1-stefanha@redhat.com> References: <20260129212035.219676-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham 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 @redhat.com) X-ZM-MESSAGEID: 1769721724398154100 Content-Type: text/plain; charset="utf-8" Add a vmstate subsection to SCSIDiskState so that scsi-block devices can transfer their reservation state during live migration. Upon loading the subsection, the destination QEMU invokes the PERSISTENT RESERVE OUT command's PREEMPT service action to atomically move the reservation from the source I_T nexus to the destination I_T nexus. This results in transparent live migration of SCSI reservations. This approach is incomplete since SCSI reservations are cooperative and other hosts could interfere. Neither the source QEMU nor the destination QEMU are aware of changes made by other hosts. The assumption is that reservation is not taken over by a third host without cooperation from the source host. I considered adding the vmstate subsection to SCSIDevice instead of SCSIDiskState, since reservations are part of the SCSI Primary Commands that other devices apart from disks could support. However, due to fragility of migrating reservations, we will probably limit support to scsi-block and maybe scsi-disk in the future. In the end, I think it makes sense to place this within scsi-disk.c. Signed-off-by: Stefan Hajnoczi --- include/hw/scsi/scsi.h | 1 + hw/core/machine.c | 4 +- hw/scsi/scsi-disk.c | 86 +++++++++++++++++++++++++++++++++++++++++- hw/scsi/scsi-generic.c | 83 ++++++++++++++++++++++++++++++++++++++++ hw/scsi/trace-events | 1 + 5 files changed, 173 insertions(+), 2 deletions(-) diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index c5ec58089b..a3e246dbd9 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -253,6 +253,7 @@ SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, = int target, int lun); =20 /* scsi-generic.c. */ extern const SCSIReqOps scsi_generic_req_ops; +bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp); =20 /* scsi-disk.c */ #define SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR 0 diff --git a/hw/core/machine.c b/hw/core/machine.c index 6411e68856..16134f8ce5 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -38,7 +38,9 @@ #include "hw/acpi/generic_event_device.h" #include "qemu/audio.h" =20 -GlobalProperty hw_compat_10_2[] =3D {}; +GlobalProperty hw_compat_10_2[] =3D { + { "scsi-block", "migrate-pr", "off" }, +}; const size_t hw_compat_10_2_len =3D G_N_ELEMENTS(hw_compat_10_2); =20 GlobalProperty hw_compat_10_1[] =3D { diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 76fe5f085b..abd8b7fb17 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -28,6 +28,7 @@ #include "qemu/hw-version.h" #include "qemu/memalign.h" #include "hw/scsi/scsi.h" +#include "migration/misc.h" #include "migration/qemu-file-types.h" #include "migration/vmstate.h" #include "hw/scsi/emulation.h" @@ -122,6 +123,7 @@ struct SCSIDiskState { */ uint16_t rotation_rate; bool migrate_emulated_scsi_request; + NotifierWithReturn migration_notifier; }; =20 static void scsi_free_request(SCSIRequest *req) @@ -2737,6 +2739,29 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, = uint32_t tag, uint32_t lun, } =20 #ifdef __linux__ +/* + * Preempt on the SCSI Persistent Reservation on the source when migration + * fails because the destination may have already preempted and we need to= get + * the reservation back. + */ +static int scsi_block_migration_notifier(NotifierWithReturn *notifier, + MigrationEvent *e, Error **errp) +{ + if (e->type =3D=3D MIG_EVENT_PRECOPY_FAILED) { + SCSIDiskState *s =3D + container_of(notifier, SCSIDiskState, migration_notifier); + SCSIDevice *d =3D &s->qdev; + Error *local_err =3D NULL; + + if (!scsi_generic_pr_state_preempt(d, &local_err)) { + /* MIG_EVENT_PRECOPY_FAILED cannot fail, so just warn */ + error_prepend(&local_err, "scsi-block migration rollback: "); + warn_report_err(local_err); + } + } + return 0; +} + static int get_device_type(SCSIDiskState *s) { uint8_t cmd[16]; @@ -2815,6 +2840,16 @@ static void scsi_block_realize(SCSIDevice *dev, Erro= r **errp) =20 scsi_realize(&s->qdev, errp); scsi_generic_read_device_inquiry(&s->qdev); + + migration_add_notifier(&s->migration_notifier, + scsi_block_migration_notifier); +} + +static void scsi_block_unrealize(SCSIDevice *dev) +{ + SCSIDiskState *s =3D DO_UPCAST(SCSIDiskState, qdev, dev); + + migration_remove_notifier(&s->migration_notifier); } =20 typedef struct SCSIBlockReq { @@ -3209,6 +3244,47 @@ static const Property scsi_hd_properties[] =3D { DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), }; =20 +#ifdef __linux__ +static bool scsi_disk_pr_state_post_load_errp(void *opaque, int version_id, + Error **errp) +{ + SCSIDiskState *s =3D opaque; + SCSIDevice *dev =3D &s->qdev; + + return scsi_generic_pr_state_preempt(dev, errp); +} + +static bool scsi_disk_pr_state_needed(void *opaque) +{ + SCSIDiskState *s =3D opaque; + SCSIPRState *pr_state =3D &s->qdev.pr_state; + bool ret; + + if (!s->qdev.migrate_pr) { + return false; + } + + /* A reservation requires a key, so checking this field is enough */ + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + ret =3D pr_state->key; + } + return ret; +} + +static const VMStateDescription vmstate_scsi_disk_pr_state =3D { + .name =3D "scsi-disk/pr", + .version_id =3D 1, + .minimum_version_id =3D 1, + .post_load_errp =3D scsi_disk_pr_state_post_load_errp, + .needed =3D scsi_disk_pr_state_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT64(qdev.pr_state.key, SCSIDiskState), + VMSTATE_UINT8(qdev.pr_state.resv_type, SCSIDiskState), + VMSTATE_END_OF_LIST() + } +}; +#endif /* __linux__ */ + static const VMStateDescription vmstate_scsi_disk_state =3D { .name =3D "scsi-disk", .version_id =3D 1, @@ -3221,7 +3297,13 @@ static const VMStateDescription vmstate_scsi_disk_st= ate =3D { VMSTATE_BOOL(tray_open, SCSIDiskState), VMSTATE_BOOL(tray_locked, SCSIDiskState), VMSTATE_END_OF_LIST() - } + }, + .subsections =3D (const VMStateDescription * const []) { +#ifdef __linux__ + &vmstate_scsi_disk_pr_state, +#endif + NULL + }, }; =20 static void scsi_hd_class_initfn(ObjectClass *klass, const void *data) @@ -3301,6 +3383,7 @@ static const Property scsi_block_properties[] =3D { -1), DEFINE_PROP_UINT32("io_timeout", SCSIDiskState, qdev.io_timeout, DEFAULT_IO_TIMEOUT), + DEFINE_PROP_BOOL("migrate-pr", SCSIDiskState, qdev.migrate_pr, true), }; =20 static void scsi_block_class_initfn(ObjectClass *klass, const void *data) @@ -3310,6 +3393,7 @@ static void scsi_block_class_initfn(ObjectClass *klas= s, const void *data) SCSIDiskClass *sdc =3D SCSI_DISK_BASE_CLASS(klass); =20 sc->realize =3D scsi_block_realize; + sc->unrealize =3D scsi_block_unrealize; sc->alloc_req =3D scsi_block_new_request; sc->parse_cdb =3D scsi_block_parse_cdb; sdc->dma_readv =3D scsi_block_dma_readv; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 0b3cf8f77b..a2316a5266 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -424,6 +424,89 @@ static void scsi_handle_persistent_reserve_out_reply( } } =20 +static bool scsi_generic_pr_register(SCSIDevice *s, uint64_t key, Error **= errp) +{ + uint8_t cmd[10] =3D {}; + uint8_t buf[24] =3D {}; + uint64_t key_be =3D cpu_to_be64(key); + int ret; + + cmd[0] =3D PERSISTENT_RESERVE_OUT; + cmd[1] =3D PRO_REGISTER; + cmd[8] =3D sizeof(buf); + memcpy(&buf[8], &key_be, sizeof(key_be)); + + ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_TO_DEV, cmd, sizeof(cmd), + buf, sizeof(buf), s->io_timeout, errp); + if (ret < 0) { + error_prepend(errp, "PERSISTENT RESERVE OUT with REGISTER"); + return false; + } + return true; +} + +static bool scsi_generic_pr_preempt(SCSIDevice *s, uint64_t key, + uint8_t resv_type, Error **errp) +{ + uint8_t cmd[10] =3D {}; + uint8_t buf[24] =3D {}; + uint64_t key_be =3D cpu_to_be64(key); + int ret; + + cmd[0] =3D PERSISTENT_RESERVE_OUT; + cmd[1] =3D PRO_PREEMPT; + cmd[2] =3D resv_type & 0xf; + cmd[8] =3D sizeof(buf); + memcpy(&buf[0], &key_be, sizeof(key_be)); + memcpy(&buf[8], &key_be, sizeof(key_be)); + + ret =3D scsi_SG_IO(s->conf.blk, SG_DXFER_TO_DEV, cmd, sizeof(cmd), + buf, sizeof(buf), s->io_timeout, errp); + if (ret < 0) { + error_prepend(errp, "PERSISTENT RESERVE OUT with PREEMPT"); + return false; + } + return true; +} + +/* Register keys and preempt reservations after live migration */ +bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp) +{ + SCSIPRState *pr_state =3D &s->pr_state; + uint64_t key; + uint8_t resv_type; + + WITH_QEMU_LOCK_GUARD(&pr_state->mutex) { + key =3D pr_state->key; + resv_type =3D pr_state->resv_type; + } + + trace_scsi_generic_pr_state_preempt(key, resv_type); + + if (key) { + if (!scsi_generic_pr_register(s, key, errp)) { + return false; + } + + /* + * Two cases: + * + * 1. There is no reservation (resv_type is 0) and the other I_T n= exus + * will be unregistered. This is important so the source host d= oes + * not leak registered keys across live migration. + * + * 2. There is a reservation (resv_type is not 0) and the other I_T + * nexus will be unregistered and its reservation is atomically + * taken over by us. This is the scenario where a reservation is + * migrated along with the guest. + */ + if (!scsi_generic_pr_preempt(s, key, resv_type, errp)) { + return false; + } + } + return true; +} + static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r =3D (SCSIGenericReq *)opaque; diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index ff92fff7c5..a8ac1e7f1d 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -391,3 +391,4 @@ scsi_generic_aio_sgio_command(uint32_t tag, uint8_t cmd= , uint32_t timeout) "gene scsi_generic_ioctl_sgio_command(uint8_t cmd, uint32_t timeout) "generic io= ctl sgio: cmd=3D0x%x timeout=3D%u" scsi_generic_ioctl_sgio_done(uint8_t cmd, int ret, uint8_t status, uint8_t= host_status) "generic ioctl sgio: cmd=3D0x%x ret=3D%d status=3D0x%x host_s= tatus=3D0x%x" scsi_generic_persistent_reserve_out_reply(uint8_t service_action, uint8_t = resv_type, uint64_t old_key, uint64_t new_key) "persistent reserve out repl= y service_action=3D%u resv_type=3D%u old_key=3D0x%" PRIx64 " new_key=3D0x%"= PRIx64 +scsi_generic_pr_state_preempt(uint64_t key, uint8_t resv_type) "key=3D0x%"= PRIx64 " resv_type=3D%u" --=20 2.52.0 From nobody Sat Feb 7 05:53:17 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1769721730; cv=none; d=zohomail.com; s=zohoarc; b=EkWrf0He2+BegfAhoge3jAHGddMmx+Rv8brAT8WMszYbYDQHqZqa9ESDnG/fcsECxqoYIJI2KQ6w88ysdKHStXleuMHRZszcSf/4POl9fXVNFTHigrcO+6p7rKv0amlVnB/ZQO8blodePZEn9uvXFevdROJA6vEWLXtgVRwNoVw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769721730; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=HssO8XaU3aOzfMrJOnBdsvEsYFflmJgynuuBcKjEJ5A=; b=JmF+lzyRZhPyrXtc6yM7KH5wePmc/f1JaOw9VanlYa7bV2nCtM1t36x+uXczna4Wo792+oFhibwDp0t2wC6ocXslG1qa3q/xs9e88x82LXiUcO0R/86YUCDBGghsIZv4AB6Ta3zGg5TeglBKzDc3kgIxiBs9SAPX6PCao4u7FVg= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769721730742962.250580054701; Thu, 29 Jan 2026 13:22:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vlZRn-0005UF-Fy; Thu, 29 Jan 2026 16:21:03 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRm-0005Tq-JI for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:21:02 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vlZRh-0006BF-6c for qemu-devel@nongnu.org; Thu, 29 Jan 2026 16:21:02 -0500 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-262-17TCz4KTNjCJEHzImdo4CQ-1; Thu, 29 Jan 2026 16:20:51 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2408D1956088; Thu, 29 Jan 2026 21:20:50 +0000 (UTC) Received: from localhost (unknown [10.2.16.153]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C16A13000218; Thu, 29 Jan 2026 21:20:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769721656; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HssO8XaU3aOzfMrJOnBdsvEsYFflmJgynuuBcKjEJ5A=; b=RsYM8E/lzNvQVROjYCZIYCphIHxaBIkQjOb5y47Ol+ZrJbLmLy7b4a/zn+YWA1VN9hS6YB 7hDCZxNXP4WM1CSupFga61AMV1E7B2X7PMRYeYvk5U7/IU6DS2aRLqnpuWolVSUoO2AeTd tAFTG33qVDJ51pzpW7iezRhCcCXVq7g= X-MC-Unique: 17TCz4KTNjCJEHzImdo4CQ-1 X-Mimecast-MFC-AGG-ID: 17TCz4KTNjCJEHzImdo4CQ_1769721650 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Paolo Bonzini , Yanan Wang , Zhao Liu , Qing Wang , Kevin Wolf , Fam Zheng , Marcel Apfelbaum , Hannes Reinecke , pkrempa@redhat.com, Eduardo Habkost , Alberto Faria , Stefan Hajnoczi Subject: [PATCH v3 5/5] docs: add SCSI migrate-pr documentation Date: Thu, 29 Jan 2026 16:20:35 -0500 Message-ID: <20260129212035.219676-6-stefanha@redhat.com> In-Reply-To: <20260129212035.219676-1-stefanha@redhat.com> References: <20260129212035.219676-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1769721731632158500 Content-Type: text/plain; charset="utf-8" Suggested-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- docs/system/device-emulation.rst | 1 + docs/system/devices/scsi/index.rst | 10 +++++ docs/system/devices/scsi/migrate-pr.rst | 54 +++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 docs/system/devices/scsi/index.rst create mode 100644 docs/system/devices/scsi/migrate-pr.rst diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulatio= n.rst index 971325527a..40054bb7df 100644 --- a/docs/system/device-emulation.rst +++ b/docs/system/device-emulation.rst @@ -95,6 +95,7 @@ Emulated Devices devices/keyboard.rst devices/net.rst devices/nvme.rst + devices/scsi/index.rst devices/usb-u2f.rst devices/usb.rst devices/vfio-user.rst diff --git a/docs/system/devices/scsi/index.rst b/docs/system/devices/scsi/= index.rst new file mode 100644 index 0000000000..4f0929b0ca --- /dev/null +++ b/docs/system/devices/scsi/index.rst @@ -0,0 +1,10 @@ +SCSI Devices +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Several SCSI devices are available in QEMU. They are primarily used for bl= ock +storage. + +.. toctree:: + :maxdepth: 1 + + migrate-pr.rst diff --git a/docs/system/devices/scsi/migrate-pr.rst b/docs/system/devices/= scsi/migrate-pr.rst new file mode 100644 index 0000000000..a8f2790a86 --- /dev/null +++ b/docs/system/devices/scsi/migrate-pr.rst @@ -0,0 +1,54 @@ +.. + SPDX-License-Identifier: GPL-2.0-or-later + +.. _scsi_migrate_pr: + +SCSI Persistent Reservation Live Migration +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This document explains how to live migrate SCSI Persistent Reservations. + +The ``scsi-block`` device migrates SCSI Persistent Reservations when the +``migrate-pr=3Don`` parameter is given. Migration is enabled by default in +versioned machine types since QEMU 11.0. It is disabled by default on older +machine types and needs to be explicitly enabled with ``--device +scsi-block,migrate-pr=3Don,...``. + +When migration is enabled, QEMU snoops PERSISTENT RESERVATION OUT commands= and +tracks the reservation key registered by the guest as well as reservations= that +the guest acquires. This information is migrated along with the guest and = the +destination QEMU submits a PERSISTENT RESERVATION OUT command with the PRE= EMPT +service action to atomically transfer the reservation to the destination b= efore +the guest starts running on the destination. + +The following persistent reservation capabilities reported by the PERSISTE= NT +RESERVATION IN command with the REPORT CAPABILITIES service action are mas= ked +from the guest by QEMU when migration is enabled: + + * Specify Initiator Ports Capable (SIP_C) + * All Target Ports Capable (ATC_C) + +When migration is disabled, the ``scsi-block`` device is live migrated but +reservations remain in place on the source. Usually this is not the intend= ed +behavior unless there is another mechanism to update reservations during +migration. The PERSISTENT RESERVATION IN command also does not mask +capabilities reported to the guest when migration is disabled. + +Limitations +----------- + +QEMU does not remember snooped reservation details across restart, so soft= ware +inside the guest must acquire the reservation after boot in order for live +migration to work. Similarly, if the reservation is acquired outside the g= uest +then it will not live migrate along with the guest. + +Snooping only considers the PERSISTENT RESERVATION OUT commands from the g= uest +and does not track reservation changes made by other SCSI initiators. QEMU= 's +snooped reservation details can become stale if another SCSI initiator +makes changes to the reservation. + +Guests running on the same host share a single SCSI initiator identity unl= ess +Fibre Channel N_Port ID Virtualization is configured. As a consequence, +multiple guests on the same hosts may observe unexpected behavior if they = use +the same physical LUN. From the LUN's perspective all guests are the same +initiator and there is no way to distinguish between guests. --=20 2.52.0