lkml.org 
[lkml]   [2020]   [Dec]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 236/242] xen/xenbus: Allow watches discard events before queueing
    Date
    From: SeongJae Park <sjpark@amazon.de>

    commit fed1755b118147721f2c87b37b9d66e62c39b668 upstream.

    If handling logics of watch events are slower than the events enqueue
    logic and the events can be created from the guests, the guests could
    trigger memory pressure by intensively inducing the events, because it
    will create a huge number of pending events that exhausting the memory.

    Fortunately, some watch events could be ignored, depending on its
    handler callback. For example, if the callback has interest in only one
    single path, the watch wouldn't want multiple pending events. Or, some
    watches could ignore events to same path.

    To let such watches to volutarily help avoiding the memory pressure
    situation, this commit introduces new watch callback, 'will_handle'. If
    it is not NULL, it will be called for each new event just before
    enqueuing it. Then, if the callback returns false, the event will be
    discarded. No watch is using the callback for now, though.

    This is part of XSA-349

    Cc: stable@vger.kernel.org
    Signed-off-by: SeongJae Park <sjpark@amazon.de>
    Reported-by: Michael Kurth <mku@amazon.de>
    Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
    Reviewed-by: Juergen Gross <jgross@suse.com>
    Signed-off-by: Juergen Gross <jgross@suse.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/net/xen-netback/xenbus.c | 4 ++++
    drivers/xen/xenbus/xenbus_client.c | 1 +
    drivers/xen/xenbus/xenbus_xs.c | 5 ++++-
    include/xen/xenbus.h | 7 +++++++
    4 files changed, 16 insertions(+), 1 deletion(-)

    --- a/drivers/net/xen-netback/xenbus.c
    +++ b/drivers/net/xen-netback/xenbus.c
    @@ -777,12 +777,14 @@ static int xen_register_credit_watch(str
    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;
    @@ -829,6 +831,7 @@ static int xen_register_mcast_ctrl_watch
    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) {
    @@ -836,6 +839,7 @@ static int xen_register_mcast_ctrl_watch
    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;
    --- a/drivers/xen/xenbus/xenbus_client.c
    +++ b/drivers/xen/xenbus/xenbus_client.c
    @@ -120,6 +120,7 @@ int xenbus_watch_path(struct xenbus_devi
    int err;

    watch->node = path;
    + watch->will_handle = NULL;
    watch->callback = callback;

    err = register_xenbus_watch(watch);
    --- a/drivers/xen/xenbus/xenbus_xs.c
    +++ b/drivers/xen/xenbus/xenbus_xs.c
    @@ -700,7 +700,10 @@ int xs_watch_msg(struct xs_watch_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);
    wake_up(&watch_events_waitq);
    --- a/include/xen/xenbus.h
    +++ b/include/xen/xenbus.h
    @@ -59,6 +59,13 @@ struct xenbus_watch
    /* Path being watched. */
    const char *node;

    + /*
    + * 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);

    \
     
     \ /
      Last update: 2020-12-28 17:40    [W:2.114 / U:0.368 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site