Commit 67d12145 authored by Al Viro's avatar Al Viro

merge task_work and rcu_head, get rid of separate allocation for keyring case

task_work and rcu_head are identical now; merge them (calling the result
struct callback_head, rcu_head #define'd to it), kill separate allocation
in security/keys since we can just use cred->rcu now.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 158e1645
...@@ -1405,7 +1405,7 @@ struct task_struct { ...@@ -1405,7 +1405,7 @@ struct task_struct {
int (*notifier)(void *priv); int (*notifier)(void *priv);
void *notifier_data; void *notifier_data;
sigset_t *notifier_mask; sigset_t *notifier_mask;
void *task_works; struct callback_head *task_works;
struct audit_context *audit_context; struct audit_context *audit_context;
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
......
...@@ -4,22 +4,16 @@ ...@@ -4,22 +4,16 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/sched.h> #include <linux/sched.h>
struct task_work; typedef void (*task_work_func_t)(struct callback_head *);
typedef void (*task_work_func_t)(struct task_work *);
struct task_work {
struct task_work *next;
task_work_func_t func;
};
static inline void static inline void
init_task_work(struct task_work *twork, task_work_func_t func) init_task_work(struct callback_head *twork, task_work_func_t func)
{ {
twork->func = func; twork->func = func;
} }
int task_work_add(struct task_struct *task, struct task_work *twork, bool); int task_work_add(struct task_struct *task, struct callback_head *twork, bool);
struct task_work *task_work_cancel(struct task_struct *, task_work_func_t); struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
void task_work_run(void); void task_work_run(void);
static inline void exit_task_work(struct task_struct *task) static inline void exit_task_work(struct task_struct *task)
......
...@@ -246,14 +246,15 @@ struct ustat { ...@@ -246,14 +246,15 @@ struct ustat {
}; };
/** /**
* struct rcu_head - callback structure for use with RCU * struct callback_head - callback structure for use with RCU and task_work
* @next: next update requests in a list * @next: next update requests in a list
* @func: actual update function to call after the grace period. * @func: actual update function to call after the grace period.
*/ */
struct rcu_head { struct callback_head {
struct rcu_head *next; struct callback_head *next;
void (*func)(struct rcu_head *head); void (*func)(struct callback_head *head);
}; };
#define rcu_head callback_head
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
......
...@@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc) ...@@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc)
wake_up(&desc->wait_for_threads); wake_up(&desc->wait_for_threads);
} }
static void irq_thread_dtor(struct task_work *unused) static void irq_thread_dtor(struct callback_head *unused)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct irq_desc *desc; struct irq_desc *desc;
...@@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused) ...@@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused)
*/ */
static int irq_thread(void *data) static int irq_thread(void *data)
{ {
struct task_work on_exit_work; struct callback_head on_exit_work;
static const struct sched_param param = { static const struct sched_param param = {
.sched_priority = MAX_USER_RT_PRIO/2, .sched_priority = MAX_USER_RT_PRIO/2,
}; };
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include <linux/tracehook.h> #include <linux/tracehook.h>
int int
task_work_add(struct task_struct *task, struct task_work *twork, bool notify) task_work_add(struct task_struct *task, struct callback_head *twork, bool notify)
{ {
unsigned long flags; unsigned long flags;
int err = -ESRCH; int err = -ESRCH;
...@@ -19,8 +19,8 @@ task_work_add(struct task_struct *task, struct task_work *twork, bool notify) ...@@ -19,8 +19,8 @@ task_work_add(struct task_struct *task, struct task_work *twork, bool notify)
*/ */
raw_spin_lock_irqsave(&task->pi_lock, flags); raw_spin_lock_irqsave(&task->pi_lock, flags);
if (likely(!(task->flags & PF_EXITING))) { if (likely(!(task->flags & PF_EXITING))) {
struct task_work *last = task->task_works; struct callback_head *last = task->task_works;
struct task_work *first = last ? last->next : twork; struct callback_head *first = last ? last->next : twork;
twork->next = first; twork->next = first;
if (last) if (last)
last->next = twork; last->next = twork;
...@@ -35,16 +35,16 @@ task_work_add(struct task_struct *task, struct task_work *twork, bool notify) ...@@ -35,16 +35,16 @@ task_work_add(struct task_struct *task, struct task_work *twork, bool notify)
return err; return err;
} }
struct task_work * struct callback_head *
task_work_cancel(struct task_struct *task, task_work_func_t func) task_work_cancel(struct task_struct *task, task_work_func_t func)
{ {
unsigned long flags; unsigned long flags;
struct task_work *last, *res = NULL; struct callback_head *last, *res = NULL;
raw_spin_lock_irqsave(&task->pi_lock, flags); raw_spin_lock_irqsave(&task->pi_lock, flags);
last = task->task_works; last = task->task_works;
if (last) { if (last) {
struct task_work *q = last, *p = q->next; struct callback_head *q = last, *p = q->next;
while (1) { while (1) {
if (p->func == func) { if (p->func == func) {
q->next = p->next; q->next = p->next;
...@@ -66,7 +66,7 @@ task_work_cancel(struct task_struct *task, task_work_func_t func) ...@@ -66,7 +66,7 @@ task_work_cancel(struct task_struct *task, task_work_func_t func)
void task_work_run(void) void task_work_run(void)
{ {
struct task_struct *task = current; struct task_struct *task = current;
struct task_work *p, *q; struct callback_head *p, *q;
raw_spin_lock_irq(&task->pi_lock); raw_spin_lock_irq(&task->pi_lock);
p = task->task_works; p = task->task_works;
......
...@@ -148,12 +148,8 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, ...@@ -148,12 +148,8 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
#define KEY_LOOKUP_PARTIAL 0x02 #define KEY_LOOKUP_PARTIAL 0x02
#define KEY_LOOKUP_FOR_UNLINK 0x04 #define KEY_LOOKUP_FOR_UNLINK 0x04
struct kludge { /* this will die off very soon */
struct task_work twork;
struct cred *cred;
};
extern long join_session_keyring(const char *name); extern long join_session_keyring(const char *name);
extern void key_change_session_keyring(struct task_work *twork); extern void key_change_session_keyring(struct callback_head *twork);
extern struct work_struct key_gc_work; extern struct work_struct key_gc_work;
extern unsigned key_gc_delay; extern unsigned key_gc_delay;
......
...@@ -1456,8 +1456,7 @@ long keyctl_session_to_parent(void) ...@@ -1456,8 +1456,7 @@ long keyctl_session_to_parent(void)
{ {
struct task_struct *me, *parent; struct task_struct *me, *parent;
const struct cred *mycred, *pcred; const struct cred *mycred, *pcred;
struct kludge *newwork; struct callback_head *newwork, *oldwork;
struct task_work *oldwork;
key_ref_t keyring_r; key_ref_t keyring_r;
struct cred *cred; struct cred *cred;
int ret; int ret;
...@@ -1467,20 +1466,17 @@ long keyctl_session_to_parent(void) ...@@ -1467,20 +1466,17 @@ long keyctl_session_to_parent(void)
return PTR_ERR(keyring_r); return PTR_ERR(keyring_r);
ret = -ENOMEM; ret = -ENOMEM;
newwork = kmalloc(sizeof(struct kludge), GFP_KERNEL);
if (!newwork)
goto error_keyring;
/* our parent is going to need a new cred struct, a new tgcred struct /* our parent is going to need a new cred struct, a new tgcred struct
* and new security data, so we allocate them here to prevent ENOMEM in * and new security data, so we allocate them here to prevent ENOMEM in
* our parent */ * our parent */
cred = cred_alloc_blank(); cred = cred_alloc_blank();
if (!cred) if (!cred)
goto error_newwork; goto error_keyring;
newwork = &cred->rcu;
cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
init_task_work(&newwork->twork, key_change_session_keyring); init_task_work(newwork, key_change_session_keyring);
newwork->cred = cred;
me = current; me = current;
rcu_read_lock(); rcu_read_lock();
...@@ -1529,24 +1525,18 @@ long keyctl_session_to_parent(void) ...@@ -1529,24 +1525,18 @@ long keyctl_session_to_parent(void)
/* the replacement session keyring is applied just prior to userspace /* the replacement session keyring is applied just prior to userspace
* restarting */ * restarting */
ret = task_work_add(parent, &newwork->twork, true); ret = task_work_add(parent, newwork, true);
if (!ret) if (!ret)
newwork = NULL; newwork = NULL;
unlock: unlock:
write_unlock_irq(&tasklist_lock); write_unlock_irq(&tasklist_lock);
rcu_read_unlock(); rcu_read_unlock();
if (oldwork) { if (oldwork)
put_cred(container_of(oldwork, struct kludge, twork)->cred); put_cred(container_of(oldwork, struct cred, rcu));
kfree(oldwork); if (newwork)
} put_cred(cred);
if (newwork) {
put_cred(newwork->cred);
kfree(newwork);
}
return ret; return ret;
error_newwork:
kfree(newwork);
error_keyring: error_keyring:
key_ref_put(keyring_r); key_ref_put(keyring_r);
return ret; return ret;
......
...@@ -834,13 +834,11 @@ long join_session_keyring(const char *name) ...@@ -834,13 +834,11 @@ long join_session_keyring(const char *name)
* Replace a process's session keyring on behalf of one of its children when * Replace a process's session keyring on behalf of one of its children when
* the target process is about to resume userspace execution. * the target process is about to resume userspace execution.
*/ */
void key_change_session_keyring(struct task_work *twork) void key_change_session_keyring(struct callback_head *twork)
{ {
const struct cred *old = current_cred(); const struct cred *old = current_cred();
struct kludge *p = container_of(twork, struct kludge, twork); struct cred *new = container_of(twork, struct cred, rcu);
struct cred *new = p->cred;
kfree(p);
if (unlikely(current->flags & PF_EXITING)) { if (unlikely(current->flags & PF_EXITING)) {
put_cred(new); put_cred(new);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment