aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-08-26 15:38:11 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-08-30 09:19:38 -0400
commit6739ffb754b47e6c0fa9d9e268bde828f6856528 (patch)
tree2bb59f676758404f87954c5f631c816935064490
parentd7631250b20119ea763d9ba461c3a9c5710cfa98 (diff)
SUNRPC: Add a framework to clean up management of rpc_pipefs directories
The current system requires everyone to set up notifiers, manage directory locking, etc. What we really want to do is have the rpc_client create its directory, and then create all the entries. This patch will allow the RPCSEC_GSS and NFS code to register all the objects that they want to have appear in the directory, and then have the sunrpc code call them back to actually create/destroy their pipefs dentries when the rpc_client creates/destroys the parent. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/linux/sunrpc/rpc_pipe_fs.h33
-rw-r--r--net/sunrpc/clnt.c3
-rw-r--r--net/sunrpc/rpc_pipe.c134
4 files changed, 168 insertions, 4 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index b93b4aa49ffd..0dccd01ae2de 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -21,6 +21,7 @@
21#include <linux/sunrpc/stats.h> 21#include <linux/sunrpc/stats.h>
22#include <linux/sunrpc/xdr.h> 22#include <linux/sunrpc/xdr.h>
23#include <linux/sunrpc/timer.h> 23#include <linux/sunrpc/timer.h>
24#include <linux/sunrpc/rpc_pipe_fs.h>
24#include <asm/signal.h> 25#include <asm/signal.h>
25#include <linux/path.h> 26#include <linux/path.h>
26#include <net/ipv6.h> 27#include <net/ipv6.h>
@@ -55,6 +56,7 @@ struct rpc_clnt {
55 56
56 int cl_nodelen; /* nodename length */ 57 int cl_nodelen; /* nodename length */
57 char cl_nodename[UNX_MAXNODENAME]; 58 char cl_nodename[UNX_MAXNODENAME];
59 struct rpc_pipe_dir_head cl_pipedir_objects;
58 struct dentry * cl_dentry; 60 struct dentry * cl_dentry;
59 struct rpc_clnt * cl_parent; /* Points to parent of clones */ 61 struct rpc_clnt * cl_parent; /* Points to parent of clones */
60 struct rpc_rtt cl_rtt_default; 62 struct rpc_rtt cl_rtt_default;
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index aa5b582cc471..188e7fca67e1 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -5,6 +5,26 @@
5 5
6#include <linux/workqueue.h> 6#include <linux/workqueue.h>
7 7
8struct rpc_pipe_dir_head {
9 struct list_head pdh_entries;
10 struct dentry *pdh_dentry;
11};
12
13struct rpc_pipe_dir_object_ops;
14struct rpc_pipe_dir_object {
15 struct list_head pdo_head;
16 const struct rpc_pipe_dir_object_ops *pdo_ops;
17
18 void *pdo_data;
19};
20
21struct rpc_pipe_dir_object_ops {
22 int (*create)(struct dentry *dir,
23 struct rpc_pipe_dir_object *pdo);
24 void (*destroy)(struct dentry *dir,
25 struct rpc_pipe_dir_object *pdo);
26};
27
8struct rpc_pipe_msg { 28struct rpc_pipe_msg {
9 struct list_head list; 29 struct list_head list;
10 void *data; 30 void *data;
@@ -74,7 +94,18 @@ extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
74 94
75struct rpc_clnt; 95struct rpc_clnt;
76extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *); 96extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *);
77extern int rpc_remove_client_dir(struct dentry *); 97extern int rpc_remove_client_dir(struct dentry *, struct rpc_clnt *);
98
99extern void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh);
100extern void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
101 const struct rpc_pipe_dir_object_ops *pdo_ops,
102 void *pdo_data);
103extern int rpc_add_pipe_dir_object(struct net *net,
104 struct rpc_pipe_dir_head *pdh,
105 struct rpc_pipe_dir_object *pdo);
106extern void rpc_remove_pipe_dir_object(struct net *net,
107 struct rpc_pipe_dir_head *pdh,
108 struct rpc_pipe_dir_object *pdo);
78 109
79struct cache_detail; 110struct cache_detail;
80extern struct dentry *rpc_create_cache_dir(struct dentry *, 111extern struct dentry *rpc_create_cache_dir(struct dentry *,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 7407f1d86ebb..01d22961a0ce 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -105,7 +105,7 @@ static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
105 if (clnt->cl_dentry) { 105 if (clnt->cl_dentry) {
106 if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) 106 if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy)
107 clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); 107 clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth);
108 rpc_remove_client_dir(clnt->cl_dentry); 108 rpc_remove_client_dir(clnt->cl_dentry, clnt);
109 } 109 }
110 clnt->cl_dentry = NULL; 110 clnt->cl_dentry = NULL;
111} 111}
@@ -355,6 +355,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
355 clnt->cl_vers = version->number; 355 clnt->cl_vers = version->number;
356 clnt->cl_stats = program->stats; 356 clnt->cl_stats = program->stats;
357 clnt->cl_metrics = rpc_alloc_iostats(clnt); 357 clnt->cl_metrics = rpc_alloc_iostats(clnt);
358 rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects);
358 err = -ENOMEM; 359 err = -ENOMEM;
359 if (clnt->cl_metrics == NULL) 360 if (clnt->cl_metrics == NULL)
360 goto out_no_stats; 361 goto out_no_stats;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index b36bfb93924c..cfeba77de567 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -884,6 +884,124 @@ rpc_unlink(struct dentry *dentry)
884} 884}
885EXPORT_SYMBOL_GPL(rpc_unlink); 885EXPORT_SYMBOL_GPL(rpc_unlink);
886 886
887/**
888 * rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head
889 * @pdh: pointer to struct rpc_pipe_dir_head
890 */
891void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh)
892{
893 INIT_LIST_HEAD(&pdh->pdh_entries);
894 pdh->pdh_dentry = NULL;
895}
896EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_head);
897
898/**
899 * rpc_init_pipe_dir_object - initialise a struct rpc_pipe_dir_object
900 * @pdo: pointer to struct rpc_pipe_dir_object
901 * @pdo_ops: pointer to const struct rpc_pipe_dir_object_ops
902 * @pdo_data: pointer to caller-defined data
903 */
904void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
905 const struct rpc_pipe_dir_object_ops *pdo_ops,
906 void *pdo_data)
907{
908 INIT_LIST_HEAD(&pdo->pdo_head);
909 pdo->pdo_ops = pdo_ops;
910 pdo->pdo_data = pdo_data;
911}
912EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object);
913
914static int
915rpc_add_pipe_dir_object_locked(struct net *net,
916 struct rpc_pipe_dir_head *pdh,
917 struct rpc_pipe_dir_object *pdo)
918{
919 int ret = 0;
920
921 if (pdh->pdh_dentry)
922 ret = pdo->pdo_ops->create(pdh->pdh_dentry, pdo);
923 if (ret == 0)
924 list_add_tail(&pdo->pdo_head, &pdh->pdh_entries);
925 return ret;
926}
927
928static void
929rpc_remove_pipe_dir_object_locked(struct net *net,
930 struct rpc_pipe_dir_head *pdh,
931 struct rpc_pipe_dir_object *pdo)
932{
933 if (pdh->pdh_dentry)
934 pdo->pdo_ops->destroy(pdh->pdh_dentry, pdo);
935 list_del_init(&pdo->pdo_head);
936}
937
938/**
939 * rpc_add_pipe_dir_object - associate a rpc_pipe_dir_object to a directory
940 * @net: pointer to struct net
941 * @pdh: pointer to struct rpc_pipe_dir_head
942 * @pdo: pointer to struct rpc_pipe_dir_object
943 *
944 */
945int
946rpc_add_pipe_dir_object(struct net *net,
947 struct rpc_pipe_dir_head *pdh,
948 struct rpc_pipe_dir_object *pdo)
949{
950 int ret = 0;
951
952 if (list_empty(&pdo->pdo_head)) {
953 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
954
955 mutex_lock(&sn->pipefs_sb_lock);
956 ret = rpc_add_pipe_dir_object_locked(net, pdh, pdo);
957 mutex_unlock(&sn->pipefs_sb_lock);
958 }
959 return ret;
960}
961EXPORT_SYMBOL_GPL(rpc_add_pipe_dir_object);
962
963/**
964 * rpc_remove_pipe_dir_object - remove a rpc_pipe_dir_object from a directory
965 * @net: pointer to struct net
966 * @pdh: pointer to struct rpc_pipe_dir_head
967 * @pdo: pointer to struct rpc_pipe_dir_object
968 *
969 */
970void
971rpc_remove_pipe_dir_object(struct net *net,
972 struct rpc_pipe_dir_head *pdh,
973 struct rpc_pipe_dir_object *pdo)
974{
975 if (!list_empty(&pdo->pdo_head)) {
976 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
977
978 mutex_lock(&sn->pipefs_sb_lock);
979 rpc_remove_pipe_dir_object_locked(net, pdh, pdo);
980 mutex_unlock(&sn->pipefs_sb_lock);
981 }
982}
983EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object);
984
985static void
986rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
987{
988 struct rpc_pipe_dir_object *pdo;
989 struct dentry *dir = pdh->pdh_dentry;
990
991 list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
992 pdo->pdo_ops->create(dir, pdo);
993}
994
995static void
996rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
997{
998 struct rpc_pipe_dir_object *pdo;
999 struct dentry *dir = pdh->pdh_dentry;
1000
1001 list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
1002 pdo->pdo_ops->destroy(dir, pdo);
1003}
1004
887enum { 1005enum {
888 RPCAUTH_info, 1006 RPCAUTH_info,
889 RPCAUTH_EOF 1007 RPCAUTH_EOF
@@ -924,16 +1042,28 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry,
924 const char *name, 1042 const char *name,
925 struct rpc_clnt *rpc_client) 1043 struct rpc_clnt *rpc_client)
926{ 1044{
927 return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, 1045 struct dentry *ret;
1046
1047 ret = rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL,
928 rpc_clntdir_populate, rpc_client); 1048 rpc_clntdir_populate, rpc_client);
1049 if (!IS_ERR(ret)) {
1050 rpc_client->cl_pipedir_objects.pdh_dentry = ret;
1051 rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
1052 }
1053 return ret;
929} 1054}
930 1055
931/** 1056/**
932 * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() 1057 * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
933 * @dentry: dentry for the pipe 1058 * @dentry: dentry for the pipe
1059 * @rpc_client: rpc_client for the pipe
934 */ 1060 */
935int rpc_remove_client_dir(struct dentry *dentry) 1061int rpc_remove_client_dir(struct dentry *dentry, struct rpc_clnt *rpc_client)
936{ 1062{
1063 if (rpc_client->cl_pipedir_objects.pdh_dentry) {
1064 rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
1065 rpc_client->cl_pipedir_objects.pdh_dentry = NULL;
1066 }
937 return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); 1067 return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate);
938} 1068}
939 1069