Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754146AbaAJNra (ORCPT ); Fri, 10 Jan 2014 08:47:30 -0500 Received: from mail-qe0-f41.google.com ([209.85.128.41]:43887 "EHLO mail-qe0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752781AbaAJNrV (ORCPT ); Fri, 10 Jan 2014 08:47:21 -0500 From: Tejun Heo 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 Subject: [PATCH 08/14] kernfs: make kernfs_get_active() block if the node is deactivated but not removed Date: Fri, 10 Jan 2014 08:46:54 -0500 Message-Id: <1389361620-5086-9-git-send-email-tj@kernel.org> X-Mailer: git-send-email 1.8.4.2 In-Reply-To: <1389361620-5086-1-git-send-email-tj@kernel.org> References: <1389361620-5086-1-git-send-email-tj@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, kernfs_get_active() fails if the target node is deactivated. This is fine as a node always gets removed after deactivation; however, we're gonna add reactivation so the assumption won't hold. It'd be incorrect for kernfs_get_active() to fail for a node which was deactivated only temporarily. This patch makes kernfs_get_active() block if the node is deactivated but not removed. If the node gets reactivated (not yet implemented), it will be retried and succeed. If the node gets removed, it will be woken up and fail. Signed-off-by: Tejun Heo --- fs/kernfs/dir.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 52ffac7..f18fc5e 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -149,12 +149,25 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn) if (unlikely(!kn)) return NULL; - if (!atomic_inc_unless_negative(&kn->active)) - return NULL; - if (kernfs_lockdep(kn)) rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_); - return kn; + + /* + * Try to obtain an active ref. If @kn is deactivated, we block + * till either it's reactivated or killed. + */ + do { + if (atomic_inc_unless_negative(&kn->active)) + return kn; + + wait_event(kernfs_root(kn)->deactivate_waitq, + atomic_read(&kn->active) >= 0 || + RB_EMPTY_NODE(&kn->rb)); + } while (!RB_EMPTY_NODE(&kn->rb)); + + if (kernfs_lockdep(kn)) + rwsem_release(&kn->dep_map, 1, _RET_IP_); + return NULL; } /** @@ -786,6 +799,7 @@ static void __kernfs_deactivate(struct kernfs_node *kn) static void __kernfs_remove(struct kernfs_node *kn) { + struct kernfs_root *root = kernfs_root(kn); struct kernfs_node *pos; lockdep_assert_held(&kernfs_mutex); @@ -830,6 +844,9 @@ static void __kernfs_remove(struct kernfs_node *kn) kernfs_put(pos); } while (pos != kn); + + /* some nodes killed, kick get_active waiters */ + wake_up_all(&root->deactivate_waitq); } /** -- 1.8.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/