Skip to content

Commit

Permalink
SUNRPC: subscribe RPC clients to pipefs notifications
Browse files Browse the repository at this point in the history
This patch subscribes RPC clients to RPC pipefs notifications. RPC clients
notifier block is registering with pipefs initialization during SUNRPC module
init.
This notifier callback is responsible for RPC client PipeFS directory and GSS
pipes creation. For pipes creation and destruction two additional callbacks
were added to struct rpc_authops.
Note that no locking required in notifier callback because PipeFS superblock
pointer is passed as an argument from it's creation or destruction routine and
thus we can be sure about it's validity.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Stanislav Kinsbursky authored and Trond Myklebust committed Jan 31, 2012
1 parent 70abc49 commit 80df9d2
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 10 deletions.
2 changes: 2 additions & 0 deletions include/linux/sunrpc/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ struct rpc_authops {

struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
int (*pipes_create)(struct rpc_auth *);
void (*pipes_destroy)(struct rpc_auth *);
};

struct rpc_credops {
Expand Down
10 changes: 7 additions & 3 deletions net/sunrpc/auth_gss/auth_gss.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,8 +762,10 @@ static void gss_pipes_dentries_destroy(struct rpc_auth *auth)
struct gss_auth *gss_auth;

gss_auth = container_of(auth, struct gss_auth, rpc_auth);
rpc_unlink(gss_auth->pipe[0]->dentry);
rpc_unlink(gss_auth->pipe[1]->dentry);
if (gss_auth->pipe[0]->dentry)
rpc_unlink(gss_auth->pipe[0]->dentry);
if (gss_auth->pipe[1]->dentry)
rpc_unlink(gss_auth->pipe[1]->dentry);
}

static int gss_pipes_dentries_create(struct rpc_auth *auth)
Expand Down Expand Up @@ -1614,7 +1616,9 @@ static const struct rpc_authops authgss_ops = {
.create = gss_create,
.destroy = gss_destroy,
.lookup_cred = gss_lookup_cred,
.crcreate = gss_create_cred
.crcreate = gss_create_cred,
.pipes_create = gss_pipes_dentries_create,
.pipes_destroy = gss_pipes_dentries_destroy,
};

static const struct rpc_credops gss_credops = {
Expand Down
69 changes: 68 additions & 1 deletion net/sunrpc/clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)

static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
{
if (clnt->cl_path.dentry)
if (clnt->cl_path.dentry) {
if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy)
clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth);
rpc_remove_client_dir(clnt->cl_path.dentry);
}
clnt->cl_path.dentry = NULL;
}

Expand Down Expand Up @@ -181,6 +184,70 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
return 0;
}

static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
struct super_block *sb)
{
struct dentry *dentry;
int err = 0;

switch (event) {
case RPC_PIPEFS_MOUNT:
if (clnt->cl_program->pipe_dir_name == NULL)
break;
dentry = rpc_setup_pipedir_sb(sb, clnt,
clnt->cl_program->pipe_dir_name);
BUG_ON(dentry == NULL);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
clnt->cl_path.dentry = dentry;
if (clnt->cl_auth->au_ops->pipes_create) {
err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth);
if (err)
__rpc_clnt_remove_pipedir(clnt);
}
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 notifier_block *nb, unsigned long event,
void *ptr)
{
struct super_block *sb = ptr;
struct rpc_clnt *clnt;
int error = 0;
struct sunrpc_net *sn = net_generic(sb->s_fs_info, sunrpc_net_id);

spin_lock(&sn->rpc_client_lock);
list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
error = __rpc_pipefs_event(clnt, event, sb);
if (error)
break;
}
spin_unlock(&sn->rpc_client_lock);
return error;
}

static struct notifier_block rpc_clients_block = {
.notifier_call = rpc_pipefs_event,
};

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_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
{
struct rpc_program *program = args->program;
Expand Down
19 changes: 13 additions & 6 deletions net/sunrpc/rpc_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry,

/**
* rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
* @dentry: directory to remove
* @clnt: rpc client
*/
int rpc_remove_client_dir(struct dentry *dentry)
{
Expand Down Expand Up @@ -1188,17 +1188,24 @@ int register_rpc_pipefs(void)
init_once);
if (!rpc_inode_cachep)
return -ENOMEM;
err = rpc_clients_notifier_register();
if (err)
goto err_notifier;
err = register_filesystem(&rpc_pipe_fs_type);
if (err) {
kmem_cache_destroy(rpc_inode_cachep);
return err;
}

if (err)
goto err_register;
return 0;

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);
}
Expand Down
2 changes: 2 additions & 0 deletions net/sunrpc/sunrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,7 @@ 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 */

0 comments on commit 80df9d2

Please sign in to comment.