From patchwork Tue Nov 17 19:40:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tejun Heo X-Patchwork-Id: 545751 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id ACD3C141435 for ; Wed, 18 Nov 2015 06:43:17 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=QoNRV89J; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932464AbbKQTk4 (ORCPT ); Tue, 17 Nov 2015 14:40:56 -0500 Received: from mail-yk0-f171.google.com ([209.85.160.171]:35819 "EHLO mail-yk0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932085AbbKQTkx (ORCPT ); Tue, 17 Nov 2015 14:40:53 -0500 Received: by ykba77 with SMTP id a77so24803456ykb.2; Tue, 17 Nov 2015 11:40:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=qjw+eatWKmmEhfEvDwzcaB8n2ZzovHWFsg5+jM7+gu8=; b=QoNRV89JWCSdSO5K0Xz3mbdnP5FALKN1ytGkt/iTmgWE/TQkPvGn5Tr701atVuckjr 8Y180ryTOOqqCcEOm9YY4KjnhjWwrK5p/8n5WKS10tkjQ+yboFsGpHWzaS862LTfb3PT KtvQSQcLe8fIrqkdfD6qqoEpvC+SvwnS0OqjNK6s9yt1O/7aMPQzoOMQC4aS9Ai7IXWt fquCqktjmTR7dcp9HCM8f/N8QL1xx4r740aF0h2jpwj0nOlIiOPPqgWD7r/8MRrQxHXM KpOju4n8hSJd+mE5UiMWLxrnGbw2p4sj2UfAAu114QZhVs+r0jfZjN+kdjOHsJwYqe7b Vu6Q== X-Received: by 10.129.125.137 with SMTP id y131mr42038132ywc.5.1447789252670; Tue, 17 Nov 2015 11:40:52 -0800 (PST) Received: from mtj.duckdns.org.com ([2620:10d:c091:200::a:4bca]) by smtp.googlemail.com with ESMTPSA id r69sm2792881ywg.46.2015.11.17.11.40.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Nov 2015 11:40:52 -0800 (PST) From: Tejun Heo To: davem@davemloft.net, pablo@netfilter.org, kaber@trash.net, kadlec@blackhole.kfki.hu, lizefan@huawei.com, hannes@cmpxchg.org Cc: netdev@vger.kernel.org, netfilter-devel@vger.kernel.org, coreteam@netfilter.org, cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-team@fb.com, daniel@iogearbox.net, daniel.wagner@bmw-carit.de, nhorman@tuxdriver.com, Tejun Heo , Greg Kroah-Hartman Subject: [PATCH 2/5] kernfs: implement kernfs_walk_and_get() Date: Tue, 17 Nov 2015 14:40:37 -0500 Message-Id: <1447789240-29394-3-git-send-email-tj@kernel.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1447789240-29394-1-git-send-email-tj@kernel.org> References: <1447789240-29394-1-git-send-email-tj@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implement kernfs_walk_and_get() which is similar to kernfs_find_and_get() but can walk a path instead of just a name. Signed-off-by: Tejun Heo Cc: Greg Kroah-Hartman --- fs/kernfs/dir.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/kernfs.h | 12 ++++++++++++ 2 files changed, 60 insertions(+) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 91e0045..95dc415 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -694,6 +694,31 @@ static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent, return NULL; } +static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent, + const unsigned char *path, + const void *ns) +{ + static char path_buf[PATH_MAX]; /* protected by kernfs_mutex */ + int len = strlen(path); + char *p, *name; + + lockdep_assert_held(&kernfs_mutex); + + if (len >= PATH_MAX) + return NULL; + + memcpy(path_buf, path, len + 1); + p = path_buf; + + while ((name = strsep(&p, "/")) && parent) { + if (*name == '\0') + continue; + parent = kernfs_find_ns(parent, name, ns); + } + + return parent; +} + /** * kernfs_find_and_get_ns - find and get kernfs_node with the given name * @parent: kernfs_node to search under @@ -719,6 +744,29 @@ struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns); /** + * kernfs_walk_and_get_ns - find and get kernfs_node with the given path + * @parent: kernfs_node to search under + * @path: path to look for + * @ns: the namespace tag to use + * + * Look for kernfs_node with path @path under @parent and get a reference + * if found. This function may sleep and returns pointer to the found + * kernfs_node on success, %NULL on failure. + */ +struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent, + const char *path, const void *ns) +{ + struct kernfs_node *kn; + + mutex_lock(&kernfs_mutex); + kn = kernfs_walk_ns(parent, path, ns); + kernfs_get(kn); + mutex_unlock(&kernfs_mutex); + + return kn; +} + +/** * kernfs_create_root - create a new kernfs hierarchy * @scops: optional syscall operations for the hierarchy * @flags: KERNFS_ROOT_* flags diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 5d4e9c4..af51df3 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -274,6 +274,8 @@ void pr_cont_kernfs_path(struct kernfs_node *kn); struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn); struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, const void *ns); +struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent, + const char *path, const void *ns); void kernfs_get(struct kernfs_node *kn); void kernfs_put(struct kernfs_node *kn); @@ -350,6 +352,10 @@ static inline struct kernfs_node * kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, const void *ns) { return NULL; } +static inline struct kernfs_node * +kernfs_walk_and_get_ns(struct kernfs_node *parent, const char *path, + const void *ns) +{ return NULL; } static inline void kernfs_get(struct kernfs_node *kn) { } static inline void kernfs_put(struct kernfs_node *kn) { } @@ -431,6 +437,12 @@ kernfs_find_and_get(struct kernfs_node *kn, const char *name) } static inline struct kernfs_node * +kernfs_walk_and_get(struct kernfs_node *kn, const char *path) +{ + return kernfs_walk_and_get_ns(kn, path, NULL); +} + +static inline struct kernfs_node * kernfs_create_dir(struct kernfs_node *parent, const char *name, umode_t mode, void *priv) {