aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-01-09 18:19:03 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-01-25 23:16:29 -0500
commit360f54796ed65939093ae373b92ebd5ef3341776 (patch)
treeb89eeed53d0f4ff4ca9b753ca3f239e6fa0be005 /lib
parent32426f6653cbfde1ca16aff27a530ee36332f796 (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.c36
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)
60EXPORT_SYMBOL(lockref_get); 60EXPORT_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)
88EXPORT_SYMBOL(lockref_get_not_zero); 88EXPORT_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)
113EXPORT_SYMBOL(lockref_get_or_lock); 113EXPORT_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 */
122int 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}
133EXPORT_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 }