xen: branch for v5.11-rc1
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRTLbB6QfY48x44uB6AXGG7T9hjvgUCX9iqjQAKCRCAXGG7T9hj vvNXAQCNirQi0LTN7LGZvL2eDTg1SDcq7XII8YomcJl8UFBwvQD9HtRo5CwGzVKc PbDqGdvZdl9+VyVyeEvZTv/baaollAo= =MPh4 -----END PGP SIGNATURE----- Merge tag 'for-linus-5.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen updates from Juergen Gross: "Fixes for security issues just having been disclosed: - a five patch series for fixing of XSA-349 (DoS via resource depletion in Xen dom0) - a patch fixing XSA-350 (access of stale pointer in a Xen dom0)" * tag 'for-linus-5.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen-blkback: set ring->xenblkd to NULL after kthread_stop() xenbus/xenbus_backend: Disallow pending watch messages xen/xenbus: Count pending messages for each watch xen/xenbus/xen_bus_type: Support will_handle watch callback xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path() xen/xenbus: Allow watches discard events before queueing
This commit is contained in:
commit
7acfd4274e
|
@ -274,6 +274,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
|
|||
|
||||
if (ring->xenblkd) {
|
||||
kthread_stop(ring->xenblkd);
|
||||
ring->xenblkd = NULL;
|
||||
wake_up(&ring->shutdown_wq);
|
||||
}
|
||||
|
||||
|
@ -675,7 +676,8 @@ static int xen_blkbk_probe(struct xenbus_device *dev,
|
|||
/* setup back pointer */
|
||||
be->blkif->be = be;
|
||||
|
||||
err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed,
|
||||
err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL,
|
||||
backend_changed,
|
||||
"%s/%s", dev->nodename, "physical-device");
|
||||
if (err)
|
||||
goto fail;
|
||||
|
|
|
@ -557,12 +557,14 @@ static int xen_register_credit_watch(struct xenbus_device *dev,
|
|||
return -ENOMEM;
|
||||
snprintf(node, maxlen, "%s/rate", dev->nodename);
|
||||
vif->credit_watch.node = node;
|
||||
vif->credit_watch.will_handle = NULL;
|
||||
vif->credit_watch.callback = xen_net_rate_changed;
|
||||
err = register_xenbus_watch(&vif->credit_watch);
|
||||
if (err) {
|
||||
pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
|
||||
kfree(node);
|
||||
vif->credit_watch.node = NULL;
|
||||
vif->credit_watch.will_handle = NULL;
|
||||
vif->credit_watch.callback = NULL;
|
||||
}
|
||||
return err;
|
||||
|
@ -609,6 +611,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
|
|||
snprintf(node, maxlen, "%s/request-multicast-control",
|
||||
dev->otherend);
|
||||
vif->mcast_ctrl_watch.node = node;
|
||||
vif->mcast_ctrl_watch.will_handle = NULL;
|
||||
vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed;
|
||||
err = register_xenbus_watch(&vif->mcast_ctrl_watch);
|
||||
if (err) {
|
||||
|
@ -616,6 +619,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
|
|||
vif->mcast_ctrl_watch.node);
|
||||
kfree(node);
|
||||
vif->mcast_ctrl_watch.node = NULL;
|
||||
vif->mcast_ctrl_watch.will_handle = NULL;
|
||||
vif->mcast_ctrl_watch.callback = NULL;
|
||||
}
|
||||
return err;
|
||||
|
@ -820,7 +824,7 @@ static void connect(struct backend_info *be)
|
|||
xenvif_carrier_on(be->vif);
|
||||
|
||||
unregister_hotplug_status_watch(be);
|
||||
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
|
||||
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL,
|
||||
hotplug_status_changed,
|
||||
"%s/%s", dev->nodename, "hotplug-status");
|
||||
if (!err)
|
||||
|
|
|
@ -689,7 +689,7 @@ static int xen_pcibk_xenbus_probe(struct xenbus_device *dev,
|
|||
|
||||
/* watch the backend node for backend configuration information */
|
||||
err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
|
||||
xen_pcibk_be_watch);
|
||||
NULL, xen_pcibk_be_watch);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ struct xen_bus_type {
|
|||
int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
|
||||
int (*probe)(struct xen_bus_type *bus, const char *type,
|
||||
const char *dir);
|
||||
bool (*otherend_will_handle)(struct xenbus_watch *watch,
|
||||
const char *path, const char *token);
|
||||
void (*otherend_changed)(struct xenbus_watch *watch, const char *path,
|
||||
const char *token);
|
||||
struct bus_type bus;
|
||||
|
|
|
@ -127,18 +127,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);
|
|||
*/
|
||||
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
|
||||
struct xenbus_watch *watch,
|
||||
bool (*will_handle)(struct xenbus_watch *,
|
||||
const char *, const char *),
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char *, const char *))
|
||||
{
|
||||
int err;
|
||||
|
||||
watch->node = path;
|
||||
watch->will_handle = will_handle;
|
||||
watch->callback = callback;
|
||||
|
||||
err = register_xenbus_watch(watch);
|
||||
|
||||
if (err) {
|
||||
watch->node = NULL;
|
||||
watch->will_handle = NULL;
|
||||
watch->callback = NULL;
|
||||
xenbus_dev_fatal(dev, err, "adding watch on %s", path);
|
||||
}
|
||||
|
@ -165,6 +169,8 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path);
|
|||
*/
|
||||
int xenbus_watch_pathfmt(struct xenbus_device *dev,
|
||||
struct xenbus_watch *watch,
|
||||
bool (*will_handle)(struct xenbus_watch *,
|
||||
const char *, const char *),
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char *, const char *),
|
||||
const char *pathfmt, ...)
|
||||
|
@ -181,7 +187,7 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev,
|
|||
xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
|
||||
return -ENOMEM;
|
||||
}
|
||||
err = xenbus_watch_path(dev, path, watch, callback);
|
||||
err = xenbus_watch_path(dev, path, watch, will_handle, callback);
|
||||
|
||||
if (err)
|
||||
kfree(path);
|
||||
|
|
|
@ -136,6 +136,7 @@ static int watch_otherend(struct xenbus_device *dev)
|
|||
container_of(dev->dev.bus, struct xen_bus_type, bus);
|
||||
|
||||
return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
|
||||
bus->otherend_will_handle,
|
||||
bus->otherend_changed,
|
||||
"%s/%s", dev->otherend, "state");
|
||||
}
|
||||
|
|
|
@ -180,6 +180,12 @@ static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type,
|
|||
return err;
|
||||
}
|
||||
|
||||
static bool frontend_will_handle(struct xenbus_watch *watch,
|
||||
const char *path, const char *token)
|
||||
{
|
||||
return watch->nr_pending == 0;
|
||||
}
|
||||
|
||||
static void frontend_changed(struct xenbus_watch *watch,
|
||||
const char *path, const char *token)
|
||||
{
|
||||
|
@ -191,6 +197,7 @@ static struct xen_bus_type xenbus_backend = {
|
|||
.levels = 3, /* backend/type/<frontend>/<id> */
|
||||
.get_bus_id = backend_bus_id,
|
||||
.probe = xenbus_probe_backend,
|
||||
.otherend_will_handle = frontend_will_handle,
|
||||
.otherend_changed = frontend_changed,
|
||||
.bus = {
|
||||
.name = "xen-backend",
|
||||
|
|
|
@ -705,9 +705,13 @@ int xs_watch_msg(struct xs_watch_event *event)
|
|||
|
||||
spin_lock(&watches_lock);
|
||||
event->handle = find_watch(event->token);
|
||||
if (event->handle != NULL) {
|
||||
if (event->handle != NULL &&
|
||||
(!event->handle->will_handle ||
|
||||
event->handle->will_handle(event->handle,
|
||||
event->path, event->token))) {
|
||||
spin_lock(&watch_events_lock);
|
||||
list_add_tail(&event->list, &watch_events);
|
||||
event->handle->nr_pending++;
|
||||
wake_up(&watch_events_waitq);
|
||||
spin_unlock(&watch_events_lock);
|
||||
} else
|
||||
|
@ -765,6 +769,8 @@ int register_xenbus_watch(struct xenbus_watch *watch)
|
|||
|
||||
sprintf(token, "%lX", (long)watch);
|
||||
|
||||
watch->nr_pending = 0;
|
||||
|
||||
down_read(&xs_watch_rwsem);
|
||||
|
||||
spin_lock(&watches_lock);
|
||||
|
@ -814,11 +820,14 @@ void unregister_xenbus_watch(struct xenbus_watch *watch)
|
|||
|
||||
/* Cancel pending watch events. */
|
||||
spin_lock(&watch_events_lock);
|
||||
list_for_each_entry_safe(event, tmp, &watch_events, list) {
|
||||
if (event->handle != watch)
|
||||
continue;
|
||||
list_del(&event->list);
|
||||
kfree(event);
|
||||
if (watch->nr_pending) {
|
||||
list_for_each_entry_safe(event, tmp, &watch_events, list) {
|
||||
if (event->handle != watch)
|
||||
continue;
|
||||
list_del(&event->list);
|
||||
kfree(event);
|
||||
}
|
||||
watch->nr_pending = 0;
|
||||
}
|
||||
spin_unlock(&watch_events_lock);
|
||||
|
||||
|
@ -865,7 +874,6 @@ void xs_suspend_cancel(void)
|
|||
|
||||
static int xenwatch_thread(void *unused)
|
||||
{
|
||||
struct list_head *ent;
|
||||
struct xs_watch_event *event;
|
||||
|
||||
xenwatch_pid = current->pid;
|
||||
|
@ -880,13 +888,15 @@ static int xenwatch_thread(void *unused)
|
|||
mutex_lock(&xenwatch_mutex);
|
||||
|
||||
spin_lock(&watch_events_lock);
|
||||
ent = watch_events.next;
|
||||
if (ent != &watch_events)
|
||||
list_del(ent);
|
||||
event = list_first_entry_or_null(&watch_events,
|
||||
struct xs_watch_event, list);
|
||||
if (event) {
|
||||
list_del(&event->list);
|
||||
event->handle->nr_pending--;
|
||||
}
|
||||
spin_unlock(&watch_events_lock);
|
||||
|
||||
if (ent != &watch_events) {
|
||||
event = list_entry(ent, struct xs_watch_event, list);
|
||||
if (event) {
|
||||
event->handle->callback(event->handle, event->path,
|
||||
event->token);
|
||||
kfree(event);
|
||||
|
|
|
@ -61,6 +61,15 @@ struct xenbus_watch
|
|||
/* Path being watched. */
|
||||
const char *node;
|
||||
|
||||
unsigned int nr_pending;
|
||||
|
||||
/*
|
||||
* Called just before enqueing new event while a spinlock is held.
|
||||
* The event will be discarded if this callback returns false.
|
||||
*/
|
||||
bool (*will_handle)(struct xenbus_watch *,
|
||||
const char *path, const char *token);
|
||||
|
||||
/* Callback (executed in a process context with no locks held). */
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char *path, const char *token);
|
||||
|
@ -197,10 +206,14 @@ void xenbus_probe(struct work_struct *);
|
|||
|
||||
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
|
||||
struct xenbus_watch *watch,
|
||||
bool (*will_handle)(struct xenbus_watch *,
|
||||
const char *, const char *),
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char *, const char *));
|
||||
__printf(4, 5)
|
||||
__printf(5, 6)
|
||||
int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
|
||||
bool (*will_handle)(struct xenbus_watch *,
|
||||
const char *, const char *),
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char *, const char *),
|
||||
const char *pathfmt, ...);
|
||||
|
|
Loading…
Reference in New Issue