* [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
@ 2006-04-04 9:55 David Howells
2006-04-04 10:23 ` [Keyrings] " David Howells
2006-04-04 10:58 ` Nick Piggin
0 siblings, 2 replies; 6+ messages in thread
From: David Howells @ 2006-04-04 9:55 UTC (permalink / raw)
To: torvalds, akpm; +Cc: keyrings, linux-kernel
The attached patch adds a missing memory barrier into the key_put() and removes
an unnecessary barrier from install_session_keyring().
install_session_keyring() is also rearranged a little to make it slightly more
efficient.
As install_*_keyring() may schedule (in synchronize_rcu() or keyring_alloc()),
they may not be entered with interrupts disabled - and so there's no point
saving the interrupt disablement state over the critical section.
exec_keys() will also be invoked with interrupts enabled, and so that doesn't
need to save the interrupt state either.
---
security/keys/key.c | 1 +
security/keys/process_keys.c | 41 ++++++++++++++++++++---------------------
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/security/keys/key.c b/security/keys/key.c
index 99781b7..d8a6e00 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -619,6 +619,7 @@ void key_put(struct key *key)
if (key) {
key_check(key);
+ smp_mb__before_atomic_dec();
if (atomic_dec_and_test(&key->usage))
schedule_work(&key_cleanup_task);
}
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 74cb79e..ad123c3 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -167,11 +167,12 @@ error:
*/
int install_process_keyring(struct task_struct *tsk)
{
- unsigned long flags;
struct key *keyring;
char buf[20];
int ret;
+ might_sleep();
+
if (!tsk->signal->process_keyring) {
sprintf(buf, "_pid.%u", tsk->tgid);
@@ -182,12 +183,12 @@ int install_process_keyring(struct task_
}
/* attach keyring */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ spin_lock_irq(&tsk->sighand->siglock);
if (!tsk->signal->process_keyring) {
tsk->signal->process_keyring = keyring;
keyring = NULL;
}
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
key_put(keyring);
}
@@ -206,38 +207,37 @@ error:
static int install_session_keyring(struct task_struct *tsk,
struct key *keyring)
{
- unsigned long flags;
struct key *old;
char buf[20];
- int ret;
+
+ might_sleep();
/* create an empty session keyring */
if (!keyring) {
sprintf(buf, "_ses.%u", tsk->tgid);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto error;
- }
+ if (IS_ERR(keyring))
+ return PTR_ERR(keyring);
}
else {
atomic_inc(&keyring->usage);
}
/* install the keyring */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
- old = rcu_dereference(tsk->signal->session_keyring);
+ spin_lock_irq(&tsk->sighand->siglock);
+ old = tsk->signal->session_keyring;
rcu_assign_pointer(tsk->signal->session_keyring, keyring);
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
- ret = 0;
+ /* we're using RCU on the pointer, but there's no point synchronising
+ * on it if it didn't previously point to anything */
+ if (old) {
+ synchronize_rcu();
+ key_put(old);
+ }
- /* we're using RCU on the pointer */
- synchronize_rcu();
- key_put(old);
-error:
- return ret;
+ return 0;
} /* end install_session_keyring() */
@@ -310,7 +310,6 @@ void exit_keys(struct task_struct *tsk)
*/
int exec_keys(struct task_struct *tsk)
{
- unsigned long flags;
struct key *old;
/* newly exec'd tasks don't get a thread keyring */
@@ -322,10 +321,10 @@ int exec_keys(struct task_struct *tsk)
key_put(old);
/* discard the process keyring from a newly exec'd task */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ spin_lock_irq(&tsk->sighand->siglock);
old = tsk->signal->process_keyring;
tsk->signal->process_keyring = NULL;
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
key_put(old);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Keyrings] [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
2006-04-04 9:55 [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement David Howells
@ 2006-04-04 10:23 ` David Howells
2006-04-04 10:58 ` Nick Piggin
1 sibling, 0 replies; 6+ messages in thread
From: David Howells @ 2006-04-04 10:23 UTC (permalink / raw)
To: David Howells; +Cc: torvalds, akpm, keyrings, linux-kernel
David Howells <dhowells@redhat.com> wrote:
> The attached patch adds a missing memory barrier into the key_put() and
> removes an unnecessary barrier from install_session_keyring().
> ...
Signed-Off-By: David Howells <dhowells@redhat.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
2006-04-04 9:55 [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement David Howells
2006-04-04 10:23 ` [Keyrings] " David Howells
@ 2006-04-04 10:58 ` Nick Piggin
2006-04-05 8:46 ` David Howells
1 sibling, 1 reply; 6+ messages in thread
From: Nick Piggin @ 2006-04-04 10:58 UTC (permalink / raw)
To: David Howells; +Cc: torvalds, akpm, keyrings, linux-kernel, David S. Miller
David Howells wrote:
> diff --git a/security/keys/key.c b/security/keys/key.c
> index 99781b7..d8a6e00 100644
> --- a/security/keys/key.c
> +++ b/security/keys/key.c
> @@ -619,6 +619,7 @@ void key_put(struct key *key)
> if (key) {
> key_check(key);
>
> + smp_mb__before_atomic_dec();
> if (atomic_dec_and_test(&key->usage))
> schedule_work(&key_cleanup_task);
Shouldn't be needed: Documentation/atomic_ops.txt specifies that any atomic_
which both modifies its atomic operand and returns something is to be a full
barrier before and after the operation.
This misuse occurs a few times in core code, which makes it a bit confusing.
However, I think it is nice to add a comment if these implicit barriers are
used, if the purpose is not really obvious.
--
SUSE Labs, Novell Inc.
Send instant messages to your online friends http://au.messenger.yahoo.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
2006-04-04 10:58 ` Nick Piggin
@ 2006-04-05 8:46 ` David Howells
2006-04-05 9:23 ` Nick Piggin
0 siblings, 1 reply; 6+ messages in thread
From: David Howells @ 2006-04-05 8:46 UTC (permalink / raw)
To: Nick Piggin
Cc: David Howells, torvalds, akpm, keyrings, linux-kernel,
David S. Miller
Nick Piggin <nickpiggin@yahoo.com.au> wrote:
> Shouldn't be needed: Documentation/atomic_ops.txt specifies that any atomic_
> which both modifies its atomic operand and returns something is to be a full
> barrier before and after the operation.
Hmmm... It's possible that I've misunderstood what atomic_ops.txt actually
says. For instance:
| int atomic_inc_and_test(atomic_t *v);
| int atomic_dec_and_test(atomic_t *v);
|
| These two routines increment and decrement by 1, respectively, the
| given atomic counter. They return a boolean indicating whether the
| resulting counter value was zero or not.
|
| It requires explicit memory barrier semantics around the operation as
| above.
Note the last paragraph. "It requires" should be "They require", but the
sense would seem to be obvious. However, it's not clear on a second reading
as to whether this is an instruction to the _caller_ or an instruction to the
arch _implementer_.
I suppose from reading the abstract at the top:
| This document is intended to serve as a guide to Linux port maintainers on
| how to implement atomic counter, bitops, and spinlock interfaces properly.
that it is meant to be read by the implementor and not the user/caller, in which
case, Nick is correct.
It seems I need to adjust my memory barrier doc, and perhaps I should adjust
atomic_ops.txt too to make it clearer.
David
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
2006-04-05 8:46 ` David Howells
@ 2006-04-05 9:23 ` Nick Piggin
2006-04-05 22:51 ` David S. Miller
0 siblings, 1 reply; 6+ messages in thread
From: Nick Piggin @ 2006-04-05 9:23 UTC (permalink / raw)
To: David Howells; +Cc: torvalds, akpm, keyrings, linux-kernel, David S. Miller
David Howells wrote:
> Nick Piggin <nickpiggin@yahoo.com.au> wrote:
> | int atomic_inc_and_test(atomic_t *v);
> | int atomic_dec_and_test(atomic_t *v);
> |
> | These two routines increment and decrement by 1, respectively, the
> | given atomic counter. They return a boolean indicating whether the
> | resulting counter value was zero or not.
> |
> | It requires explicit memory barrier semantics around the operation as
> | above.
>
> Note the last paragraph. "It requires" should be "They require", but the
> sense would seem to be obvious. However, it's not clear on a second reading
> as to whether this is an instruction to the _caller_ or an instruction to the
> arch _implementer_.
>
Yes, I remember Dave M clarified this sometime ago (on lkml I guess). It
is a little confusing, but I think the wording is for the implementer's
point of view. Dave will pull me up if I'm wrong...
> I suppose from reading the abstract at the top:
>
> | This document is intended to serve as a guide to Linux port maintainers on
> | how to implement atomic counter, bitops, and spinlock interfaces properly.
>
> that it is meant to be read by the implementor and not the user/caller, in which
> case, Nick is correct.
>
> It seems I need to adjust my memory barrier doc, and perhaps I should adjust
> atomic_ops.txt too to make it clearer.
>
I think that would be good. atomic_ops.txt is very useful for API users
as well, so if it can be made more general without becoming ambiguous,
I'm sure that would be appreciated.
Thanks,
Nick
--
SUSE Labs, Novell Inc.
Send instant messages to your online friends http://au.messenger.yahoo.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
2006-04-05 9:23 ` Nick Piggin
@ 2006-04-05 22:51 ` David S. Miller
0 siblings, 0 replies; 6+ messages in thread
From: David S. Miller @ 2006-04-05 22:51 UTC (permalink / raw)
To: nickpiggin; +Cc: dhowells, torvalds, akpm, keyrings, linux-kernel
From: Nick Piggin <nickpiggin@yahoo.com.au>
Date: Wed, 05 Apr 2006 19:23:58 +1000
> David Howells wrote:
> > Nick Piggin <nickpiggin@yahoo.com.au> wrote:
>
> > | int atomic_inc_and_test(atomic_t *v);
> > | int atomic_dec_and_test(atomic_t *v);
> > |
> > | These two routines increment and decrement by 1, respectively, the
> > | given atomic counter. They return a boolean indicating whether the
> > | resulting counter value was zero or not.
> > |
> > | It requires explicit memory barrier semantics around the operation as
> > | above.
> >
> > Note the last paragraph. "It requires" should be "They require", but the
> > sense would seem to be obvious. However, it's not clear on a second reading
> > as to whether this is an instruction to the _caller_ or an instruction to the
> > arch _implementer_.
> >
>
> Yes, I remember Dave M clarified this sometime ago (on lkml I guess). It
> is a little confusing, but I think the wording is for the implementer's
> point of view. Dave will pull me up if I'm wrong...
Any routine which returns state must have the barriers in the arch
implementation. These two routines returns state.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2006-04-05 22:55 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-04 9:55 [PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement David Howells
2006-04-04 10:23 ` [Keyrings] " David Howells
2006-04-04 10:58 ` Nick Piggin
2006-04-05 8:46 ` David Howells
2006-04-05 9:23 ` Nick Piggin
2006-04-05 22:51 ` David S. Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox