* [PATCH 01/11] sunrpc: allocate pipefs inodes using kmalloc
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 14:26 ` Jeff Layton
2013-12-01 13:14 ` [PATCH 02/11] rpc_pipefs: always mount on net namespace initialization Christoph Hellwig
` (13 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
There's not a lot of them, and not needing our own slab makes
initialization ordering a whole lot simpler.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
net/sunrpc/rpc_pipe.c | 39 +++++++--------------------------------
1 file changed, 7 insertions(+), 32 deletions(-)
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index bf04b30..395eb5f 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -40,8 +40,6 @@
static struct file_system_type rpc_pipe_fs_type;
-static struct kmem_cache *rpc_inode_cachep __read_mostly;
-
#define RPC_UPCALL_TIMEOUT (30*HZ)
static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
@@ -193,24 +191,21 @@ rpc_close_pipes(struct inode *inode)
static struct inode *
rpc_alloc_inode(struct super_block *sb)
{
- struct rpc_inode *rpci;
- rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
+ struct rpc_inode *rpci = kmalloc(sizeof(struct rpc_inode), GFP_KERNEL);
if (!rpci)
return NULL;
- return &rpci->vfs_inode;
-}
-static void
-rpc_i_callback(struct rcu_head *head)
-{
- struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
+ inode_init_once(&rpci->vfs_inode);
+ rpci->private = NULL;
+ rpci->pipe = NULL;
+ init_waitqueue_head(&rpci->waitq);
+ return &rpci->vfs_inode;
}
static void
rpc_destroy_inode(struct inode *inode)
{
- call_rcu(&inode->i_rcu, rpc_i_callback);
+ kfree_rcu(inode, i_rcu);
}
static int
@@ -1327,28 +1322,10 @@ static struct file_system_type rpc_pipe_fs_type = {
MODULE_ALIAS_FS("rpc_pipefs");
MODULE_ALIAS("rpc_pipefs");
-static void
-init_once(void *foo)
-{
- struct rpc_inode *rpci = (struct rpc_inode *) foo;
-
- inode_init_once(&rpci->vfs_inode);
- rpci->private = NULL;
- rpci->pipe = NULL;
- init_waitqueue_head(&rpci->waitq);
-}
-
int register_rpc_pipefs(void)
{
int err;
- rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
- sizeof(struct rpc_inode),
- 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
- SLAB_MEM_SPREAD),
- init_once);
- if (!rpc_inode_cachep)
- return -ENOMEM;
err = rpc_clients_notifier_register();
if (err)
goto err_notifier;
@@ -1360,13 +1337,11 @@ int register_rpc_pipefs(void)
err_register:
rpc_clients_notifier_unregister();
err_notifier:
- kmem_cache_destroy(rpc_inode_cachep);
return err;
}
void unregister_rpc_pipefs(void)
{
rpc_clients_notifier_unregister();
- kmem_cache_destroy(rpc_inode_cachep);
unregister_filesystem(&rpc_pipe_fs_type);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 01/11] sunrpc: allocate pipefs inodes using kmalloc
2013-12-01 13:14 ` [PATCH 01/11] sunrpc: allocate pipefs inodes using kmalloc Christoph Hellwig
@ 2013-12-01 14:26 ` Jeff Layton
0 siblings, 0 replies; 36+ messages in thread
From: Jeff Layton @ 2013-12-01 14:26 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-nfs, viro, linux-fsdevel
On Sun, 01 Dec 2013 05:14:42 -0800
Christoph Hellwig <hch@infradead.org> wrote:
> There's not a lot of them, and not needing our own slab makes
> initialization ordering a whole lot simpler.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> net/sunrpc/rpc_pipe.c | 39 +++++++--------------------------------
> 1 file changed, 7 insertions(+), 32 deletions(-)
>
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index bf04b30..395eb5f 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -40,8 +40,6 @@
> static struct file_system_type rpc_pipe_fs_type;
>
>
> -static struct kmem_cache *rpc_inode_cachep __read_mostly;
> -
> #define RPC_UPCALL_TIMEOUT (30*HZ)
>
> static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
> @@ -193,24 +191,21 @@ rpc_close_pipes(struct inode *inode)
> static struct inode *
> rpc_alloc_inode(struct super_block *sb)
> {
> - struct rpc_inode *rpci;
> - rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
> + struct rpc_inode *rpci = kmalloc(sizeof(struct rpc_inode), GFP_KERNEL);
> if (!rpci)
> return NULL;
> - return &rpci->vfs_inode;
> -}
>
> -static void
> -rpc_i_callback(struct rcu_head *head)
> -{
> - struct inode *inode = container_of(head, struct inode, i_rcu);
> - kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
> + inode_init_once(&rpci->vfs_inode);
> + rpci->private = NULL;
> + rpci->pipe = NULL;
> + init_waitqueue_head(&rpci->waitq);
> + return &rpci->vfs_inode;
> }
>
> static void
> rpc_destroy_inode(struct inode *inode)
> {
> - call_rcu(&inode->i_rcu, rpc_i_callback);
> + kfree_rcu(inode, i_rcu);
> }
>
> static int
> @@ -1327,28 +1322,10 @@ static struct file_system_type rpc_pipe_fs_type = {
> MODULE_ALIAS_FS("rpc_pipefs");
> MODULE_ALIAS("rpc_pipefs");
>
> -static void
> -init_once(void *foo)
> -{
> - struct rpc_inode *rpci = (struct rpc_inode *) foo;
> -
> - inode_init_once(&rpci->vfs_inode);
> - rpci->private = NULL;
> - rpci->pipe = NULL;
> - init_waitqueue_head(&rpci->waitq);
> -}
> -
> int register_rpc_pipefs(void)
> {
> int err;
>
> - rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
> - sizeof(struct rpc_inode),
> - 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
> - SLAB_MEM_SPREAD),
> - init_once);
> - if (!rpc_inode_cachep)
> - return -ENOMEM;
> err = rpc_clients_notifier_register();
> if (err)
> goto err_notifier;
> @@ -1360,13 +1337,11 @@ int register_rpc_pipefs(void)
> err_register:
> rpc_clients_notifier_unregister();
> err_notifier:
> - kmem_cache_destroy(rpc_inode_cachep);
> return err;
> }
>
> void unregister_rpc_pipefs(void)
> {
> rpc_clients_notifier_unregister();
> - kmem_cache_destroy(rpc_inode_cachep);
> unregister_filesystem(&rpc_pipe_fs_type);
> }
Makes sense...
Acked-by: Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 02/11] rpc_pipefs: always mount on net namespace initialization
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
2013-12-01 13:14 ` [PATCH 01/11] sunrpc: allocate pipefs inodes using kmalloc Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 15:24 ` Jeff Layton
2013-12-01 13:14 ` [PATCH 03/11] sunrpc: remove the rpc_clients_block notifier Christoph Hellwig
` (12 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
Make sure every network namespace has an rpc_pipefs mount available.
This makes creating a pipes a heck lot easier.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/sunrpc/rpc_pipe_fs.h | 1 -
net/sunrpc/netns.h | 4 ++++
net/sunrpc/rpc_pipe.c | 14 +++++++++++++-
net/sunrpc/sunrpc_syms.c | 8 +++++++-
4 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index a353e03..d5807e7 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -84,7 +84,6 @@ enum {
extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
const unsigned char *dir_name);
-extern void rpc_pipefs_init_net(struct net *net);
extern struct super_block *rpc_get_sb_net(const struct net *net);
extern void rpc_put_sb_net(const struct net *net);
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 779742c..a80b069 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -13,6 +13,7 @@ struct sunrpc_net {
struct cache_detail *rsc_cache;
struct cache_detail *rsi_cache;
+ struct vfsmount *pipefs_mnt;
struct super_block *pipefs_sb;
struct mutex pipefs_sb_lock;
@@ -41,4 +42,7 @@ extern int sunrpc_net_id;
int ip_map_cache_create(struct net *);
void ip_map_cache_destroy(struct net *);
+extern int rpc_pipefs_init_net(struct net *net);
+extern void rpc_pipefs_exit_net(struct net *net);
+
#endif
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 395eb5f..e654b65 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1203,13 +1203,25 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
}
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
-void rpc_pipefs_init_net(struct net *net)
+int rpc_pipefs_init_net(struct net *net)
{
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
mutex_init(&sn->pipefs_sb_lock);
sn->gssd_running = 1;
sn->pipe_version = -1;
+
+ sn->pipefs_mnt = kern_mount(&rpc_pipe_fs_type);
+ if (IS_ERR(sn->pipefs_mnt))
+ return PTR_ERR(sn->pipefs_mnt);
+ return 0;
+}
+
+void rpc_pipefs_exit_net(struct net *net)
+{
+ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+ kern_unmount(sn->pipefs_mnt);
}
/*
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 3d6498a..5d7e961 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(struct net *net)
if (err)
goto err_unixgid;
- rpc_pipefs_init_net(net);
+ err = rpc_pipefs_init_net(net);
+ if (err)
+ goto err_gidcache;
+
INIT_LIST_HEAD(&sn->all_clients);
spin_lock_init(&sn->rpc_client_lock);
spin_lock_init(&sn->rpcb_clnt_lock);
return 0;
+err_gidcache:
+ unix_gid_cache_destroy(net);
err_unixgid:
ip_map_cache_destroy(net);
err_ipmap:
@@ -60,6 +65,7 @@ err_proc:
static __net_exit void sunrpc_exit_net(struct net *net)
{
+ rpc_pipefs_exit_net(net);
unix_gid_cache_destroy(net);
ip_map_cache_destroy(net);
rpc_proc_exit(net);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 02/11] rpc_pipefs: always mount on net namespace initialization
2013-12-01 13:14 ` [PATCH 02/11] rpc_pipefs: always mount on net namespace initialization Christoph Hellwig
@ 2013-12-01 15:24 ` Jeff Layton
0 siblings, 0 replies; 36+ messages in thread
From: Jeff Layton @ 2013-12-01 15:24 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-nfs, viro, linux-fsdevel
On Sun, 01 Dec 2013 05:14:43 -0800
Christoph Hellwig <hch@infradead.org> wrote:
> Make sure every network namespace has an rpc_pipefs mount available.
> This makes creating a pipes a heck lot easier.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> include/linux/sunrpc/rpc_pipe_fs.h | 1 -
> net/sunrpc/netns.h | 4 ++++
> net/sunrpc/rpc_pipe.c | 14 +++++++++++++-
> net/sunrpc/sunrpc_syms.c | 8 +++++++-
> 4 files changed, 24 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
> index a353e03..d5807e7 100644
> --- a/include/linux/sunrpc/rpc_pipe_fs.h
> +++ b/include/linux/sunrpc/rpc_pipe_fs.h
> @@ -84,7 +84,6 @@ enum {
>
> extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
> const unsigned char *dir_name);
> -extern void rpc_pipefs_init_net(struct net *net);
> extern struct super_block *rpc_get_sb_net(const struct net *net);
> extern void rpc_put_sb_net(const struct net *net);
>
> diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
> index 779742c..a80b069 100644
> --- a/net/sunrpc/netns.h
> +++ b/net/sunrpc/netns.h
> @@ -13,6 +13,7 @@ struct sunrpc_net {
> struct cache_detail *rsc_cache;
> struct cache_detail *rsi_cache;
>
> + struct vfsmount *pipefs_mnt;
> struct super_block *pipefs_sb;
> struct mutex pipefs_sb_lock;
>
> @@ -41,4 +42,7 @@ extern int sunrpc_net_id;
> int ip_map_cache_create(struct net *);
> void ip_map_cache_destroy(struct net *);
>
> +extern int rpc_pipefs_init_net(struct net *net);
> +extern void rpc_pipefs_exit_net(struct net *net);
> +
> #endif
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index 395eb5f..e654b65 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -1203,13 +1203,25 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
> }
> EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
>
> -void rpc_pipefs_init_net(struct net *net)
> +int rpc_pipefs_init_net(struct net *net)
> {
> struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
>
> mutex_init(&sn->pipefs_sb_lock);
> sn->gssd_running = 1;
> sn->pipe_version = -1;
> +
> + sn->pipefs_mnt = kern_mount(&rpc_pipe_fs_type);
> + if (IS_ERR(sn->pipefs_mnt))
> + return PTR_ERR(sn->pipefs_mnt);
> + return 0;
> +}
> +
> +void rpc_pipefs_exit_net(struct net *net)
> +{
> + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
> +
> + kern_unmount(sn->pipefs_mnt);
> }
>
> /*
> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
> index 3d6498a..5d7e961 100644
> --- a/net/sunrpc/sunrpc_syms.c
> +++ b/net/sunrpc/sunrpc_syms.c
> @@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(struct net *net)
> if (err)
> goto err_unixgid;
>
> - rpc_pipefs_init_net(net);
> + err = rpc_pipefs_init_net(net);
> + if (err)
> + goto err_gidcache;
> +
> INIT_LIST_HEAD(&sn->all_clients);
> spin_lock_init(&sn->rpc_client_lock);
> spin_lock_init(&sn->rpcb_clnt_lock);
> return 0;
>
> +err_gidcache:
> + unix_gid_cache_destroy(net);
> err_unixgid:
> ip_map_cache_destroy(net);
> err_ipmap:
> @@ -60,6 +65,7 @@ err_proc:
>
> static __net_exit void sunrpc_exit_net(struct net *net)
> {
> + rpc_pipefs_exit_net(net);
> unix_gid_cache_destroy(net);
> ip_map_cache_destroy(net);
> rpc_proc_exit(net);
Much cleaner.
Reviewed-by: Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 03/11] sunrpc: remove the rpc_clients_block notifier
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
2013-12-01 13:14 ` [PATCH 01/11] sunrpc: allocate pipefs inodes using kmalloc Christoph Hellwig
2013-12-01 13:14 ` [PATCH 02/11] rpc_pipefs: always mount on net namespace initialization Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 15:25 ` Jeff Layton
2013-12-01 13:14 ` [PATCH 04/11] sunrpc: no need to have a lock or superblock for rpc_unlink Christoph Hellwig
` (11 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
Now that a rpc_pipefs mount is always availble there is no need for it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/blocklayout/blocklayout.c | 56 ++-----------------
fs/nfs/cache_lib.c | 6 ++-
fs/nfs/cache_lib.h | 4 --
fs/nfs/dns_resolve.c | 49 +----------------
fs/nfsd/nfs4recover.c | 55 -------------------
fs/nfsd/nfsctl.c | 9 +---
fs/nfsd/nfsd.h | 6 ---
include/linux/sunrpc/rpc_pipe_fs.h | 13 -----
net/sunrpc/clnt.c | 104 ------------------------------------
net/sunrpc/rpc_pipe.c | 48 +----------------
net/sunrpc/sunrpc.h | 2 -
11 files changed, 11 insertions(+), 341 deletions(-)
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index e242bbf..17088b9 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -1315,48 +1315,6 @@ static void nfs4blocklayout_unregister_sb(struct super_block *sb,
rpc_unlink(pipe->dentry);
}
-static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
- void *ptr)
-{
- struct super_block *sb = ptr;
- struct net *net = sb->s_fs_info;
- struct nfs_net *nn = net_generic(net, nfs_net_id);
- struct dentry *dentry;
- int ret = 0;
-
- if (!try_module_get(THIS_MODULE))
- return 0;
-
- if (nn->bl_device_pipe == NULL) {
- module_put(THIS_MODULE);
- return 0;
- }
-
- switch (event) {
- case RPC_PIPEFS_MOUNT:
- dentry = nfs4blocklayout_register_sb(sb, nn->bl_device_pipe);
- if (IS_ERR(dentry)) {
- ret = PTR_ERR(dentry);
- break;
- }
- nn->bl_device_pipe->dentry = dentry;
- break;
- case RPC_PIPEFS_UMOUNT:
- if (nn->bl_device_pipe->dentry)
- nfs4blocklayout_unregister_sb(sb, nn->bl_device_pipe);
- break;
- default:
- ret = -ENOTSUPP;
- break;
- }
- module_put(THIS_MODULE);
- return ret;
-}
-
-static struct notifier_block nfs4blocklayout_block = {
- .notifier_call = rpc_pipefs_event,
-};
-
static struct dentry *nfs4blocklayout_register_net(struct net *net,
struct rpc_pipe *pipe)
{
@@ -1424,20 +1382,13 @@ static int __init nfs4blocklayout_init(void)
ret = pnfs_register_layoutdriver(&blocklayout_type);
if (ret)
goto out;
-
- ret = rpc_pipefs_notifier_register(&nfs4blocklayout_block);
- if (ret)
- goto out_remove;
ret = register_pernet_subsys(&nfs4blocklayout_net_ops);
if (ret)
- goto out_notifier;
-out:
- return ret;
-
-out_notifier:
- rpc_pipefs_notifier_unregister(&nfs4blocklayout_block);
+ goto out_remove;
+ return 0;
out_remove:
pnfs_unregister_layoutdriver(&blocklayout_type);
+out:
return ret;
}
@@ -1446,7 +1397,6 @@ static void __exit nfs4blocklayout_exit(void)
dprintk("%s: NFSv4 Block Layout Driver Unregistering...\n",
__func__);
- rpc_pipefs_notifier_unregister(&nfs4blocklayout_block);
unregister_pernet_subsys(&nfs4blocklayout_net_ops);
pnfs_unregister_layoutdriver(&blocklayout_type);
}
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index 5f7b053..4e9226f 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -112,7 +112,8 @@ int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq)
return 0;
}
-int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd)
+static int nfs_cache_register_sb(struct super_block *sb,
+ struct cache_detail *cd)
{
int ret;
struct dentry *dir;
@@ -139,7 +140,8 @@ int nfs_cache_register_net(struct net *net, struct cache_detail *cd)
return ret;
}
-void nfs_cache_unregister_sb(struct super_block *sb, struct cache_detail *cd)
+static void nfs_cache_unregister_sb(struct super_block *sb,
+ struct cache_detail *cd)
{
if (cd->u.pipefs.dir)
sunrpc_cache_unregister_pipefs(cd);
diff --git a/fs/nfs/cache_lib.h b/fs/nfs/cache_lib.h
index 4116d2c..27280b8 100644
--- a/fs/nfs/cache_lib.h
+++ b/fs/nfs/cache_lib.h
@@ -25,7 +25,3 @@ extern int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq);
extern int nfs_cache_register_net(struct net *net, struct cache_detail *cd);
extern void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd);
-extern int nfs_cache_register_sb(struct super_block *sb,
- struct cache_detail *cd);
-extern void nfs_cache_unregister_sb(struct super_block *sb,
- struct cache_detail *cd);
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index fc0f95e..d9e641a 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -409,60 +409,13 @@ static struct pernet_operations nfs4_dns_resolver_ops = {
.exit = nfs4_dns_net_exit,
};
-static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
- void *ptr)
-{
- struct super_block *sb = ptr;
- struct net *net = sb->s_fs_info;
- struct nfs_net *nn = net_generic(net, nfs_net_id);
- struct cache_detail *cd = nn->nfs_dns_resolve;
- int ret = 0;
-
- if (cd == NULL)
- return 0;
-
- if (!try_module_get(THIS_MODULE))
- return 0;
-
- switch (event) {
- case RPC_PIPEFS_MOUNT:
- ret = nfs_cache_register_sb(sb, cd);
- break;
- case RPC_PIPEFS_UMOUNT:
- nfs_cache_unregister_sb(sb, cd);
- break;
- default:
- ret = -ENOTSUPP;
- break;
- }
- module_put(THIS_MODULE);
- return ret;
-}
-
-static struct notifier_block nfs_dns_resolver_block = {
- .notifier_call = rpc_pipefs_event,
-};
-
int nfs_dns_resolver_init(void)
{
- int err;
-
- err = register_pernet_subsys(&nfs4_dns_resolver_ops);
- if (err < 0)
- goto out;
- err = rpc_pipefs_notifier_register(&nfs_dns_resolver_block);
- if (err < 0)
- goto out1;
- return 0;
-out1:
- unregister_pernet_subsys(&nfs4_dns_resolver_ops);
-out:
- return err;
+ return register_pernet_subsys(&nfs4_dns_resolver_ops);
}
void nfs_dns_resolver_destroy(void)
{
- rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block);
unregister_pernet_subsys(&nfs4_dns_resolver_ops);
}
#endif
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 9c271f4..d9a03e4 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1361,58 +1361,3 @@ nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time)
if (nn->client_tracking_ops)
nn->client_tracking_ops->grace_done(nn, boot_time);
}
-
-static int
-rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
-{
- struct super_block *sb = ptr;
- struct net *net = sb->s_fs_info;
- struct nfsd_net *nn = net_generic(net, nfsd_net_id);
- struct cld_net *cn = nn->cld_net;
- struct dentry *dentry;
- int ret = 0;
-
- if (!try_module_get(THIS_MODULE))
- return 0;
-
- if (!cn) {
- module_put(THIS_MODULE);
- return 0;
- }
-
- switch (event) {
- case RPC_PIPEFS_MOUNT:
- dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
- if (IS_ERR(dentry)) {
- ret = PTR_ERR(dentry);
- break;
- }
- cn->cn_pipe->dentry = dentry;
- break;
- case RPC_PIPEFS_UMOUNT:
- if (cn->cn_pipe->dentry)
- nfsd4_cld_unregister_sb(cn->cn_pipe);
- break;
- default:
- ret = -ENOTSUPP;
- break;
- }
- module_put(THIS_MODULE);
- return ret;
-}
-
-static struct notifier_block nfsd4_cld_block = {
- .notifier_call = rpc_pipefs_event,
-};
-
-int
-register_cld_notifier(void)
-{
- return rpc_pipefs_notifier_register(&nfsd4_cld_block);
-}
-
-void
-unregister_cld_notifier(void)
-{
- rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
-}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 7f55517..14da88f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1165,12 +1165,9 @@ static int __init init_nfsd(void)
int retval;
printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
- retval = register_cld_notifier();
- if (retval)
- return retval;
retval = register_pernet_subsys(&nfsd_net_ops);
if (retval < 0)
- goto out_unregister_notifier;
+ goto out;
retval = nfsd4_init_slabs();
if (retval)
goto out_unregister_pernet;
@@ -1203,8 +1200,7 @@ out_free_slabs:
nfsd4_free_slabs();
out_unregister_pernet:
unregister_pernet_subsys(&nfsd_net_ops);
-out_unregister_notifier:
- unregister_cld_notifier();
+out:
return retval;
}
@@ -1219,7 +1215,6 @@ static void __exit exit_nfsd(void)
nfsd_fault_inject_cleanup();
unregister_filesystem(&nfsd_fs_type);
unregister_pernet_subsys(&nfsd_net_ops);
- unregister_cld_notifier();
}
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 30f34ab..10d35f1 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -384,17 +384,11 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
NFSD_WRITEABLE_ATTRS_WORD2
extern int nfsd4_is_junction(struct dentry *dentry);
-extern int register_cld_notifier(void);
-extern void unregister_cld_notifier(void);
#else /* CONFIG_NFSD_V4 */
static inline int nfsd4_is_junction(struct dentry *dentry)
{
return 0;
}
-
-#define register_cld_notifier() 0
-#define unregister_cld_notifier() do { } while(0)
-
#endif /* CONFIG_NFSD_V4 */
#endif /* LINUX_NFSD_NFSD_H */
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index d5807e7..b9f3805 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -69,19 +69,6 @@ RPC_I(struct inode *inode)
return container_of(inode, struct rpc_inode, vfs_inode);
}
-enum {
- SUNRPC_PIPEFS_NFS_PRIO,
- SUNRPC_PIPEFS_RPC_PRIO,
-};
-
-extern int rpc_pipefs_notifier_register(struct notifier_block *);
-extern void rpc_pipefs_notifier_unregister(struct notifier_block *);
-
-enum {
- RPC_PIPEFS_MOUNT,
- RPC_PIPEFS_UMOUNT,
-};
-
extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
const unsigned char *dir_name);
extern struct super_block *rpc_get_sb_net(const struct net *net);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f09b7db..ec059c2 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -160,110 +160,6 @@ rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
return 0;
}
-static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
-{
- if (clnt->cl_program->pipe_dir_name == NULL)
- return 1;
-
- switch (event) {
- case RPC_PIPEFS_MOUNT:
- if (clnt->cl_pipedir_objects.pdh_dentry != NULL)
- return 1;
- if (atomic_read(&clnt->cl_count) == 0)
- return 1;
- break;
- case RPC_PIPEFS_UMOUNT:
- if (clnt->cl_pipedir_objects.pdh_dentry == NULL)
- return 1;
- break;
- }
- return 0;
-}
-
-static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
- struct super_block *sb)
-{
- struct dentry *dentry;
- int err = 0;
-
- switch (event) {
- case RPC_PIPEFS_MOUNT:
- dentry = rpc_setup_pipedir_sb(sb, clnt);
- if (!dentry)
- return -ENOENT;
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- break;
- case RPC_PIPEFS_UMOUNT:
- __rpc_clnt_remove_pipedir(clnt);
- break;
- default:
- printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event);
- return -ENOTSUPP;
- }
- return err;
-}
-
-static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
- struct super_block *sb)
-{
- int error = 0;
-
- for (;; clnt = clnt->cl_parent) {
- if (!rpc_clnt_skip_event(clnt, event))
- error = __rpc_clnt_handle_event(clnt, event, sb);
- if (error || clnt == clnt->cl_parent)
- break;
- }
- return error;
-}
-
-static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
-{
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- struct rpc_clnt *clnt;
-
- spin_lock(&sn->rpc_client_lock);
- list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
- if (rpc_clnt_skip_event(clnt, event))
- continue;
- spin_unlock(&sn->rpc_client_lock);
- return clnt;
- }
- spin_unlock(&sn->rpc_client_lock);
- return NULL;
-}
-
-static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
- void *ptr)
-{
- struct super_block *sb = ptr;
- struct rpc_clnt *clnt;
- int error = 0;
-
- while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) {
- error = __rpc_pipefs_event(clnt, event, sb);
- if (error)
- break;
- }
- return error;
-}
-
-static struct notifier_block rpc_clients_block = {
- .notifier_call = rpc_pipefs_event,
- .priority = SUNRPC_PIPEFS_RPC_PRIO,
-};
-
-int rpc_clients_notifier_register(void)
-{
- return rpc_pipefs_notifier_register(&rpc_clients_block);
-}
-
-void rpc_clients_notifier_unregister(void)
-{
- return rpc_pipefs_notifier_unregister(&rpc_clients_block);
-}
-
static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
struct rpc_xprt *xprt,
const struct rpc_timeout *timeout)
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index e654b65..73e7963 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -42,20 +42,6 @@ static struct file_system_type rpc_pipe_fs_type;
#define RPC_UPCALL_TIMEOUT (30*HZ)
-static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
-
-int rpc_pipefs_notifier_register(struct notifier_block *nb)
-{
- return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register);
-
-void rpc_pipefs_notifier_unregister(struct notifier_block *nb)
-{
- blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister);
-
static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head,
void (*destroy_msg)(struct rpc_pipe_msg *), int err)
{
@@ -1258,7 +1244,6 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
struct dentry *root;
struct net *net = data;
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- int err;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -1277,23 +1262,9 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
net, NET_NAME(net));
mutex_lock(&sn->pipefs_sb_lock);
sn->pipefs_sb = sb;
- err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
- RPC_PIPEFS_MOUNT,
- sb);
- if (err)
- goto err_depopulate;
sb->s_fs_info = get_net(net);
mutex_unlock(&sn->pipefs_sb_lock);
return 0;
-
-err_depopulate:
- blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
- RPC_PIPEFS_UMOUNT,
- sb);
- sn->pipefs_sb = NULL;
- __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
- mutex_unlock(&sn->pipefs_sb_lock);
- return err;
}
static struct dentry *
@@ -1316,9 +1287,6 @@ static void rpc_kill_sb(struct super_block *sb)
sn->pipefs_sb = NULL;
dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n",
net, NET_NAME(net));
- blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
- RPC_PIPEFS_UMOUNT,
- sb);
mutex_unlock(&sn->pipefs_sb_lock);
put_net(net);
out:
@@ -1336,24 +1304,10 @@ MODULE_ALIAS("rpc_pipefs");
int register_rpc_pipefs(void)
{
- int err;
-
- err = rpc_clients_notifier_register();
- if (err)
- goto err_notifier;
- err = register_filesystem(&rpc_pipe_fs_type);
- if (err)
- goto err_register;
- return 0;
-
-err_register:
- rpc_clients_notifier_unregister();
-err_notifier:
- return err;
+ return register_filesystem(&rpc_pipe_fs_type);
}
void unregister_rpc_pipefs(void)
{
- rpc_clients_notifier_unregister();
unregister_filesystem(&rpc_pipe_fs_type);
}
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
index 14c9f6d..90c292e 100644
--- a/net/sunrpc/sunrpc.h
+++ b/net/sunrpc/sunrpc.h
@@ -47,7 +47,5 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr,
struct page *headpage, unsigned long headoffset,
struct page *tailpage, unsigned long tailoffset);
-int rpc_clients_notifier_register(void);
-void rpc_clients_notifier_unregister(void);
#endif /* _NET_SUNRPC_SUNRPC_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 03/11] sunrpc: remove the rpc_clients_block notifier
2013-12-01 13:14 ` [PATCH 03/11] sunrpc: remove the rpc_clients_block notifier Christoph Hellwig
@ 2013-12-01 15:25 ` Jeff Layton
0 siblings, 0 replies; 36+ messages in thread
From: Jeff Layton @ 2013-12-01 15:25 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-nfs, viro, linux-fsdevel
On Sun, 01 Dec 2013 05:14:44 -0800
Christoph Hellwig <hch@infradead.org> wrote:
> Now that a rpc_pipefs mount is always availble there is no need for it.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/nfs/blocklayout/blocklayout.c | 56 ++-----------------
> fs/nfs/cache_lib.c | 6 ++-
> fs/nfs/cache_lib.h | 4 --
> fs/nfs/dns_resolve.c | 49 +----------------
> fs/nfsd/nfs4recover.c | 55 -------------------
> fs/nfsd/nfsctl.c | 9 +---
> fs/nfsd/nfsd.h | 6 ---
> include/linux/sunrpc/rpc_pipe_fs.h | 13 -----
> net/sunrpc/clnt.c | 104 ------------------------------------
> net/sunrpc/rpc_pipe.c | 48 +----------------
> net/sunrpc/sunrpc.h | 2 -
> 11 files changed, 11 insertions(+), 341 deletions(-)
>
> diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
> index e242bbf..17088b9 100644
> --- a/fs/nfs/blocklayout/blocklayout.c
> +++ b/fs/nfs/blocklayout/blocklayout.c
> @@ -1315,48 +1315,6 @@ static void nfs4blocklayout_unregister_sb(struct super_block *sb,
> rpc_unlink(pipe->dentry);
> }
>
> -static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
> - void *ptr)
> -{
> - struct super_block *sb = ptr;
> - struct net *net = sb->s_fs_info;
> - struct nfs_net *nn = net_generic(net, nfs_net_id);
> - struct dentry *dentry;
> - int ret = 0;
> -
> - if (!try_module_get(THIS_MODULE))
> - return 0;
> -
> - if (nn->bl_device_pipe == NULL) {
> - module_put(THIS_MODULE);
> - return 0;
> - }
> -
> - switch (event) {
> - case RPC_PIPEFS_MOUNT:
> - dentry = nfs4blocklayout_register_sb(sb, nn->bl_device_pipe);
> - if (IS_ERR(dentry)) {
> - ret = PTR_ERR(dentry);
> - break;
> - }
> - nn->bl_device_pipe->dentry = dentry;
> - break;
> - case RPC_PIPEFS_UMOUNT:
> - if (nn->bl_device_pipe->dentry)
> - nfs4blocklayout_unregister_sb(sb, nn->bl_device_pipe);
> - break;
> - default:
> - ret = -ENOTSUPP;
> - break;
> - }
> - module_put(THIS_MODULE);
> - return ret;
> -}
> -
> -static struct notifier_block nfs4blocklayout_block = {
> - .notifier_call = rpc_pipefs_event,
> -};
> -
> static struct dentry *nfs4blocklayout_register_net(struct net *net,
> struct rpc_pipe *pipe)
> {
> @@ -1424,20 +1382,13 @@ static int __init nfs4blocklayout_init(void)
> ret = pnfs_register_layoutdriver(&blocklayout_type);
> if (ret)
> goto out;
> -
> - ret = rpc_pipefs_notifier_register(&nfs4blocklayout_block);
> - if (ret)
> - goto out_remove;
> ret = register_pernet_subsys(&nfs4blocklayout_net_ops);
> if (ret)
> - goto out_notifier;
> -out:
> - return ret;
> -
> -out_notifier:
> - rpc_pipefs_notifier_unregister(&nfs4blocklayout_block);
> + goto out_remove;
> + return 0;
> out_remove:
> pnfs_unregister_layoutdriver(&blocklayout_type);
> +out:
> return ret;
> }
>
> @@ -1446,7 +1397,6 @@ static void __exit nfs4blocklayout_exit(void)
> dprintk("%s: NFSv4 Block Layout Driver Unregistering...\n",
> __func__);
>
> - rpc_pipefs_notifier_unregister(&nfs4blocklayout_block);
> unregister_pernet_subsys(&nfs4blocklayout_net_ops);
> pnfs_unregister_layoutdriver(&blocklayout_type);
> }
> diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
> index 5f7b053..4e9226f 100644
> --- a/fs/nfs/cache_lib.c
> +++ b/fs/nfs/cache_lib.c
> @@ -112,7 +112,8 @@ int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq)
> return 0;
> }
>
> -int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd)
> +static int nfs_cache_register_sb(struct super_block *sb,
> + struct cache_detail *cd)
> {
> int ret;
> struct dentry *dir;
> @@ -139,7 +140,8 @@ int nfs_cache_register_net(struct net *net, struct cache_detail *cd)
> return ret;
> }
>
> -void nfs_cache_unregister_sb(struct super_block *sb, struct cache_detail *cd)
> +static void nfs_cache_unregister_sb(struct super_block *sb,
> + struct cache_detail *cd)
> {
> if (cd->u.pipefs.dir)
> sunrpc_cache_unregister_pipefs(cd);
> diff --git a/fs/nfs/cache_lib.h b/fs/nfs/cache_lib.h
> index 4116d2c..27280b8 100644
> --- a/fs/nfs/cache_lib.h
> +++ b/fs/nfs/cache_lib.h
> @@ -25,7 +25,3 @@ extern int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq);
>
> extern int nfs_cache_register_net(struct net *net, struct cache_detail *cd);
> extern void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd);
> -extern int nfs_cache_register_sb(struct super_block *sb,
> - struct cache_detail *cd);
> -extern void nfs_cache_unregister_sb(struct super_block *sb,
> - struct cache_detail *cd);
> diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
> index fc0f95e..d9e641a 100644
> --- a/fs/nfs/dns_resolve.c
> +++ b/fs/nfs/dns_resolve.c
> @@ -409,60 +409,13 @@ static struct pernet_operations nfs4_dns_resolver_ops = {
> .exit = nfs4_dns_net_exit,
> };
>
> -static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
> - void *ptr)
> -{
> - struct super_block *sb = ptr;
> - struct net *net = sb->s_fs_info;
> - struct nfs_net *nn = net_generic(net, nfs_net_id);
> - struct cache_detail *cd = nn->nfs_dns_resolve;
> - int ret = 0;
> -
> - if (cd == NULL)
> - return 0;
> -
> - if (!try_module_get(THIS_MODULE))
> - return 0;
> -
> - switch (event) {
> - case RPC_PIPEFS_MOUNT:
> - ret = nfs_cache_register_sb(sb, cd);
> - break;
> - case RPC_PIPEFS_UMOUNT:
> - nfs_cache_unregister_sb(sb, cd);
> - break;
> - default:
> - ret = -ENOTSUPP;
> - break;
> - }
> - module_put(THIS_MODULE);
> - return ret;
> -}
> -
> -static struct notifier_block nfs_dns_resolver_block = {
> - .notifier_call = rpc_pipefs_event,
> -};
> -
> int nfs_dns_resolver_init(void)
> {
> - int err;
> -
> - err = register_pernet_subsys(&nfs4_dns_resolver_ops);
> - if (err < 0)
> - goto out;
> - err = rpc_pipefs_notifier_register(&nfs_dns_resolver_block);
> - if (err < 0)
> - goto out1;
> - return 0;
> -out1:
> - unregister_pernet_subsys(&nfs4_dns_resolver_ops);
> -out:
> - return err;
> + return register_pernet_subsys(&nfs4_dns_resolver_ops);
> }
>
> void nfs_dns_resolver_destroy(void)
> {
> - rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block);
> unregister_pernet_subsys(&nfs4_dns_resolver_ops);
> }
> #endif
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 9c271f4..d9a03e4 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -1361,58 +1361,3 @@ nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time)
> if (nn->client_tracking_ops)
> nn->client_tracking_ops->grace_done(nn, boot_time);
> }
> -
> -static int
> -rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
> -{
> - struct super_block *sb = ptr;
> - struct net *net = sb->s_fs_info;
> - struct nfsd_net *nn = net_generic(net, nfsd_net_id);
> - struct cld_net *cn = nn->cld_net;
> - struct dentry *dentry;
> - int ret = 0;
> -
> - if (!try_module_get(THIS_MODULE))
> - return 0;
> -
> - if (!cn) {
> - module_put(THIS_MODULE);
> - return 0;
> - }
> -
> - switch (event) {
> - case RPC_PIPEFS_MOUNT:
> - dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
> - if (IS_ERR(dentry)) {
> - ret = PTR_ERR(dentry);
> - break;
> - }
> - cn->cn_pipe->dentry = dentry;
> - break;
> - case RPC_PIPEFS_UMOUNT:
> - if (cn->cn_pipe->dentry)
> - nfsd4_cld_unregister_sb(cn->cn_pipe);
> - break;
> - default:
> - ret = -ENOTSUPP;
> - break;
> - }
> - module_put(THIS_MODULE);
> - return ret;
> -}
> -
> -static struct notifier_block nfsd4_cld_block = {
> - .notifier_call = rpc_pipefs_event,
> -};
> -
> -int
> -register_cld_notifier(void)
> -{
> - return rpc_pipefs_notifier_register(&nfsd4_cld_block);
> -}
> -
> -void
> -unregister_cld_notifier(void)
> -{
> - rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
> -}
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index 7f55517..14da88f 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -1165,12 +1165,9 @@ static int __init init_nfsd(void)
> int retval;
> printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
>
> - retval = register_cld_notifier();
> - if (retval)
> - return retval;
> retval = register_pernet_subsys(&nfsd_net_ops);
> if (retval < 0)
> - goto out_unregister_notifier;
> + goto out;
> retval = nfsd4_init_slabs();
> if (retval)
> goto out_unregister_pernet;
> @@ -1203,8 +1200,7 @@ out_free_slabs:
> nfsd4_free_slabs();
> out_unregister_pernet:
> unregister_pernet_subsys(&nfsd_net_ops);
> -out_unregister_notifier:
> - unregister_cld_notifier();
> +out:
> return retval;
> }
>
> @@ -1219,7 +1215,6 @@ static void __exit exit_nfsd(void)
> nfsd_fault_inject_cleanup();
> unregister_filesystem(&nfsd_fs_type);
> unregister_pernet_subsys(&nfsd_net_ops);
> - unregister_cld_notifier();
> }
>
> MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
> diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
> index 30f34ab..10d35f1 100644
> --- a/fs/nfsd/nfsd.h
> +++ b/fs/nfsd/nfsd.h
> @@ -384,17 +384,11 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
> NFSD_WRITEABLE_ATTRS_WORD2
>
> extern int nfsd4_is_junction(struct dentry *dentry);
> -extern int register_cld_notifier(void);
> -extern void unregister_cld_notifier(void);
> #else /* CONFIG_NFSD_V4 */
> static inline int nfsd4_is_junction(struct dentry *dentry)
> {
> return 0;
> }
> -
> -#define register_cld_notifier() 0
> -#define unregister_cld_notifier() do { } while(0)
> -
> #endif /* CONFIG_NFSD_V4 */
>
> #endif /* LINUX_NFSD_NFSD_H */
> diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
> index d5807e7..b9f3805 100644
> --- a/include/linux/sunrpc/rpc_pipe_fs.h
> +++ b/include/linux/sunrpc/rpc_pipe_fs.h
> @@ -69,19 +69,6 @@ RPC_I(struct inode *inode)
> return container_of(inode, struct rpc_inode, vfs_inode);
> }
>
> -enum {
> - SUNRPC_PIPEFS_NFS_PRIO,
> - SUNRPC_PIPEFS_RPC_PRIO,
> -};
> -
> -extern int rpc_pipefs_notifier_register(struct notifier_block *);
> -extern void rpc_pipefs_notifier_unregister(struct notifier_block *);
> -
> -enum {
> - RPC_PIPEFS_MOUNT,
> - RPC_PIPEFS_UMOUNT,
> -};
> -
> extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
> const unsigned char *dir_name);
> extern struct super_block *rpc_get_sb_net(const struct net *net);
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index f09b7db..ec059c2 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -160,110 +160,6 @@ rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
> return 0;
> }
>
> -static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
> -{
> - if (clnt->cl_program->pipe_dir_name == NULL)
> - return 1;
> -
> - switch (event) {
> - case RPC_PIPEFS_MOUNT:
> - if (clnt->cl_pipedir_objects.pdh_dentry != NULL)
> - return 1;
> - if (atomic_read(&clnt->cl_count) == 0)
> - return 1;
> - break;
> - case RPC_PIPEFS_UMOUNT:
> - if (clnt->cl_pipedir_objects.pdh_dentry == NULL)
> - return 1;
> - break;
> - }
> - return 0;
> -}
> -
> -static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
> - struct super_block *sb)
> -{
> - struct dentry *dentry;
> - int err = 0;
> -
> - switch (event) {
> - case RPC_PIPEFS_MOUNT:
> - dentry = rpc_setup_pipedir_sb(sb, clnt);
> - if (!dentry)
> - return -ENOENT;
> - if (IS_ERR(dentry))
> - return PTR_ERR(dentry);
> - break;
> - case RPC_PIPEFS_UMOUNT:
> - __rpc_clnt_remove_pipedir(clnt);
> - break;
> - default:
> - printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event);
> - return -ENOTSUPP;
> - }
> - return err;
> -}
> -
> -static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
> - struct super_block *sb)
> -{
> - int error = 0;
> -
> - for (;; clnt = clnt->cl_parent) {
> - if (!rpc_clnt_skip_event(clnt, event))
> - error = __rpc_clnt_handle_event(clnt, event, sb);
> - if (error || clnt == clnt->cl_parent)
> - break;
> - }
> - return error;
> -}
> -
> -static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
> -{
> - struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
> - struct rpc_clnt *clnt;
> -
> - spin_lock(&sn->rpc_client_lock);
> - list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
> - if (rpc_clnt_skip_event(clnt, event))
> - continue;
> - spin_unlock(&sn->rpc_client_lock);
> - return clnt;
> - }
> - spin_unlock(&sn->rpc_client_lock);
> - return NULL;
> -}
> -
> -static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
> - void *ptr)
> -{
> - struct super_block *sb = ptr;
> - struct rpc_clnt *clnt;
> - int error = 0;
> -
> - while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) {
> - error = __rpc_pipefs_event(clnt, event, sb);
> - if (error)
> - break;
> - }
> - return error;
> -}
> -
> -static struct notifier_block rpc_clients_block = {
> - .notifier_call = rpc_pipefs_event,
> - .priority = SUNRPC_PIPEFS_RPC_PRIO,
> -};
> -
> -int rpc_clients_notifier_register(void)
> -{
> - return rpc_pipefs_notifier_register(&rpc_clients_block);
> -}
> -
> -void rpc_clients_notifier_unregister(void)
> -{
> - return rpc_pipefs_notifier_unregister(&rpc_clients_block);
> -}
> -
> static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
> struct rpc_xprt *xprt,
> const struct rpc_timeout *timeout)
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index e654b65..73e7963 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -42,20 +42,6 @@ static struct file_system_type rpc_pipe_fs_type;
>
> #define RPC_UPCALL_TIMEOUT (30*HZ)
>
> -static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
> -
> -int rpc_pipefs_notifier_register(struct notifier_block *nb)
> -{
> - return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb);
> -}
> -EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register);
> -
> -void rpc_pipefs_notifier_unregister(struct notifier_block *nb)
> -{
> - blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb);
> -}
> -EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister);
> -
> static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head,
> void (*destroy_msg)(struct rpc_pipe_msg *), int err)
> {
> @@ -1258,7 +1244,6 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
> struct dentry *root;
> struct net *net = data;
> struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
> - int err;
>
> sb->s_blocksize = PAGE_CACHE_SIZE;
> sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
> @@ -1277,23 +1262,9 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
> net, NET_NAME(net));
> mutex_lock(&sn->pipefs_sb_lock);
> sn->pipefs_sb = sb;
> - err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
> - RPC_PIPEFS_MOUNT,
> - sb);
> - if (err)
> - goto err_depopulate;
> sb->s_fs_info = get_net(net);
> mutex_unlock(&sn->pipefs_sb_lock);
> return 0;
> -
> -err_depopulate:
> - blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
> - RPC_PIPEFS_UMOUNT,
> - sb);
> - sn->pipefs_sb = NULL;
> - __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
> - mutex_unlock(&sn->pipefs_sb_lock);
> - return err;
> }
>
> static struct dentry *
> @@ -1316,9 +1287,6 @@ static void rpc_kill_sb(struct super_block *sb)
> sn->pipefs_sb = NULL;
> dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n",
> net, NET_NAME(net));
> - blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
> - RPC_PIPEFS_UMOUNT,
> - sb);
> mutex_unlock(&sn->pipefs_sb_lock);
> put_net(net);
> out:
> @@ -1336,24 +1304,10 @@ MODULE_ALIAS("rpc_pipefs");
>
> int register_rpc_pipefs(void)
> {
> - int err;
> -
> - err = rpc_clients_notifier_register();
> - if (err)
> - goto err_notifier;
> - err = register_filesystem(&rpc_pipe_fs_type);
> - if (err)
> - goto err_register;
> - return 0;
> -
> -err_register:
> - rpc_clients_notifier_unregister();
> -err_notifier:
> - return err;
> + return register_filesystem(&rpc_pipe_fs_type);
> }
>
> void unregister_rpc_pipefs(void)
> {
> - rpc_clients_notifier_unregister();
> unregister_filesystem(&rpc_pipe_fs_type);
> }
> diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
> index 14c9f6d..90c292e 100644
> --- a/net/sunrpc/sunrpc.h
> +++ b/net/sunrpc/sunrpc.h
> @@ -47,7 +47,5 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr,
> struct page *headpage, unsigned long headoffset,
> struct page *tailpage, unsigned long tailoffset);
>
> -int rpc_clients_notifier_register(void);
> -void rpc_clients_notifier_unregister(void);
> #endif /* _NET_SUNRPC_SUNRPC_H */
>
Good riddance... ;)
Reviewed-by: Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 04/11] sunrpc: no need to have a lock or superblock for rpc_unlink
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (2 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 03/11] sunrpc: remove the rpc_clients_block notifier Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 05/11] sunprc: add sensible pipe creation and removal helpers Christoph Hellwig
` (10 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
It translates to simple dcache operations that have their own
synchronization.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/blocklayout/blocklayout.c | 22 ++--------------------
fs/nfsd/nfs4recover.c | 22 ++--------------------
2 files changed, 4 insertions(+), 40 deletions(-)
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 17088b9..d5950aa 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -1308,13 +1308,6 @@ static struct dentry *nfs4blocklayout_register_sb(struct super_block *sb,
return dentry;
}
-static void nfs4blocklayout_unregister_sb(struct super_block *sb,
- struct rpc_pipe *pipe)
-{
- if (pipe->dentry)
- rpc_unlink(pipe->dentry);
-}
-
static struct dentry *nfs4blocklayout_register_net(struct net *net,
struct rpc_pipe *pipe)
{
@@ -1329,18 +1322,6 @@ static struct dentry *nfs4blocklayout_register_net(struct net *net,
return dentry;
}
-static void nfs4blocklayout_unregister_net(struct net *net,
- struct rpc_pipe *pipe)
-{
- struct super_block *pipefs_sb;
-
- pipefs_sb = rpc_get_sb_net(net);
- if (pipefs_sb) {
- nfs4blocklayout_unregister_sb(pipefs_sb, pipe);
- rpc_put_sb_net(net);
- }
-}
-
static int nfs4blocklayout_net_init(struct net *net)
{
struct nfs_net *nn = net_generic(net, nfs_net_id);
@@ -1363,7 +1344,8 @@ static void nfs4blocklayout_net_exit(struct net *net)
{
struct nfs_net *nn = net_generic(net, nfs_net_id);
- nfs4blocklayout_unregister_net(net, nn->bl_device_pipe);
+ if (nn->bl_device_pipe->dentry)
+ rpc_unlink(nn->bl_device_pipe->dentry);
rpc_destroy_pipe_data(nn->bl_device_pipe);
nn->bl_device_pipe = NULL;
}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index d9a03e4..f4fe7d6 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -774,13 +774,6 @@ nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
return dentry;
}
-static void
-nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
-{
- if (pipe->dentry)
- rpc_unlink(pipe->dentry);
-}
-
static struct dentry *
nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
{
@@ -795,18 +788,6 @@ nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
return dentry;
}
-static void
-nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
-{
- struct super_block *sb;
-
- sb = rpc_get_sb_net(net);
- if (sb) {
- nfsd4_cld_unregister_sb(pipe);
- rpc_put_sb_net(net);
- }
-}
-
/* Initialize rpc_pipefs pipe for communication with client tracking daemon */
static int
nfsd4_init_cld_pipe(struct net *net)
@@ -858,7 +839,8 @@ nfsd4_remove_cld_pipe(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct cld_net *cn = nn->cld_net;
- nfsd4_cld_unregister_net(net, cn->cn_pipe);
+ if (cn->cn_pipe->dentry)
+ rpc_unlink(cn->cn_pipe->dentry);
rpc_destroy_pipe_data(cn->cn_pipe);
kfree(nn->cld_net);
nn->cld_net = NULL;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 05/11] sunprc: add sensible pipe creation and removal helpers
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (3 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 04/11] sunrpc: no need to have a lock or superblock for rpc_unlink Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 06/11] sunrpc: clean up rpc_pipefs client dir creation Christoph Hellwig
` (9 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
Add rpc_mkpipe, rpc_mkpipe_clnt and rpc_rmpipe that allow creating
and removing pipes without having to write enormous amounts of
boilerplate code. Use them in the trivially to convert consumers.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/blocklayout/blocklayout.c | 43 +++-----------------------
fs/nfsd/nfs4recover.c | 60 +++++++-----------------------------
include/linux/sunrpc/rpc_pipe_fs.h | 5 +++
net/sunrpc/rpc_pipe.c | 57 ++++++++++++++++++++++++++++++++++
4 files changed, 77 insertions(+), 88 deletions(-)
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index d5950aa..c879a39 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -1295,48 +1295,16 @@ static const struct rpc_pipe_ops bl_upcall_ops = {
.destroy_msg = bl_pipe_destroy_msg,
};
-static struct dentry *nfs4blocklayout_register_sb(struct super_block *sb,
- struct rpc_pipe *pipe)
-{
- struct dentry *dir, *dentry;
-
- dir = rpc_d_lookup_sb(sb, NFS_PIPE_DIRNAME);
- if (dir == NULL)
- return ERR_PTR(-ENOENT);
- dentry = rpc_mkpipe_dentry(dir, "blocklayout", NULL, pipe);
- dput(dir);
- return dentry;
-}
-
-static struct dentry *nfs4blocklayout_register_net(struct net *net,
- struct rpc_pipe *pipe)
-{
- struct super_block *pipefs_sb;
- struct dentry *dentry;
-
- pipefs_sb = rpc_get_sb_net(net);
- if (!pipefs_sb)
- return NULL;
- dentry = nfs4blocklayout_register_sb(pipefs_sb, pipe);
- rpc_put_sb_net(net);
- return dentry;
-}
-
static int nfs4blocklayout_net_init(struct net *net)
{
struct nfs_net *nn = net_generic(net, nfs_net_id);
- struct dentry *dentry;
init_waitqueue_head(&nn->bl_wq);
- nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0);
+
+ nn->bl_device_pipe = rpc_mkpipe(net, NFS_PIPE_DIRNAME, "blocklayout",
+ &bl_upcall_ops, NULL, 0);
if (IS_ERR(nn->bl_device_pipe))
return PTR_ERR(nn->bl_device_pipe);
- dentry = nfs4blocklayout_register_net(net, nn->bl_device_pipe);
- if (IS_ERR(dentry)) {
- rpc_destroy_pipe_data(nn->bl_device_pipe);
- return PTR_ERR(dentry);
- }
- nn->bl_device_pipe->dentry = dentry;
return 0;
}
@@ -1344,10 +1312,7 @@ static void nfs4blocklayout_net_exit(struct net *net)
{
struct nfs_net *nn = net_generic(net, nfs_net_id);
- if (nn->bl_device_pipe->dentry)
- rpc_unlink(nn->bl_device_pipe->dentry);
- rpc_destroy_pipe_data(nn->bl_device_pipe);
- nn->bl_device_pipe = NULL;
+ rpc_rmpipe(nn->bl_device_pipe);
}
static struct pernet_operations nfs4blocklayout_net_ops = {
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index f4fe7d6..cda82b7 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -761,73 +761,37 @@ static const struct rpc_pipe_ops cld_upcall_ops = {
.destroy_msg = cld_pipe_destroy_msg,
};
-static struct dentry *
-nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
-{
- struct dentry *dir, *dentry;
-
- dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
- if (dir == NULL)
- return ERR_PTR(-ENOENT);
- dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
- dput(dir);
- return dentry;
-}
-
-static struct dentry *
-nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
-{
- struct super_block *sb;
- struct dentry *dentry;
-
- sb = rpc_get_sb_net(net);
- if (!sb)
- return NULL;
- dentry = nfsd4_cld_register_sb(sb, pipe);
- rpc_put_sb_net(net);
- return dentry;
-}
-
/* Initialize rpc_pipefs pipe for communication with client tracking daemon */
static int
nfsd4_init_cld_pipe(struct net *net)
{
- int ret;
- struct dentry *dentry;
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct cld_net *cn;
+ int ret = -ENOMEM;
if (nn->cld_net)
return 0;
cn = kzalloc(sizeof(*cn), GFP_KERNEL);
- if (!cn) {
- ret = -ENOMEM;
+ if (!cn)
goto err;
- }
-
- cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
- if (IS_ERR(cn->cn_pipe)) {
- ret = PTR_ERR(cn->cn_pipe);
- goto err;
- }
spin_lock_init(&cn->cn_lock);
INIT_LIST_HEAD(&cn->cn_list);
- dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
- if (IS_ERR(dentry)) {
- ret = PTR_ERR(dentry);
- goto err_destroy_data;
+ cn->cn_pipe = rpc_mkpipe(net, NFSD_PIPE_DIR, NFSD_CLD_PIPE,
+ &cld_upcall_ops, NULL,
+ RPC_PIPE_WAIT_FOR_OPEN);
+ if (IS_ERR(cn->cn_pipe)) {
+ ret = PTR_ERR(cn->cn_pipe);
+ goto err_kfree;
}
- cn->cn_pipe->dentry = dentry;
nn->cld_net = cn;
return 0;
-err_destroy_data:
- rpc_destroy_pipe_data(cn->cn_pipe);
-err:
+err_kfree:
kfree(cn);
+err:
printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
ret);
return ret;
@@ -839,9 +803,7 @@ nfsd4_remove_cld_pipe(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct cld_net *cn = nn->cld_net;
- if (cn->cn_pipe->dentry)
- rpc_unlink(cn->cn_pipe->dentry);
- rpc_destroy_pipe_data(cn->cn_pipe);
+ rpc_rmpipe(cn->cn_pipe);
kfree(nn->cld_net);
nn->cld_net = NULL;
}
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index b9f3805..0e1cfb7 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -112,6 +112,11 @@ struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags);
void rpc_destroy_pipe_data(struct rpc_pipe *pipe);
extern struct dentry *rpc_mkpipe_dentry(struct dentry *, const char *, void *,
struct rpc_pipe *);
+extern struct rpc_pipe *rpc_mkpipe(struct net *, const char *, const char *,
+ const struct rpc_pipe_ops *, void *private, int);
+extern struct rpc_pipe *rpc_mkpipe_clnt(struct rpc_clnt *, const char *,
+ const struct rpc_pipe_ops *, void *, int);
+extern void rpc_rmpipe(struct rpc_pipe *);
extern int rpc_unlink(struct dentry *);
extern int register_rpc_pipefs(void);
extern void unregister_rpc_pipefs(void);
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 73e7963..dea4008 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -831,6 +831,55 @@ out_err:
}
EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
+struct rpc_pipe *
+__rpc_mkpipe(struct dentry *dir, const char *name,
+ const struct rpc_pipe_ops *ops, void *private, int flags)
+{
+ struct rpc_pipe *pipe;
+ int err = -ENOENT;
+
+ pipe = rpc_mkpipe_data(ops, flags);
+ if (IS_ERR(pipe))
+ return pipe;
+
+ pipe->dentry = rpc_mkpipe_dentry(dir, name, private, pipe);
+ if (IS_ERR(pipe->dentry)) {
+ err = PTR_ERR(pipe->dentry);
+ goto out_destroy_pipe;
+ }
+ return pipe;
+out_destroy_pipe:
+ rpc_destroy_pipe_data(pipe);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(__rpc_mkpipe);
+
+struct rpc_pipe *
+rpc_mkpipe(struct net *net, const char *dirname, const char *name,
+ const struct rpc_pipe_ops *ops, void *private, int flags)
+{
+ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+ struct rpc_pipe *pipe;
+ struct dentry *dir;
+
+ dir = rpc_d_lookup_sb(sn->pipefs_sb, dirname);
+ if (dir == NULL)
+ return ERR_PTR(-ENOENT);
+ pipe = __rpc_mkpipe(dir, name, ops, private, flags);
+ dput(dir);
+ return pipe;
+}
+EXPORT_SYMBOL_GPL(rpc_mkpipe);
+
+struct rpc_pipe *
+rpc_mkpipe_clnt(struct rpc_clnt *clnt, const char *name,
+ const struct rpc_pipe_ops *ops, void *private, int flags)
+{
+ return __rpc_mkpipe(clnt->cl_pipedir_objects.pdh_dentry, name,
+ ops, private, flags);
+}
+EXPORT_SYMBOL_GPL(rpc_mkpipe_clnt);
+
/**
* rpc_unlink - remove a pipe
* @dentry: dentry for the pipe, as returned from rpc_mkpipe
@@ -856,6 +905,14 @@ rpc_unlink(struct dentry *dentry)
}
EXPORT_SYMBOL_GPL(rpc_unlink);
+void rpc_rmpipe(struct rpc_pipe *pipe)
+{
+ if (pipe->dentry)
+ rpc_unlink(pipe->dentry);
+ rpc_destroy_pipe_data(pipe);
+}
+EXPORT_SYMBOL_GPL(rpc_rmpipe);
+
/**
* rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head
* @pdh: pointer to struct rpc_pipe_dir_head
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 06/11] sunrpc: clean up rpc_pipefs client dir creation
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (4 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 05/11] sunprc: add sensible pipe creation and removal helpers Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 07/11] sunrpc: make rpc_mkdir_populate net-namespace aware Christoph Hellwig
` (8 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
Remove redundant wrappers, take it out of clnt.c and into rpc_pipe.c.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/sunrpc/rpc_pipe_fs.h | 2 +-
net/sunrpc/clnt.c | 78 +++---------------------------------
net/sunrpc/rpc_pipe.c | 54 +++++++++++++++++--------
3 files changed, 44 insertions(+), 90 deletions(-)
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 0e1cfb7..fefbfa3 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -79,7 +79,7 @@ extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
struct rpc_clnt;
-extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *);
+extern int rpc_create_client_dir(struct rpc_clnt *);
extern int rpc_remove_client_dir(struct rpc_clnt *);
extern void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ec059c2..ae57193 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -100,66 +100,6 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)
spin_unlock(&sn->rpc_client_lock);
}
-static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
-{
- rpc_remove_client_dir(clnt);
-}
-
-static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
-{
- struct net *net = rpc_net_ns(clnt);
- struct super_block *pipefs_sb;
-
- pipefs_sb = rpc_get_sb_net(net);
- if (pipefs_sb) {
- __rpc_clnt_remove_pipedir(clnt);
- rpc_put_sb_net(net);
- }
-}
-
-static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
- struct rpc_clnt *clnt)
-{
- static uint32_t clntid;
- const char *dir_name = clnt->cl_program->pipe_dir_name;
- char name[15];
- struct dentry *dir, *dentry;
-
- dir = rpc_d_lookup_sb(sb, dir_name);
- if (dir == NULL) {
- pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name);
- return dir;
- }
- for (;;) {
- snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
- name[sizeof(name) - 1] = '\0';
- dentry = rpc_create_client_dir(dir, name, clnt);
- if (!IS_ERR(dentry))
- break;
- if (dentry == ERR_PTR(-EEXIST))
- continue;
- printk(KERN_INFO "RPC: Couldn't create pipefs entry"
- " %s/%s, error %ld\n",
- dir_name, name, PTR_ERR(dentry));
- break;
- }
- dput(dir);
- return dentry;
-}
-
-static int
-rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
-{
- struct dentry *dentry;
-
- if (clnt->cl_program->pipe_dir_name != NULL) {
- dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- }
- return 0;
-}
-
static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
struct rpc_xprt *xprt,
const struct rpc_timeout *timeout)
@@ -197,20 +137,15 @@ static int rpc_client_register(struct rpc_clnt *clnt,
.target_name = client_name,
};
struct rpc_auth *auth;
- struct net *net = rpc_net_ns(clnt);
- struct super_block *pipefs_sb;
int err;
- pipefs_sb = rpc_get_sb_net(net);
- if (pipefs_sb) {
- err = rpc_setup_pipedir(pipefs_sb, clnt);
+ if (clnt->cl_program->pipe_dir_name) {
+ err = rpc_create_client_dir(clnt);
if (err)
goto out;
}
rpc_register_client(clnt);
- if (pipefs_sb)
- rpc_put_sb_net(net);
auth = rpcauth_create(&auth_args, clnt);
if (IS_ERR(auth)) {
@@ -221,12 +156,9 @@ static int rpc_client_register(struct rpc_clnt *clnt,
}
return 0;
err_auth:
- pipefs_sb = rpc_get_sb_net(net);
rpc_unregister_client(clnt);
- __rpc_clnt_remove_pipedir(clnt);
+ rpc_remove_client_dir(clnt);
out:
- if (pipefs_sb)
- rpc_put_sb_net(net);
return err;
}
@@ -554,7 +486,7 @@ int rpc_switch_client_transport(struct rpc_clnt *clnt,
old = rpc_clnt_set_transport(clnt, xprt, timeout);
rpc_unregister_client(clnt);
- __rpc_clnt_remove_pipedir(clnt);
+ rpc_remove_client_dir(clnt);
/*
* A new transport was created. "clnt" therefore
@@ -656,7 +588,7 @@ rpc_free_client(struct rpc_clnt *clnt)
rcu_dereference(clnt->cl_xprt)->servername);
if (clnt->cl_parent != clnt)
parent = clnt->cl_parent;
- rpc_clnt_remove_pipedir(clnt);
+ rpc_remove_client_dir(clnt);
rpc_unregister_client(clnt);
rpc_free_iostats(clnt->cl_metrics);
clnt->cl_metrics = NULL;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index dea4008..751aba5 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1093,27 +1093,49 @@ static void rpc_clntdir_depopulate(struct dentry *dentry)
/**
* rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
- * @dentry: the parent of new directory
- * @name: the name of new directory
- * @rpc_client: rpc client to associate with this directory
+ * @clnt: rpc client to associate with this directory
*
- * This creates a directory at the given @path associated with
- * @rpc_clnt, which will contain a file named "info" with some basic
- * information about the client, together with any "pipes" that may
- * later be created using rpc_mkpipe().
+ * This creates a directory associated with @clnt, which will contain a file
+ * named "info" with some basic information about the client, together with
+ * any "pipes" that may later be created using rpc_mkpipe().
*/
-struct dentry *rpc_create_client_dir(struct dentry *dentry,
- const char *name,
- struct rpc_clnt *rpc_client)
+int rpc_create_client_dir(struct rpc_clnt *clnt)
{
- struct dentry *ret;
+ static uint32_t clntid;
+ struct net *net = rpc_net_ns(clnt);
+ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+ const char *dir_name = clnt->cl_program->pipe_dir_name;
+ struct dentry *dir, *dentry;
+ char name[15];
+ int ret = 0;
- ret = rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL,
- rpc_clntdir_populate, rpc_client);
- if (!IS_ERR(ret)) {
- rpc_client->cl_pipedir_objects.pdh_dentry = ret;
- rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
+ dir = rpc_d_lookup_sb(sn->pipefs_sb, dir_name);
+ if (dir == NULL) {
+ pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name);
+ return -ENOENT;
+ }
+
+retry:
+ snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
+ name[sizeof(name) - 1] = '\0';
+
+ dentry = rpc_mkdir_populate(dir, name, S_IRUGO | S_IXUGO, NULL,
+ rpc_clntdir_populate, clnt);
+ if (IS_ERR(dentry)) {
+ if (dentry == ERR_PTR(-EEXIST))
+ goto retry;
+ printk(KERN_INFO "RPC: Couldn't create pipefs entry"
+ " %s/%s, error %ld\n",
+ dir_name, name, PTR_ERR(dentry));
+ ret = PTR_ERR(dentry);
+ goto out;
}
+
+ clnt->cl_pipedir_objects.pdh_dentry = dentry;
+ rpc_create_pipe_dir_objects(&clnt->cl_pipedir_objects);
+
+out:
+ dput(dir);
return ret;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 07/11] sunrpc: make rpc_mkdir_populate net-namespace aware
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (5 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 06/11] sunrpc: clean up rpc_pipefs client dir creation Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 08/11] sunrpc: rpc_get_sb_net, die, die, die Christoph Hellwig
` (7 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
And clean up the caller to not bother about intricate details of
rpc_pipefs internals.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/cache_lib.c | 38 ++++--------------------------------
include/linux/sunrpc/cache.h | 4 ++--
include/linux/sunrpc/rpc_pipe_fs.h | 6 ++----
net/sunrpc/cache.c | 8 ++++----
net/sunrpc/rpc_pipe.c | 34 +++++++++++++++-----------------
5 files changed, 28 insertions(+), 62 deletions(-)
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index 4e9226f..bc2bfb1 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -112,49 +112,19 @@ int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq)
return 0;
}
-static int nfs_cache_register_sb(struct super_block *sb,
- struct cache_detail *cd)
-{
- int ret;
- struct dentry *dir;
-
- dir = rpc_d_lookup_sb(sb, "cache");
- ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd);
- dput(dir);
- return ret;
-}
-
int nfs_cache_register_net(struct net *net, struct cache_detail *cd)
{
- struct super_block *pipefs_sb;
int ret = 0;
sunrpc_init_cache_detail(cd);
- pipefs_sb = rpc_get_sb_net(net);
- if (pipefs_sb) {
- ret = nfs_cache_register_sb(pipefs_sb, cd);
- rpc_put_sb_net(net);
- if (ret)
- sunrpc_destroy_cache_detail(cd);
- }
+ ret = sunrpc_cache_register_pipefs(net, cd);
+ if (ret)
+ sunrpc_destroy_cache_detail(cd);
return ret;
}
-static void nfs_cache_unregister_sb(struct super_block *sb,
- struct cache_detail *cd)
-{
- if (cd->u.pipefs.dir)
- sunrpc_cache_unregister_pipefs(cd);
-}
-
void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd)
{
- struct super_block *pipefs_sb;
-
- pipefs_sb = rpc_get_sb_net(net);
- if (pipefs_sb) {
- nfs_cache_unregister_sb(pipefs_sb, cd);
- rpc_put_sb_net(net);
- }
+ sunrpc_cache_unregister_pipefs(cd);
sunrpc_destroy_cache_detail(cd);
}
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 437ddb6..db1ad29 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -220,8 +220,8 @@ extern void cache_destroy_net(struct cache_detail *cd, struct net *net);
extern void sunrpc_init_cache_detail(struct cache_detail *cd);
extern void sunrpc_destroy_cache_detail(struct cache_detail *cd);
-extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
- umode_t, struct cache_detail *);
+extern int sunrpc_cache_register_pipefs(struct net *net,
+ struct cache_detail *cd);
extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
extern void qword_add(char **bpp, int *lp, char *str);
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index fefbfa3..ae0a109 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -100,10 +100,8 @@ extern struct rpc_pipe_dir_object *rpc_find_or_alloc_pipe_dir_object(
void *data);
struct cache_detail;
-extern struct dentry *rpc_create_cache_dir(struct dentry *,
- const char *,
- umode_t umode,
- struct cache_detail *);
+extern struct dentry *rpc_create_cache_dir(struct net *n, const char *,
+ const char *, umode_t umode, struct cache_detail *);
extern void rpc_remove_cache_dir(struct dentry *);
extern int rpc_rmdir(struct dentry *dentry);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index a72de07..c654377 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1819,11 +1819,11 @@ const struct file_operations cache_flush_operations_pipefs = {
.llseek = no_llseek,
};
-int sunrpc_cache_register_pipefs(struct dentry *parent,
- const char *name, umode_t umode,
- struct cache_detail *cd)
+int sunrpc_cache_register_pipefs(struct net *net, struct cache_detail *cd)
{
- struct dentry *dir = rpc_create_cache_dir(parent, name, umode, cd);
+ struct dentry *dir;
+
+ dir = rpc_create_cache_dir(net, "cache", cd->name, 0600, cd);
if (IS_ERR(dir))
return PTR_ERR(dir);
cd->u.pipefs.dir = dir;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 751aba5..3f4905a 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -732,14 +732,20 @@ out_bad:
return err;
}
-static struct dentry *rpc_mkdir_populate(struct dentry *parent,
+static struct dentry *rpc_mkdir_populate(struct net *net, const char *dirname,
const char *name, umode_t mode, void *private,
int (*populate)(struct dentry *, void *), void *args_populate)
{
- struct dentry *dentry;
- struct inode *dir = parent->d_inode;
+ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+ struct dentry *dentry, *parent;
+ struct inode *dir;
int error;
+ parent = rpc_d_lookup_sb(sn->pipefs_sb, dirname);
+ if (parent == NULL)
+ return ERR_PTR(-ENOENT);
+ dir = parent->d_inode;
+
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
dentry = __rpc_lookup_create_exclusive(parent, name);
if (IS_ERR(dentry))
@@ -754,6 +760,7 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent,
}
out:
mutex_unlock(&dir->i_mutex);
+ dput(parent);
return dentry;
err_rmdir:
__rpc_rmdir(dir, dentry);
@@ -1103,24 +1110,17 @@ int rpc_create_client_dir(struct rpc_clnt *clnt)
{
static uint32_t clntid;
struct net *net = rpc_net_ns(clnt);
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
const char *dir_name = clnt->cl_program->pipe_dir_name;
- struct dentry *dir, *dentry;
+ struct dentry *dentry;
char name[15];
int ret = 0;
- dir = rpc_d_lookup_sb(sn->pipefs_sb, dir_name);
- if (dir == NULL) {
- pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name);
- return -ENOENT;
- }
-
retry:
snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
name[sizeof(name) - 1] = '\0';
- dentry = rpc_mkdir_populate(dir, name, S_IRUGO | S_IXUGO, NULL,
- rpc_clntdir_populate, clnt);
+ dentry = rpc_mkdir_populate(net, dir_name, name, S_IRUGO | S_IXUGO,
+ NULL, rpc_clntdir_populate, clnt);
if (IS_ERR(dentry)) {
if (dentry == ERR_PTR(-EEXIST))
goto retry;
@@ -1133,9 +1133,7 @@ retry:
clnt->cl_pipedir_objects.pdh_dentry = dentry;
rpc_create_pipe_dir_objects(&clnt->cl_pipedir_objects);
-
out:
- dput(dir);
return ret;
}
@@ -1184,10 +1182,10 @@ static void rpc_cachedir_depopulate(struct dentry *dentry)
rpc_depopulate(dentry, cache_pipefs_files, 0, 3);
}
-struct dentry *rpc_create_cache_dir(struct dentry *parent, const char *name,
- umode_t umode, struct cache_detail *cd)
+struct dentry *rpc_create_cache_dir(struct net *net, const char *dirname,
+ const char *name, umode_t umode, struct cache_detail *cd)
{
- return rpc_mkdir_populate(parent, name, umode, NULL,
+ return rpc_mkdir_populate(net, dirname, name, umode, NULL,
rpc_cachedir_populate, cd);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 08/11] sunrpc: rpc_get_sb_net, die, die, die
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (6 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 07/11] sunrpc: make rpc_mkdir_populate net-namespace aware Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 09/11] nfs: convert idmapper to rpc_mkpipe_clnt Christoph Hellwig
` (6 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
rpc_get_sb_net can go away now that no caller is left. Also
rpc_d_lookup_sb can be static inside rpc_pipe.c now.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/sunrpc/rpc_pipe_fs.h | 5 ----
net/sunrpc/rpc_pipe.c | 45 ++++++------------------------------
2 files changed, 7 insertions(+), 43 deletions(-)
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index ae0a109..29c66f9 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -69,11 +69,6 @@ RPC_I(struct inode *inode)
return container_of(inode, struct rpc_inode, vfs_inode);
}
-extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
- const unsigned char *dir_name);
-extern struct super_block *rpc_get_sb_net(const struct net *net);
-extern void rpc_put_sb_net(const struct net *net);
-
extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
char __user *, size_t);
extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 3f4905a..0485796 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -627,6 +627,13 @@ static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry)
return __rpc_unlink(dir, dentry);
}
+static struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
+ const unsigned char *dir_name)
+{
+ struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
+ return d_hash_and_lookup(sb->s_root, &dir);
+}
+
static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
const char *name)
{
@@ -1255,17 +1262,6 @@ static const struct rpc_filelist files[] = {
},
};
-/*
- * This call can be used only in RPC pipefs mount notification hooks.
- */
-struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
- const unsigned char *dir_name)
-{
- struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
- return d_hash_and_lookup(sb->s_root, &dir);
-}
-EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
-
int rpc_pipefs_init_net(struct net *net)
{
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
@@ -1287,33 +1283,6 @@ void rpc_pipefs_exit_net(struct net *net)
kern_unmount(sn->pipefs_mnt);
}
-/*
- * This call will be used for per network namespace operations calls.
- * Note: Function will be returned with pipefs_sb_lock taken if superblock was
- * found. This lock have to be released by rpc_put_sb_net() when all operations
- * will be completed.
- */
-struct super_block *rpc_get_sb_net(const struct net *net)
-{
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-
- mutex_lock(&sn->pipefs_sb_lock);
- if (sn->pipefs_sb)
- return sn->pipefs_sb;
- mutex_unlock(&sn->pipefs_sb_lock);
- return NULL;
-}
-EXPORT_SYMBOL_GPL(rpc_get_sb_net);
-
-void rpc_put_sb_net(const struct net *net)
-{
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-
- WARN_ON(sn->pipefs_sb == NULL);
- mutex_unlock(&sn->pipefs_sb_lock);
-}
-EXPORT_SYMBOL_GPL(rpc_put_sb_net);
-
static int
rpc_fill_super(struct super_block *sb, void *data, int silent)
{
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 09/11] nfs: convert idmapper to rpc_mkpipe_clnt
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (7 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 08/11] sunrpc: rpc_get_sb_net, die, die, die Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 10/11] auth_gss: convert " Christoph Hellwig
` (5 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/idmap.c | 74 +++++++-------------------------------------------------
1 file changed, 9 insertions(+), 65 deletions(-)
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 567983d..91459b0 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -64,7 +64,6 @@ struct idmap_legacy_upcalldata {
};
struct idmap {
- struct rpc_pipe_dir_object idmap_pdo;
struct rpc_pipe *idmap_pipe;
struct idmap_legacy_upcalldata *idmap_upcall_data;
struct mutex idmap_mutex;
@@ -403,73 +402,25 @@ static struct key_type key_type_id_resolver_legacy = {
.request_key = nfs_idmap_legacy_upcall,
};
-static void nfs_idmap_pipe_destroy(struct dentry *dir,
- struct rpc_pipe_dir_object *pdo)
-{
- struct idmap *idmap = pdo->pdo_data;
- struct rpc_pipe *pipe = idmap->idmap_pipe;
-
- if (pipe->dentry) {
- rpc_unlink(pipe->dentry);
- pipe->dentry = NULL;
- }
-}
-
-static int nfs_idmap_pipe_create(struct dentry *dir,
- struct rpc_pipe_dir_object *pdo)
-{
- struct idmap *idmap = pdo->pdo_data;
- struct rpc_pipe *pipe = idmap->idmap_pipe;
- struct dentry *dentry;
-
- dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- pipe->dentry = dentry;
- return 0;
-}
-
-static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
- .create = nfs_idmap_pipe_create,
- .destroy = nfs_idmap_pipe_destroy,
-};
-
int
nfs_idmap_new(struct nfs_client *clp)
{
struct idmap *idmap;
- struct rpc_pipe *pipe;
- int error;
idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
if (idmap == NULL)
return -ENOMEM;
-
- rpc_init_pipe_dir_object(&idmap->idmap_pdo,
- &nfs_idmap_pipe_dir_object_ops,
- idmap);
-
- pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
- if (IS_ERR(pipe)) {
- error = PTR_ERR(pipe);
- goto err;
- }
- idmap->idmap_pipe = pipe;
mutex_init(&idmap->idmap_mutex);
- error = rpc_add_pipe_dir_object(clp->cl_net,
- &clp->cl_rpcclient->cl_pipedir_objects,
- &idmap->idmap_pdo);
- if (error)
- goto err_destroy_pipe;
+ idmap->idmap_pipe = rpc_mkpipe_clnt(clp->cl_rpcclient, "idmap",
+ &idmap_upcall_ops, idmap, 0);
+ if (IS_ERR(idmap->idmap_pipe)) {
+ kfree(idmap);
+ return PTR_ERR(idmap->idmap_pipe);
+ }
clp->cl_idmap = idmap;
return 0;
-err_destroy_pipe:
- rpc_destroy_pipe_data(idmap->idmap_pipe);
-err:
- kfree(idmap);
- return error;
}
void
@@ -479,22 +430,15 @@ nfs_idmap_delete(struct nfs_client *clp)
if (!idmap)
return;
+
+ rpc_rmpipe(idmap->idmap_pipe);
clp->cl_idmap = NULL;
- rpc_remove_pipe_dir_object(clp->cl_net,
- &clp->cl_rpcclient->cl_pipedir_objects,
- &idmap->idmap_pdo);
- rpc_destroy_pipe_data(idmap->idmap_pipe);
kfree(idmap);
}
int nfs_idmap_init(void)
{
- int ret;
- ret = nfs_idmap_init_keyring();
- if (ret != 0)
- goto out;
-out:
- return ret;
+ return nfs_idmap_init_keyring();
}
void nfs_idmap_quit(void)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 10/11] auth_gss: convert to rpc_mkpipe_clnt
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (8 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 09/11] nfs: convert idmapper to rpc_mkpipe_clnt Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 13:14 ` [PATCH 11/11] sunrpc: rpc_pipefs cleanup Christoph Hellwig
` (4 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
This is a bit more elaborate as auth_gcc offloaded it's own little
list of pipes to rpc_pipes. Fixed by rewriting the ovely generic
code into self-contained variants and removing the superflous
infrastructure.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/sunrpc/clnt.h | 4 +-
include/linux/sunrpc/rpc_pipe_fs.h | 37 --------
net/sunrpc/auth_gss/auth_gss.c | 146 ++++++++---------------------
net/sunrpc/clnt.c | 4 +-
net/sunrpc/netns.h | 1 -
net/sunrpc/rpc_pipe.c | 177 +-----------------------------------
6 files changed, 49 insertions(+), 320 deletions(-)
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 8af2804..a78bc9a 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -58,11 +58,13 @@ struct rpc_clnt {
int cl_nodelen; /* nodename length */
char cl_nodename[UNX_MAXNODENAME];
- struct rpc_pipe_dir_head cl_pipedir_objects;
+ struct dentry *cl_dentry;
struct rpc_clnt * cl_parent; /* Points to parent of clones */
struct rpc_rtt cl_rtt_default;
struct rpc_timeout cl_timeout_default;
const struct rpc_program *cl_program;
+ struct list_head cl_gss_pipes;
+ struct mutex cl_gss_pipe_mutex;
};
/*
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 29c66f9..d37a1e2 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -5,26 +5,6 @@
#include <linux/workqueue.h>
-struct rpc_pipe_dir_head {
- struct list_head pdh_entries;
- struct dentry *pdh_dentry;
-};
-
-struct rpc_pipe_dir_object_ops;
-struct rpc_pipe_dir_object {
- struct list_head pdo_head;
- const struct rpc_pipe_dir_object_ops *pdo_ops;
-
- void *pdo_data;
-};
-
-struct rpc_pipe_dir_object_ops {
- int (*create)(struct dentry *dir,
- struct rpc_pipe_dir_object *pdo);
- void (*destroy)(struct dentry *dir,
- struct rpc_pipe_dir_object *pdo);
-};
-
struct rpc_pipe_msg {
struct list_head list;
void *data;
@@ -77,23 +57,6 @@ struct rpc_clnt;
extern int rpc_create_client_dir(struct rpc_clnt *);
extern int rpc_remove_client_dir(struct rpc_clnt *);
-extern void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh);
-extern void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
- const struct rpc_pipe_dir_object_ops *pdo_ops,
- void *pdo_data);
-extern int rpc_add_pipe_dir_object(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- struct rpc_pipe_dir_object *pdo);
-extern void rpc_remove_pipe_dir_object(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- struct rpc_pipe_dir_object *pdo);
-extern struct rpc_pipe_dir_object *rpc_find_or_alloc_pipe_dir_object(
- struct net *net,
- struct rpc_pipe_dir_head *pdh,
- int (*match)(struct rpc_pipe_dir_object *, void *),
- struct rpc_pipe_dir_object *(*alloc)(void *),
- void *data);
-
struct cache_detail;
extern struct dentry *rpc_create_cache_dir(struct net *n, const char *,
const char *, umode_t umode, struct cache_detail *);
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 97912b4..b67f8d4 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -79,7 +79,7 @@ static DEFINE_HASHTABLE(gss_auth_hash_table, 4);
static DEFINE_SPINLOCK(gss_auth_hash_lock);
struct gss_pipe {
- struct rpc_pipe_dir_object pdo;
+ struct list_head list;
struct rpc_pipe *pipe;
struct rpc_clnt *clnt;
const char *name;
@@ -826,141 +826,71 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
}
}
-static void gss_pipe_dentry_destroy(struct dentry *dir,
- struct rpc_pipe_dir_object *pdo)
+static struct gss_pipe *
+__gss_pipe_find(struct rpc_clnt *clnt, const char *name)
{
- struct gss_pipe *gss_pipe = pdo->pdo_data;
- struct rpc_pipe *pipe = gss_pipe->pipe;
+ struct gss_pipe *p;
- if (pipe->dentry != NULL) {
- rpc_unlink(pipe->dentry);
- pipe->dentry = NULL;
+ list_for_each_entry(p, &clnt->cl_gss_pipes, list) {
+ if (strcmp(p->name, name) != 0)
+ continue;
+ if (!kref_get_unless_zero(&p->kref))
+ continue;
+ return p;
}
-}
-
-static int gss_pipe_dentry_create(struct dentry *dir,
- struct rpc_pipe_dir_object *pdo)
-{
- struct gss_pipe *p = pdo->pdo_data;
- struct dentry *dentry;
- dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- p->pipe->dentry = dentry;
- return 0;
+ return NULL;
}
-static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = {
- .create = gss_pipe_dentry_create,
- .destroy = gss_pipe_dentry_destroy,
-};
-
-static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
+static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt,
const char *name,
const struct rpc_pipe_ops *upcall_ops)
{
struct gss_pipe *p;
- int err = -ENOMEM;
+
+ mutex_lock(&clnt->cl_gss_pipe_mutex);
+ p = __gss_pipe_find(clnt, name);
+ if (p)
+ goto out;
p = kmalloc(sizeof(*p), GFP_KERNEL);
- if (p == NULL)
- goto err;
- p->pipe = rpc_mkpipe_data(upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
- if (IS_ERR(p->pipe)) {
- err = PTR_ERR(p->pipe);
- goto err_free_gss_pipe;
+ if (p == NULL) {
+ p = ERR_PTR(-ENOMEM);
+ goto out;
}
+
p->name = name;
p->clnt = clnt;
kref_init(&p->kref);
- rpc_init_pipe_dir_object(&p->pdo,
- &gss_pipe_dir_object_ops,
- p);
- return p;
-err_free_gss_pipe:
- kfree(p);
-err:
- return ERR_PTR(err);
-}
-
-struct gss_alloc_pdo {
- struct rpc_clnt *clnt;
- const char *name;
- const struct rpc_pipe_ops *upcall_ops;
-};
-
-static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data)
-{
- struct gss_pipe *gss_pipe;
- struct gss_alloc_pdo *args = data;
-
- if (pdo->pdo_ops != &gss_pipe_dir_object_ops)
- return 0;
- gss_pipe = container_of(pdo, struct gss_pipe, pdo);
- if (strcmp(gss_pipe->name, args->name) != 0)
- return 0;
- if (!kref_get_unless_zero(&gss_pipe->kref))
- return 0;
- return 1;
-}
-
-static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data)
-{
- struct gss_pipe *gss_pipe;
- struct gss_alloc_pdo *args = data;
-
- gss_pipe = gss_pipe_alloc(args->clnt, args->name, args->upcall_ops);
- if (!IS_ERR(gss_pipe))
- return &gss_pipe->pdo;
- return NULL;
-}
-
-static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt,
- const char *name,
- const struct rpc_pipe_ops *upcall_ops)
-{
- struct net *net = rpc_net_ns(clnt);
- struct rpc_pipe_dir_object *pdo;
- struct gss_alloc_pdo args = {
- .clnt = clnt,
- .name = name,
- .upcall_ops = upcall_ops,
- };
-
- pdo = rpc_find_or_alloc_pipe_dir_object(net,
- &clnt->cl_pipedir_objects,
- gss_pipe_match_pdo,
- gss_pipe_alloc_pdo,
- &args);
- if (pdo != NULL)
- return container_of(pdo, struct gss_pipe, pdo);
- return ERR_PTR(-ENOMEM);
-}
+ p->pipe = rpc_mkpipe_clnt(clnt, name, upcall_ops, clnt,
+ RPC_PIPE_WAIT_FOR_OPEN);
+ if (IS_ERR(p->pipe)) {
+ kfree(p);
+ return ERR_CAST(p->pipe);
+ }
-static void __gss_pipe_free(struct gss_pipe *p)
-{
- struct rpc_clnt *clnt = p->clnt;
- struct net *net = rpc_net_ns(clnt);
+ list_add_tail(&p->list, &clnt->cl_gss_pipes);
- rpc_remove_pipe_dir_object(net,
- &clnt->cl_pipedir_objects,
- &p->pdo);
- rpc_destroy_pipe_data(p->pipe);
- kfree(p);
+out:
+ mutex_unlock(&clnt->cl_gss_pipe_mutex);
+ return p;
}
-static void __gss_pipe_release(struct kref *kref)
+static void __gss_pipe_free(struct kref *kref)
{
struct gss_pipe *p = container_of(kref, struct gss_pipe, kref);
- __gss_pipe_free(p);
+ mutex_lock(&p->clnt->cl_gss_pipe_mutex);
+ list_del(&p->list);
+ mutex_unlock(&p->clnt->cl_gss_pipe_mutex);
+ rpc_rmpipe(p->pipe);
+ kfree(p);
}
static void gss_pipe_free(struct gss_pipe *p)
{
if (p != NULL)
- kref_put(&p->kref, __gss_pipe_release);
+ kref_put(&p->kref, __gss_pipe_free);
}
/*
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ae57193..029f468 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -221,7 +221,6 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
clnt->cl_vers = version->number;
clnt->cl_stats = program->stats;
clnt->cl_metrics = rpc_alloc_iostats(clnt);
- rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects);
err = -ENOMEM;
if (clnt->cl_metrics == NULL)
goto out_no_stats;
@@ -229,6 +228,9 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
INIT_LIST_HEAD(&clnt->cl_tasks);
spin_lock_init(&clnt->cl_lock);
+ INIT_LIST_HEAD(&clnt->cl_gss_pipes);
+ mutex_init(&clnt->cl_gss_pipe_mutex);
+
timeout = xprt->timeout;
if (args->timeout != NULL) {
memcpy(&clnt->cl_timeout_default, args->timeout,
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index a80b069..0773142 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -15,7 +15,6 @@ struct sunrpc_net {
struct vfsmount *pipefs_mnt;
struct super_block *pipefs_sb;
- struct mutex pipefs_sb_lock;
struct list_head all_clients;
spinlock_t rpc_client_lock;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 0485796..6bce5f6 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -889,8 +889,7 @@ struct rpc_pipe *
rpc_mkpipe_clnt(struct rpc_clnt *clnt, const char *name,
const struct rpc_pipe_ops *ops, void *private, int flags)
{
- return __rpc_mkpipe(clnt->cl_pipedir_objects.pdh_dentry, name,
- ops, private, flags);
+ return __rpc_mkpipe(clnt->cl_dentry, name, ops, private, flags);
}
EXPORT_SYMBOL_GPL(rpc_mkpipe_clnt);
@@ -927,159 +926,6 @@ void rpc_rmpipe(struct rpc_pipe *pipe)
}
EXPORT_SYMBOL_GPL(rpc_rmpipe);
-/**
- * rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head
- * @pdh: pointer to struct rpc_pipe_dir_head
- */
-void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh)
-{
- INIT_LIST_HEAD(&pdh->pdh_entries);
- pdh->pdh_dentry = NULL;
-}
-EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_head);
-
-/**
- * rpc_init_pipe_dir_object - initialise a struct rpc_pipe_dir_object
- * @pdo: pointer to struct rpc_pipe_dir_object
- * @pdo_ops: pointer to const struct rpc_pipe_dir_object_ops
- * @pdo_data: pointer to caller-defined data
- */
-void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
- const struct rpc_pipe_dir_object_ops *pdo_ops,
- void *pdo_data)
-{
- INIT_LIST_HEAD(&pdo->pdo_head);
- pdo->pdo_ops = pdo_ops;
- pdo->pdo_data = pdo_data;
-}
-EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object);
-
-static int
-rpc_add_pipe_dir_object_locked(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- struct rpc_pipe_dir_object *pdo)
-{
- int ret = 0;
-
- if (pdh->pdh_dentry)
- ret = pdo->pdo_ops->create(pdh->pdh_dentry, pdo);
- if (ret == 0)
- list_add_tail(&pdo->pdo_head, &pdh->pdh_entries);
- return ret;
-}
-
-static void
-rpc_remove_pipe_dir_object_locked(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- struct rpc_pipe_dir_object *pdo)
-{
- if (pdh->pdh_dentry)
- pdo->pdo_ops->destroy(pdh->pdh_dentry, pdo);
- list_del_init(&pdo->pdo_head);
-}
-
-/**
- * rpc_add_pipe_dir_object - associate a rpc_pipe_dir_object to a directory
- * @net: pointer to struct net
- * @pdh: pointer to struct rpc_pipe_dir_head
- * @pdo: pointer to struct rpc_pipe_dir_object
- *
- */
-int
-rpc_add_pipe_dir_object(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- struct rpc_pipe_dir_object *pdo)
-{
- int ret = 0;
-
- if (list_empty(&pdo->pdo_head)) {
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-
- mutex_lock(&sn->pipefs_sb_lock);
- ret = rpc_add_pipe_dir_object_locked(net, pdh, pdo);
- mutex_unlock(&sn->pipefs_sb_lock);
- }
- return ret;
-}
-EXPORT_SYMBOL_GPL(rpc_add_pipe_dir_object);
-
-/**
- * rpc_remove_pipe_dir_object - remove a rpc_pipe_dir_object from a directory
- * @net: pointer to struct net
- * @pdh: pointer to struct rpc_pipe_dir_head
- * @pdo: pointer to struct rpc_pipe_dir_object
- *
- */
-void
-rpc_remove_pipe_dir_object(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- struct rpc_pipe_dir_object *pdo)
-{
- if (!list_empty(&pdo->pdo_head)) {
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-
- mutex_lock(&sn->pipefs_sb_lock);
- rpc_remove_pipe_dir_object_locked(net, pdh, pdo);
- mutex_unlock(&sn->pipefs_sb_lock);
- }
-}
-EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object);
-
-/**
- * rpc_find_or_alloc_pipe_dir_object
- * @net: pointer to struct net
- * @pdh: pointer to struct rpc_pipe_dir_head
- * @match: match struct rpc_pipe_dir_object to data
- * @alloc: allocate a new struct rpc_pipe_dir_object
- * @data: user defined data for match() and alloc()
- *
- */
-struct rpc_pipe_dir_object *
-rpc_find_or_alloc_pipe_dir_object(struct net *net,
- struct rpc_pipe_dir_head *pdh,
- int (*match)(struct rpc_pipe_dir_object *, void *),
- struct rpc_pipe_dir_object *(*alloc)(void *),
- void *data)
-{
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- struct rpc_pipe_dir_object *pdo;
-
- mutex_lock(&sn->pipefs_sb_lock);
- list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) {
- if (!match(pdo, data))
- continue;
- goto out;
- }
- pdo = alloc(data);
- if (!pdo)
- goto out;
- rpc_add_pipe_dir_object_locked(net, pdh, pdo);
-out:
- mutex_unlock(&sn->pipefs_sb_lock);
- return pdo;
-}
-EXPORT_SYMBOL_GPL(rpc_find_or_alloc_pipe_dir_object);
-
-static void
-rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
-{
- struct rpc_pipe_dir_object *pdo;
- struct dentry *dir = pdh->pdh_dentry;
-
- list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
- pdo->pdo_ops->create(dir, pdo);
-}
-
-static void
-rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
-{
- struct rpc_pipe_dir_object *pdo;
- struct dentry *dir = pdh->pdh_dentry;
-
- list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
- pdo->pdo_ops->destroy(dir, pdo);
-}
-
enum {
RPCAUTH_info,
RPCAUTH_EOF
@@ -1138,8 +984,7 @@ retry:
goto out;
}
- clnt->cl_pipedir_objects.pdh_dentry = dentry;
- rpc_create_pipe_dir_objects(&clnt->cl_pipedir_objects);
+ clnt->cl_dentry = dentry;
out:
return ret;
}
@@ -1150,12 +995,12 @@ out:
*/
int rpc_remove_client_dir(struct rpc_clnt *rpc_client)
{
- struct dentry *dentry = rpc_client->cl_pipedir_objects.pdh_dentry;
+ struct dentry *dentry = rpc_client->cl_dentry;
if (dentry == NULL)
return 0;
- rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
- rpc_client->cl_pipedir_objects.pdh_dentry = NULL;
+
+ rpc_client->cl_dentry = NULL;
return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate);
}
@@ -1266,7 +1111,6 @@ int rpc_pipefs_init_net(struct net *net)
{
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- mutex_init(&sn->pipefs_sb_lock);
sn->gssd_running = 1;
sn->pipe_version = -1;
@@ -1306,10 +1150,8 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
return -ENOMEM;
dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n",
net, NET_NAME(net));
- mutex_lock(&sn->pipefs_sb_lock);
sn->pipefs_sb = sb;
sb->s_fs_info = get_net(net);
- mutex_unlock(&sn->pipefs_sb_lock);
return 0;
}
@@ -1323,19 +1165,10 @@ rpc_mount(struct file_system_type *fs_type,
static void rpc_kill_sb(struct super_block *sb)
{
struct net *net = sb->s_fs_info;
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- mutex_lock(&sn->pipefs_sb_lock);
- if (sn->pipefs_sb != sb) {
- mutex_unlock(&sn->pipefs_sb_lock);
- goto out;
- }
- sn->pipefs_sb = NULL;
dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n",
net, NET_NAME(net));
- mutex_unlock(&sn->pipefs_sb_lock);
put_net(net);
-out:
kill_litter_super(sb);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 11/11] sunrpc: rpc_pipefs cleanup
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (9 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 10/11] auth_gss: convert " Christoph Hellwig
@ 2013-12-01 13:14 ` Christoph Hellwig
2013-12-01 14:36 ` [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Jeff Layton
` (3 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-01 13:14 UTC (permalink / raw)
To: linux-nfs, viro; +Cc: linux-fsdevel
Remove or fold now unused pipe creation and removal functions.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/sunrpc/rpc_pipe_fs.h | 8 +---
net/sunrpc/rpc_pipe.c | 87 ++++++++----------------------------
2 files changed, 19 insertions(+), 76 deletions(-)
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index d37a1e2..bed3845 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -62,18 +62,12 @@ extern struct dentry *rpc_create_cache_dir(struct net *n, const char *,
const char *, umode_t umode, struct cache_detail *);
extern void rpc_remove_cache_dir(struct dentry *);
-extern int rpc_rmdir(struct dentry *dentry);
-
-struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags);
-void rpc_destroy_pipe_data(struct rpc_pipe *pipe);
-extern struct dentry *rpc_mkpipe_dentry(struct dentry *, const char *, void *,
- struct rpc_pipe *);
extern struct rpc_pipe *rpc_mkpipe(struct net *, const char *, const char *,
const struct rpc_pipe_ops *, void *private, int);
extern struct rpc_pipe *rpc_mkpipe_clnt(struct rpc_clnt *, const char *,
const struct rpc_pipe_ops *, void *, int);
extern void rpc_rmpipe(struct rpc_pipe *);
-extern int rpc_unlink(struct dentry *);
+
extern int register_rpc_pipefs(void);
extern void unregister_rpc_pipefs(void);
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 6bce5f6..f70eec9 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -526,42 +526,6 @@ static int __rpc_mkdir(struct inode *dir, struct dentry *dentry,
return 0;
}
-static void
-init_pipe(struct rpc_pipe *pipe)
-{
- pipe->nreaders = 0;
- pipe->nwriters = 0;
- INIT_LIST_HEAD(&pipe->in_upcall);
- INIT_LIST_HEAD(&pipe->in_downcall);
- INIT_LIST_HEAD(&pipe->pipe);
- pipe->pipelen = 0;
- INIT_DELAYED_WORK(&pipe->queue_timeout,
- rpc_timeout_upcall_queue);
- pipe->ops = NULL;
- spin_lock_init(&pipe->lock);
- pipe->dentry = NULL;
-}
-
-void rpc_destroy_pipe_data(struct rpc_pipe *pipe)
-{
- kfree(pipe);
-}
-EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data);
-
-struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags)
-{
- struct rpc_pipe *pipe;
-
- pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
- if (!pipe)
- return ERR_PTR(-ENOMEM);
- init_pipe(pipe);
- pipe->ops = ops;
- pipe->flags = flags;
- return pipe;
-}
-EXPORT_SYMBOL_GPL(rpc_mkpipe_data);
-
static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry,
umode_t mode,
const struct file_operations *i_fop,
@@ -592,22 +556,6 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
return ret;
}
-int rpc_rmdir(struct dentry *dentry)
-{
- struct dentry *parent;
- struct inode *dir;
- int error;
-
- parent = dget_parent(dentry);
- dir = parent->d_inode;
- mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
- error = __rpc_rmdir(dir, dentry);
- mutex_unlock(&dir->i_mutex);
- dput(parent);
- return error;
-}
-EXPORT_SYMBOL_GPL(rpc_rmdir);
-
static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
{
int ret;
@@ -812,7 +760,7 @@ static int rpc_rmdir_depopulate(struct dentry *dentry,
* The @private argument passed here will be available to all these methods
* from the file pointer, via RPC_I(file_inode(file))->private.
*/
-struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
+static struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
void *private, struct rpc_pipe *pipe)
{
struct dentry *dentry;
@@ -843,7 +791,6 @@ out_err:
err);
goto out;
}
-EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
struct rpc_pipe *
__rpc_mkpipe(struct dentry *dir, const char *name,
@@ -852,10 +799,21 @@ __rpc_mkpipe(struct dentry *dir, const char *name,
struct rpc_pipe *pipe;
int err = -ENOENT;
- pipe = rpc_mkpipe_data(ops, flags);
- if (IS_ERR(pipe))
- return pipe;
+ pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
+ if (!pipe)
+ return ERR_PTR(-ENOMEM);
+
+ pipe->nreaders = 0;
+ pipe->nwriters = 0;
+ INIT_LIST_HEAD(&pipe->in_upcall);
+ INIT_LIST_HEAD(&pipe->in_downcall);
+ INIT_LIST_HEAD(&pipe->pipe);
+ pipe->pipelen = 0;
+ INIT_DELAYED_WORK(&pipe->queue_timeout, rpc_timeout_upcall_queue);
+ spin_lock_init(&pipe->lock);
+ pipe->ops = ops;
+ pipe->flags = flags;
pipe->dentry = rpc_mkpipe_dentry(dir, name, private, pipe);
if (IS_ERR(pipe->dentry)) {
err = PTR_ERR(pipe->dentry);
@@ -863,7 +821,7 @@ __rpc_mkpipe(struct dentry *dir, const char *name,
}
return pipe;
out_destroy_pipe:
- rpc_destroy_pipe_data(pipe);
+ kfree(pipe);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(__rpc_mkpipe);
@@ -893,15 +851,7 @@ rpc_mkpipe_clnt(struct rpc_clnt *clnt, const char *name,
}
EXPORT_SYMBOL_GPL(rpc_mkpipe_clnt);
-/**
- * rpc_unlink - remove a pipe
- * @dentry: dentry for the pipe, as returned from rpc_mkpipe
- *
- * After this call, lookups will no longer find the pipe, and any
- * attempts to read or write using preexisting opens of the pipe will
- * return -EPIPE.
- */
-int
+static int
rpc_unlink(struct dentry *dentry)
{
struct dentry *parent;
@@ -916,13 +866,12 @@ rpc_unlink(struct dentry *dentry)
dput(parent);
return error;
}
-EXPORT_SYMBOL_GPL(rpc_unlink);
void rpc_rmpipe(struct rpc_pipe *pipe)
{
if (pipe->dentry)
rpc_unlink(pipe->dentry);
- rpc_destroy_pipe_data(pipe);
+ kfree(pipe);
}
EXPORT_SYMBOL_GPL(rpc_rmpipe);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (10 preceding siblings ...)
2013-12-01 13:14 ` [PATCH 11/11] sunrpc: rpc_pipefs cleanup Christoph Hellwig
@ 2013-12-01 14:36 ` Jeff Layton
2013-12-01 15:44 ` Jeff Layton
` (2 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: Jeff Layton @ 2013-12-01 14:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-nfs, viro, linux-fsdevel
On Sun, 01 Dec 2013 05:14:41 -0800
Christoph Hellwig <hch@infradead.org> wrote:
> This series tries to get rid of the damage created by sprinkling the
> network namespace cat poo all over rpc_pipefs and users.
>
> Instead of getting lost in a maze of notifiers and infrastructure build
> around it a cargo cult manner we revert to a slightly nicer version of
> the pre-namespace API.
>
> To do this we just have to create an in-kernel instance of rpc_pipefs
> that is mounted at network namespace creation so that all functions can
> operated on it.
>
> As-is this has one major downside: because the initial mount already grabs
> a reference to the network namespace we'll create a cyclic reference and
> will never free the network namespace. To get around this we'd need
> some way to only grab it once user mounts show up / disapear in the VFS.
>
> Given that the namespace kraken has infected various internal filesystem
> and will get more soon I suspect this problem is or will become generic
> and will need a proper solution anyway. Al, any good ideas how to deal
> with this? Most straight forward way would be to add a counter of
> user vfsmount to the superblock and methods when it goes to 1 and 0,
> but that seems a bit ugly.
Looks like a good set overall -- I'll plan to review it in more detail
in the next day or two. If we do take it, it'll need to be reconciled
with the set I sent recently that makes some changes in this code:
[PATCH v4 0/3] sunrpc/nfs: more reliable detection of running gssd
Right offhand, I don't see anything fundamentally at odds with it here,
so it's probably a matter of just fixing up the merge of the two. You
may want to base the next version of this on top of Trond's "devel"
branch since it has those patches.
--
Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (11 preceding siblings ...)
2013-12-01 14:36 ` [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Jeff Layton
@ 2013-12-01 15:44 ` Jeff Layton
2013-12-01 15:57 ` Jeff Layton
2013-12-01 18:13 ` Al Viro
2013-12-02 7:23 ` [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Stanislav Kinsbursky
14 siblings, 1 reply; 36+ messages in thread
From: Jeff Layton @ 2013-12-01 15:44 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-nfs, viro, linux-fsdevel
On Sun, 01 Dec 2013 05:14:41 -0800
Christoph Hellwig <hch@infradead.org> wrote:
> This series tries to get rid of the damage created by sprinkling the
> network namespace cat poo all over rpc_pipefs and users.
>
> Instead of getting lost in a maze of notifiers and infrastructure build
> around it a cargo cult manner we revert to a slightly nicer version of
> the pre-namespace API.
>
> To do this we just have to create an in-kernel instance of rpc_pipefs
> that is mounted at network namespace creation so that all functions can
> operated on it.
>
> As-is this has one major downside: because the initial mount already grabs
> a reference to the network namespace we'll create a cyclic reference and
> will never free the network namespace. To get around this we'd need
> some way to only grab it once user mounts show up / disapear in the VFS.
>
> Given that the namespace kraken has infected various internal filesystem
> and will get more soon I suspect this problem is or will become generic
> and will need a proper solution anyway. Al, any good ideas how to deal
> with this? Most straight forward way would be to add a counter of
> user vfsmount to the superblock and methods when it goes to 1 and 0,
> but that seems a bit ugly.
I see what you mean here...hrm...
One possibility (though it may have holes that I don't see right
offhand):
Don't call get_ns in rpc_fill_super. Do it in rpc_mount instead, and
only take the reference if MS_KERNMOUNT isn't set?
--
Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-01 15:44 ` Jeff Layton
@ 2013-12-01 15:57 ` Jeff Layton
0 siblings, 0 replies; 36+ messages in thread
From: Jeff Layton @ 2013-12-01 15:57 UTC (permalink / raw)
To: Jeff Layton; +Cc: Christoph Hellwig, linux-nfs, viro, linux-fsdevel
On Sun, 1 Dec 2013 10:44:22 -0500
Jeff Layton <jlayton@redhat.com> wrote:
> On Sun, 01 Dec 2013 05:14:41 -0800
> Christoph Hellwig <hch@infradead.org> wrote:
>
> > This series tries to get rid of the damage created by sprinkling the
> > network namespace cat poo all over rpc_pipefs and users.
> >
> > Instead of getting lost in a maze of notifiers and infrastructure build
> > around it a cargo cult manner we revert to a slightly nicer version of
> > the pre-namespace API.
> >
> > To do this we just have to create an in-kernel instance of rpc_pipefs
> > that is mounted at network namespace creation so that all functions can
> > operated on it.
> >
> > As-is this has one major downside: because the initial mount already grabs
> > a reference to the network namespace we'll create a cyclic reference and
> > will never free the network namespace. To get around this we'd need
> > some way to only grab it once user mounts show up / disapear in the VFS.
> >
> > Given that the namespace kraken has infected various internal filesystem
> > and will get more soon I suspect this problem is or will become generic
> > and will need a proper solution anyway. Al, any good ideas how to deal
> > with this? Most straight forward way would be to add a counter of
> > user vfsmount to the superblock and methods when it goes to 1 and 0,
> > but that seems a bit ugly.
>
> I see what you mean here...hrm...
>
> One possibility (though it may have holes that I don't see right
> offhand):
>
> Don't call get_ns in rpc_fill_super. Do it in rpc_mount instead, and
> only take the reference if MS_KERNMOUNT isn't set?
...except that we have no mechanism to put those references on each
umount. Nevermind...
--
Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (12 preceding siblings ...)
2013-12-01 15:44 ` Jeff Layton
@ 2013-12-01 18:13 ` Al Viro
2013-12-02 8:12 ` Christoph Hellwig
2013-12-03 2:11 ` [RFC] alloc_pid() breakage Al Viro
2013-12-02 7:23 ` [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Stanislav Kinsbursky
14 siblings, 2 replies; 36+ messages in thread
From: Al Viro @ 2013-12-01 18:13 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linux-nfs, linux-fsdevel, Linus Torvalds, Eric Biederman
On Sun, Dec 01, 2013 at 05:14:41AM -0800, Christoph Hellwig wrote:
> This series tries to get rid of the damage created by sprinkling the
> network namespace cat poo all over rpc_pipefs and users.
>
> Instead of getting lost in a maze of notifiers and infrastructure build
> around it a cargo cult manner we revert to a slightly nicer version of
> the pre-namespace API.
>
> To do this we just have to create an in-kernel instance of rpc_pipefs
> that is mounted at network namespace creation so that all functions can
> operated on it.
>
> As-is this has one major downside: because the initial mount already grabs
> a reference to the network namespace we'll create a cyclic reference and
> will never free the network namespace.
Making the series no-go in that form, obviously.
> To get around this we'd need
> some way to only grab it once user mounts show up / disapear in the VFS.
Hmm... FWIW, there already is something of that sort; it _is_ ugly, but it
might be a food for thought...
AFAICS, pid_ns gets internal procfs instance and it pins the sucker down.
Which would cause exact same problems, obviously. The trick done there
is more or less to introduce a "being shut down" state of pid_ns - from
the moment when we don't have any pids in it to actual destruction.
Entering that state schedules (yes, it is async and yes, it is ugly)
dropping the internal procfs vfsmount.
Additional headache, AFAICS, comes from /proc/self/ns/pid - it can be
opened, passed to somebody in ancestor pidns and then fed by it to
setns(2). After that fork() by that somebody will trigger alloc_pid() in
that pid_ns. What happens if it comes just before the (already scheduled)
pid_ns_release_proc()? AFAICS, nothing good - there's no protection
against leaks, access to freed vfsmount, double-mntput, etc. Eric, am
I missing something subtle and relevant in that code?
> Given that the namespace kraken has infected various internal filesystem
> and will get more soon I suspect this problem is or will become generic
> and will need a proper solution anyway. Al, any good ideas how to deal
> with this? Most straight forward way would be to add a counter of
> user vfsmount to the superblock and methods when it goes to 1 and 0,
> but that seems a bit ugly.
Folks, please, _please_, let's formulate the lifecycle rules first; we
already had way too much trouble from putting mechanism first only to
run into questions like the above ("what happens if somebody tries to
allocate a PID in pid_ns that is already scheduled for shutdown?").
Remember the (recurring) fun with kobject-related lifetime issues?
Or rpc_pipefs notifier ugliness, for that matter...
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-01 18:13 ` Al Viro
@ 2013-12-02 8:12 ` Christoph Hellwig
2013-12-02 13:44 ` Trond Myklebust
2013-12-03 2:11 ` [RFC] alloc_pid() breakage Al Viro
1 sibling, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-02 8:12 UTC (permalink / raw)
To: Al Viro
Cc: Christoph Hellwig, linux-nfs, linux-fsdevel, Linus Torvalds,
Eric Biederman
On Sun, Dec 01, 2013 at 06:13:29PM +0000, Al Viro wrote:
> Making the series no-go in that form, obviously.
Looking at the mess it made I'd almost be tempted to say a little leak
for a less used features is better than lots of pain for everyone..
Looking at the mess it made I'm really upset.
> > Given that the namespace kraken has infected various internal filesystem
> > and will get more soon I suspect this problem is or will become generic
> > and will need a proper solution anyway. Al, any good ideas how to deal
> > with this? Most straight forward way would be to add a counter of
> > user vfsmount to the superblock and methods when it goes to 1 and 0,
> > but that seems a bit ugly.
>
> Folks, please, _please_, let's formulate the lifecycle rules first; we
> already had way too much trouble from putting mechanism first only to
> run into questions like the above ("what happens if somebody tries to
> allocate a PID in pid_ns that is already scheduled for shutdown?").
> Remember the (recurring) fun with kobject-related lifetime issues?
> Or rpc_pipefs notifier ugliness, for that matter...
I'll have to let the net namespace folks chime in for that, as far as
I'm concerned it's a featured better config'ed off. If they can't come
up with anything better the procfs hack above would be it.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 8:12 ` Christoph Hellwig
@ 2013-12-02 13:44 ` Trond Myklebust
2013-12-02 14:24 ` Stanislav Kinsbursky
` (2 more replies)
0 siblings, 3 replies; 36+ messages in thread
From: Trond Myklebust @ 2013-12-02 13:44 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Viro Alexander, Linux NFS Mailing List, Devel FS Linux,
Torvalds Linus, Eric Biederman
On Dec 2, 2013, at 3:12, Christoph Hellwig <hch@infradead.org> wrote:
> On Sun, Dec 01, 2013 at 06:13:29PM +0000, Al Viro wrote:
>> Making the series no-go in that form, obviously.
>
> Looking at the mess it made I'd almost be tempted to say a little leak
> for a less used features is better than lots of pain for everyone..
>
> Looking at the mess it made I'm really upset.
>
>>> Given that the namespace kraken has infected various internal filesystem
>>> and will get more soon I suspect this problem is or will become generic
>>> and will need a proper solution anyway. Al, any good ideas how to deal
>>> with this? Most straight forward way would be to add a counter of
>>> user vfsmount to the superblock and methods when it goes to 1 and 0,
>>> but that seems a bit ugly.
>>
>> Folks, please, _please_, let's formulate the lifecycle rules first; we
>> already had way too much trouble from putting mechanism first only to
>> run into questions like the above ("what happens if somebody tries to
>> allocate a PID in pid_ns that is already scheduled for shutdown?").
>> Remember the (recurring) fun with kobject-related lifetime issues?
>> Or rpc_pipefs notifier ugliness, for that matter...
>
> I'll have to let the net namespace folks chime in for that, as far as
> I'm concerned it's a featured better config'ed off. If they can't come
> up with anything better the procfs hack above would be it.
The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
IOW: move the kernel mount/umount back to the rpc_client create/destroy methods and all should be well.
Cheers
Trond
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 13:44 ` Trond Myklebust
@ 2013-12-02 14:24 ` Stanislav Kinsbursky
2013-12-02 15:36 ` Christoph Hellwig
2013-12-02 15:58 ` Trond Myklebust
2013-12-02 15:34 ` Christoph Hellwig
2013-12-02 15:57 ` Al Viro
2 siblings, 2 replies; 36+ messages in thread
From: Stanislav Kinsbursky @ 2013-12-02 14:24 UTC (permalink / raw)
To: Trond Myklebust, Christoph Hellwig
Cc: Viro Alexander, Linux NFS Mailing List, Devel FS Linux,
Torvalds Linus, Eric Biederman
02.12.2013 17:44, Trond Myklebust пишет:
>
> On Dec 2, 2013, at 3:12, Christoph Hellwig <hch@infradead.org> wrote:
>
>> On Sun, Dec 01, 2013 at 06:13:29PM +0000, Al Viro wrote:
>>> Making the series no-go in that form, obviously.
>>
>> Looking at the mess it made I'd almost be tempted to say a little leak
>> for a less used features is better than lots of pain for everyone..
>>
>> Looking at the mess it made I'm really upset.
>>
>>>> Given that the namespace kraken has infected various internal filesystem
>>>> and will get more soon I suspect this problem is or will become generic
>>>> and will need a proper solution anyway. Al, any good ideas how to deal
>>>> with this? Most straight forward way would be to add a counter of
>>>> user vfsmount to the superblock and methods when it goes to 1 and 0,
>>>> but that seems a bit ugly.
>>>
>>> Folks, please, _please_, let's formulate the lifecycle rules first; we
>>> already had way too much trouble from putting mechanism first only to
>>> run into questions like the above ("what happens if somebody tries to
>>> allocate a PID in pid_ns that is already scheduled for shutdown?").
>>> Remember the (recurring) fun with kobject-related lifetime issues?
>>> Or rpc_pipefs notifier ugliness, for that matter...
>>
>> I'll have to let the net namespace folks chime in for that, as far as
>> I'm concerned it's a featured better config'ed off. If they can't come
>> up with anything better the procfs hack above would be it.
>
> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
>
> IOW: move the kernel mount/umount back to the rpc_client create/destroy methods and all should be well.
>
I'm sorry, guys, if I'm missing the point.
But there was the reason, why all this notifier infrastructure was introduced:
"RPC pipefs superblock should holds network namespace while active."
And that's why:
"RPC pipefs mount can't be performed in kernel context since new super block
will holds networks namespace reference and it's impossible to recognize, when
and how we have to release this mount point."
https://lkml.org/lkml/2011/10/17/123
Circumstances has changed and now all this can be fixed much simplier?
> Cheers
> Trond--
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Best regards,
Stanislav Kinsbursky
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 14:24 ` Stanislav Kinsbursky
@ 2013-12-02 15:36 ` Christoph Hellwig
2013-12-02 15:58 ` Trond Myklebust
1 sibling, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-02 15:36 UTC (permalink / raw)
To: Stanislav Kinsbursky
Cc: Trond Myklebust, Christoph Hellwig, Viro Alexander,
Linux NFS Mailing List, Devel FS Linux, Torvalds Linus,
Eric Biederman
On Mon, Dec 02, 2013 at 06:24:43PM +0400, Stanislav Kinsbursky wrote:
> I'm sorry, guys, if I'm missing the point.
> But there was the reason, why all this notifier infrastructure was introduced:
And the reason is that you're a lazy bastard who let's others clean up
the poo your sprinkle over the tree, and that the maintainers weren't
strict enought to reject that massive pile of junk, which unfortunately
is the common theme in current Linux development.
>
> "RPC pipefs mount can't be performed in kernel context since new super block
> will holds networks namespace reference and it's impossible to recognize, when
> and how we have to release this mount point."
>
> https://lkml.org/lkml/2011/10/17/123
>
> Circumstances has changed and now all this can be fixed much simplier?
As Al pointed our an easy workaround is easily available, and he's also
asked you about exact namespace semantics to be provided so we can
possibly find a less bad option.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 14:24 ` Stanislav Kinsbursky
2013-12-02 15:36 ` Christoph Hellwig
@ 2013-12-02 15:58 ` Trond Myklebust
2013-12-03 7:24 ` Stanislav Kinsbursky
1 sibling, 1 reply; 36+ messages in thread
From: Trond Myklebust @ 2013-12-02 15:58 UTC (permalink / raw)
To: Stanislav Kinsbursky
Cc: Christoph Hellwig, Viro Alexander, Linux NFS Mailing List,
Devel FS Linux, Torvalds Linus, Eric Biederman
On Dec 2, 2013, at 9:24, Stanislav Kinsbursky <skinsbursky@parallels.com> wrote:
> 02.12.2013 17:44, Trond Myklebust пишет:
>>
>> On Dec 2, 2013, at 3:12, Christoph Hellwig <hch@infradead.org> wrote:
>>
>>> On Sun, Dec 01, 2013 at 06:13:29PM +0000, Al Viro wrote:
>>>> Making the series no-go in that form, obviously.
>>>
>>> Looking at the mess it made I'd almost be tempted to say a little leak
>>> for a less used features is better than lots of pain for everyone..
>>>
>>> Looking at the mess it made I'm really upset.
>>>
>>>>> Given that the namespace kraken has infected various internal filesystem
>>>>> and will get more soon I suspect this problem is or will become generic
>>>>> and will need a proper solution anyway. Al, any good ideas how to deal
>>>>> with this? Most straight forward way would be to add a counter of
>>>>> user vfsmount to the superblock and methods when it goes to 1 and 0,
>>>>> but that seems a bit ugly.
>>>>
>>>> Folks, please, _please_, let's formulate the lifecycle rules first; we
>>>> already had way too much trouble from putting mechanism first only to
>>>> run into questions like the above ("what happens if somebody tries to
>>>> allocate a PID in pid_ns that is already scheduled for shutdown?").
>>>> Remember the (recurring) fun with kobject-related lifetime issues?
>>>> Or rpc_pipefs notifier ugliness, for that matter...
>>>
>>> I'll have to let the net namespace folks chime in for that, as far as
>>> I'm concerned it's a featured better config'ed off. If they can't come
>>> up with anything better the procfs hack above would be it.
>>
>> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
>>
>> IOW: move the kernel mount/umount back to the rpc_client create/destroy methods and all should be well.
>>
>
> I'm sorry, guys, if I'm missing the point.
> But there was the reason, why all this notifier infrastructure was introduced:
>
> "RPC pipefs superblock should holds network namespace while active."
>
> And that's why:
>
> "RPC pipefs mount can't be performed in kernel context since new super block
> will holds networks namespace reference and it's impossible to recognize, when
> and how we have to release this mount point."
>
> https://lkml.org/lkml/2011/10/17/123
>
> Circumstances has changed and now all this can be fixed much simplier?
I’m just pointing out that we _do_ know when the rpc_clients no longer needs to access the (per-net namespace) super block. Once we've destroyed the rpc_clients (well, OK, technically once we've destroyed the struct rpc_xprts) that refer to that net namespace, then the kernel no longer needs the super block to be mounted anywhere.
IOW: if we add back a rpc_get_mount(net)/rpc_put_mount(net), then we can call the former when creating the rpc_xprt, and the latter when destroying it. The rpc_pipefs super block is destroyed when both user space and the kernel have umounted it. i.e. when all NFS super blocks from that net name space have been destroyed and the container has unmounted rpc_pipefs.
No?
Cheers,
Trond
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 15:58 ` Trond Myklebust
@ 2013-12-03 7:24 ` Stanislav Kinsbursky
0 siblings, 0 replies; 36+ messages in thread
From: Stanislav Kinsbursky @ 2013-12-03 7:24 UTC (permalink / raw)
To: Trond Myklebust
Cc: Christoph Hellwig, Viro Alexander, Linux NFS Mailing List,
Devel FS Linux, Torvalds Linus, Eric Biederman
02.12.2013 19:58, Trond Myklebust пишет:
>
> On Dec 2, 2013, at 9:24, Stanislav Kinsbursky <skinsbursky@parallels.com> wrote:
>
>> 02.12.2013 17:44, Trond Myklebust пишет:
>>>
>>> On Dec 2, 2013, at 3:12, Christoph Hellwig <hch@infradead.org> wrote:
>>>
>>>> On Sun, Dec 01, 2013 at 06:13:29PM +0000, Al Viro wrote:
>>>>> Making the series no-go in that form, obviously.
>>>>
>>>> Looking at the mess it made I'd almost be tempted to say a little leak
>>>> for a less used features is better than lots of pain for everyone..
>>>>
>>>> Looking at the mess it made I'm really upset.
>>>>
>>>>>> Given that the namespace kraken has infected various internal filesystem
>>>>>> and will get more soon I suspect this problem is or will become generic
>>>>>> and will need a proper solution anyway. Al, any good ideas how to deal
>>>>>> with this? Most straight forward way would be to add a counter of
>>>>>> user vfsmount to the superblock and methods when it goes to 1 and 0,
>>>>>> but that seems a bit ugly.
>>>>>
>>>>> Folks, please, _please_, let's formulate the lifecycle rules first; we
>>>>> already had way too much trouble from putting mechanism first only to
>>>>> run into questions like the above ("what happens if somebody tries to
>>>>> allocate a PID in pid_ns that is already scheduled for shutdown?").
>>>>> Remember the (recurring) fun with kobject-related lifetime issues?
>>>>> Or rpc_pipefs notifier ugliness, for that matter...
>>>>
>>>> I'll have to let the net namespace folks chime in for that, as far as
>>>> I'm concerned it's a featured better config'ed off. If they can't come
>>>> up with anything better the procfs hack above would be it.
>>>
>>> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
>>>
>>> IOW: move the kernel mount/umount back to the rpc_client create/destroy methods and all should be well.
>>>
>>
>> I'm sorry, guys, if I'm missing the point.
>> But there was the reason, why all this notifier infrastructure was introduced:
>>
>> "RPC pipefs superblock should holds network namespace while active."
>>
>> And that's why:
>>
>> "RPC pipefs mount can't be performed in kernel context since new super block
>> will holds networks namespace reference and it's impossible to recognize, when
>> and how we have to release this mount point."
>>
>> https://lkml.org/lkml/2011/10/17/123
>>
>> Circumstances has changed and now all this can be fixed much simplier?
>
> I’m just pointing out that we _do_ know when the rpc_clients no longer needs to access the (per-net namespace) super block. Once we've destroyed the rpc_clients (well, OK, technically once we've destroyed the struct rpc_xprts) that refer to that net namespace, then the kernel no longer needs the super block to be mounted anywhere.
>
> IOW: if we add back a rpc_get_mount(net)/rpc_put_mount(net), then we can call the former when creating the rpc_xprt, and the latter when destroying it. The rpc_pipefs super block is destroyed when both user space and the kernel have umounted it. i.e. when all NFS super blocks from that net name space have been destroyed and the container has unmounted rpc_pipefs.
>
> No?
>
So, you are proposing to create/get per-net mount point either on user space action or rpc client creation?
This should work, I suppose... The only thing which looks weird, is layer violation, when network namespace is being hold by mount point.
> Cheers,
> Trond
>
--
Best regards,
Stanislav Kinsbursky
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 13:44 ` Trond Myklebust
2013-12-02 14:24 ` Stanislav Kinsbursky
@ 2013-12-02 15:34 ` Christoph Hellwig
2013-12-02 16:00 ` Trond Myklebust
2013-12-02 15:57 ` Al Viro
2 siblings, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-02 15:34 UTC (permalink / raw)
To: Trond Myklebust
Cc: Christoph Hellwig, Viro Alexander, Linux NFS Mailing List,
Devel FS Linux, Torvalds Linus, Eric Biederman
On Mon, Dec 02, 2013 at 08:44:25AM -0500, Trond Myklebust wrote:
> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
Except for the non-rpc_client users of rpc_pipefs?
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 15:34 ` Christoph Hellwig
@ 2013-12-02 16:00 ` Trond Myklebust
2013-12-02 16:27 ` Christoph Hellwig
2013-12-02 16:33 ` Jeff Layton
0 siblings, 2 replies; 36+ messages in thread
From: Trond Myklebust @ 2013-12-02 16:00 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Viro Alexander, Linux NFS Mailing List, Devel FS Linux,
Torvalds Linus, Eric Biederman
On Dec 2, 2013, at 10:34, Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Dec 02, 2013 at 08:44:25AM -0500, Trond Myklebust wrote:
>> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
>
> Except for the non-rpc_client users of rpc_pipefs?
There is the idmapper pipe which is created as part of setting up a NFSv4 mount: that could either call rpc_get_mount(), or just rely on the fact that the nfs_client has an rpc_client. Ditto for the DNS resolver pipe.
Any more?
Cheers
Trond
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 16:00 ` Trond Myklebust
@ 2013-12-02 16:27 ` Christoph Hellwig
2013-12-02 16:46 ` Trond Myklebust
2013-12-02 16:33 ` Jeff Layton
1 sibling, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2013-12-02 16:27 UTC (permalink / raw)
To: Trond Myklebust
Cc: Christoph Hellwig, Viro Alexander, Linux NFS Mailing List,
Devel FS Linux, Torvalds Linus, Eric Biederman
On Mon, Dec 02, 2013 at 11:00:50AM -0500, Trond Myklebust wrote:
> > Except for the non-rpc_client users of rpc_pipefs?
>
> There is the idmapper pipe which is created as part of setting up a NFSv4 mount: that could either call rpc_get_mount(), or just rely on the fact that the nfs_client has an rpc_client. Ditto for the DNS resolver pipe.
We got idmapper, dns, pnfs-block upcall.
idmapper seems per-nfs_client, the other two are created on module load
and removed at unload time.
Similarly the pipe in nfsd works globally as well.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 16:27 ` Christoph Hellwig
@ 2013-12-02 16:46 ` Trond Myklebust
0 siblings, 0 replies; 36+ messages in thread
From: Trond Myklebust @ 2013-12-02 16:46 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Viro Alexander, Linux NFS Mailing List, Devel FS Linux,
Torvalds Linus, Eric Biederman
On Dec 2, 2013, at 11:27, Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Dec 02, 2013 at 11:00:50AM -0500, Trond Myklebust wrote:
>>> Except for the non-rpc_client users of rpc_pipefs?
>>
>> There is the idmapper pipe which is created as part of setting up a NFSv4 mount: that could either call rpc_get_mount(), or just rely on the fact that the nfs_client has an rpc_client. Ditto for the DNS resolver pipe.
>
> We got idmapper, dns, pnfs-block upcall.
>
> idmapper seems per-nfs_client, the other two are created on module load
> and removed at unload time.
Do they need to be? AFAICS, we can trivially convert the DNS resolver to be created on mount. The pnfs block upcall looks to be a little more difficult, but we should be able to do it in ld_type->set_layoutdriver()/clear_layoutdriver().
> Similarly the pipe in nfsd works globally as well.
Mount the rpc_pipefs in nfs4_state_create_net() and unmount it in nfs4_state_destroy_net()?
Cheers
Trond
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 16:00 ` Trond Myklebust
2013-12-02 16:27 ` Christoph Hellwig
@ 2013-12-02 16:33 ` Jeff Layton
2013-12-02 16:37 ` J. Bruce Fields
1 sibling, 1 reply; 36+ messages in thread
From: Jeff Layton @ 2013-12-02 16:33 UTC (permalink / raw)
To: Trond Myklebust, bfields
Cc: Christoph Hellwig, Viro Alexander, Linux NFS Mailing List,
Devel FS Linux, Torvalds Linus, Eric Biederman
On Mon, 2 Dec 2013 11:00:50 -0500
Trond Myklebust <trond.myklebust@primarydata.com> wrote:
>
> On Dec 2, 2013, at 10:34, Christoph Hellwig <hch@infradead.org> wrote:
>
> > On Mon, Dec 02, 2013 at 08:44:25AM -0500, Trond Myklebust wrote:
> >> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
> >
> > Except for the non-rpc_client users of rpc_pipefs?
>
> There is the idmapper pipe which is created as part of setting up a NFSv4 mount: that could either call rpc_get_mount(), or just rely on the fact that the nfs_client has an rpc_client. Ditto for the DNS resolver pipe.
>
> Any more?
>
There's the nfsdcld pipe stuff, but that was supposed to have been
ripped out in 3.10. Bruce wasn't ready to do that since we didn't have
a solution to the problem of using a UMH upcall in a container.
As far as I'm concerned, we should go ahead and rip that out and worry
about the UMH in a container problem later. Bruce, any objection to
going ahead and doing that? I can respin/resend the patch to do that if
you're ready for it...
--
Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 16:33 ` Jeff Layton
@ 2013-12-02 16:37 ` J. Bruce Fields
2013-12-02 16:45 ` Jeff Layton
0 siblings, 1 reply; 36+ messages in thread
From: J. Bruce Fields @ 2013-12-02 16:37 UTC (permalink / raw)
To: Jeff Layton
Cc: Trond Myklebust, Christoph Hellwig, Viro Alexander,
Linux NFS Mailing List, Devel FS Linux, Torvalds Linus,
Eric Biederman
On Mon, Dec 02, 2013 at 11:33:19AM -0500, Jeff Layton wrote:
> On Mon, 2 Dec 2013 11:00:50 -0500
> Trond Myklebust <trond.myklebust@primarydata.com> wrote:
>
> >
> > On Dec 2, 2013, at 10:34, Christoph Hellwig <hch@infradead.org> wrote:
> >
> > > On Mon, Dec 02, 2013 at 08:44:25AM -0500, Trond Myklebust wrote:
> > >> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
> > >
> > > Except for the non-rpc_client users of rpc_pipefs?
> >
> > There is the idmapper pipe which is created as part of setting up a NFSv4 mount: that could either call rpc_get_mount(), or just rely on the fact that the nfs_client has an rpc_client. Ditto for the DNS resolver pipe.
> >
> > Any more?
> >
>
> There's the nfsdcld pipe stuff, but that was supposed to have been
> ripped out in 3.10. Bruce wasn't ready to do that since we didn't have
> a solution to the problem of using a UMH upcall in a container.
>
> As far as I'm concerned, we should go ahead and rip that out and worry
> about the UMH in a container problem later. Bruce, any objection to
> going ahead and doing that? I can respin/resend the patch to do that if
> you're ready for it...
I still haven't seen a solution to the UMH problem. Do we even expect
that there will be one at this point?
I just want to avoid the worst case where we decide that UMH was just
not designed for this kind of upcall, period, and then need to backtrack
again....
--b.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 16:37 ` J. Bruce Fields
@ 2013-12-02 16:45 ` Jeff Layton
0 siblings, 0 replies; 36+ messages in thread
From: Jeff Layton @ 2013-12-02 16:45 UTC (permalink / raw)
To: J. Bruce Fields
Cc: Trond Myklebust, Christoph Hellwig, Viro Alexander,
Linux NFS Mailing List, Devel FS Linux, Torvalds Linus,
Eric Biederman
On Mon, 2 Dec 2013 11:37:35 -0500
"J. Bruce Fields" <bfields@fieldses.org> wrote:
> On Mon, Dec 02, 2013 at 11:33:19AM -0500, Jeff Layton wrote:
> > On Mon, 2 Dec 2013 11:00:50 -0500
> > Trond Myklebust <trond.myklebust@primarydata.com> wrote:
> >
> > >
> > > On Dec 2, 2013, at 10:34, Christoph Hellwig <hch@infradead.org> wrote:
> > >
> > > > On Mon, Dec 02, 2013 at 08:44:25AM -0500, Trond Myklebust wrote:
> > > >> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
> > > >
> > > > Except for the non-rpc_client users of rpc_pipefs?
> > >
> > > There is the idmapper pipe which is created as part of setting up a NFSv4 mount: that could either call rpc_get_mount(), or just rely on the fact that the nfs_client has an rpc_client. Ditto for the DNS resolver pipe.
> > >
> > > Any more?
> > >
> >
> > There's the nfsdcld pipe stuff, but that was supposed to have been
> > ripped out in 3.10. Bruce wasn't ready to do that since we didn't have
> > a solution to the problem of using a UMH upcall in a container.
> >
> > As far as I'm concerned, we should go ahead and rip that out and worry
> > about the UMH in a container problem later. Bruce, any objection to
> > going ahead and doing that? I can respin/resend the patch to do that if
> > you're ready for it...
>
> I still haven't seen a solution to the UMH problem. Do we even expect
> that there will be one at this point?
>
> I just want to avoid the worst case where we decide that UMH was just
> not designed for this kind of upcall, period, and then need to backtrack
> again....
>
I don't think there's a solution as of yet...
I'd like to avoid that too, but I expect that no one is actually using
that code anyway. If we have to put it back in (ugh) then we'll
probably need to rethink parts of it anyhow. I'm not aware of any
distro that ever shipped with it enabled.
--
Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 13:44 ` Trond Myklebust
2013-12-02 14:24 ` Stanislav Kinsbursky
2013-12-02 15:34 ` Christoph Hellwig
@ 2013-12-02 15:57 ` Al Viro
2013-12-02 16:04 ` Trond Myklebust
2 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2013-12-02 15:57 UTC (permalink / raw)
To: Trond Myklebust
Cc: Christoph Hellwig, Linux NFS Mailing List, Devel FS Linux,
Torvalds Linus, Eric Biederman
On Mon, Dec 02, 2013 at 08:44:25AM -0500, Trond Myklebust wrote:
> > I'll have to let the net namespace folks chime in for that, as far as
> > I'm concerned it's a featured better config'ed off. If they can't come
> > up with anything better the procfs hack above would be it.
>
> The lifetime of the kernel mount only needs to match that of the rpc_client, since each rpc_client is associated to a single net namespace, and each net namespace is in a 1-1 relationship with an rpc_pipefs super block.
>
> IOW: move the kernel mount/umount back to the rpc_client create/destroy methods and all should be well.
Hmm... I'm looking through rpc_pipe.c and there are some fun issues in there:
* ->kill_sb() *is* called after rpc_fill_super() failures. It's
not ->put_super() (and even ->put_super() would've been called for failures
past setting ->s_root). With ->s_fs_info set only on success, it means
that rpc_kill_sb() will just oops after such failure exits.
* just what is
if (sn->pipefs_sb != sb) {
mutex_unlock(&sn->pipefs_sb_lock);
goto out;
}
sn->pipefs_sb = NULL;
about? In which scenario is it not equal to ->pipefs_sb? When said
->pipefs_sb is NULL? But that, AFAICS, can happen only on cleanup after
failing rpc_fill_super(), in which case we won't get that sn thing in
the first place (in fact, we'll oops trying to get it).
Trond, am I right interpreting you as "that filesystem has non-empty
contents only when there is at least one rpc_client in that netns;
after rpc_client removal there won't be any accesses to data structures
associated with it (due to rpc_close_pipes() and friends, presumably),
so there won't be any need to keep netns alive after that"?
If so and if rpc_client really can't outlive netns, then yes, having each
of them hold an internal vfsmount reference pinning rpc_pipefs down would
suffice.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-02 15:57 ` Al Viro
@ 2013-12-02 16:04 ` Trond Myklebust
0 siblings, 0 replies; 36+ messages in thread
From: Trond Myklebust @ 2013-12-02 16:04 UTC (permalink / raw)
To: Viro Alexander
Cc: Christoph Hellwig, Linux NFS Mailing List, Devel FS Linux,
Torvalds Linus, Eric Biederman
On Dec 2, 2013, at 10:57, Al Viro <viro@ZenIV.linux.org.uk> wrote:
> Trond, am I right interpreting you as "that filesystem has non-empty
> contents only when there is at least one rpc_client in that netns;
> after rpc_client removal there won't be any accesses to data structures
> associated with it (due to rpc_close_pipes() and friends, presumably),
> so there won't be any need to keep netns alive after that"?
>
> If so and if rpc_client really can't outlive netns, then yes, having each
> of them hold an internal vfsmount reference pinning rpc_pipefs down would
> suffice.
We do have some “external” users but in practice their lifetimes are bounded by the lifetimes of the rpc_clients (See my reply to Christoph’s mail).
So yes, I believe that it is the case that we need at least one rpc_client in a given nets for the filesystem to be non-empty.
Cheers,
Trond
^ permalink raw reply [flat|nested] 36+ messages in thread
* [RFC] alloc_pid() breakage
2013-12-01 18:13 ` Al Viro
2013-12-02 8:12 ` Christoph Hellwig
@ 2013-12-03 2:11 ` Al Viro
1 sibling, 0 replies; 36+ messages in thread
From: Al Viro @ 2013-12-03 2:11 UTC (permalink / raw)
To: Eric Biederman
Cc: linux-nfs, linux-fsdevel, Linus Torvalds, Christoph Hellwig
On Sun, Dec 01, 2013 at 06:13:29PM +0000, Al Viro wrote:
> AFAICS, pid_ns gets internal procfs instance and it pins the sucker down.
> Which would cause exact same problems, obviously. The trick done there
> is more or less to introduce a "being shut down" state of pid_ns - from
> the moment when we don't have any pids in it to actual destruction.
> Entering that state schedules (yes, it is async and yes, it is ugly)
> dropping the internal procfs vfsmount.
>
> Additional headache, AFAICS, comes from /proc/self/ns/pid - it can be
> opened, passed to somebody in ancestor pidns and then fed by it to
> setns(2). After that fork() by that somebody will trigger alloc_pid() in
> that pid_ns. What happens if it comes just before the (already scheduled)
> pid_ns_release_proc()? AFAICS, nothing good - there's no protection
> against leaks, access to freed vfsmount, double-mntput, etc. Eric, am
> I missing something subtle and relevant in that code?
Egads... I think I see what's going on, but it's convoluted as hell -
you rely on 1 not getting returned more than once by alloc_pidmap(), even
after having been freed, so this
if (unlikely(is_child_reaper(pid))) {
if (pid_ns_prepare_proc(ns))
goto out_free;
}
is essentially "on the first call of alloc_pid() for given pidns". And
upper bit in ->nr_hashed acts as "it's not in rundown state".
OK, so... what happens if I do unshare(CLONE_NEWPID) and the first fork()
attempt fails (e.g. due to failure to allocate a map page when allocating
a number in parent pidns, or OOM-induced failure to mount procfs, whatever).
Sure, that fork() has failed. No pid had been allocated, thus no free_pid()
calls made. After a while the memory becomes less tight and the same process
tries to fork() again. What happens then? pidns with processes in it,
but no reaper and NULL ->proc_mnt? sysctl(2) called in it won't be happy;
neither will exit(2), actually, since it'll hit proc_flush_task_mnt() and
oops on trying to evaluate ->proc_mnt->mnt_root...
Another question: can free_pid() end up scheduling ->proc_work for anything
other than the last level? After all, reaper in parent pidns couldn't have
gotten through the zap_pid_ns_process() yet, let alone getting to its
free_pid(), right?
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs
2013-12-01 13:14 [PATCH 00/11] [RFC] repair net namespace damage to rpc_pipefs Christoph Hellwig
` (13 preceding siblings ...)
2013-12-01 18:13 ` Al Viro
@ 2013-12-02 7:23 ` Stanislav Kinsbursky
14 siblings, 0 replies; 36+ messages in thread
From: Stanislav Kinsbursky @ 2013-12-02 7:23 UTC (permalink / raw)
To: Christoph Hellwig, linux-nfs, viro; +Cc: linux-fsdevel
01.12.2013 17:14, Christoph Hellwig пишет:
> As-is this has one major downside: because the initial mount already grabs
> a reference to the network namespace we'll create a cyclic reference and
> will never free the network namespace. To get around this we'd need
> some way to only grab it once user mounts show up / disapear in the VFS.
That's a great cleanup of the whole PipeFS mount/umount logic. And it actually
moves code to the state it was (with minor changes) before net namespace
changes.
But the reason for all this "damage" was exactly to remove this major downside
and do _not_ tie network namespace to mount point..
So, please, solve the problem before reverting all this notifiers and friends.
--
Best regards,
Stanislav Kinsbursky
^ permalink raw reply [flat|nested] 36+ messages in thread