lkml.org 
[lkml]   [2021]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[RFC][PATCH 3/7] sched,livepatch: Use task_try_func()
    Instead of frobbing around with scheduler internals, use the shiny new
    task_try_func() interface.

    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    ---
    kernel/livepatch/transition.c | 84 ++++++++++++++++++------------------------
    1 file changed, 37 insertions(+), 47 deletions(-)

    --- a/kernel/livepatch/transition.c
    +++ b/kernel/livepatch/transition.c
    @@ -13,7 +13,6 @@
    #include "core.h"
    #include "patch.h"
    #include "transition.h"
    -#include "../sched/sched.h"

    #define MAX_STACK_ENTRIES 100
    #define STACK_ERR_BUF_SIZE 128
    @@ -240,7 +239,7 @@ static int klp_check_stack_func(struct k
    * Determine whether it's safe to transition the task to the target patch state
    * by looking for any to-be-patched or to-be-unpatched functions on its stack.
    */
    -static int klp_check_stack(struct task_struct *task, char *err_buf)
    +static int klp_check_stack(struct task_struct *task, const char **oldname)
    {
    static unsigned long entries[MAX_STACK_ENTRIES];
    struct klp_object *obj;
    @@ -248,12 +247,8 @@ static int klp_check_stack(struct task_s
    int ret, nr_entries;

    ret = stack_trace_save_tsk_reliable(task, entries, ARRAY_SIZE(entries));
    - if (ret < 0) {
    - snprintf(err_buf, STACK_ERR_BUF_SIZE,
    - "%s: %s:%d has an unreliable stack\n",
    - __func__, task->comm, task->pid);
    - return ret;
    - }
    + if (ret < 0)
    + return -EINVAL;
    nr_entries = ret;

    klp_for_each_object(klp_transition_patch, obj) {
    @@ -262,11 +257,8 @@ static int klp_check_stack(struct task_s
    klp_for_each_func(obj, func) {
    ret = klp_check_stack_func(func, entries, nr_entries);
    if (ret) {
    - snprintf(err_buf, STACK_ERR_BUF_SIZE,
    - "%s: %s:%d is sleeping on function %s\n",
    - __func__, task->comm, task->pid,
    - func->old_name);
    - return ret;
    + *oldname = func->old_name;
    + return -EADDRINUSE;
    }
    }
    }
    @@ -274,6 +266,22 @@ static int klp_check_stack(struct task_s
    return 0;
    }

    +static int klp_check_task(struct task_struct *task, void *arg)
    +{
    + int ret;
    +
    + if (task_curr(task))
    + return -EBUSY;
    +
    + ret = klp_check_stack(task, arg);
    + if (ret)
    + return ret;
    +
    + clear_tsk_thread_flag(task, TIF_PATCH_PENDING);
    + task->patch_state = klp_target_state;
    + return 0;
    +}
    +
    /*
    * Try to safely switch a task to the target patch state. If it's currently
    * running, or it's sleeping on a to-be-patched or to-be-unpatched function, or
    @@ -281,13 +289,8 @@ static int klp_check_stack(struct task_s
    */
    static bool klp_try_switch_task(struct task_struct *task)
    {
    - static char err_buf[STACK_ERR_BUF_SIZE];
    - struct rq *rq;
    - struct rq_flags flags;
    + const char *old_name;
    int ret;
    - bool success = false;
    -
    - err_buf[0] = '\0';

    /* check if this task has already switched over */
    if (task->patch_state == klp_target_state)
    @@ -305,36 +308,23 @@ static bool klp_try_switch_task(struct t
    * functions. If all goes well, switch the task to the target patch
    * state.
    */
    - rq = task_rq_lock(task, &flags);
    -
    - if (task_running(rq, task) && task != current) {
    - snprintf(err_buf, STACK_ERR_BUF_SIZE,
    - "%s: %s:%d is running\n", __func__, task->comm,
    - task->pid);
    - goto done;
    + ret = task_try_func(task, klp_check_task, &old_name);
    + switch (ret) {
    + case -EBUSY:
    + pr_debug("%s: %s:%d is running\n",
    + __func__, task->comm, task->pid);
    + break;
    + case -EINVAL:
    + pr_debug("%s: %s:%d has an unreliable stack\n",
    + __func__, task->comm, task->pid);
    + break;
    + case -EADDRINUSE:
    + pr_debug("%s: %s:%d is sleeping on function %s\n",
    + __func__, task->comm, task->pid, old_name);
    + break;
    }

    - ret = klp_check_stack(task, err_buf);
    - if (ret)
    - goto done;
    -
    - success = true;
    -
    - clear_tsk_thread_flag(task, TIF_PATCH_PENDING);
    - task->patch_state = klp_target_state;
    -
    -done:
    - task_rq_unlock(rq, task, &flags);
    -
    - /*
    - * Due to console deadlock issues, pr_debug() can't be used while
    - * holding the task rq lock. Instead we have to use a temporary buffer
    - * and print the debug message after releasing the lock.
    - */
    - if (err_buf[0] != '\0')
    - pr_debug("%s", err_buf);
    -
    - return success;
    + return !ret;
    }

    /*

    \
     
     \ /
      Last update: 2021-09-22 13:13    [W:3.780 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site