diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-01-09 18:19:03 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-01-25 23:16:29 -0500 |
commit | 360f54796ed65939093ae373b92ebd5ef3341776 (patch) | |
tree | b89eeed53d0f4ff4ca9b753ca3f239e6fa0be005 /lib | |
parent | 32426f6653cbfde1ca16aff27a530ee36332f796 (diff) |
dcache: let the dentry count go down to zero without taking d_lock
We can be more aggressive about this, if we are clever and careful. This is subtle.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lockref.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/lockref.c b/lib/lockref.c index d2233de9a86e..ecb9a665ec19 100644 --- a/lib/lockref.c +++ b/lib/lockref.c | |||
@@ -60,7 +60,7 @@ void lockref_get(struct lockref *lockref) | |||
60 | EXPORT_SYMBOL(lockref_get); | 60 | EXPORT_SYMBOL(lockref_get); |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * lockref_get_not_zero - Increments count unless the count is 0 | 63 | * lockref_get_not_zero - Increments count unless the count is 0 or dead |
64 | * @lockref: pointer to lockref structure | 64 | * @lockref: pointer to lockref structure |
65 | * Return: 1 if count updated successfully or 0 if count was zero | 65 | * Return: 1 if count updated successfully or 0 if count was zero |
66 | */ | 66 | */ |
@@ -70,7 +70,7 @@ int lockref_get_not_zero(struct lockref *lockref) | |||
70 | 70 | ||
71 | CMPXCHG_LOOP( | 71 | CMPXCHG_LOOP( |
72 | new.count++; | 72 | new.count++; |
73 | if (!old.count) | 73 | if (old.count <= 0) |
74 | return 0; | 74 | return 0; |
75 | , | 75 | , |
76 | return 1; | 76 | return 1; |
@@ -78,7 +78,7 @@ int lockref_get_not_zero(struct lockref *lockref) | |||
78 | 78 | ||
79 | spin_lock(&lockref->lock); | 79 | spin_lock(&lockref->lock); |
80 | retval = 0; | 80 | retval = 0; |
81 | if (lockref->count) { | 81 | if (lockref->count > 0) { |
82 | lockref->count++; | 82 | lockref->count++; |
83 | retval = 1; | 83 | retval = 1; |
84 | } | 84 | } |
@@ -88,7 +88,7 @@ int lockref_get_not_zero(struct lockref *lockref) | |||
88 | EXPORT_SYMBOL(lockref_get_not_zero); | 88 | EXPORT_SYMBOL(lockref_get_not_zero); |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * lockref_get_or_lock - Increments count unless the count is 0 | 91 | * lockref_get_or_lock - Increments count unless the count is 0 or dead |
92 | * @lockref: pointer to lockref structure | 92 | * @lockref: pointer to lockref structure |
93 | * Return: 1 if count updated successfully or 0 if count was zero | 93 | * Return: 1 if count updated successfully or 0 if count was zero |
94 | * and we got the lock instead. | 94 | * and we got the lock instead. |
@@ -97,14 +97,14 @@ int lockref_get_or_lock(struct lockref *lockref) | |||
97 | { | 97 | { |
98 | CMPXCHG_LOOP( | 98 | CMPXCHG_LOOP( |
99 | new.count++; | 99 | new.count++; |
100 | if (!old.count) | 100 | if (old.count <= 0) |
101 | break; | 101 | break; |
102 | , | 102 | , |
103 | return 1; | 103 | return 1; |
104 | ); | 104 | ); |
105 | 105 | ||
106 | spin_lock(&lockref->lock); | 106 | spin_lock(&lockref->lock); |
107 | if (!lockref->count) | 107 | if (lockref->count <= 0) |
108 | return 0; | 108 | return 0; |
109 | lockref->count++; | 109 | lockref->count++; |
110 | spin_unlock(&lockref->lock); | 110 | spin_unlock(&lockref->lock); |
@@ -113,6 +113,26 @@ int lockref_get_or_lock(struct lockref *lockref) | |||
113 | EXPORT_SYMBOL(lockref_get_or_lock); | 113 | EXPORT_SYMBOL(lockref_get_or_lock); |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * lockref_put_return - Decrement reference count if possible | ||
117 | * @lockref: pointer to lockref structure | ||
118 | * | ||
119 | * Decrement the reference count and return the new value. | ||
120 | * If the lockref was dead or locked, return an error. | ||
121 | */ | ||
122 | int lockref_put_return(struct lockref *lockref) | ||
123 | { | ||
124 | CMPXCHG_LOOP( | ||
125 | new.count--; | ||
126 | if (old.count <= 0) | ||
127 | return -1; | ||
128 | , | ||
129 | return new.count; | ||
130 | ); | ||
131 | return -1; | ||
132 | } | ||
133 | EXPORT_SYMBOL(lockref_put_return); | ||
134 | |||
135 | /** | ||
116 | * lockref_put_or_lock - decrements count unless count <= 1 before decrement | 136 | * lockref_put_or_lock - decrements count unless count <= 1 before decrement |
117 | * @lockref: pointer to lockref structure | 137 | * @lockref: pointer to lockref structure |
118 | * Return: 1 if count updated successfully or 0 if count <= 1 and lock taken | 138 | * Return: 1 if count updated successfully or 0 if count <= 1 and lock taken |
@@ -158,7 +178,7 @@ int lockref_get_not_dead(struct lockref *lockref) | |||
158 | 178 | ||
159 | CMPXCHG_LOOP( | 179 | CMPXCHG_LOOP( |
160 | new.count++; | 180 | new.count++; |
161 | if ((int)old.count < 0) | 181 | if (old.count < 0) |
162 | return 0; | 182 | return 0; |
163 | , | 183 | , |
164 | return 1; | 184 | return 1; |
@@ -166,7 +186,7 @@ int lockref_get_not_dead(struct lockref *lockref) | |||
166 | 186 | ||
167 | spin_lock(&lockref->lock); | 187 | spin_lock(&lockref->lock); |
168 | retval = 0; | 188 | retval = 0; |
169 | if ((int) lockref->count >= 0) { | 189 | if (lockref->count >= 0) { |
170 | lockref->count++; | 190 | lockref->count++; |
171 | retval = 1; | 191 | retval = 1; |
172 | } | 192 | } |