2013-09-02 18:58:20 +00:00
|
|
|
#include <linux/export.h>
|
|
|
|
#include <linux/lockref.h>
|
|
|
|
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
#ifdef CONFIG_CMPXCHG_LOCKREF
|
|
|
|
|
2013-09-26 16:27:00 +00:00
|
|
|
/*
|
|
|
|
* Allow weakly-ordered memory architectures to provide barrier-less
|
|
|
|
* cmpxchg semantics for lockref updates.
|
|
|
|
*/
|
|
|
|
#ifndef cmpxchg64_relaxed
|
|
|
|
# define cmpxchg64_relaxed cmpxchg64
|
|
|
|
#endif
|
|
|
|
|
2013-09-23 10:59:56 +00:00
|
|
|
/*
|
|
|
|
* Allow architectures to override the default cpu_relax() within CMPXCHG_LOOP.
|
|
|
|
* This is useful for architectures with an expensive cpu_relax().
|
|
|
|
*/
|
|
|
|
#ifndef arch_mutex_cpu_relax
|
|
|
|
# define arch_mutex_cpu_relax() cpu_relax()
|
|
|
|
#endif
|
|
|
|
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
/*
|
|
|
|
* Note that the "cmpxchg()" reloads the "old" value for the
|
|
|
|
* failure case.
|
|
|
|
*/
|
|
|
|
#define CMPXCHG_LOOP(CODE, SUCCESS) do { \
|
|
|
|
struct lockref old; \
|
|
|
|
BUILD_BUG_ON(sizeof(old) != 8); \
|
|
|
|
old.lock_count = ACCESS_ONCE(lockref->lock_count); \
|
|
|
|
while (likely(arch_spin_value_unlocked(old.lock.rlock.raw_lock))) { \
|
|
|
|
struct lockref new = old, prev = old; \
|
|
|
|
CODE \
|
2013-09-26 16:27:00 +00:00
|
|
|
old.lock_count = cmpxchg64_relaxed(&lockref->lock_count, \
|
|
|
|
old.lock_count, \
|
|
|
|
new.lock_count); \
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
if (likely(old.lock_count == prev.lock_count)) { \
|
|
|
|
SUCCESS; \
|
|
|
|
} \
|
2013-09-23 10:59:56 +00:00
|
|
|
arch_mutex_cpu_relax(); \
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define CMPXCHG_LOOP(CODE, SUCCESS) do { } while (0)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2013-09-02 18:58:20 +00:00
|
|
|
/**
|
|
|
|
* lockref_get - Increments reference count unconditionally
|
2013-09-07 22:30:29 +00:00
|
|
|
* @lockref: pointer to lockref structure
|
2013-09-02 18:58:20 +00:00
|
|
|
*
|
|
|
|
* This operation is only valid if you already hold a reference
|
|
|
|
* to the object, so you know the count cannot be zero.
|
|
|
|
*/
|
|
|
|
void lockref_get(struct lockref *lockref)
|
|
|
|
{
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
CMPXCHG_LOOP(
|
|
|
|
new.count++;
|
|
|
|
,
|
|
|
|
return;
|
|
|
|
);
|
|
|
|
|
2013-09-02 18:58:20 +00:00
|
|
|
spin_lock(&lockref->lock);
|
|
|
|
lockref->count++;
|
|
|
|
spin_unlock(&lockref->lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lockref_get);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* lockref_get_not_zero - Increments count unless the count is 0
|
2013-09-07 22:30:29 +00:00
|
|
|
* @lockref: pointer to lockref structure
|
2013-09-02 18:58:20 +00:00
|
|
|
* Return: 1 if count updated successfully or 0 if count was zero
|
|
|
|
*/
|
|
|
|
int lockref_get_not_zero(struct lockref *lockref)
|
|
|
|
{
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
int retval;
|
|
|
|
|
|
|
|
CMPXCHG_LOOP(
|
|
|
|
new.count++;
|
|
|
|
if (!old.count)
|
|
|
|
return 0;
|
|
|
|
,
|
|
|
|
return 1;
|
|
|
|
);
|
2013-09-02 18:58:20 +00:00
|
|
|
|
|
|
|
spin_lock(&lockref->lock);
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
retval = 0;
|
2013-09-02 18:58:20 +00:00
|
|
|
if (lockref->count) {
|
|
|
|
lockref->count++;
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
spin_unlock(&lockref->lock);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lockref_get_not_zero);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* lockref_get_or_lock - Increments count unless the count is 0
|
2013-09-07 22:30:29 +00:00
|
|
|
* @lockref: pointer to lockref structure
|
2013-09-02 18:58:20 +00:00
|
|
|
* Return: 1 if count updated successfully or 0 if count was zero
|
|
|
|
* and we got the lock instead.
|
|
|
|
*/
|
|
|
|
int lockref_get_or_lock(struct lockref *lockref)
|
|
|
|
{
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
CMPXCHG_LOOP(
|
|
|
|
new.count++;
|
|
|
|
if (!old.count)
|
|
|
|
break;
|
|
|
|
,
|
|
|
|
return 1;
|
|
|
|
);
|
|
|
|
|
2013-09-02 18:58:20 +00:00
|
|
|
spin_lock(&lockref->lock);
|
|
|
|
if (!lockref->count)
|
|
|
|
return 0;
|
|
|
|
lockref->count++;
|
|
|
|
spin_unlock(&lockref->lock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lockref_get_or_lock);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* lockref_put_or_lock - decrements count unless count <= 1 before decrement
|
2013-09-07 22:30:29 +00:00
|
|
|
* @lockref: pointer to lockref structure
|
2013-09-02 18:58:20 +00:00
|
|
|
* Return: 1 if count updated successfully or 0 if count <= 1 and lock taken
|
|
|
|
*/
|
|
|
|
int lockref_put_or_lock(struct lockref *lockref)
|
|
|
|
{
|
lockref: implement lockless reference count updates using cmpxchg()
Instead of taking the spinlock, the lockless versions atomically check
that the lock is not taken, and do the reference count update using a
cmpxchg() loop. This is semantically identical to doing the reference
count update protected by the lock, but avoids the "wait for lock"
contention that you get when accesses to the reference count are
contended.
Note that a "lockref" is absolutely _not_ equivalent to an atomic_t.
Even when the lockref reference counts are updated atomically with
cmpxchg, the fact that they also verify the state of the spinlock means
that the lockless updates can never happen while somebody else holds the
spinlock.
So while "lockref_put_or_lock()" looks a lot like just another name for
"atomic_dec_and_lock()", and both optimize to lockless updates, they are
fundamentally different: the decrement done by atomic_dec_and_lock() is
truly independent of any lock (as long as it doesn't decrement to zero),
so a locked region can still see the count change.
The lockref structure, in contrast, really is a *locked* reference
count. If you hold the spinlock, the reference count will be stable and
you can modify the reference count without using atomics, because even
the lockless updates will see and respect the state of the lock.
In order to enable the cmpxchg lockless code, the architecture needs to
do three things:
(1) Make sure that the "arch_spinlock_t" and an "unsigned int" can fit
in an aligned u64, and have a "cmpxchg()" implementation that works
on such a u64 data type.
(2) define a helper function to test for a spinlock being unlocked
("arch_spin_value_unlocked()")
(3) select the "ARCH_USE_CMPXCHG_LOCKREF" config variable in its
Kconfig file.
This enables it for x86-64 (but not 32-bit, we'd need to make sure
cmpxchg() turns into the proper cmpxchg8b in order to enable it for
32-bit mode).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-02 19:12:15 +00:00
|
|
|
CMPXCHG_LOOP(
|
|
|
|
new.count--;
|
|
|
|
if (old.count <= 1)
|
|
|
|
break;
|
|
|
|
,
|
|
|
|
return 1;
|
|
|
|
);
|
|
|
|
|
2013-09-02 18:58:20 +00:00
|
|
|
spin_lock(&lockref->lock);
|
|
|
|
if (lockref->count <= 1)
|
|
|
|
return 0;
|
|
|
|
lockref->count--;
|
|
|
|
spin_unlock(&lockref->lock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lockref_put_or_lock);
|
lockref: add ability to mark lockrefs "dead"
The only actual current lockref user (dcache) uses zero reference counts
even for perfectly live dentries, because it's a cache: there may not be
any users, but that doesn't mean that we want to throw away the dentry.
At the same time, the dentry cache does have a notion of a truly "dead"
dentry that we must not even increment the reference count of, because
we have pruned it and it is not valid.
Currently that distinction is not visible in the lockref itself, and the
dentry cache validation uses "lockref_get_or_lock()" to either get a new
reference to a dentry that already had existing references (and thus
cannot be dead), or get the dentry lock so that we can then verify the
dentry and increment the reference count under the lock if that
verification was successful.
That's all somewhat complicated.
This adds the concept of being "dead" to the lockref itself, by simply
using a count that is negative. This allows a usage scenario where we
can increment the refcount of a dentry without having to validate it,
and pushing the special "we killed it" case into the lockref code.
The dentry code itself doesn't actually use this yet, and it's probably
too late in the merge window to do that code (the dentry_kill() code
with its "should I decrement the count" logic really is pretty complex
code), but let's introduce the concept at the lockref level now.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-07 22:49:18 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* lockref_mark_dead - mark lockref dead
|
|
|
|
* @lockref: pointer to lockref structure
|
|
|
|
*/
|
|
|
|
void lockref_mark_dead(struct lockref *lockref)
|
|
|
|
{
|
|
|
|
assert_spin_locked(&lockref->lock);
|
|
|
|
lockref->count = -128;
|
|
|
|
}
|
2013-10-15 14:18:08 +00:00
|
|
|
EXPORT_SYMBOL(lockref_mark_dead);
|
lockref: add ability to mark lockrefs "dead"
The only actual current lockref user (dcache) uses zero reference counts
even for perfectly live dentries, because it's a cache: there may not be
any users, but that doesn't mean that we want to throw away the dentry.
At the same time, the dentry cache does have a notion of a truly "dead"
dentry that we must not even increment the reference count of, because
we have pruned it and it is not valid.
Currently that distinction is not visible in the lockref itself, and the
dentry cache validation uses "lockref_get_or_lock()" to either get a new
reference to a dentry that already had existing references (and thus
cannot be dead), or get the dentry lock so that we can then verify the
dentry and increment the reference count under the lock if that
verification was successful.
That's all somewhat complicated.
This adds the concept of being "dead" to the lockref itself, by simply
using a count that is negative. This allows a usage scenario where we
can increment the refcount of a dentry without having to validate it,
and pushing the special "we killed it" case into the lockref code.
The dentry code itself doesn't actually use this yet, and it's probably
too late in the merge window to do that code (the dentry_kill() code
with its "should I decrement the count" logic really is pretty complex
code), but let's introduce the concept at the lockref level now.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-07 22:49:18 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* lockref_get_not_dead - Increments count unless the ref is dead
|
|
|
|
* @lockref: pointer to lockref structure
|
|
|
|
* Return: 1 if count updated successfully or 0 if lockref was dead
|
|
|
|
*/
|
|
|
|
int lockref_get_not_dead(struct lockref *lockref)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
CMPXCHG_LOOP(
|
|
|
|
new.count++;
|
|
|
|
if ((int)old.count < 0)
|
|
|
|
return 0;
|
|
|
|
,
|
|
|
|
return 1;
|
|
|
|
);
|
|
|
|
|
|
|
|
spin_lock(&lockref->lock);
|
|
|
|
retval = 0;
|
|
|
|
if ((int) lockref->count >= 0) {
|
|
|
|
lockref->count++;
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
spin_unlock(&lockref->lock);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lockref_get_not_dead);
|