aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/kernfs/dir.c27
-rw-r--r--include/linux/kernfs.h4
2 files changed, 18 insertions, 13 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index ed62de6cdf8f..510b5062ef30 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -8,7 +8,6 @@
8 * This file is released under the GPLv2. 8 * This file is released under the GPLv2.
9 */ 9 */
10 10
11#include <linux/sched.h>
12#include <linux/fs.h> 11#include <linux/fs.h>
13#include <linux/namei.h> 12#include <linux/namei.h>
14#include <linux/idr.h> 13#include <linux/idr.h>
@@ -152,7 +151,6 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn)
152 */ 151 */
153void kernfs_put_active(struct kernfs_node *kn) 152void kernfs_put_active(struct kernfs_node *kn)
154{ 153{
155 struct kernfs_root *root = kernfs_root(kn);
156 int v; 154 int v;
157 155
158 if (unlikely(!kn)) 156 if (unlikely(!kn))
@@ -164,7 +162,11 @@ void kernfs_put_active(struct kernfs_node *kn)
164 if (likely(v != KN_DEACTIVATED_BIAS)) 162 if (likely(v != KN_DEACTIVATED_BIAS))
165 return; 163 return;
166 164
167 wake_up_all(&root->deactivate_waitq); 165 /*
166 * atomic_dec_return() is a mb(), we'll always see the updated
167 * kn->u.completion.
168 */
169 complete(kn->u.completion);
168} 170}
169 171
170/** 172/**
@@ -175,22 +177,26 @@ void kernfs_put_active(struct kernfs_node *kn)
175 */ 177 */
176static void kernfs_deactivate(struct kernfs_node *kn) 178static void kernfs_deactivate(struct kernfs_node *kn)
177{ 179{
178 struct kernfs_root *root = kernfs_root(kn); 180 DECLARE_COMPLETION_ONSTACK(wait);
181 int v;
179 182
180 BUG_ON(!(kn->flags & KERNFS_REMOVED)); 183 BUG_ON(!(kn->flags & KERNFS_REMOVED));
181 184
182 if (!(kernfs_type(kn) & KERNFS_ACTIVE_REF)) 185 if (!(kernfs_type(kn) & KERNFS_ACTIVE_REF))
183 return; 186 return;
184 187
185 rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); 188 kn->u.completion = (void *)&wait;
186 189
187 atomic_add(KN_DEACTIVATED_BIAS, &kn->active); 190 rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_);
191 /* atomic_add_return() is a mb(), put_active() will always see
192 * the updated kn->u.completion.
193 */
194 v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active);
188 195
189 if (atomic_read(&kn->active) != KN_DEACTIVATED_BIAS) 196 if (v != KN_DEACTIVATED_BIAS) {
190 lock_contended(&kn->dep_map, _RET_IP_); 197 lock_contended(&kn->dep_map, _RET_IP_);
191 198 wait_for_completion(&wait);
192 wait_event(root->deactivate_waitq, 199 }
193 atomic_read(&kn->active) == KN_DEACTIVATED_BIAS);
194 200
195 lock_acquired(&kn->dep_map, _RET_IP_); 201 lock_acquired(&kn->dep_map, _RET_IP_);
196 rwsem_release(&kn->dep_map, 1, _RET_IP_); 202 rwsem_release(&kn->dep_map, 1, _RET_IP_);
@@ -607,7 +613,6 @@ struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
607 613
608 root->dir_ops = kdops; 614 root->dir_ops = kdops;
609 root->kn = kn; 615 root->kn = kn;
610 init_waitqueue_head(&root->deactivate_waitq);
611 616
612 return root; 617 return root;
613} 618}
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 232f1a632383..d2c439db4efa 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,7 +15,7 @@
15#include <linux/lockdep.h> 15#include <linux/lockdep.h>
16#include <linux/rbtree.h> 16#include <linux/rbtree.h>
17#include <linux/atomic.h> 17#include <linux/atomic.h>
18#include <linux/wait.h> 18#include <linux/completion.h>
19 19
20struct file; 20struct file;
21struct iattr; 21struct iattr;
@@ -91,6 +91,7 @@ struct kernfs_node {
91 struct rb_node rb; 91 struct rb_node rb;
92 92
93 union { 93 union {
94 struct completion *completion;
94 struct kernfs_node *removed_list; 95 struct kernfs_node *removed_list;
95 } u; 96 } u;
96 97
@@ -131,7 +132,6 @@ struct kernfs_root {
131 /* private fields, do not use outside kernfs proper */ 132 /* private fields, do not use outside kernfs proper */
132 struct ida ino_ida; 133 struct ida ino_ida;
133 struct kernfs_dir_ops *dir_ops; 134 struct kernfs_dir_ops *dir_ops;
134 wait_queue_head_t deactivate_waitq;
135}; 135};
136 136
137struct kernfs_open_file { 137struct kernfs_open_file {