public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2]  xen/xenbus: better handle backend crash
@ 2026-02-18  9:52 Juergen Gross
  2026-02-18  9:52 ` [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state() Juergen Gross
  2026-02-18  9:52 ` [PATCH v2 2/2] xen/xenbus: better handle backend crash Juergen Gross
  0 siblings, 2 replies; 6+ messages in thread
From: Juergen Gross @ 2026-02-18  9:52 UTC (permalink / raw)
  To: linux-kernel, netdev, linux-pci, linux-scsi
  Cc: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Bjorn Helgaas, James E.J. Bottomley,
	Martin K. Petersen, xen-devel

This small series fixes PV-device frontend side handling in case the
backend crashed and has come up again.

The old device will be discarded and the replacement can be used
instead.

Changes in V2:
- fixed one comment related build warning

Juergen Gross (2):
  xenbus: add xenbus_device parameter to xenbus_read_driver_state()
  xen/xenbus: better handle backend crash

 drivers/net/xen-netfront.c                 | 34 +++++++++---------
 drivers/pci/xen-pcifront.c                 |  8 ++---
 drivers/scsi/xen-scsifront.c               |  2 +-
 drivers/xen/xen-pciback/xenbus.c           | 10 +++---
 drivers/xen/xenbus/xenbus_client.c         | 17 +++++++--
 drivers/xen/xenbus/xenbus_probe.c          | 42 ++++++++++++++++++++--
 drivers/xen/xenbus/xenbus_probe_frontend.c |  2 +-
 include/xen/xenbus.h                       |  4 ++-
 8 files changed, 84 insertions(+), 35 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state()
  2026-02-18  9:52 [PATCH v2 0/2] xen/xenbus: better handle backend crash Juergen Gross
@ 2026-02-18  9:52 ` Juergen Gross
  2026-02-18 17:44   ` Bjorn Helgaas
                     ` (2 more replies)
  2026-02-18  9:52 ` [PATCH v2 2/2] xen/xenbus: better handle backend crash Juergen Gross
  1 sibling, 3 replies; 6+ messages in thread
From: Juergen Gross @ 2026-02-18  9:52 UTC (permalink / raw)
  To: linux-kernel, netdev, linux-pci, linux-scsi
  Cc: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Bjorn Helgaas, James E.J. Bottomley,
	Martin K. Petersen, xen-devel, Marek Marczykowski-Górecki

In order to prepare checking the xenbus device status in
xenbus_read_driver_state(), add the pointer to struct xenbus_device
as a parameter.

Signed-off-by: Juergen Gross <jgross@suse.com>
Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- add dev parameter description (kernel test robot)
---
 drivers/net/xen-netfront.c                 | 34 +++++++++++-----------
 drivers/pci/xen-pcifront.c                 |  8 ++---
 drivers/scsi/xen-scsifront.c               |  2 +-
 drivers/xen/xen-pciback/xenbus.c           | 10 +++----
 drivers/xen/xenbus/xenbus_client.c         |  4 ++-
 drivers/xen/xenbus/xenbus_probe.c          |  6 ++--
 drivers/xen/xenbus/xenbus_probe_frontend.c |  2 +-
 include/xen/xenbus.h                       |  3 +-
 8 files changed, 36 insertions(+), 33 deletions(-)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 0969d5c9f6b7..2c414b77dd0f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1646,7 +1646,7 @@ static int xennet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 
 	/* avoid the race with XDP headroom adjustment */
 	wait_event(module_wq,
-		   xenbus_read_driver_state(np->xbdev->otherend) ==
+		   xenbus_read_driver_state(np->xbdev, np->xbdev->otherend) ==
 		   XenbusStateReconfigured);
 	np->netfront_xdp_enabled = true;
 
@@ -1764,9 +1764,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 	do {
 		xenbus_switch_state(dev, XenbusStateInitialising);
 		err = wait_event_timeout(module_wq,
-				 xenbus_read_driver_state(dev->otherend) !=
+				 xenbus_read_driver_state(dev, dev->otherend) !=
 				 XenbusStateClosed &&
-				 xenbus_read_driver_state(dev->otherend) !=
+				 xenbus_read_driver_state(dev, dev->otherend) !=
 				 XenbusStateUnknown, XENNET_TIMEOUT);
 	} while (!err);
 
