aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-07 18:49:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-07 18:49:18 -0400
commite7d33bb5ea82922e6ddcfc6b28a630b1a4ced071 (patch)
tree6a3d2da32c73b38246750cd8d163029d8a9afcf3 /lib
parent44a0cf92926c343366a4986808d12ab068504eed (diff)
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/lockref.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/lib/lockref.c b/lib/lockref.c
index 7aae8df37f67..e2cd2c0a8821 100644
--- a/lib/lockref.c
+++ b/lib/lockref.c
@@ -126,3 +126,41 @@ int lockref_put_or_lock(struct lockref *lockref)
126 return 1; 126 return 1;
127} 127}
128EXPORT_SYMBOL(lockref_put_or_lock); 128EXPORT_SYMBOL(lockref_put_or_lock);
129
130/**
131 * lockref_mark_dead - mark lockref dead
132 * @lockref: pointer to lockref structure
133 */
134void lockref_mark_dead(struct lockref *lockref)
135{
136 assert_spin_locked(&lockref->lock);
137 lockref->count = -128;
138}
139
140/**
141 * lockref_get_not_dead - Increments count unless the ref is dead
142 * @lockref: pointer to lockref structure
143 * Return: 1 if count updated successfully or 0 if lockref was dead
144 */
145int lockref_get_not_dead(struct lockref *lockref)
146{
147 int retval;
148
149 CMPXCHG_LOOP(
150 new.count++;
151 if ((int)old.count < 0)
152 return 0;
153 ,
154 return 1;
155 );
156
157 spin_lock(&lockref->lock);
158 retval = 0;
159 if ((int) lockref->count >= 0) {
160 lockref->count++;
161 retval = 1;
162 }
163 spin_unlock(&lockref->lock);
164 return retval;
165}
166EXPORT_SYMBOL(lockref_get_not_dead);