convert write_threads, write_version and write_ports to netlink commands
Subsystems (5)
v7 cover convert write_threads, write_version and write_ports to netlink commands
Introduce write_threads, write_version and write_ports netlink commands similar to the ones available through the procfs.
Changes since v6:
- add the capability to pass sockaddr from userspace through listener-set command
- rebase on top of nfsd-next
Changes since v5:
- for write_ports and write_version commands, userspace is expected to provide a NFS listeners/supported versions list it want to enable (all the other ports/versions will be disabled).
- fix comments
- rebase on top of nfsd-next
Changes since v4:
- rebase on top of nfsd-next tree
Changes since v3:
- drop write_maxconn and write_maxblksize for the moment
- add write_version and write_ports commands
Changes since v2:
- use u32 to store nthreads in nfsd_nl_threads_set_doit
- rename server-attr in control-plane in nfsd.yaml specs
Changes since v1:
- remove write_v4_end_grace command
- add write_maxblksize and write_maxconn netlink commands
This patch can be tested with user-space tool reported below:
https://github.com/LorenzoBianconi/nfsdctl
Jeff Layton (1):
SUNRPC: add a new svc_find_listener helper
Lorenzo Bianconi (4):
NFSD: convert write_threads to netlink command
NFSD: add write_version to netlink command
SUNRPC: introduce svc_xprt_create_from_sa utility routine
NFSD: add listener-{set,get} netlink command
Documentation/netlink/specs/nfsd.yaml | 94 ++++++ fs/nfsd/netlink.c | 63 ++++ fs/nfsd/netlink.h | 10 + fs/nfsd/netns.h | 1 + fs/nfsd/nfsctl.c | 433 ++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 3 +- include/linux/sunrpc/svc_xprt.h | 5 + include/uapi/linux/nfsd_netlink.h | 44 +++ net/sunrpc/svc_xprt.c | 167 ++++++---- 9 files changed, 760 insertions(+), 60 deletions(-)
Signature · 1 line
2.44.0
PATCH v7 1/5 NFSD: convert write_threads to netlink command
Introduce write_threads netlink command similar to the one available through the procfs.
--- Documentation/netlink/specs/nfsd.yaml | 23 ++++++++++ fs/nfsd/netlink.c | 17 ++++++++ fs/nfsd/netlink.h | 2 + fs/nfsd/nfsctl.c | 60 +++++++++++++++++++++++++++ include/uapi/linux/nfsd_netlink.h | 9 ++++ 5 files changed, 111 insertions(+)
Documentation/netlink/specs/nfsd.yaml +23 -0
@@ -62,6 +62,12 @@ attribute-sets: name: compound-ops type: u32 multi-attr: true + - + name: server-worker + attributes: + - + name: threads + type: u32 operations: list:
@@ -87,3 +93,20 @@ operations: - sport - dport - compound-ops + - + name: threads-set + doc: set the number of running threads + attribute-set: server-worker + flags: [ admin-perm ] + do: + request: + attributes: + - threads + - + name: threads-get + doc: get the number of running threads + attribute-set: server-worker + do: + reply: + attributes: + - threads
fs/nfsd/netlink.c +17 -0
@@ -10,6 +10,11 @@#include <uapi/linux/nfsd_netlink.h> +/* NFSD_CMD_THREADS_SET - do */ +static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_WORKER_THREADS +1 ] = { + [NFSD_A_SERVER_WORKER_THREADS ] = { .type =NLA_U32 , }, +}; +/* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] = { {
@@ -19,6 +24,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .done = nfsd_nl_rpc_status_get_done, .flags = GENL_CMD_CAP_DUMP, }, + { + .cmd = NFSD_CMD_THREADS_SET, + .doit = nfsd_nl_threads_set_doit, + .policy = nfsd_threads_set_nl_policy, + .maxattr = NFSD_A_SERVER_WORKER_THREADS, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = NFSD_CMD_THREADS_GET, + .doit = nfsd_nl_threads_get_doit, + .flags = GENL_CMD_CAP_DO, + }, }; struct genl_family nfsd_nl_family __ro_after_init = {
fs/nfsd/netlink.h +2 -0
@@ -16,6 +16,8 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb);int nfsd_nl_rpc_status_get_dumpit (struct sk_buff *skb,struct netlink_callback *cb); +int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info);extern struct genl_family nfsd_nl_family;
fs/nfsd/nfsctl.c +60 -0
66 lines not on this page · raw message
include/uapi/linux/nfsd_netlink.h +9 -0
@@ -29,8 +29,17 @@ enum {NFSD_A_RPC_STATUS_MAX = (__NFSD_A_RPC_STATUS_MAX -1 ) }; +enum { +NFSD_A_SERVER_WORKER_THREADS =1 , + + __NFSD_A_SERVER_WORKER_MAX, +NFSD_A_SERVER_WORKER_MAX = (__NFSD_A_SERVER_WORKER_MAX -1 ) +}; +enum {NFSD_CMD_RPC_STATUS_GET =1 , +NFSD_CMD_THREADS_SET , +NFSD_CMD_THREADS_GET , __NFSD_CMD_MAX,NFSD_CMD_MAX = (__NFSD_CMD_MAX -1 )
Signature · 1 line
2.44.0
Jeff Layton
maintainerRe: [PATCH v7 1/5] NFSD: convert write_threads to netlink command
Quoted 34 lines · Lorenzo Bianconi
Introduce
write_threadsnetlink command similar to the one available through the procfs.Tested-by Jeff Layton <[email protected]>Reviewed-by Jeff Layton <[email protected]>Signed-off-by Lorenzo Bianconi <[email protected]>--- Documentation/netlink/specs/nfsd.yaml | 23 ++++++++++ fs/nfsd/netlink.c | 17 ++++++++ fs/nfsd/netlink.h | 2 + fs/nfsd/nfsctl.c | 60 +++++++++++++++++++++++++++ include/uapi/linux/nfsd_netlink.h | 9 ++++ 5 files changed, 111 insertions(+)Documentation/netlink/specs/nfsd.yaml +6
-0@@ -62,6 +62,12 @@ attribute-sets: name: compound-ops type: u32 multi-attr: true + - + name: server-worker + attributes: + - + name: threads + type: u32 operations: list:@@ -87,3 +93,20 @@ operations: - sport - dport
Documentation/netlink/specs/nfsd.yaml operations: · line 104
Quoted 10 lines
Documentation/netlink/specs/nfsd.yaml +9
-0- compound-ops + - + name: threads-set + doc: set the number of running threads + attribute-set: server-worker + flags: [ admin-perm ] + do: + request: + attributes: + - threads
There's only one thing I think we're missing to get feature parity with rpc.nfsd, and that's the ability to set the lease-time and grace-time when starting the server.
I think the simplest thing to do would be to just add 2 optional int parameters to the threads-set command. They only matter once you're starting the server anyway. I'll see about spinning up a patch, but let me know if you see problems with that approach.
Quoted 149 lines
Documentation/netlink/specs/nfsd.yaml +8
-0+ - + name: threads-get + doc: get the number of running threads + attribute-set: server-worker + do: + reply: + attributes: + - threadsfs/nfsd/netlink.c +17
-0@@ -10,6 +10,11 @@#include <uapi/linux/nfsd_netlink.h> +/* NFSD_CMD_THREADS_SET - do */ +static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_WORKER_THREADS +1 ] = { + [NFSD_A_SERVER_WORKER_THREADS ] = { .type =NLA_U32 , }, +}; +/* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] = { {@@ -19,6 +24,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .done = nfsd_nl_rpc_status_get_done, .flags = GENL_CMD_CAP_DUMP, }, + { + .cmd = NFSD_CMD_THREADS_SET, + .doit = nfsd_nl_threads_set_doit, + .policy = nfsd_threads_set_nl_policy, + .maxattr = NFSD_A_SERVER_WORKER_THREADS, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = NFSD_CMD_THREADS_GET, + .doit = nfsd_nl_threads_get_doit, + .flags = GENL_CMD_CAP_DO, + }, }; struct genl_family nfsd_nl_family __ro_after_init = {fs/nfsd/netlink.h +2
-0@@ -16,6 +16,8 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb);int nfsd_nl_rpc_status_get_dumpit (struct sk_buff *skb,struct netlink_callback *cb); +int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info);extern struct genl_family nfsd_nl_family;fs/nfsd/nfsctl.c +60
-0@@ -1651,6 +1651,66 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb)return 0 ; } +/** +* nfsd_nl_threads_set_doit - set the number of running threads +* @skb: reply buffer +* @info: netlink metadata and command arguments +* +* Return 0 on success or a negative errno. +*/ +int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info) +{ +u32 nthreads; +int ret; + +if (GENL_REQ_ATTR_CHECK (info,NFSD_A_SERVER_WORKER_THREADS )) +return -EINVAL ; + + nthreads =nla_get_u32 (info->attrs[NFSD_A_SERVER_WORKER_THREADS ]); + ret =nfsd_svc (nthreads, +genl_info_net (info),get_current_cred ()); + +return ret == nthreads ?0 : -EINVAL ; +} + +/** +* nfsd_nl_threads_get_doit - get the number of running threads +* @skb: reply buffer +* @info: netlink metadata and command arguments +* +* Return 0 on success or a negative errno. +*/ +int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info) +{ +void *hdr; +int err; + + skb =genlmsg_new (GENLMSG_DEFAULT_SIZE ,GFP_KERNEL ); +if (!skb) +return -ENOMEM ; + + hdr =genlmsg_iput (skb, info); +if (!hdr) { + err = -EMSGSIZE ; + goto err_free_msg; + } + +if (nla_put_u32 (skb,NFSD_A_SERVER_WORKER_THREADS , +nfsd_nrthreads (genl_info_net (info)))) { + err = -EINVAL ; + goto err_free_msg; + } + +genlmsg_end (skb, hdr); + +return genlmsg_reply (skb, info); + +err_free_msg: +nlmsg_free (skb); + +return err; +} +/** * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace * @net: a freshly-created network namespace include/uapi/linux/nfsd_netlink.h +9
-0@@ -29,8 +29,17 @@ enum {NFSD_A_RPC_STATUS_MAX = (__NFSD_A_RPC_STATUS_MAX -1 ) }; +enum { +NFSD_A_SERVER_WORKER_THREADS =1 , + + __NFSD_A_SERVER_WORKER_MAX, +NFSD_A_SERVER_WORKER_MAX = (__NFSD_A_SERVER_WORKER_MAX -1 ) +}; +enum {NFSD_CMD_RPC_STATUS_GET =1 , +NFSD_CMD_THREADS_SET , +NFSD_CMD_THREADS_GET , __NFSD_CMD_MAX,NFSD_CMD_MAX = (__NFSD_CMD_MAX -1 )
Signature · 1 line
Jeff Layton <[email protected]>
Re: [PATCH v7 1/5] NFSD: convert write_threads to netlink command
Quoted 50 lines · Lorenzo Bianconi
Quoted 34 lines
Introduce
write_threadsnetlink command similar to the one available through the procfs.Tested-by Jeff Layton <[email protected]>Reviewed-by Jeff Layton <[email protected]>Signed-off-by Lorenzo Bianconi <[email protected]>--- Documentation/netlink/specs/nfsd.yaml | 23 ++++++++++ fs/nfsd/netlink.c | 17 ++++++++ fs/nfsd/netlink.h | 2 + fs/nfsd/nfsctl.c | 60 +++++++++++++++++++++++++++ include/uapi/linux/nfsd_netlink.h | 9 ++++ 5 files changed, 111 insertions(+)Documentation/netlink/specs/nfsd.yaml +6
-0@@ -62,6 +62,12 @@ attribute-sets: name: compound-ops type: u32 multi-attr: true + - + name: server-worker + attributes: + - + name: threads + type: u32 operations: list:@@ -87,3 +93,20 @@ operations: - sport - dportDocumentation/netlink/specs/nfsd.yaml operations: · line 104
Quoted 10 lines
Documentation/netlink/specs/nfsd.yaml +9
-0- compound-ops + - + name: threads-set + doc: set the number of running threads + attribute-set: server-worker + flags: [ admin-perm ] + do: + request: + attributes: + - threadsThere's only one thing I think we're missing to get feature parity with rpc.nfsd, and that's the ability to set the lease-time and grace-time when starting the server.
Quoted 4 lines
I think the simplest thing to do would be to just add 2 optional int parameters to the threads-set command. They only matter once you're starting the server anyway. I'll see about spinning up a patch, but let me know if you see problems with that approach.
ack, I am fine with it, we can squash it in the next revision or send a follow-up patch.
Regards,
Lorenzo
Quoted 154 lines
Quoted 150 lines
Documentation/netlink/specs/nfsd.yaml +8
-0+ - + name: threads-get + doc: get the number of running threads + attribute-set: server-worker + do: + reply: + attributes: + - threadsfs/nfsd/netlink.c +17
-0@@ -10,6 +10,11 @@#include <uapi/linux/nfsd_netlink.h> +/* NFSD_CMD_THREADS_SET - do */ +static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_WORKER_THREADS +1 ] = { + [NFSD_A_SERVER_WORKER_THREADS ] = { .type =NLA_U32 , }, +}; +/* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] = { {@@ -19,6 +24,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .done = nfsd_nl_rpc_status_get_done, .flags = GENL_CMD_CAP_DUMP, }, + { + .cmd = NFSD_CMD_THREADS_SET, + .doit = nfsd_nl_threads_set_doit, + .policy = nfsd_threads_set_nl_policy, + .maxattr = NFSD_A_SERVER_WORKER_THREADS, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = NFSD_CMD_THREADS_GET, + .doit = nfsd_nl_threads_get_doit, + .flags = GENL_CMD_CAP_DO, + }, }; struct genl_family nfsd_nl_family __ro_after_init = {fs/nfsd/netlink.h +2
-0@@ -16,6 +16,8 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb);int nfsd_nl_rpc_status_get_dumpit (struct sk_buff *skb,struct netlink_callback *cb); +int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info);extern struct genl_family nfsd_nl_family;fs/nfsd/nfsctl.c +60
-0@@ -1651,6 +1651,66 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb)return 0 ; } +/** +* nfsd_nl_threads_set_doit - set the number of running threads +* @skb: reply buffer +* @info: netlink metadata and command arguments +* +* Return 0 on success or a negative errno. +*/ +int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info) +{ +u32 nthreads; +int ret; + +if (GENL_REQ_ATTR_CHECK (info,NFSD_A_SERVER_WORKER_THREADS )) +return -EINVAL ; + + nthreads =nla_get_u32 (info->attrs[NFSD_A_SERVER_WORKER_THREADS ]); + ret =nfsd_svc (nthreads, +genl_info_net (info),get_current_cred ()); + +return ret == nthreads ?0 : -EINVAL ; +} + +/** +* nfsd_nl_threads_get_doit - get the number of running threads +* @skb: reply buffer +* @info: netlink metadata and command arguments +* +* Return 0 on success or a negative errno. +*/ +int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info) +{ +void *hdr; +int err; + + skb =genlmsg_new (GENLMSG_DEFAULT_SIZE ,GFP_KERNEL ); +if (!skb) +return -ENOMEM ; + + hdr =genlmsg_iput (skb, info); +if (!hdr) { + err = -EMSGSIZE ; + goto err_free_msg; + } + +if (nla_put_u32 (skb,NFSD_A_SERVER_WORKER_THREADS , +nfsd_nrthreads (genl_info_net (info)))) { + err = -EINVAL ; + goto err_free_msg; + } + +genlmsg_end (skb, hdr); + +return genlmsg_reply (skb, info); + +err_free_msg: +nlmsg_free (skb); + +return err; +} +/** * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace * @net: a freshly-created network namespace include/uapi/linux/nfsd_netlink.h +9
-0@@ -29,8 +29,17 @@ enum {NFSD_A_RPC_STATUS_MAX = (__NFSD_A_RPC_STATUS_MAX -1 ) }; +enum { +NFSD_A_SERVER_WORKER_THREADS =1 , + + __NFSD_A_SERVER_WORKER_MAX, +NFSD_A_SERVER_WORKER_MAX = (__NFSD_A_SERVER_WORKER_MAX -1 ) +}; +enum {NFSD_CMD_RPC_STATUS_GET =1 , +NFSD_CMD_THREADS_SET , +NFSD_CMD_THREADS_GET , __NFSD_CMD_MAX,NFSD_CMD_MAX = (__NFSD_CMD_MAX -1 )Signature · 1 line
Jeff Layton <[email protected]>
PATCH v7 2/5 NFSD: add write_version to netlink command
In reply to Lorenzo BianconiIntroduce write_version netlink command through a "declarative" interface. This patch introduces a change in behavior since for version-set userspace is expected to provide a NFS major/minor version list it wants to enable while all the other ones will be disabled. (procfs write_version command implements imperative interface where the admin writes +3/-3 to enable/disable a single version.
--- Documentation/netlink/specs/nfsd.yaml | 37 +++++++ fs/nfsd/netlink.c | 24 ++++ fs/nfsd/netlink.h | 5 + fs/nfsd/netns.h | 1 + fs/nfsd/nfsctl.c | 153 ++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 3 +- include/uapi/linux/nfsd_netlink.h | 18 +++ 7 files changed, 239 insertions(+), 2 deletions(-)
Documentation/netlink/specs/nfsd.yaml +37 -0
@@ -68,6 +68,26 @@ attribute-sets: - name: threads type: u32 + - + name: version + attributes: + - + name: major + type: u32 + - + name: minor + type: u32 + - + name: enabled + type: flag + - + name: server-proto + attributes: + - + name: version + type: nest + nested-attributes: version + multi-attr: true operations: list:
@@ -110,3 +130,20 @@ operations: reply: attributes: - threads + - + name: version-set + doc: set nfs enabled versions + attribute-set: server-proto + flags: [ admin-perm ] + do: + request: + attributes: + - version + - + name: version-get + doc: get nfs enabled versions + attribute-set: server-proto + do: + reply: + attributes: + - version
fs/nfsd/netlink.c +24 -0
@@ -10,11 +10,23 @@#include <uapi/linux/nfsd_netlink.h> +/* Common nested types */ +const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED +1 ] = { + [NFSD_A_VERSION_MAJOR ] = { .type =NLA_U32 , }, + [NFSD_A_VERSION_MINOR ] = { .type =NLA_U32 , }, + [NFSD_A_VERSION_ENABLED ] = { .type =NLA_FLAG , }, +}; +/* NFSD_CMD_THREADS_SET - do */ static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_WORKER_THREADS +1 ] = { [NFSD_A_SERVER_WORKER_THREADS ] = { .type =NLA_U32 , }, }; +/* NFSD_CMD_VERSION_SET - do */ +static const struct nla_policy nfsd_version_set_nl_policy[NFSD_A_SERVER_PROTO_VERSION +1 ] = { + [NFSD_A_SERVER_PROTO_VERSION ] =NLA_POLICY_NESTED (nfsd_version_nl_policy), +}; +/* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] = { {
@@ -36,6 +48,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .doit = nfsd_nl_threads_get_doit, .flags = GENL_CMD_CAP_DO, }, + { + .cmd = NFSD_CMD_VERSION_SET, + .doit = nfsd_nl_version_set_doit, + .policy = nfsd_version_set_nl_policy, + .maxattr = NFSD_A_SERVER_PROTO_VERSION, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = NFSD_CMD_VERSION_GET, + .doit = nfsd_nl_version_get_doit, + .flags = GENL_CMD_CAP_DO, + }, }; struct genl_family nfsd_nl_family __ro_after_init = {
fs/nfsd/netlink.h +5 -0
@@ -11,6 +11,9 @@#include <uapi/linux/nfsd_netlink.h> +/* Common nested types */ +extern const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED +1 ]; +int nfsd_nl_rpc_status_get_start (struct netlink_callback *cb);int nfsd_nl_rpc_status_get_done (struct netlink_callback *cb);
@@ -18,6 +21,8 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info);int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_version_set_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_version_get_doit (struct sk_buff *skb,struct genl_info *info);extern struct genl_family nfsd_nl_family;
fs/nfsd/netns.h +1 -0
@@ -218,6 +218,7 @@ struct nfsd_net {/* Simple check to find out if a given net was properly initialized */ #define nfsd_netns_ready (nn) ((nn)->sessionid_hashtbl) +extern bool nfsd_support_version (int vers);extern void nfsd_netns_free_versions (struct nfsd_net *nn);extern unsigned int nfsd_net_id;
fs/nfsd/nfsctl.c +153 -0
159 lines not on this page · raw message
fs/nfsd/nfssvc.c +1 -2
@@ -133,8 +133,7 @@ struct svc_program nfsd_program = { .pg_rpcbind_set = nfsd_rpcbind_set, }; -static bool -nfsd_support_version (int vers) +bool nfsd_support_version (int vers) {if (vers >=NFSD_MINVERS && vers <NFSD_NRVERS )return nfsd_version[vers] !=NULL ;
include/uapi/linux/nfsd_netlink.h +18 -0
@@ -36,10 +36,28 @@ enum {NFSD_A_SERVER_WORKER_MAX = (__NFSD_A_SERVER_WORKER_MAX -1 ) }; +enum { +NFSD_A_VERSION_MAJOR =1 , +NFSD_A_VERSION_MINOR , +NFSD_A_VERSION_ENABLED , + + __NFSD_A_VERSION_MAX, +NFSD_A_VERSION_MAX = (__NFSD_A_VERSION_MAX -1 ) +}; + +enum { +NFSD_A_SERVER_PROTO_VERSION =1 , + + __NFSD_A_SERVER_PROTO_MAX, +NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX -1 ) +}; +enum {NFSD_CMD_RPC_STATUS_GET =1 ,NFSD_CMD_THREADS_SET ,NFSD_CMD_THREADS_GET , +NFSD_CMD_VERSION_SET , +NFSD_CMD_VERSION_GET , __NFSD_CMD_MAX,NFSD_CMD_MAX = (__NFSD_CMD_MAX -1 )
Signature · 1 line
2.44.0
Jeff Layton
maintainerRe: [PATCH v7 2/5] NFSD: add write_version to netlink command
Quoted 266 lines · Lorenzo Bianconi
Introduce
write_versionnetlink command through a "declarative" interface. This patch introduces a change in behavior since for version-set userspace is expected to provide a NFS major/minor version list it wants to enable while all the other ones will be disabled. (procfswrite_versioncommand implements imperative interface where the admin writes +3/-3 to enable/disable a single version.Tested-by Jeff Layton <[email protected]>Signed-off-by Lorenzo Bianconi <[email protected]>--- Documentation/netlink/specs/nfsd.yaml | 37 +++++++ fs/nfsd/netlink.c | 24 ++++ fs/nfsd/netlink.h | 5 + fs/nfsd/netns.h | 1 + fs/nfsd/nfsctl.c | 153 ++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 3 +- include/uapi/linux/nfsd_netlink.h | 18 +++ 7 files changed, 239 insertions(+), 2 deletions(-)Documentation/netlink/specs/nfsd.yaml +37
-0@@ -68,6 +68,26 @@ attribute-sets: - name: threads type: u32 + - + name: version + attributes: + - + name: major + type: u32 + - + name: minor + type: u32 + - + name: enabled + type: flag + - + name: server-proto + attributes: + - + name: version + type: nest + nested-attributes: version + multi-attr: true operations: list:@@ -110,3 +130,20 @@ operations: reply: attributes: - threads + - + name: version-set + doc: set nfs enabled versions + attribute-set: server-proto + flags: [ admin-perm ] + do: + request: + attributes: + - version + - + name: version-get + doc: get nfs enabled versions + attribute-set: server-proto + do: + reply: + attributes: + - versionfs/nfsd/netlink.c +24
-0@@ -10,11 +10,23 @@#include <uapi/linux/nfsd_netlink.h> +/* Common nested types */ +const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED +1 ] = { + [NFSD_A_VERSION_MAJOR ] = { .type =NLA_U32 , }, + [NFSD_A_VERSION_MINOR ] = { .type =NLA_U32 , }, + [NFSD_A_VERSION_ENABLED ] = { .type =NLA_FLAG , }, +}; +/* NFSD_CMD_THREADS_SET - do */ static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_WORKER_THREADS +1 ] = { [NFSD_A_SERVER_WORKER_THREADS ] = { .type =NLA_U32 , }, }; +/* NFSD_CMD_VERSION_SET - do */ +static const struct nla_policy nfsd_version_set_nl_policy[NFSD_A_SERVER_PROTO_VERSION +1 ] = { + [NFSD_A_SERVER_PROTO_VERSION ] =NLA_POLICY_NESTED (nfsd_version_nl_policy), +}; +/* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] = { {@@ -36,6 +48,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .doit = nfsd_nl_threads_get_doit, .flags = GENL_CMD_CAP_DO, }, + { + .cmd = NFSD_CMD_VERSION_SET, + .doit = nfsd_nl_version_set_doit, + .policy = nfsd_version_set_nl_policy, + .maxattr = NFSD_A_SERVER_PROTO_VERSION, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = NFSD_CMD_VERSION_GET, + .doit = nfsd_nl_version_get_doit, + .flags = GENL_CMD_CAP_DO, + }, }; struct genl_family nfsd_nl_family __ro_after_init = {fs/nfsd/netlink.h +5
-0@@ -11,6 +11,9 @@#include <uapi/linux/nfsd_netlink.h> +/* Common nested types */ +extern const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED +1 ]; +int nfsd_nl_rpc_status_get_start (struct netlink_callback *cb);int nfsd_nl_rpc_status_get_done (struct netlink_callback *cb);@@ -18,6 +21,8 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);int nfsd_nl_threads_set_doit (struct sk_buff *skb,struct genl_info *info);int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_version_set_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_version_get_doit (struct sk_buff *skb,struct genl_info *info);extern struct genl_family nfsd_nl_family;fs/nfsd/netns.h +1
-0@@ -218,6 +218,7 @@ struct nfsd_net {/* Simple check to find out if a given net was properly initialized */ #define nfsd_netns_ready (nn) ((nn)->sessionid_hashtbl) +extern bool nfsd_support_version (int vers);extern void nfsd_netns_free_versions (struct nfsd_net *nn);extern unsigned int nfsd_net_id;fs/nfsd/nfsctl.c +105
-0@@ -1711,6 +1711,159 @@ int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info)return err; } +/** +* nfsd_nl_version_set_doit - set the nfs enabled versions +* @skb: reply buffer +* @info: netlink metadata and command arguments +* +* Return 0 on success or a negative errno. +*/ +int nfsd_nl_version_set_doit (struct sk_buff *skb,struct genl_info *info) +{ +const struct nlattr *attr; +struct nfsd_net *nn; +int i, rem; + +if (GENL_REQ_ATTR_CHECK (info,NFSD_A_SERVER_PROTO_VERSION )) +return -EINVAL ; + +mutex_lock (&nfsd_mutex); + + nn =net_generic (genl_info_net (info), nfsd_net_id); +if (nn->nfsd_serv) { +mutex_unlock (&nfsd_mutex); +return -EBUSY ; + } + +/* clear current supported versions. */ +nfsd_vers (nn,2 ,NFSD_CLEAR ); +nfsd_vers (nn,3 ,NFSD_CLEAR ); +for (i =0 ; i <=NFSD_SUPPORTED_MINOR_VERSION ; i++) +nfsd_minorversion (nn, i,NFSD_CLEAR ); + +nlmsg_for_each_attr (attr, info->nlhdr,GENL_HDRLEN , rem) { +struct nlattr *tb[NFSD_A_VERSION_MAX +1 ]; +u32 major, minor =0 ; +bool enabled; + +if (nla_type (attr) !=NFSD_A_SERVER_PROTO_VERSION ) +continue ; + +if (nla_parse_nested (tb,NFSD_A_VERSION_MAX , attr, + nfsd_version_nl_policy, info->extack) <0 ) +continue ; + +if (!tb[NFSD_A_VERSION_MAJOR ]) +continue ; + + major =nla_get_u32 (tb[NFSD_A_VERSION_MAJOR ]); +if (tb[NFSD_A_VERSION_MINOR ]) + minor =nla_get_u32 (tb[NFSD_A_VERSION_MINOR ]); + + enabled =nla_get_flag (tb[NFSD_A_VERSION_ENABLED ]); + +switch (major) { +case 4 : +nfsd_minorversion (nn, minor, enabled ?NFSD_SET :NFSD_CLEAR ); +break ; +case 3 : +case 2 : +if (!minor) +nfsd_vers (nn, major, enabled ?NFSD_SET :NFSD_CLEAR ); +break ; +default : +break ; + } + } + +mutex_unlock (&nfsd_mutex); + +return 0 ; +} + +/** +* nfsd_nl_version_get_doit - get the nfs enabled versions +* @skb: reply buffer +* @info: netlink metadata and command arguments +* +* Return 0 on success or a negative errno. +*/ +int nfsd_nl_version_get_doit (struct sk_buff *skb,struct genl_info *info) +{ +struct nfsd_net *nn; +int i, err; +void *hdr; + + skb =genlmsg_new (GENLMSG_DEFAULT_SIZE ,GFP_KERNEL ); +if (!skb) +return -ENOMEM ; + + hdr =genlmsg_iput (skb, info); +if (!hdr) { + err = -EMSGSIZE ; + goto err_free_msg; + } + +mutex_lock (&nfsd_mutex); + nn =net_generic (genl_info_net (info), nfsd_net_id); + +for (i =2 ; i <=4 ; i++) { +int j; + +for (j =0 ; j <=NFSD_SUPPORTED_MINOR_VERSION ; j++) { +struct nlattr *attr; + +/* Don't record any versions the kernel doesn't have +* compiled in +*/
fs/nfsd/nfsctl.c int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info) · line 1828
Quoted 10 lines
fs/nfsd/nfsctl.c +10
-0+if (!nfsd_support_version (i)) +continue ; + +/* NFSv{2,3} does not support minor numbers */ +if (i <4 && j) +continue ; + +if (i ==4 && !nfsd_minorversion (nn, j,NFSD_TEST )) +continue ; +
I think this is not quite right. We don't want to skip returning a minorversion just because it's not enabled. We want to return the entry with the enabled flag cleared. I'd suggest just dropping the above if statement entirely.
Quoted 88 lines
fs/nfsd/nfsctl.c +38
-0+ attr =nla_nest_start_noflag (skb, +NFSD_A_SERVER_PROTO_VERSION ); +if (!attr) { + err = -EINVAL ; + goto err_nfsd_unlock; + } + +if (nla_put_u32 (skb,NFSD_A_VERSION_MAJOR , i) || +nla_put_u32 (skb,NFSD_A_VERSION_MINOR , j)) { + err = -EINVAL ; + goto err_nfsd_unlock; + } + +/* Set the enabled flag if the version is enabled */ +if (nfsd_vers (nn, i,NFSD_TEST ) && + (i <4 ||nfsd_minorversion (nn, j,NFSD_TEST )) && +nla_put_flag (skb,NFSD_A_VERSION_ENABLED )) { + err = -EINVAL ; + goto err_nfsd_unlock; + } + +nla_nest_end (skb, attr); + } + } + +mutex_unlock (&nfsd_mutex); +genlmsg_end (skb, hdr); + +return genlmsg_reply (skb, info); + +err_nfsd_unlock: +mutex_unlock (&nfsd_mutex); +err_free_msg: +nlmsg_free (skb); + +return err; +} +/** * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace * @net: a freshly-created network namespace fs/nfsd/nfssvc.c +1
-2@@ -133,8 +133,7 @@ struct svc_program nfsd_program = { .pg_rpcbind_set = nfsd_rpcbind_set, }; -static bool -nfsd_support_version (int vers) +bool nfsd_support_version (int vers) {if (vers >=NFSD_MINVERS && vers <NFSD_NRVERS )return nfsd_version[vers] !=NULL ;include/uapi/linux/nfsd_netlink.h +18
-0@@ -36,10 +36,28 @@ enum {NFSD_A_SERVER_WORKER_MAX = (__NFSD_A_SERVER_WORKER_MAX -1 ) }; +enum { +NFSD_A_VERSION_MAJOR =1 , +NFSD_A_VERSION_MINOR , +NFSD_A_VERSION_ENABLED , + + __NFSD_A_VERSION_MAX, +NFSD_A_VERSION_MAX = (__NFSD_A_VERSION_MAX -1 ) +}; + +enum { +NFSD_A_SERVER_PROTO_VERSION =1 , + + __NFSD_A_SERVER_PROTO_MAX, +NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX -1 ) +}; +enum {NFSD_CMD_RPC_STATUS_GET =1 ,NFSD_CMD_THREADS_SET ,NFSD_CMD_THREADS_GET , +NFSD_CMD_VERSION_SET , +NFSD_CMD_VERSION_GET , __NFSD_CMD_MAX,NFSD_CMD_MAX = (__NFSD_CMD_MAX -1 )
Signature · 1 line
Jeff Layton <[email protected]>
Jakub Kicinski
maintainerRe: [PATCH v7 2/5] NFSD: add write_version to netlink command
In reply to Lorenzo Bianconifs/nfsd/nfsctl.c int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info) · line 1830
Quoted 2 lines · On Thu, 11 Apr 2024 18:47:25 +0200 Lorenzo Bianconi wrote:
fs/nfsd/nfsctl.c +2
-0+ attr =nla_nest_start_noflag (skb, +NFSD_A_SERVER_PROTO_VERSION );
The _noflag() version is for legacy code, I think you should let the nest be marked appropriately.
PATCH v7 3/5 SUNRPC: introduce svc_xprt_create_from_sa utility routine
In reply to Lorenzo BianconiAdd svc_xprt_create_from_sa utility routine and refactor svc_xprt_create() codebase in order to introduce the capability to create a svc port from socket address.
--- include/linux/sunrpc/svc_xprt.h | 3 + net/sunrpc/svc_xprt.c | 133 ++++++++++++++++++-------------- 2 files changed, 78 insertions(+), 58 deletions(-)
include/linux/sunrpc/svc_xprt.h +3 -0
@@ -135,6 +135,9 @@ int svc_reg_xprt_class(struct svc_xprt_class *);void svc_unreg_xprt_class (struct svc_xprt_class *);void svc_xprt_init (struct net *,struct svc_xprt_class *,struct svc_xprt *,struct svc_serv *); +int svc_xprt_create_from_sa (struct svc_serv *serv,const char *xprt_name, +struct net *net,struct sockaddr *sap, +int flags,const struct cred *cred); int svc_xprt_create(struct svc_serv *serv, const char *xprt_name, struct net *net, const int family, const unsigned short port, int flags,
net/sunrpc/svc_xprt.c +75 -58
172 lines not on this page · raw message
Signature · 1 line
2.44.0
PATCH v7 4/5 SUNRPC: add a new svc_find_listener helper
In reply to Lorenzo BianconiFrom: Jeff Layton <[email protected]>
svc_find_listener will return the transport instance pointer for the endpoint accepting connections/peer traffic from the specified transport class, and matching sockaddr.
--- include/linux/sunrpc/svc_xprt.h | 2 ++ net/sunrpc/svc_xprt.c | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+)
include/linux/sunrpc/svc_xprt.h +2 -0
@@ -150,6 +150,8 @@ void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt);void svc_xprt_close (struct svc_xprt *xprt);int svc_port_is_privileged (struct sockaddr *sin);int svc_print_xprts (char *buf,int maxlen); +struct svc_xprt *svc_find_listener (struct svc_serv *serv,const char *xcl_name, +struct net *net,const struct sockaddr *sa);struct svc_xprt *svc_find_xprt (struct svc_serv *serv,const char *xcl_name,struct net *net,const sa_family_t af,const unsigned short port);
net/sunrpc/svc_xprt.c +34 -0
@@ -1276,6 +1276,40 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt)return dr; } +/** +* svc_find_listener - find an RPC transport instance +* @serv: pointer to svc_serv to search +* @xcl_name: C string containing transport's class name +* @net: owner net pointer +* @sa: sockaddr containing address +* +* Return the transport instance pointer for the endpoint accepting +* connections/peer traffic from the specified transport class, +* and matching sockaddr. +*/ +struct svc_xprt *svc_find_listener (struct svc_serv *serv,const char *xcl_name, +struct net *net,const struct sockaddr *sa) +{ +struct svc_xprt *xprt; +struct svc_xprt *found =NULL ; + +spin_lock_bh (&serv->sv_lock); +list_for_each_entry (xprt, &serv->sv_permsocks, xpt_list) { +if (xprt->xpt_net != net) +continue ; +if (strcmp (xprt->xpt_class->xcl_name, xcl_name)) +continue ; +if (!rpc_cmp_addr_port (sa, (struct sockaddr *)&xprt->xpt_local)) +continue ; + found = xprt; +svc_xprt_get (xprt); +break ; + } +spin_unlock_bh (&serv->sv_lock); +return found; +} +EXPORT_SYMBOL_GPL (svc_find_listener); +/** * svc_find_xprt - find an RPC transport instance * @serv: pointer to svc_serv to search
Signature · 1 line
2.44.0
PATCH v7 5/5 NFSD: add listener-{set,get} netlink command
In reply to Lorenzo BianconiIntroduce write_ports netlink command. For listener-set, userspace is expected to provide a NFS listeners list it wants enabled. All other sockets will be closed.
--- Documentation/netlink/specs/nfsd.yaml | 34 ++++ fs/nfsd/netlink.c | 22 +++ fs/nfsd/netlink.h | 3 + fs/nfsd/nfsctl.c | 220 ++++++++++++++++++++++++++ include/uapi/linux/nfsd_netlink.h | 17 ++ 5 files changed, 296 insertions(+)
Documentation/netlink/specs/nfsd.yaml +34 -0
@@ -88,6 +88,23 @@ attribute-sets: type: nest nested-attributes: version multi-attr: true + - + name: sock + attributes: + - + name: addr + type: binary + - + name: transport-name + type: string + - + name: server-sock + attributes: + - + name: addr + type: nest + nested-attributes: sock + multi-attr: true operations: list:
@@ -147,3 +164,20 @@ operations: reply: attributes: - version + - + name: listener-set + doc: set nfs running sockets + attribute-set: server-sock + flags: [ admin-perm ] + do: + request: + attributes: + - addr + - + name: listener-get + doc: get nfs running listeners + attribute-set: server-sock + do: + reply: + attributes: + - addr
fs/nfsd/netlink.c +22 -0
@@ -11,6 +11,11 @@#include <uapi/linux/nfsd_netlink.h> /* Common nested types */ +const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_NAME +1 ] = { + [NFSD_A_SOCK_ADDR ] = { .type =NLA_BINARY , }, + [NFSD_A_SOCK_TRANSPORT_NAME ] = { .type =NLA_NUL_STRING , }, +}; +const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED +1 ] = { [NFSD_A_VERSION_MAJOR ] = { .type =NLA_U32 , }, [NFSD_A_VERSION_MINOR ] = { .type =NLA_U32 , },
@@ -27,6 +32,11 @@ static const struct nla_policy nfsd_version_set_nl_policy[NFSD_A_SERVER_PROTO_VE [NFSD_A_SERVER_PROTO_VERSION] = NLA_POLICY_NESTED(nfsd_version_nl_policy), }; +/* NFSD_CMD_LISTENER_SET - do */ +static const struct nla_policy nfsd_listener_set_nl_policy[NFSD_A_SERVER_SOCK_ADDR +1 ] = { + [NFSD_A_SERVER_SOCK_ADDR ] =NLA_POLICY_NESTED (nfsd_sock_nl_policy), +}; +/* Ops table for nfsd */ static const struct genl_split_ops nfsd_nl_ops[] = { {
@@ -60,6 +70,18 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .doit = nfsd_nl_version_get_doit, .flags = GENL_CMD_CAP_DO, }, + { + .cmd = NFSD_CMD_LISTENER_SET, + .doit = nfsd_nl_listener_set_doit, + .policy = nfsd_listener_set_nl_policy, + .maxattr = NFSD_A_SERVER_SOCK_ADDR, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = NFSD_CMD_LISTENER_GET, + .doit = nfsd_nl_listener_get_doit, + .flags = GENL_CMD_CAP_DO, + }, }; struct genl_family nfsd_nl_family __ro_after_init = {
fs/nfsd/netlink.h +3 -0
@@ -12,6 +12,7 @@#include <uapi/linux/nfsd_netlink.h> /* Common nested types */ +extern const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_NAME +1 ];extern const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED +1 ];int nfsd_nl_rpc_status_get_start (struct netlink_callback *cb);
@@ -23,6 +24,8 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info);int nfsd_nl_threads_get_doit (struct sk_buff *skb,struct genl_info *info);int nfsd_nl_version_set_doit (struct sk_buff *skb,struct genl_info *info);int nfsd_nl_version_get_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_listener_set_doit (struct sk_buff *skb,struct genl_info *info); +int nfsd_nl_listener_get_doit (struct sk_buff *skb,struct genl_info *info);extern struct genl_family nfsd_nl_family;
fs/nfsd/nfsctl.c +220 -0
226 lines not on this page · raw message
include/uapi/linux/nfsd_netlink.h +17 -0
@@ -52,12 +52,29 @@ enum {NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX -1 ) }; +enum { +NFSD_A_SOCK_ADDR =1 , +NFSD_A_SOCK_TRANSPORT_NAME , + + __NFSD_A_SOCK_MAX, +NFSD_A_SOCK_MAX = (__NFSD_A_SOCK_MAX -1 ) +}; + +enum { +NFSD_A_SERVER_SOCK_ADDR =1 , + + __NFSD_A_SERVER_SOCK_MAX, +NFSD_A_SERVER_SOCK_MAX = (__NFSD_A_SERVER_SOCK_MAX -1 ) +}; +enum {NFSD_CMD_RPC_STATUS_GET =1 ,NFSD_CMD_THREADS_SET ,NFSD_CMD_THREADS_GET ,NFSD_CMD_VERSION_SET ,NFSD_CMD_VERSION_GET , +NFSD_CMD_LISTENER_SET , +NFSD_CMD_LISTENER_GET , __NFSD_CMD_MAX,NFSD_CMD_MAX = (__NFSD_CMD_MAX -1 )
Signature · 1 line
2.44.0
Quoted 25 lines · Lorenzo Bianconi
Introduce
write_threads,write_versionandwrite_portsnetlink commands similar to the ones available through the procfs.Changes since v6:
- add the capability to pass sockaddr from userspace through listener-set command
- rebase on top of nfsd-next
Changes since v5:
- forwrite_portsandwrite_versioncommands, userspace is expected to provide a NFS listeners/supported versions list it want to enable (all the other ports/versions will be disabled).
- fix comments
- rebase on top of nfsd-next
Changes since v4:
- rebase on top of nfsd-next tree
Changes since v3:
- dropwrite_maxconnandwrite_maxblksizefor the moment
- addwrite_versionandwrite_portscommands
Changes since v2:
- use u32 to store nthreads innfsd_nl_threads_set_doit
- rename server-attr in control-plane innfsd.yamlspecs
Changes since v1:
- removewrite_v4_end_gracecommand
- addwrite_maxblksizeandwrite_maxconnnetlink commands
Quoted 3 lines
This patch can be tested with user-space tool reported below:
https://github.com/LorenzoBianconi/nfsdctl
I'm reworking the interface on that tool and adding it to nfs-utils as well. Patches will be coming soon.
Quoted 9 lines
Jeff Layton (1):
SUNRPC: add a newsvc_find_listenerhelperLorenzo Bianconi (4):
NFSD: convertwrite_threadsto netlink command
NFSD: addwrite_versionto netlink command
SUNRPC: introducesvc_xprt_create_from_sautility routine
NFSD: add listener-{set,get} netlink command
Quoted 11 lines
Documentation/netlink/specs/nfsd.yaml | 94 ++++++ fs/nfsd/netlink.c | 63 ++++ fs/nfsd/netlink.h | 10 + fs/nfsd/netns.h | 1 + fs/nfsd/nfsctl.c | 433 ++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 3 +- include/linux/sunrpc/svc_xprt.h | 5 + include/uapi/linux/nfsd_netlink.h | 44 +++ net/sunrpc/svc_xprt.c | 167 ++++++---- 9 files changed, 760 insertions(+), 60 deletions(-)