@@ -2627,31 +2627,31 @@ static void xennet_bus_close(struct xenbus_device *dev)
 {
 	int ret;
 
-	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+	if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
 		return;
 	do {
 		xenbus_switch_state(dev, XenbusStateClosing);
 		ret = wait_event_timeout(module_wq,
-				   xenbus_read_driver_state(dev->otherend) ==
-				   XenbusStateClosing ||
-				   xenbus_read_driver_state(dev->otherend) ==
-				   XenbusStateClosed ||
-				   xenbus_read_driver_state(dev->otherend) ==
-				   XenbusStateUnknown,
-				   XENNET_TIMEOUT);
+				xenbus_read_driver_state(dev, dev->otherend) ==
+				XenbusStateClosing ||
+				xenbus_read_driver_state(dev, dev->otherend) ==
+				XenbusStateClosed ||
+				xenbus_read_driver_state(dev, dev->otherend) ==
+				XenbusStateUnknown,
+				XENNET_TIMEOUT);
 	} while (!ret);
 
-	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+	if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
 		return;
 
 	do {
 		xenbus_switch_state(dev, XenbusStateClosed);
 		ret = wait_event_timeout(module_wq,
-				   xenbus_read_driver_state(dev->otherend) ==
-				   XenbusStateClosed ||
-				   xenbus_read_driver_state(dev->otherend) ==
-				   XenbusStateUnknown,
-				   XENNET_TIMEOUT);
+				xenbus_read_driver_state(dev, dev->otherend) ==
+				XenbusStateClosed ||
+				xenbus_read_driver_state(dev, dev->otherend) ==
+				XenbusStateUnknown,
+				XENNET_TIMEOUT);
 	} while (!ret);
 }
 
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 11636634ae51..cd22bf984024 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -856,7 +856,7 @@ static void pcifront_try_connect(struct pcifront_device *pdev)
 	int err;
 
 	/* Only connect once */
-	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
 	    XenbusStateInitialised)
 		return;
 
@@ -876,7 +876,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
 	enum xenbus_state prev_state;
 
 
-	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
+	prev_state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
 
 	if (prev_state >= XenbusStateClosing)
 		goto out;
@@ -895,7 +895,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
 
 static void pcifront_attach_devices(struct pcifront_device *pdev)
 {
-	if (xenbus_read_driver_state(pdev->xdev->nodename) ==
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) ==
 	    XenbusStateReconfiguring)
 		pcifront_connect(pdev);
 }
@@ -909,7 +909,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
 	struct pci_dev *pci_dev;
 	char str[64];
 
-	state = xenbus_read_driver_state(pdev->xdev->nodename);
+	state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
 	if (state == XenbusStateInitialised) {
 		dev_dbg(&pdev->xdev->dev, "Handle skipped connect.\n");
 		/* We missed Connected and need to initialize. */
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index 924025305753..ef74d4da5ab0 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -1175,7 +1175,7 @@ static void scsifront_backend_changed(struct xenbus_device *dev,
 			return;
 		}
 
-		if (xenbus_read_driver_state(dev->nodename) ==
+		if (xenbus_read_driver_state(dev, dev->nodename) ==
 		    XenbusStateInitialised)
 			scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
 
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index b11e401f1b1e..4bd1c7a8957e 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -149,12 +149,12 @@ static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
 
 	mutex_lock(&pdev->dev_lock);
 	/* Make sure we only do this setup once */
-	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
 	    XenbusStateInitialised)
 		goto out;
 
 	/* Wait for frontend to state that it has published the configuration */
-	if (xenbus_read_driver_state(pdev->xdev->otherend) !=
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->otherend) !=
 	    XenbusStateInitialised)
 		goto out;
 
@@ -374,7 +374,7 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev,
 	dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
 
 	mutex_lock(&pdev->dev_lock);
-	if (xenbus_read_driver_state(pdev->xdev->nodename) != state)
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) != state)
 		goto out;
 
 	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
@@ -572,7 +572,7 @@ static int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev)
 	/* It's possible we could get the call to setup twice, so make sure
 	 * we're not already connected.
 	 */
-	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
 	    XenbusStateInitWait)
 		goto out;
 
