linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: gregkh@linuxfoundation.org
Cc: linux-kernel@vger.kernel.org, schwidefsky@de.ibm.com,
	heiko.carstens@de.ibm.com, stern@rowland.harvard.edu,
	JBottomley@parallels.com, bhelgaas@google.com,
	Tejun Heo <tj@kernel.org>
Subject: [PATCH 02/12] kernfs: replace kernfs_node->u.completion with kernfs_root->deactivate_waitq
Date: Mon,  3 Feb 2014 14:02:55 -0500	[thread overview]
Message-ID: <1391454185-32143-3-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1391454185-32143-1-git-send-email-tj@kernel.org>

kernfs_node->u.completion is used to notify deactivation completion
from kernfs_put_active() to kernfs_deactivate().  We now allow
multiple racing removals of the same node and the current removal
scheme is no longer correct - kernfs_remove() invocation may return
before the node is properly deactivated if it races against another
removal.  The removal path will be restructured to address the issue.

To help such restructure which requires supporting multiple waiters,
this patch replaces kernfs_node->u.completion with
kernfs_root->deactivate_waitq.  This makes deactivation event
notifications share a per-root waitqueue_head; however, the wait path
is quite cold and this will also allow shaving one pointer off
kernfs_node.

v2: Refreshed on top of ("kernfs: make kernfs_deactivate() honor
    KERNFS_LOCKDEP flag").

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 fs/kernfs/dir.c        | 31 +++++++++++++------------------
 include/linux/kernfs.h |  4 ++--
 2 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index bd6e18b..2193d30 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -8,6 +8,7 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
@@ -151,6 +152,7 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn)
  */
 void kernfs_put_active(struct kernfs_node *kn)
 {
+	struct kernfs_root *root = kernfs_root(kn);
 	int v;
 
 	if (unlikely(!kn))
@@ -162,11 +164,7 @@ void kernfs_put_active(struct kernfs_node *kn)
 	if (likely(v != KN_DEACTIVATED_BIAS))
 		return;
 
-	/*
-	 * atomic_dec_return() is a mb(), we'll always see the updated
-	 * kn->u.completion.
-	 */
-	complete(kn->u.completion);
+	wake_up_all(&root->deactivate_waitq);
 }
 
 /**
@@ -177,28 +175,24 @@ void kernfs_put_active(struct kernfs_node *kn)
  */
 static void kernfs_deactivate(struct kernfs_node *kn)
 {
-	DECLARE_COMPLETION_ONSTACK(wait);
-	int v;
+	struct kernfs_root *root = kernfs_root(kn);
 
 	BUG_ON(!(kn->flags & KERNFS_REMOVED));
 
 	if (!(kernfs_type(kn) & KERNFS_ACTIVE_REF))
 		return;
 
-	kn->u.completion = (void *)&wait;
-
 	if (kn->flags & KERNFS_LOCKDEP)
 		rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_);
-	/* atomic_add_return() is a mb(), put_active() will always see
-	 * the updated kn->u.completion.
-	 */
-	v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active);
 
-	if (v != KN_DEACTIVATED_BIAS) {
-		if (kn->flags & KERNFS_LOCKDEP)
-			lock_contended(&kn->dep_map, _RET_IP_);
-		wait_for_completion(&wait);
-	}
+	atomic_add(KN_DEACTIVATED_BIAS, &kn->active);
+
+	if ((kn->flags & KERNFS_LOCKDEP) &&
+	    atomic_read(&kn->active) != KN_DEACTIVATED_BIAS)
+		lock_contended(&kn->dep_map, _RET_IP_);
+
+	wait_event(root->deactivate_waitq,
+		   atomic_read(&kn->active) == KN_DEACTIVATED_BIAS);
 
 	if (kn->flags & KERNFS_LOCKDEP) {
 		lock_acquired(&kn->dep_map, _RET_IP_);
@@ -630,6 +624,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
 
 	root->dir_ops = kdops;
 	root->kn = kn;
+	init_waitqueue_head(&root->deactivate_waitq);
 
 	return root;
 }
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 5be9f02..295a3bf 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,7 +15,7 @@
 #include <linux/lockdep.h>
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
-#include <linux/completion.h>
+#include <linux/wait.h>
 
 struct file;
 struct dentry;
@@ -92,7 +92,6 @@ struct kernfs_node {
 	struct rb_node		rb;
 
 	union {
-		struct completion	*completion;
 		struct kernfs_node	*removed_list;
 	} u;
 
@@ -133,6 +132,7 @@ struct kernfs_root {
 	/* private fields, do not use outside kernfs proper */
 	struct ida		ino_ida;
 	struct kernfs_dir_ops	*dir_ops;
+	wait_queue_head_t	deactivate_waitq;
 };
 
 struct kernfs_open_file {
-- 
1.8.5.3


  parent reply	other threads:[~2014-02-03 19:03 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-03 19:02 [PATCHSET v5 driver-core-next] kernfs, sysfs, driver-core: implement synchronous self-removal Tejun Heo
2014-02-03 19:02 ` [PATCH 01/12] kernfs: make kernfs_deactivate() honor KERNFS_LOCKDEP flag Tejun Heo
2014-02-03 19:02 ` Tejun Heo [this message]
2014-02-03 19:02 ` [PATCH 03/12] kernfs: restructure removal path to fix possible premature return Tejun Heo
2014-02-03 19:02 ` [PATCH 04/12] kernfs: invoke kernfs_unmap_bin_file() directly from kernfs_deactivate() Tejun Heo
2014-02-03 19:02 ` [PATCH 05/12] kernfs: remove kernfs_addrm_cxt Tejun Heo
2014-02-03 19:02 ` [PATCH 06/12] kernfs: remove KERNFS_ACTIVE_REF and add kernfs_lockdep() Tejun Heo
2014-02-03 19:03 ` [PATCH 07/12] kernfs: remove KERNFS_REMOVED Tejun Heo
2014-02-03 19:03 ` [PATCH 08/12] kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers Tejun Heo
2014-02-03 19:03 ` [PATCH 09/12] pci: use device_remove_file_self() instead of device_schedule_callback() Tejun Heo
2014-02-03 19:03 ` [PATCH 10/12] scsi: " Tejun Heo
2014-02-03 19:03 ` [PATCH 11/12] s390: " Tejun Heo
2014-02-03 19:03 ` [PATCH 12/12] sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner() Tejun Heo
  -- strict thread matches above, loose matches on Subject: below --
2014-01-07 17:59 [PATCHSET driver-core-next] kernfs, sysfs, driver-core: implement synchronous self-removal Tejun Heo
2014-01-07 17:59 ` [PATCH 02/12] kernfs: replace kernfs_node->u.completion with kernfs_root->deactivate_waitq Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1391454185-32143-3-git-send-email-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=JBottomley@parallels.com \
    --cc=bhelgaas@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heiko.carstens@de.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=schwidefsky@de.ibm.com \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).