diff options
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 193 |
1 files changed, 171 insertions, 22 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 406859cc68aa..f94567b45bb3 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -409,7 +409,7 @@ rpc_show_info(struct seq_file *m, void *v) | |||
409 | rcu_read_lock(); | 409 | rcu_read_lock(); |
410 | seq_printf(m, "RPC server: %s\n", | 410 | seq_printf(m, "RPC server: %s\n", |
411 | rcu_dereference(clnt->cl_xprt)->servername); | 411 | rcu_dereference(clnt->cl_xprt)->servername); |
412 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, | 412 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_program->name, |
413 | clnt->cl_prog, clnt->cl_vers); | 413 | clnt->cl_prog, clnt->cl_vers); |
414 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 414 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
415 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 415 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
@@ -480,23 +480,6 @@ static const struct dentry_operations rpc_dentry_operations = { | |||
480 | .d_delete = rpc_delete_dentry, | 480 | .d_delete = rpc_delete_dentry, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | /* | ||
484 | * Lookup the data. This is trivial - if the dentry didn't already | ||
485 | * exist, we know it is negative. | ||
486 | */ | ||
487 | static struct dentry * | ||
488 | rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | ||
489 | { | ||
490 | if (dentry->d_name.len > NAME_MAX) | ||
491 | return ERR_PTR(-ENAMETOOLONG); | ||
492 | d_add(dentry, NULL); | ||
493 | return NULL; | ||
494 | } | ||
495 | |||
496 | static const struct inode_operations rpc_dir_inode_operations = { | ||
497 | .lookup = rpc_lookup, | ||
498 | }; | ||
499 | |||
500 | static struct inode * | 483 | static struct inode * |
501 | rpc_get_inode(struct super_block *sb, umode_t mode) | 484 | rpc_get_inode(struct super_block *sb, umode_t mode) |
502 | { | 485 | { |
@@ -509,7 +492,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode) | |||
509 | switch (mode & S_IFMT) { | 492 | switch (mode & S_IFMT) { |
510 | case S_IFDIR: | 493 | case S_IFDIR: |
511 | inode->i_fop = &simple_dir_operations; | 494 | inode->i_fop = &simple_dir_operations; |
512 | inode->i_op = &rpc_dir_inode_operations; | 495 | inode->i_op = &simple_dir_inode_operations; |
513 | inc_nlink(inode); | 496 | inc_nlink(inode); |
514 | default: | 497 | default: |
515 | break; | 498 | break; |
@@ -901,6 +884,159 @@ rpc_unlink(struct dentry *dentry) | |||
901 | } | 884 | } |
902 | EXPORT_SYMBOL_GPL(rpc_unlink); | 885 | EXPORT_SYMBOL_GPL(rpc_unlink); |
903 | 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 | */ | ||
891 | void 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 | } | ||
896 | EXPORT_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 | */ | ||
904 | void 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 | } | ||
912 | EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object); | ||
913 | |||
914 | static int | ||
915 | rpc_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 | |||
928 | static void | ||
929 | rpc_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 | */ | ||
945 | int | ||
946 | rpc_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 | } | ||
961 | EXPORT_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 | */ | ||
970 | void | ||
971 | rpc_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 | } | ||
983 | EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object); | ||
984 | |||
985 | /** | ||
986 | * rpc_find_or_alloc_pipe_dir_object | ||
987 | * @net: pointer to struct net | ||
988 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
989 | * @match: match struct rpc_pipe_dir_object to data | ||
990 | * @alloc: allocate a new struct rpc_pipe_dir_object | ||
991 | * @data: user defined data for match() and alloc() | ||
992 | * | ||
993 | */ | ||
994 | struct rpc_pipe_dir_object * | ||
995 | rpc_find_or_alloc_pipe_dir_object(struct net *net, | ||
996 | struct rpc_pipe_dir_head *pdh, | ||
997 | int (*match)(struct rpc_pipe_dir_object *, void *), | ||
998 | struct rpc_pipe_dir_object *(*alloc)(void *), | ||
999 | void *data) | ||
1000 | { | ||
1001 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1002 | struct rpc_pipe_dir_object *pdo; | ||
1003 | |||
1004 | mutex_lock(&sn->pipefs_sb_lock); | ||
1005 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) { | ||
1006 | if (!match(pdo, data)) | ||
1007 | continue; | ||
1008 | goto out; | ||
1009 | } | ||
1010 | pdo = alloc(data); | ||
1011 | if (!pdo) | ||
1012 | goto out; | ||
1013 | rpc_add_pipe_dir_object_locked(net, pdh, pdo); | ||
1014 | out: | ||
1015 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1016 | return pdo; | ||
1017 | } | ||
1018 | EXPORT_SYMBOL_GPL(rpc_find_or_alloc_pipe_dir_object); | ||
1019 | |||
1020 | static void | ||
1021 | rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh) | ||
1022 | { | ||
1023 | struct rpc_pipe_dir_object *pdo; | ||
1024 | struct dentry *dir = pdh->pdh_dentry; | ||
1025 | |||
1026 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) | ||
1027 | pdo->pdo_ops->create(dir, pdo); | ||
1028 | } | ||
1029 | |||
1030 | static void | ||
1031 | rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh) | ||
1032 | { | ||
1033 | struct rpc_pipe_dir_object *pdo; | ||
1034 | struct dentry *dir = pdh->pdh_dentry; | ||
1035 | |||
1036 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) | ||
1037 | pdo->pdo_ops->destroy(dir, pdo); | ||
1038 | } | ||
1039 | |||
904 | enum { | 1040 | enum { |
905 | RPCAUTH_info, | 1041 | RPCAUTH_info, |
906 | RPCAUTH_EOF | 1042 | RPCAUTH_EOF |
@@ -941,16 +1077,29 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry, | |||
941 | const char *name, | 1077 | const char *name, |
942 | struct rpc_clnt *rpc_client) | 1078 | struct rpc_clnt *rpc_client) |
943 | { | 1079 | { |
944 | return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, | 1080 | struct dentry *ret; |
1081 | |||
1082 | ret = rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, | ||
945 | rpc_clntdir_populate, rpc_client); | 1083 | rpc_clntdir_populate, rpc_client); |
1084 | if (!IS_ERR(ret)) { | ||
1085 | rpc_client->cl_pipedir_objects.pdh_dentry = ret; | ||
1086 | rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects); | ||
1087 | } | ||
1088 | return ret; | ||
946 | } | 1089 | } |
947 | 1090 | ||
948 | /** | 1091 | /** |
949 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() | 1092 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() |
950 | * @dentry: dentry for the pipe | 1093 | * @rpc_client: rpc_client for the pipe |
951 | */ | 1094 | */ |
952 | int rpc_remove_client_dir(struct dentry *dentry) | 1095 | int rpc_remove_client_dir(struct rpc_clnt *rpc_client) |
953 | { | 1096 | { |
1097 | struct dentry *dentry = rpc_client->cl_pipedir_objects.pdh_dentry; | ||
1098 | |||
1099 | if (dentry == NULL) | ||
1100 | return 0; | ||
1101 | rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects); | ||
1102 | rpc_client->cl_pipedir_objects.pdh_dentry = NULL; | ||
954 | return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); | 1103 | return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); |
955 | } | 1104 | } |
956 | 1105 | ||