@@ -662,7 +662,7 @@ static void xen_pcibk_be_watch(struct xenbus_watch *watch,
 	struct xen_pcibk_device *pdev =
 	    container_of(watch, struct xen_pcibk_device, be_watch);
 
-	switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
+	switch (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename)) {
 	case XenbusStateInitWait:
 		xen_pcibk_setup_backend(pdev);
 		break;
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 2dc874fb5506..e502435145ae 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -931,12 +931,14 @@ static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
 
 /**
  * xenbus_read_driver_state - read state from a store path
+ * @dev: xenbus device pointer
  * @path: path for driver
  *
  * Returns: the state of the driver rooted at the given store path, or
  * XenbusStateUnknown if no state can be read.
  */
-enum xenbus_state xenbus_read_driver_state(const char *path)
+enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
+					   const char *path)
 {
 	enum xenbus_state result;
 	int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 9f9011cd7447..2eed06ba5d38 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -191,7 +191,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch,
 		return;
 	}
 
-	state = xenbus_read_driver_state(dev->otherend);
+	state = xenbus_read_driver_state(dev, dev->otherend);
 
 	dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
 		state, xenbus_strstate(state), dev->otherend_watch.node, path);
@@ -364,7 +364,7 @@ void xenbus_dev_remove(struct device *_dev)
 	 * closed.
 	 */
 	if (!drv->allow_rebind ||
-	    xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
+	    xenbus_read_driver_state(dev, dev->nodename) == XenbusStateClosing)
 		xenbus_switch_state(dev, XenbusStateClosed);
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_remove);
@@ -514,7 +514,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
 	size_t stringlen;
 	char *tmpstring;
 
-	enum xenbus_state state = xenbus_read_driver_state(nodename);
+	enum xenbus_state state = xenbus_read_driver_state(NULL, nodename);
 
 	if (state != XenbusStateInitialising) {
 		/* Device is not new, so ignore it.  This can happen if a
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index f04707d1f667..ca04609730df 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -253,7 +253,7 @@ static int print_device_status(struct device *dev, void *data)
 	} else if (xendev->state < XenbusStateConnected) {
 		enum xenbus_state rstate = XenbusStateUnknown;
 		if (xendev->otherend)
-			rstate = xenbus_read_driver_state(xendev->otherend);
+			rstate = xenbus_read_driver_state(xendev, xendev->otherend);
 		pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
 			xendev->nodename, xendev->state, rstate);
 	}
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index c94caf852aea..15319da65b7f 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -228,7 +228,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
 int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port);
 int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port);
 
-enum xenbus_state xenbus_read_driver_state(const char *path);
+enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
+					   const char *path);
 
 __printf(3, 4)
 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] xen/xenbus: better handle backend crash
  2026-02-18  9:52 [PATCH v2 0/2] xen/xenbus: better handle backend crash Juergen Gross
  2026-02-18  9:52 ` [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state() Juergen Gross
@ 2026-02-18  9:52 ` Juergen Gross
  1 sibling, 0 replies; 6+ messages in thread
From: Juergen Gross @ 2026-02-18  9:52 UTC (permalink / raw)
  To: linux-kernel
  Cc: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
	xen-devel, Marek Marczykowski-Górecki

When the backend domain crashes, coordinated device cleanup is not
possible (as it involves waiting for the backend state change). In that
case, toolstack forcefully removes frontend xenstore entries.
xenbus_dev_changed() handles this case, and triggers device cleanup.
It's possible that toolstack manages to connect new device in that
place, before xenbus_dev_changed() notices the old one is missing. If
that happens, new one won't be probed and will forever remain in
XenbusStateInitialising.

Fix this by checking the frontend's state in Xenstore. In case it has
been reset to XenbusStateInitialising by Xen tools, consider this
being the result of an unplug+plug operation.

It's important that cleanup on such unplug doesn't modify Xenstore
entries (especially the "state" key) as it belong to the new device
to be probed - changing it would derail establishing connection to the
new backend (most likely, closing the device before it was even
connected). Handle this case by setting new xenbus_device->vanished
flag to true, and check it before changing state entry.

And even if xenbus_dev_changed() correctly detects the device was
forcefully removed, the cleanup handling is still racy. Since this whole
handling doesn't happened in a single Xenstore transaction, it's possible
that toolstack might put a new device there already. Avoid re-creating
the state key (which in the case of loosing the race would actually
close newly attached device).

The problem does not apply to frontend domain crash, as this case
involves coordinated cleanup.

Problem originally reported at
https://lore.kernel.org/xen-devel/aOZvivyZ9YhVWDLN@mail-itl/T/#t,
including reproduction steps.

Based-on-patch-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
 drivers/xen/xenbus/xenbus_client.c | 13 +++++++++--
 drivers/xen/xenbus/xenbus_probe.c  | 36 ++++++++++++++++++++++++++++++
 include/xen/xenbus.h               |  1 +
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index e502435145ae..19672b08a680 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -226,8 +226,9 @@ __xenbus_switch_state(struct xenbus_device *dev,
 	struct xenbus_transaction xbt;
 	int current_state;
 	int err, abort;
+	bool vanished = false;
 
-	if (state == dev->state)
+	if (state == dev->state || dev->vanished)
 		return 0;
 
 again:
@@ -242,6 +243,10 @@ __xenbus_switch_state(struct xenbus_device *dev,
 	err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
 	if (err != 1)
 		goto abort;
+	if (current_state != dev->state && current_state == XenbusStateInitialising) {
+		vanished = true;
+		goto abort;
+	}
 
 	err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
 	if (err) {
@@ -256,7 +261,7 @@ __xenbus_switch_state(struct xenbus_device *dev,
 		if (err == -EAGAIN && !abort)
 			goto again;
 		xenbus_switch_fatal(dev, depth, err, "ending transaction");
-	} else
+	} else if (!vanished)
 		dev->state = state;
 
 	return 0;
@@ -941,6 +946,10 @@ enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
 					   const char *path)
 {
 	enum xenbus_state result;
+
+	if (dev && dev->vanished)
+		return XenbusStateUnknown;
+
 	int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
 	if (err)
 		result = XenbusStateUnknown;
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 2eed06ba5d38..eb260eceb4d2 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -444,6 +444,9 @@ static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
 		info.dev = NULL;
 		bus_for_each_dev(bus, NULL, &info, cleanup_dev);
 		if (info.dev) {
+			dev_warn(&info.dev->dev,
+				 "device forcefully removed from xenstore\n");
+			info.dev->vanished = true;
 			device_unregister(&info.dev->dev);
 			put_device(&info.dev->dev);
 		}
@@ -659,6 +662,39 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
 		return;
 
 	dev = xenbus_device_find(root, &bus->bus);
+	/*
+	 * Backend domain crash results in not coordinated frontend removal,
+	 * without going through XenbusStateClosing. If this is a new instance
+	 * of the same device Xen tools will have reset the state to
+	 * XenbusStateInitializing.
+	 * It might be that the backend crashed early during the init phase of
+	 * device setup, in which case the known state would have been
+	 * XenbusStateInitializing. So test the backend domid to match the
+	 * saved one. In case the new backend happens to have the same domid as
+	 * the old one, we can just carry on, as there is no inconsistency
+	 * resulting in this case.
+	 */
+	if (dev && !strcmp(bus->root, "device")) {
+		enum xenbus_state state = xenbus_read_driver_state(dev, dev->nodename);
+		unsigned int backend = xenbus_read_unsigned(root, "backend-id",
+							    dev->otherend_id);
+
+		if (state == XenbusStateInitialising &&
+		    (state != dev->state || backend != dev->otherend_id)) {
+			/*
+			 * State has been reset, assume the old one vanished
+			 * and new one needs to be probed.
+			 */
+			dev_warn(&dev->dev,
+				 "state reset occurred, reconnecting\n");
+			dev->vanished = true;
+		}
+		if (dev->vanished) {
+			device_unregister(&dev->dev);
+			put_device(&dev->dev);
+			dev = NULL;
+		}
+	}
 	if (!dev)
 		xenbus_probe_node(bus, type, root);
 	else
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index 15319da65b7f..8ca15743af7f 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -80,6 +80,7 @@ struct xenbus_device {
 	const char *devicetype;
 	const char *nodename;
 	const char *otherend;
+	bool vanished;
 	int otherend_id;
 	struct xenbus_watch otherend_watch;
 	struct device dev;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state()
  2026-02-18  9:52 ` [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state() Juergen Gross
@ 2026-02-18 17:44   ` Bjorn Helgaas
  2026-02-19  0:26   ` Jakub Kicinski
  2026-02-24 19:20   ` Martin K. Petersen
  2 siblings, 0 replies; 6+ messages in thread
From: Bjorn Helgaas @ 2026-02-18 17:44 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, netdev, linux-pci, linux-scsi, Stefano Stabellini,
	Oleksandr Tyshchenko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Bjorn Helgaas, James E.J. Bottomley,
	Martin K. Petersen, xen-devel, Marek Marczykowski-Górecki

On Wed, Feb 18, 2026 at 10:52:04AM +0100, Juergen Gross wrote:
> In order to prepare checking the xenbus device status in
> xenbus_read_driver_state(), add the pointer to struct xenbus_device
> as a parameter.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>
> Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> V2:
> - add dev parameter description (kernel test robot)
> ---
>  drivers/net/xen-netfront.c                 | 34 +++++++++++-----------
>  drivers/pci/xen-pcifront.c                 |  8 ++---

Acked-by: Bjorn Helgaas <bhelgaas@google.com>	# drivers/pci/xen-pcifront.c

>  drivers/scsi/xen-scsifront.c               |  2 +-
>  drivers/xen/xen-pciback/xenbus.c           | 10 +++----
>  drivers/xen/xenbus/xenbus_client.c         |  4 ++-
>  drivers/xen/xenbus/xenbus_probe.c          |  6 ++--
>  drivers/xen/xenbus/xenbus_probe_frontend.c |  2 +-
>  include/xen/xenbus.h                       |  3 +-
>  8 files changed, 36 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
> index 0969d5c9f6b7..2c414b77dd0f 100644
> --- a/drivers/net/xen-netfront.c
> +++ b/drivers/net/xen-netfront.c
> @@ -1646,7 +1646,7 @@ static int xennet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
>  
>  	/* avoid the race with XDP headroom adjustment */
>  	wait_event(module_wq,
> -		   xenbus_read_driver_state(np->xbdev->otherend) ==
> +		   xenbus_read_driver_state(np->xbdev, np->xbdev->otherend) ==
>  		   XenbusStateReconfigured);
>  	np->netfront_xdp_enabled = true;
>  
> @@ -1764,9 +1764,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
>  	do {
>  		xenbus_switch_state(dev, XenbusStateInitialising);
>  		err = wait_event_timeout(module_wq,
> -				 xenbus_read_driver_state(dev->otherend) !=
> +				 xenbus_read_driver_state(dev, dev->otherend) !=
>  				 XenbusStateClosed &&
> -				 xenbus_read_driver_state(dev->otherend) !=
> +				 xenbus_read_driver_state(dev, dev->otherend) !=
>  				 XenbusStateUnknown, XENNET_TIMEOUT);
>  	} while (!err);
>  
> @@ -2627,31 +2627,31 @@ static void xennet_bus_close(struct xenbus_device *dev)
>  {
>  	int ret;
>  
> -	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
> +	if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
>  		return;
>  	do {
>  		xenbus_switch_state(dev, XenbusStateClosing);
>  		ret = wait_event_timeout(module_wq,
> -				   xenbus_read_driver_state(dev->otherend) ==
> -				   XenbusStateClosing ||
> -				   xenbus_read_driver_state(dev->otherend) ==
> -				   XenbusStateClosed ||
> -				   xenbus_read_driver_state(dev->otherend) ==
> -				   XenbusStateUnknown,
> -				   XENNET_TIMEOUT);
> +				xenbus_read_driver_state(dev, dev->otherend) ==
> +				XenbusStateClosing ||
> +				xenbus_read_driver_state(dev, dev->otherend) ==
> +				XenbusStateClosed ||
> +				xenbus_read_driver_state(dev, dev->otherend) ==
> +				XenbusStateUnknown,
> +				XENNET_TIMEOUT);
>  	} while (!ret);
>  
> -	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
> +	if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
>  		return;
>  
>  	do {
>  		xenbus_switch_state(dev, XenbusStateClosed);
>  		ret = wait_event_timeout(module_wq,
> -				   xenbus_read_driver_state(dev->otherend) ==
> -				   XenbusStateClosed ||
> -				   xenbus_read_driver_state(dev->otherend) ==
> -				   XenbusStateUnknown,
> -				   XENNET_TIMEOUT);
> +				xenbus_read_driver_state(dev, dev->otherend) ==
> +				XenbusStateClosed ||
> +				xenbus_read_driver_state(dev, dev->otherend) ==
> +				XenbusStateUnknown,
> +				XENNET_TIMEOUT);
>  	} while (!ret);
>  }
>  
> diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
> index 11636634ae51..cd22bf984024 100644
> --- a/drivers/pci/xen-pcifront.c
> +++ b/drivers/pci/xen-pcifront.c
> @@ -856,7 +856,7 @@ static void pcifront_try_connect(struct pcifront_device *pdev)
>  	int err;
>  
>  	/* Only connect once */
> -	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
> +	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
>  	    XenbusStateInitialised)
>  		return;
>  
> @@ -876,7 +876,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
>  	enum xenbus_state prev_state;
>  
>  
> -	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
> +	prev_state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
>  
>  	if (prev_state >= XenbusStateClosing)
>  		goto out;
> @@ -895,7 +895,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
>  
>  static void pcifront_attach_devices(struct pcifront_device *pdev)
>  {
> -	if (xenbus_read_driver_state(pdev->xdev->nodename) ==
> +	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) ==
>  	    XenbusStateReconfiguring)
>  		pcifront_connect(pdev);
>  }
> @@ -909,7 +909,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
>  	struct pci_dev *pci_dev;
>  	char str[64];
>  
> -	state = xenbus_read_driver_state(pdev->xdev->nodename);
> +	state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
>  	if (state == XenbusStateInitialised) {
>  		dev_dbg(&pdev->xdev->dev, "Handle skipped connect.\n");
>  		/* We missed Connected and need to initialize. */
> diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
> index 924025305753..ef74d4da5ab0 100644
> --- a/drivers/scsi/xen-scsifront.c
> +++ b/drivers/scsi/xen-scsifront.c
> @@ -1175,7 +1175,7 @@ static void scsifront_backend_changed(struct xenbus_device *dev,
>  			return;
>  		}
>  
> -		if (xenbus_read_driver_state(dev->nodename) ==
> +		if (xenbus_read_driver_state(dev, dev->nodename) ==
>  		    XenbusStateInitialised)
>  			scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
>  
> diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
> index b11e401f1b1e..4bd1c7a8957e 100644
> --- a/drivers/xen/xen-pciback/xenbus.c
> +++ b/drivers/xen/xen-pciback/xenbus.c
> @@ -149,12 +149,12 @@ static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
>  
>  	mutex_lock(&pdev->dev_lock);
>  	/* Make sure we only do this setup once */
> -	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
> +	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
>  	    XenbusStateInitialised)
>  		goto out;
>  
>  	/* Wait for frontend to state that it has published the configuration */
> -	if (xenbus_read_driver_state(pdev->xdev->otherend) !=
> +	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->otherend) !=
>  	    XenbusStateInitialised)
>  		goto out;
>  
> @@ -374,7 +374,7 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev,
>  	dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
>  
>  	mutex_lock(&pdev->dev_lock);
> -	if (xenbus_read_driver_state(pdev->xdev->nodename) != state)
> +	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) != state)
>  		goto out;
>  
>  	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
> @@ -572,7 +572,7 @@ static int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev)
>  	/* It's possible we could get the call to setup twice, so make sure
>  	 * we're not already connected.
>  	 */
> -	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
> +	if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
>  	    XenbusStateInitWait)
>  		goto out;
>  
> @@ -662,7 +662,7 @@ static void xen_pcibk_be_watch(struct xenbus_watch *watch,
>  	struct xen_pcibk_device *pdev =
>  	    container_of(watch, struct xen_pcibk_device, be_watch);
>  
> -	switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
> +	switch (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename)) {
>  	case XenbusStateInitWait:
>  		xen_pcibk_setup_backend(pdev);
>  		break;
> diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
> index 2dc874fb5506..e502435145ae 100644
> --- a/drivers/xen/xenbus/xenbus_client.c
> +++ b/drivers/xen/xenbus/xenbus_client.c
> @@ -931,12 +931,14 @@ static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
>  
>  /**
>   * xenbus_read_driver_state - read state from a store path
> + * @dev: xenbus device pointer
>   * @path: path for driver
>   *
>   * Returns: the state of the driver rooted at the given store path, or
>   * XenbusStateUnknown if no state can be read.
>   */
> -enum xenbus_state xenbus_read_driver_state(const char *path)
> +enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
> +					   const char *path)
>  {
>  	enum xenbus_state result;
>  	int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
> diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
> index 9f9011cd7447..2eed06ba5d38 100644
> --- a/drivers/xen/xenbus/xenbus_probe.c
> +++ b/drivers/xen/xenbus/xenbus_probe.c
> @@ -191,7 +191,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch,
>  		return;
>  	}
>  
> -	state = xenbus_read_driver_state(dev->otherend);
> +	state = xenbus_read_driver_state(dev, dev->otherend);
>  
>  	dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
>  		state, xenbus_strstate(state), dev->otherend_watch.node, path);
> @@ -364,7 +364,7 @@ void xenbus_dev_remove(struct device *_dev)
>  	 * closed.
>  	 */
>  	if (!drv->allow_rebind ||
> -	    xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
> +	    xenbus_read_driver_state(dev, dev->nodename) == XenbusStateClosing)
>  		xenbus_switch_state(dev, XenbusStateClosed);
>  }
>  EXPORT_SYMBOL_GPL(xenbus_dev_remove);
> @@ -514,7 +514,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
>  	size_t stringlen;
>  	char *tmpstring;
>  
> -	enum xenbus_state state = xenbus_read_driver_state(nodename);
> +	enum xenbus_state state = xenbus_read_driver_state(NULL, nodename);
>  
>  	if (state != XenbusStateInitialising) {
>  		/* Device is not new, so ignore it.  This can happen if a
> diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
> index f04707d1f667..ca04609730df 100644
> --- a/drivers/xen/xenbus/xenbus_probe_frontend.c
> +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
> @@ -253,7 +253,7 @@ static int print_device_status(struct device *dev, void *data)
>  	} else if (xendev->state < XenbusStateConnected) {
>  		enum xenbus_state rstate = XenbusStateUnknown;
>  		if (xendev->otherend)
> -			rstate = xenbus_read_driver_state(xendev->otherend);
> +			rstate = xenbus_read_driver_state(xendev, xendev->otherend);
>  		pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
>  			xendev->nodename, xendev->state, rstate);
>  	}
> diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
> index c94caf852aea..15319da65b7f 100644
> --- a/include/xen/xenbus.h
> +++ b/include/xen/xenbus.h
> @@ -228,7 +228,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
>  int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port);
>  int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port);
>  
> -enum xenbus_state xenbus_read_driver_state(const char *path);
> +enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
> +					   const char *path);
>  
>  __printf(3, 4)
>  void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
> -- 
> 2.53.0
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state()
  2026-02-18  9:52 ` [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state() Juergen Gross
  2026-02-18 17:44   ` Bjorn Helgaas
@ 2026-02-19  0:26   ` Jakub Kicinski
  2026-02-24 19:20   ` Martin K. Petersen
  2 siblings, 0 replies; 6+ messages in thread
From: Jakub Kicinski @ 2026-02-19  0:26 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, netdev, linux-pci, linux-scsi, Stefano Stabellini,
	Oleksandr Tyshchenko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Bjorn Helgaas, James E.J. Bottomley,
	Martin K. Petersen, xen-devel, Marek Marczykowski-Górecki

On Wed, 18 Feb 2026 10:52:04 +0100 Juergen Gross wrote:
>  drivers/net/xen-netfront.c                 | 34 +++++++++++-----------

Acked-by: Jakub Kicinski <kuba@kernel.org>
-- 
pw-bot: nap

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state()
  2026-02-18  9:52 ` [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state() Juergen Gross
  2026-02-18 17:44   ` Bjorn Helgaas
  2026-02-19  0:26   ` Jakub Kicinski
@ 2026-02-24 19:20   ` Martin K. Petersen
  2 siblings, 0 replies; 6+ messages in thread
From: Martin K. Petersen @ 2026-02-24 19:20 UTC (permalink / raw)
  To: Juergen Gross
  Cc: linux-kernel, netdev, linux-pci, linux-scsi, Stefano Stabellini,
	Oleksandr Tyshchenko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Bjorn Helgaas, James E.J. Bottomley,
	Martin K. Petersen, xen-devel, Marek Marczykowski-Górecki


Juergen,

> In order to prepare checking the xenbus device status in
> xenbus_read_driver_state(), add the pointer to struct xenbus_device
> as a parameter.

Acked-by: Martin K. Petersen <martin.petersen@oracle.com> # SCSI

-- 
Martin K. Petersen

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-02-24 19:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-18  9:52 [PATCH v2 0/2] xen/xenbus: better handle backend crash Juergen Gross
2026-02-18  9:52 ` [PATCH v2 1/2] xenbus: add xenbus_device parameter to xenbus_read_driver_state() Juergen Gross
2026-02-18 17:44   ` Bjorn Helgaas
2026-02-19  0:26   ` Jakub Kicinski
2026-02-24 19:20   ` Martin K. Petersen
2026-02-18  9:52 ` [PATCH v2 2/2] xen/xenbus: better handle backend crash Juergen Gross

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox