From 74a7f08448adea6cb47cd9b260c98ff168117e92 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 15 Jun 2012 11:50:25 -0600 Subject: devicetree: add helper inline for retrieving a node's full name The pattern (np ? np->full_name : "") is rather common in the kernel, but can also make for quite long lines. This patch adds a new inline function, of_node_full_name() so that the test for a valid node pointer doesn't need to be open coded at all call sites. Signed-off-by: Grant Likely Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Thomas Gleixner Signed-off-by: Rob Herring --- kernel/irq/irqdomain.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'kernel/irq') diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 41c1564103f1..38c5eb839c92 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -448,7 +448,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, } pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", - hwirq, domain->of_node ? domain->of_node->full_name : "null", virq); + hwirq, of_node_full_name(domain->of_node), virq); return virq; } @@ -477,7 +477,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, return intspec[0]; #endif pr_warning("no irq domain found for %s !\n", - controller->full_name); + of_node_full_name(controller)); return 0; } @@ -725,8 +725,8 @@ static int virq_debug_show(struct seq_file *m, void *private) data = irq_desc_get_chip_data(desc); seq_printf(m, data ? "0x%p " : " %p ", data); - if (desc->irq_data.domain && desc->irq_data.domain->of_node) - p = desc->irq_data.domain->of_node->full_name; + if (desc->irq_data.domain) + p = of_node_full_name(desc->irq_data.domain->of_node); else p = none; seq_printf(m, "%s\n", p); -- cgit v1.2.3-59-g8ed1b From 41f9d29f09ca0b22c3631e8a39676e74cda9bcc0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 26 Jun 2012 22:10:04 +0400 Subject: trimming task_work: kill ->data get rid of the only user of ->data; this is _not_ the final variant - in the end we'll have task_work and rcu_head identical and just use cred->rcu, at which point the separate allocation will be gone completely. Signed-off-by: Al Viro --- include/linux/task_work.h | 4 +--- kernel/irq/manage.c | 2 +- security/keys/internal.h | 4 ++++ security/keys/keyctl.c | 14 ++++++++------ security/keys/process_keys.c | 5 +++-- 5 files changed, 17 insertions(+), 12 deletions(-) (limited to 'kernel/irq') diff --git a/include/linux/task_work.h b/include/linux/task_work.h index 294d5d5e90b1..627421c0e108 100644 --- a/include/linux/task_work.h +++ b/include/linux/task_work.h @@ -10,14 +10,12 @@ typedef void (*task_work_func_t)(struct task_work *); struct task_work { struct hlist_node hlist; task_work_func_t func; - void *data; }; static inline void -init_task_work(struct task_work *twork, task_work_func_t func, void *data) +init_task_work(struct task_work *twork, task_work_func_t func) { twork->func = func; - twork->data = data; } int task_work_add(struct task_struct *task, struct task_work *twork, bool); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8c548232ba39..d1dd54734ce7 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -830,7 +830,7 @@ static int irq_thread(void *data) sched_setscheduler(current, SCHED_FIFO, ¶m); - init_task_work(&on_exit_work, irq_thread_dtor, NULL); + init_task_work(&on_exit_work, irq_thread_dtor); task_work_add(current, &on_exit_work, false); while (!irq_wait_for_interrupt(action)) { diff --git a/security/keys/internal.h b/security/keys/internal.h index 3dcbf86b0d31..b510a316874a 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -148,6 +148,10 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, #define KEY_LOOKUP_PARTIAL 0x02 #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 void key_change_session_keyring(struct task_work *twork); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 0f5b3f027299..26723caaad05 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1456,7 +1456,8 @@ long keyctl_session_to_parent(void) { struct task_struct *me, *parent; const struct cred *mycred, *pcred; - struct task_work *newwork, *oldwork; + struct kludge *newwork; + struct task_work *oldwork; key_ref_t keyring_r; struct cred *cred; int ret; @@ -1466,7 +1467,7 @@ long keyctl_session_to_parent(void) return PTR_ERR(keyring_r); ret = -ENOMEM; - newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL); + newwork = kmalloc(sizeof(struct kludge), GFP_KERNEL); if (!newwork) goto error_keyring; @@ -1478,7 +1479,8 @@ long keyctl_session_to_parent(void) goto error_newwork; cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); - init_task_work(newwork, key_change_session_keyring, cred); + init_task_work(&newwork->twork, key_change_session_keyring); + newwork->cred = cred; me = current; rcu_read_lock(); @@ -1527,18 +1529,18 @@ long keyctl_session_to_parent(void) /* the replacement session keyring is applied just prior to userspace * restarting */ - ret = task_work_add(parent, newwork, true); + ret = task_work_add(parent, &newwork->twork, true); if (!ret) newwork = NULL; unlock: write_unlock_irq(&tasklist_lock); rcu_read_unlock(); if (oldwork) { - put_cred(oldwork->data); + put_cred(container_of(oldwork, struct kludge, twork)->cred); kfree(oldwork); } if (newwork) { - put_cred(newwork->data); + put_cred(newwork->cred); kfree(newwork); } return ret; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 4ad54eea1ea4..c9b07c97d7f2 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -837,9 +837,10 @@ error: void key_change_session_keyring(struct task_work *twork) { const struct cred *old = current_cred(); - struct cred *new = twork->data; + struct kludge *p = container_of(twork, struct kludge, twork); + struct cred *new = p->cred; - kfree(twork); + kfree(p); if (unlikely(current->flags & PF_EXITING)) { put_cred(new); return; -- cgit v1.2.3-59-g8ed1b From 67d1214551e800f9fe7dc7c47a346d2df0fafed5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 27 Jun 2012 11:07:19 +0400 Subject: 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: Al Viro --- include/linux/sched.h | 2 +- include/linux/task_work.h | 14 ++++---------- include/linux/types.h | 9 +++++---- kernel/irq/manage.c | 4 ++-- kernel/task_work.c | 14 +++++++------- security/keys/internal.h | 6 +----- security/keys/keyctl.c | 28 +++++++++------------------- security/keys/process_keys.c | 6 ++---- 8 files changed, 31 insertions(+), 52 deletions(-) (limited to 'kernel/irq') diff --git a/include/linux/sched.h b/include/linux/sched.h index b9216ebc2789..af3555cc760f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1405,7 +1405,7 @@ struct task_struct { int (*notifier)(void *priv); void *notifier_data; sigset_t *notifier_mask; - void *task_works; + struct callback_head *task_works; struct audit_context *audit_context; #ifdef CONFIG_AUDITSYSCALL diff --git a/include/linux/task_work.h b/include/linux/task_work.h index 3b3e2c8d037b..fb46b03b1852 100644 --- a/include/linux/task_work.h +++ b/include/linux/task_work.h @@ -4,22 +4,16 @@ #include #include -struct task_work; -typedef void (*task_work_func_t)(struct task_work *); - -struct task_work { - struct task_work *next; - task_work_func_t func; -}; +typedef void (*task_work_func_t)(struct callback_head *); 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; } -int task_work_add(struct task_struct *task, struct task_work *twork, bool); -struct task_work *task_work_cancel(struct task_struct *, task_work_func_t); +int task_work_add(struct task_struct *task, struct callback_head *twork, bool); +struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t); void task_work_run(void); static inline void exit_task_work(struct task_struct *task) diff --git a/include/linux/types.h b/include/linux/types.h index 9c1bd539ea70..bf0dd7524b2a 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -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 * @func: actual update function to call after the grace period. */ -struct rcu_head { - struct rcu_head *next; - void (*func)(struct rcu_head *head); +struct callback_head { + struct callback_head *next; + void (*func)(struct callback_head *head); }; +#define rcu_head callback_head #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index d1dd54734ce7..814c9ef6bba1 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc) 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 irq_desc *desc; @@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused) */ static int irq_thread(void *data) { - struct task_work on_exit_work; + struct callback_head on_exit_work; static const struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, }; diff --git a/kernel/task_work.c b/kernel/task_work.c index 9b8948dbdc60..76266fb665dc 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -3,7 +3,7 @@ #include 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; int err = -ESRCH; @@ -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); if (likely(!(task->flags & PF_EXITING))) { - struct task_work *last = task->task_works; - struct task_work *first = last ? last->next : twork; + struct callback_head *last = task->task_works; + struct callback_head *first = last ? last->next : twork; twork->next = first; if (last) last->next = twork; @@ -35,16 +35,16 @@ task_work_add(struct task_struct *task, struct task_work *twork, bool notify) return err; } -struct task_work * +struct callback_head * task_work_cancel(struct task_struct *task, task_work_func_t func) { unsigned long flags; - struct task_work *last, *res = NULL; + struct callback_head *last, *res = NULL; raw_spin_lock_irqsave(&task->pi_lock, flags); last = task->task_works; if (last) { - struct task_work *q = last, *p = q->next; + struct callback_head *q = last, *p = q->next; while (1) { if (p->func == func) { q->next = p->next; @@ -66,7 +66,7 @@ task_work_cancel(struct task_struct *task, task_work_func_t func) void task_work_run(void) { struct task_struct *task = current; - struct task_work *p, *q; + struct callback_head *p, *q; raw_spin_lock_irq(&task->pi_lock); p = task->task_works; diff --git a/security/keys/internal.h b/security/keys/internal.h index b510a316874a..c246ba5d43ab 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -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_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 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 unsigned key_gc_delay; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 26723caaad05..0291b3f9397c 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1456,8 +1456,7 @@ long keyctl_session_to_parent(void) { struct task_struct *me, *parent; const struct cred *mycred, *pcred; - struct kludge *newwork; - struct task_work *oldwork; + struct callback_head *newwork, *oldwork; key_ref_t keyring_r; struct cred *cred; int ret; @@ -1467,20 +1466,17 @@ long keyctl_session_to_parent(void) return PTR_ERR(keyring_r); 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 * and new security data, so we allocate them here to prevent ENOMEM in * our parent */ cred = cred_alloc_blank(); if (!cred) - goto error_newwork; + goto error_keyring; + newwork = &cred->rcu; cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); - init_task_work(&newwork->twork, key_change_session_keyring); - newwork->cred = cred; + init_task_work(newwork, key_change_session_keyring); me = current; rcu_read_lock(); @@ -1529,24 +1525,18 @@ long keyctl_session_to_parent(void) /* the replacement session keyring is applied just prior to userspace * restarting */ - ret = task_work_add(parent, &newwork->twork, true); + ret = task_work_add(parent, newwork, true); if (!ret) newwork = NULL; unlock: write_unlock_irq(&tasklist_lock); rcu_read_unlock(); - if (oldwork) { - put_cred(container_of(oldwork, struct kludge, twork)->cred); - kfree(oldwork); - } - if (newwork) { - put_cred(newwork->cred); - kfree(newwork); - } + if (oldwork) + put_cred(container_of(oldwork, struct cred, rcu)); + if (newwork) + put_cred(cred); return ret; -error_newwork: - kfree(newwork); error_keyring: key_ref_put(keyring_r); return ret; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index c9b07c97d7f2..54339cfd6734 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -834,13 +834,11 @@ error: * Replace a process's session keyring on behalf of one of its children when * 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(); - struct kludge *p = container_of(twork, struct kludge, twork); - struct cred *new = p->cred; + struct cred *new = container_of(twork, struct cred, rcu); - kfree(p); if (unlikely(current->flags & PF_EXITING)) { put_cred(new); return; -- cgit v1.2.3-59-g8ed1b