aboutsummaryrefslogtreecommitdiff
path: root/sys/xen
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2022-03-21 11:47:20 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2022-06-07 10:29:53 +0000
commitf3d54ded282ce992d168052d2c428e9df2a41e28 (patch)
treeb6b81b4df74c67eb0d5fcbe2d280c22e04f51ada /sys/xen
parent91d6afe6e2a912fd5059fc11dbeffc85474897af (diff)
downloadsrc-f3d54ded282ce992d168052d2c428e9df2a41e28.tar.gz
src-f3d54ded282ce992d168052d2c428e9df2a41e28.zip
Diffstat (limited to 'sys/xen')
-rw-r--r--sys/xen/xenbus/xenbusb.c67
1 files changed, 43 insertions, 24 deletions
diff --git a/sys/xen/xenbus/xenbusb.c b/sys/xen/xenbus/xenbusb.c
index e026f8203ea1..bd6ff552c9a6 100644
--- a/sys/xen/xenbus/xenbusb.c
+++ b/sys/xen/xenbus/xenbusb.c
@@ -254,7 +254,7 @@ xenbusb_delete_child(device_t dev, device_t child)
static void
xenbusb_verify_device(device_t dev, device_t child)
{
- if (xs_exists(XST_NIL, xenbus_get_node(child), "") == 0) {
+ if (xs_exists(XST_NIL, xenbus_get_node(child), "state") == 0) {
/*
* Device tree has been removed from Xenbus.
* Tear down the device.
@@ -907,6 +907,7 @@ xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
case XENBUS_IVAR_STATE:
{
int error;
+ struct xs_transaction xst;
newstate = (enum xenbus_state)value;
sx_xlock(&ivars->xd_lock);
@@ -915,31 +916,39 @@ xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
goto out;
}
- error = xs_scanf(XST_NIL, ivars->xd_node, "state",
- NULL, "%d", &currstate);
- if (error)
- goto out;
-
do {
- error = xs_printf(XST_NIL, ivars->xd_node, "state",
- "%d", newstate);
- } while (error == EAGAIN);
- if (error) {
- /*
- * Avoid looping through xenbus_dev_fatal()
- * which calls xenbus_write_ivar to set the
- * state to closing.
- */
- if (newstate != XenbusStateClosing)
- xenbus_dev_fatal(dev, error,
- "writing new state");
- goto out;
- }
+ error = xs_transaction_start(&xst);
+ if (error != 0)
+ goto out;
+
+ do {
+ error = xs_scanf(xst, ivars->xd_node, "state",
+ NULL, "%d", &currstate);
+ } while (error == EAGAIN);
+ if (error)
+ goto out;
+
+ do {
+ error = xs_printf(xst, ivars->xd_node, "state",
+ "%d", newstate);
+ } while (error == EAGAIN);
+ if (error) {
+ /*
+ * Avoid looping through xenbus_dev_fatal()
+ * which calls xenbus_write_ivar to set the
+ * state to closing.
+ */
+ if (newstate != XenbusStateClosing)
+ xenbus_dev_fatal(dev, error,
+ "writing new state");
+ goto out;
+ }
+ } while (xs_transaction_end(xst, 0));
ivars->xd_state = newstate;
- if ((ivars->xd_flags & XDF_CONNECTING) != 0
- && (newstate == XenbusStateClosed
- || newstate == XenbusStateConnected)) {
+ if ((ivars->xd_flags & XDF_CONNECTING) != 0 &&
+ (newstate == XenbusStateClosed ||
+ newstate == XenbusStateConnected)) {
struct xenbusb_softc *xbs;
ivars->xd_flags &= ~XDF_CONNECTING;
@@ -949,8 +958,18 @@ xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
wakeup(&ivars->xd_state);
out:
+ if (error != 0)
+ xs_transaction_end(xst, 1);
sx_xunlock(&ivars->xd_lock);
- return (error);
+ /*
+ * Shallow ENOENT errors, as returning an error here will
+ * trigger a panic. ENOENT is fine to ignore, because it means
+ * the toolstack has removed the state node as part of
+ * destroying the device, and so we have to shut down the
+ * device without recreating it or else the node would be
+ * leaked.
+ */
+ return (error == ENOENT ? 0 : error);
}
case XENBUS_IVAR_NODE: