From: Jeff Layton <jlayton@kernel.org>
To: Tom Talpey <tom@talpey.com>, Steve Dickson <steved@redhat.com>
Cc: Scott Mayhew <smayhew@redhat.com>,
Yongcheng Yang <yoyang@redhat.com>,
linux-nfs@vger.kernel.org
Subject: Re: [PATCH v2 3/3] nfsdctl: add necessary bits to configure lockd
Date: Fri, 10 Jan 2025 10:21:28 -0500 [thread overview]
Message-ID: <5b7b7284cb844b36ab89e77689f5baf5035f93e1.camel@kernel.org> (raw)
In-Reply-To: <6c6bdf9b-858b-4a10-9317-f55aeda1ab80@talpey.com>
On Fri, 2025-01-10 at 10:05 -0500, Tom Talpey wrote:
> On 1/10/2025 8:46 AM, Jeff Layton wrote:
> > The legacy rpc.nfsd program would configure the nlm_grace_period to
> > match the NFSv4 grace period when starting the server. This adds similar
> > functionality to the autostart subcommand using the new lockd netlink
> > configuration interfaces. In addition, if lockd's udp or tcp listener
> > ports are specified, also configure them before starting the server.
> >
> > A "nlm" subcommand is also added that will display the current lockd
> > config settings in the current net ns. In the future, we could add the
> > ability to set these values using the "nlm" subcommand, but for now I
> > didn't see a real use-case for that, so I left it out.
>
> It seems unnatural that the nlm_grace_period is tied to the netns.
>
> It seems to me it's more dependent on the network and its likely
> failure modes, the backend storage/filesystem, and perhaps the
> scale of clients performing possibly-conflicting locks. Oh, and
> also perhaps the minor version, since 4.1+ have the RECLAIM_COMPLETE
> termination event.
>
> Food for thought, perhaps.
>
> Tom.
>
Fair point. More food:
My guess is that nlm_grace_period handling is likely horribly broken in
multi-container scenarios anyway. If you have multiple nfs server
containers with different grace period settings, then they will all be
competing to set the global nlm_grace_period.
Most clients end up reclaiming quickly enough that we don't hit major
problems here, but it would be good to make this more "airtight".
> >
> > Link: https://issues.redhat.com/browse/RHEL-71698
> > Signed-off-by: Jeff Layton <jlayton@kernel.org>
> > ---
> > configure.ac | 4 +
> > utils/nfsdctl/lockd_netlink.h | 29 ++++++
> > utils/nfsdctl/nfsdctl.8 | 6 ++
> > utils/nfsdctl/nfsdctl.adoc | 5 +
> > utils/nfsdctl/nfsdctl.c | 218 +++++++++++++++++++++++++++++++++++++++---
> > 5 files changed, 249 insertions(+), 13 deletions(-)
> >
> > diff --git a/configure.ac b/configure.ac
> > index 561e894dc46f48997df4ba6dc3e7691876589fdb..1d865fbc1c7f79e3ac6152bc59995e99fe10a38e 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -268,6 +268,10 @@ AC_ARG_ENABLE(nfsdctl,
> > [[int foo = NFSD_CMD_POOL_MODE_GET;]])],
> > [AC_DEFINE([USE_SYSTEM_NFSD_NETLINK_H], 1,
> > ["Use system's linux/nfsd_netlink.h"])])
> > + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <linux/lockd_netlink.h>]],
> > + [[int foo = LOCKD_CMD_SERVER_GET;]])],
> > + [AC_DEFINE([USE_SYSTEM_LOCKD_NETLINK_H], 1,
> > + ["Use system's linux/lockd_netlink.h"])])
> > fi
> >
> > AC_ARG_ENABLE(nfsv4server,
> > diff --git a/utils/nfsdctl/lockd_netlink.h b/utils/nfsdctl/lockd_netlink.h
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..21c65aec3bc6d1839961937081e6d16540332179
> > --- /dev/null
> > +++ b/utils/nfsdctl/lockd_netlink.h
> > @@ -0,0 +1,29 @@
> > +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
> > +/* Do not edit directly, auto-generated from: */
> > +/* Documentation/netlink/specs/lockd.yaml */
> > +/* YNL-GEN uapi header */
> > +
> > +#ifndef _UAPI_LINUX_LOCKD_NETLINK_H
> > +#define _UAPI_LINUX_LOCKD_NETLINK_H
> > +
> > +#define LOCKD_FAMILY_NAME "lockd"
> > +#define LOCKD_FAMILY_VERSION 1
> > +
> > +enum {
> > + LOCKD_A_SERVER_GRACETIME = 1,
> > + LOCKD_A_SERVER_TCP_PORT,
> > + LOCKD_A_SERVER_UDP_PORT,
> > +
> > + __LOCKD_A_SERVER_MAX,
> > + LOCKD_A_SERVER_MAX = (__LOCKD_A_SERVER_MAX - 1)
> > +};
> > +
> > +enum {
> > + LOCKD_CMD_SERVER_SET = 1,
> > + LOCKD_CMD_SERVER_GET,
> > +
> > + __LOCKD_CMD_MAX,
> > + LOCKD_CMD_MAX = (__LOCKD_CMD_MAX - 1)
> > +};
> > +
> > +#endif /* _UAPI_LINUX_LOCKD_NETLINK_H */
> > diff --git a/utils/nfsdctl/nfsdctl.8 b/utils/nfsdctl/nfsdctl.8
> > index 39ae1855ae50e94da113981d5e8cf8ac14440c3a..d69922448eb17fb155f05dc4ddc9aefffbf966e4 100644
> > --- a/utils/nfsdctl/nfsdctl.8
> > +++ b/utils/nfsdctl/nfsdctl.8
> > @@ -127,6 +127,12 @@ colon separated form, and must be enclosed in square brackets.
> > .if n .RE
> > .RE
> > .sp
> > +\fBnlm\fP
> > +.RS 4
> > +Get information about NLM (lockd) settings in the current net namespace. This
> > +subcommand takes no arguments.
> > +.RE
> > +.sp
> > \fBstatus\fP
> > .RS 4
> > Get information about RPCs currently executing in the server. This subcommand
> > diff --git a/utils/nfsdctl/nfsdctl.adoc b/utils/nfsdctl/nfsdctl.adoc
> > index 2114693042594297b7c5d8600ca16813a0f2356c..0207eff6118d2dcc5a794d2013c039d9beb11ddc 100644
> > --- a/utils/nfsdctl/nfsdctl.adoc
> > +++ b/utils/nfsdctl/nfsdctl.adoc
> > @@ -67,6 +67,11 @@ Each subcommand can also accept its own set of options and arguments. The
> > addresses must be in dotted-quad form. IPv6 addresses should be in standard
> > colon separated form, and must be enclosed in square brackets.
> >
> > +*nlm*::
> > +
> > + Get information about NLM (lockd) settings in the current net namespace. This
> > + subcommand takes no arguments.
> > +
> > *status*::
> >
> > Get information about RPCs currently executing in the server. This subcommand
> > diff --git a/utils/nfsdctl/nfsdctl.c b/utils/nfsdctl/nfsdctl.c
> > index 5c319a74273fd2bbe84003c1261043c4b2f1ff29..003daba5f30a403eb4168f6103e5a496d96968a4 100644
> > --- a/utils/nfsdctl/nfsdctl.c
> > +++ b/utils/nfsdctl/nfsdctl.c
> > @@ -35,6 +35,12 @@
> > #include "nfsd_netlink.h"
> > #endif
> >
> > +#ifdef USE_SYSTEM_LOCKD_NETLINK_H
> > +#include <linux/lockd_netlink.h>
> > +#else
> > +#include "lockd_netlink.h"
> > +#endif
> > +
> > #include "nfsdctl.h"
> > #include "conffile.h"
> > #include "xlog.h"
> > @@ -348,6 +354,28 @@ static void parse_pool_mode_get(struct genlmsghdr *gnlh)
> > }
> > }
> >
> > +static void parse_lockd_get(struct genlmsghdr *gnlh)
> > +{
> > + struct nlattr *attr;
> > + int rem;
> > +
> > + nla_for_each_attr(attr, genlmsg_attrdata(gnlh, 0),
> > + genlmsg_attrlen(gnlh, 0), rem) {
> > + switch (nla_type(attr)) {
> > + case LOCKD_A_SERVER_GRACETIME:
> > + printf("gracetime: %u\n", nla_get_u32(attr));
> > + break;
> > + case LOCKD_A_SERVER_TCP_PORT:
> > + printf("tcp_port: %hu\n", nla_get_u16(attr));
> > + break;
> > + case LOCKD_A_SERVER_UDP_PORT:
> > + printf("udp_port: %hu\n", nla_get_u16(attr));
> > + break;
> > + default:
> > + break;
> > + }
> > + }
> > +}
> > static int recv_handler(struct nl_msg *msg, void *arg)
> > {
> > struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
> > @@ -368,6 +396,9 @@ static int recv_handler(struct nl_msg *msg, void *arg)
> > case NFSD_CMD_POOL_MODE_GET:
> > parse_pool_mode_get(gnlh);
> > break;
> > + case LOCKD_CMD_SERVER_GET:
> > + parse_lockd_get(gnlh);
> > + break;
> > default:
> > break;
> > }
> > @@ -398,12 +429,12 @@ static struct nl_sock *netlink_sock_alloc(void)
> > return sock;
> > }
> >
> > -static struct nl_msg *netlink_msg_alloc(struct nl_sock *sock)
> > +static struct nl_msg *netlink_msg_alloc(struct nl_sock *sock, const char *family)
> > {
> > struct nl_msg *msg;
> > int id;
> >
> > - id = genl_ctrl_resolve(sock, NFSD_FAMILY_NAME);
> > + id = genl_ctrl_resolve(sock, family);
> > if (id < 0) {
> > xlog(L_ERROR, "%s not found", NFSD_FAMILY_NAME);
> > return NULL;
> > @@ -447,7 +478,7 @@ static int status_func(struct nl_sock *sock, int argc, char ** argv)
> > }
> > }
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -495,7 +526,7 @@ static int threads_doit(struct nl_sock *sock, int cmd, int grace, int lease,
> > struct nl_cb *cb;
> > int ret;
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -607,7 +638,7 @@ static int fetch_nfsd_versions(struct nl_sock *sock)
> > struct nl_cb *cb;
> > int ret;
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -672,7 +703,7 @@ static int set_nfsd_versions(struct nl_sock *sock)
> > struct nl_cb *cb;
> > int i, ret;
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -825,7 +856,7 @@ static int fetch_current_listeners(struct nl_sock *sock)
> > struct nl_cb *cb;
> > int ret;
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -1054,7 +1085,7 @@ static int set_listeners(struct nl_sock *sock)
> > struct nl_cb *cb;
> > int i, ret;
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -1170,7 +1201,7 @@ static int pool_mode_doit(struct nl_sock *sock, int cmd, const char *pool_mode)
> > struct nl_cb *cb;
> > int ret;
> >
> > - msg = netlink_msg_alloc(sock);
> > + msg = netlink_msg_alloc(sock, NFSD_FAMILY_NAME);
> > if (!msg)
> > return 1;
> >
> > @@ -1249,6 +1280,131 @@ static int pool_mode_func(struct nl_sock *sock, int argc, char **argv)
> > return pool_mode_doit(sock, cmd, pool_mode);
> > }
> >
> > +static int lockd_config_doit(struct nl_sock *sock, int cmd, int grace, int tcpport, int udpport)
> > +{
> > + struct genlmsghdr *ghdr;
> > + struct nlmsghdr *nlh;
> > + struct nl_msg *msg;
> > + struct nl_cb *cb;
> > + int ret;
> > +
> > + if (cmd == LOCKD_CMD_SERVER_SET) {
> > + /* Do nothing if there is nothing to set */
> > + if (!grace && !tcpport && !udpport)
> > + return 0;
> > + }
> > +
> > + msg = netlink_msg_alloc(sock, LOCKD_FAMILY_NAME);
> > + if (!msg)
> > + return 1;
> > +
> > + nlh = nlmsg_hdr(msg);
> > + if (cmd == LOCKD_CMD_SERVER_SET) {
> > + if (grace)
> > + nla_put_u32(msg, LOCKD_A_SERVER_GRACETIME, grace);
> > + if (tcpport)
> > + nla_put_u16(msg, LOCKD_A_SERVER_TCP_PORT, tcpport);
> > + if (udpport)
> > + nla_put_u16(msg, LOCKD_A_SERVER_UDP_PORT, udpport);
> > + }
> > +
> > + ghdr = nlmsg_data(nlh);
> > + ghdr->cmd = cmd;
> > +
> > + cb = nl_cb_alloc(NL_CB_CUSTOM);
> > + if (!cb) {
> > + xlog(L_ERROR, "failed to allocate netlink callbacks\n");
> > + ret = 1;
> > + goto out;
> > + }
> > +
> > + ret = nl_send_auto(sock, msg);
> > + if (ret < 0) {
> > + xlog(L_ERROR, "send failed (%d)!\n", ret);
> > + goto out_cb;
> > + }
> > +
> > + ret = 1;
> > + nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
> > + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &ret);
> > + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
> > + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, recv_handler, NULL);
> > +
> > + while (ret > 0)
> > + nl_recvmsgs(sock, cb);
> > + if (ret < 0) {
> > + xlog(L_ERROR, "Error: %s\n", strerror(-ret));
> > + ret = 1;
> > + }
> > +out_cb:
> > + nl_cb_put(cb);
> > +out:
> > + nlmsg_free(msg);
> > + return ret;
> > +}
> > +
> > +static int get_service(const char *svc)
> > +{
> > + struct addrinfo *res, hints = { .ai_flags = AI_PASSIVE };
> > + int ret, port;
> > +
> > + if (!svc)
> > + return 0;
> > +
> > + ret = getaddrinfo(NULL, svc, &hints, &res);
> > + if (ret) {
> > + xlog(L_ERROR, "getaddrinfo of \"%s\" failed: %s\n",
> > + svc, gai_strerror(ret));
> > + return -1;
> > + }
> > +
> > + switch (res->ai_family) {
> > + case AF_INET:
> > + {
> > + struct sockaddr_in *sin = (struct sockaddr_in *)res->ai_addr;
> > +
> > + port = ntohs(sin->sin_port);
> > + }
> > + break;
> > + case AF_INET6:
> > + {
> > + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)res->ai_addr;
> > +
> > + port = ntohs(sin6->sin6_port);
> > + }
> > + break;
> > + default:
> > + xlog(L_ERROR, "Bad address family: %d\n", res->ai_family);
> > + port = -1;
> > + }
> > + freeaddrinfo(res);
> > + return port;
> > +}
> > +
> > +static int lockd_configure(struct nl_sock *sock, int grace)
> > +{
> > + char *tcp_svc, *udp_svc;
> > + int tcpport = 0, udpport = 0;
> > + int ret;
> > +
> > + tcp_svc = conf_get_str("lockd", "port");
> > + if (tcp_svc) {
> > + tcpport = get_service(tcp_svc);
> > + if (tcpport < 0)
> > + return 1;
> > + }
> > +
> > + udp_svc = conf_get_str("lockd", "udp-port");
> > + if (udp_svc) {
> > + udpport = get_service(udp_svc);
> > + if (udpport < 0)
> > + return 1;
> > + }
> > +
> > + return lockd_config_doit(sock, LOCKD_CMD_SERVER_SET, grace, tcpport, udpport);
> > +}
> > +
> > +
> > #define MAX_LISTENER_LEN (64 * 2 + 16)
> >
> > static void
> > @@ -1355,6 +1511,13 @@ static int autostart_func(struct nl_sock *sock, int argc, char ** argv)
> >
> > read_nfsd_conf();
> >
> > + grace = conf_get_num("nfsd", "grace-time", 0);
> > + ret = lockd_configure(sock, grace);
> > + if (ret) {
> > + xlog(L_ERROR, "lockd configuration failure");
> > + return ret;
> > + }
> > +
> > pool_mode = conf_get_str("nfsd", "pool-mode");
> > if (pool_mode) {
> > ret = pool_mode_doit(sock, NFSD_CMD_POOL_MODE_SET, pool_mode);
> > @@ -1370,15 +1533,12 @@ static int autostart_func(struct nl_sock *sock, int argc, char ** argv)
> > if (ret)
> > return ret;
> >
> > + xlog(D_GENERAL, "configuring listeners");
> > configure_listeners();
> > ret = set_listeners(sock);
> > if (ret)
> > return ret;
> >
> > - grace = conf_get_num("nfsd", "grace-time", 0);
> > - lease = conf_get_num("nfsd", "lease-time", 0);
> > - scope = conf_get_str("nfsd", "scope");
> > -
> > thread_str = conf_get_list("nfsd", "threads");
> > pools = thread_str ? thread_str->cnt : 1;
> >
> > @@ -1402,6 +1562,9 @@ static int autostart_func(struct nl_sock *sock, int argc, char ** argv)
> > threads[0] = DEFAULT_AUTOSTART_THREADS;
> > }
> >
> > + lease = conf_get_num("nfsd", "lease-time", 0);
> > + scope = conf_get_str("nfsd", "scope");
> > +
> > ret = threads_doit(sock, NFSD_CMD_THREADS_SET, grace, lease, pools,
> > threads, scope);
> > out:
> > @@ -1409,6 +1572,30 @@ out:
> > return ret;
> > }
> >
> > +static void nlm_usage(void)
> > +{
> > + printf("Usage: %s nlm\n", taskname);
> > + printf(" Get the current settings for the NLM (lockd) server.\n");
> > +}
> > +
> > +static int nlm_func(struct nl_sock *sock, int argc, char ** argv)
> > +{
> > + int *threads, grace, lease, idx, ret, opt, pools;
> > + struct conf_list *thread_str;
> > + struct conf_list_node *n;
> > + char *scope, *pool_mode;
> > +
> > + optind = 1;
> > + while ((opt = getopt_long(argc, argv, "h", help_only_options, NULL)) != -1) {
> > + switch (opt) {
> > + case 'h':
> > + nlm_usage();
> > + return 0;
> > + }
> > + }
> > + return lockd_config_doit(sock, LOCKD_CMD_SERVER_GET, 0, 0, 0);
> > +}
> > +
> > enum nfsdctl_commands {
> > NFSDCTL_STATUS,
> > NFSDCTL_THREADS,
> > @@ -1416,6 +1603,7 @@ enum nfsdctl_commands {
> > NFSDCTL_LISTENER,
> > NFSDCTL_AUTOSTART,
> > NFSDCTL_POOL_MODE,
> > + NFSDCTL_NLM,
> > };
> >
> > static int parse_command(char *str)
> > @@ -1432,6 +1620,8 @@ static int parse_command(char *str)
> > return NFSDCTL_AUTOSTART;
> > if (!strcmp(str, "pool-mode"))
> > return NFSDCTL_POOL_MODE;
> > + if (!strcmp(str, "nlm"))
> > + return NFSDCTL_NLM;
> > return -1;
> > }
> >
> > @@ -1444,6 +1634,7 @@ static nfsdctl_func func[] = {
> > [NFSDCTL_LISTENER] = listener_func,
> > [NFSDCTL_AUTOSTART] = autostart_func,
> > [NFSDCTL_POOL_MODE] = pool_mode_func,
> > + [NFSDCTL_NLM] = nlm_func,
> > };
> >
> > static void usage(void)
> > @@ -1460,6 +1651,7 @@ static void usage(void)
> > printf(" listener get/set listener info\n");
> > printf(" version get/set supported NFS versions\n");
> > printf(" threads get/set nfsd thread settings\n");
> > + printf(" nlm get current nlm settings\n");
> > printf(" status get current RPC processing info\n");
> > printf(" autostart start server with settings from /etc/nfs.conf\n");
> > }
> >
>
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2025-01-10 15:21 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-10 13:46 [PATCH v2 0/3] nfsdctl: add support for new lockd configuration interface Jeff Layton
2025-01-10 13:46 ` [PATCH v2 1/3] nfsdctl: convert to xlog() Jeff Layton
2025-01-10 13:46 ` [PATCH v2 2/3] nfsdctl: fix the --version option Jeff Layton
2025-01-10 13:46 ` [PATCH v2 3/3] nfsdctl: add necessary bits to configure lockd Jeff Layton
2025-01-10 15:05 ` Tom Talpey
2025-01-10 15:21 ` Jeff Layton [this message]
2025-01-10 15:40 ` Tom Talpey
2025-01-13 13:39 ` Benjamin Coddington
2025-01-14 15:53 ` Tom Talpey
2025-01-14 21:09 ` [PATCH v2 0/3] nfsdctl: add support for new lockd configuration interface Scott Mayhew
2025-01-14 21:18 ` Jeff Layton
2025-01-15 14:44 ` Scott Mayhew
2025-01-15 14:56 ` Jeff Layton
2025-01-15 15:12 ` Steve Dickson
2025-01-15 15:28 ` Jeff Layton
2025-01-15 16:40 ` Scott Mayhew
2025-01-15 17:00 ` [nfs-utils PATCH] nfsdctl: debug logging fixups Scott Mayhew
2025-01-15 17:02 ` Jeff Layton
2025-01-15 17:32 ` Steve Dickson
2025-01-15 17:35 ` Jeff Layton
2025-01-15 17:47 ` Steve Dickson
2025-01-15 18:33 ` Jeff Layton
2025-01-15 20:53 ` Steve Dickson
2025-01-16 11:50 ` Jeff Layton
2025-01-16 21:00 ` Steve Dickson
2025-01-16 21:12 ` Jeff Layton
2025-03-19 19:47 ` [PATCH v2 0/3] nfsdctl: add support for new lockd configuration interface Steve Dickson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5b7b7284cb844b36ab89e77689f5baf5035f93e1.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=smayhew@redhat.com \
--cc=steved@redhat.com \
--cc=tom@talpey.com \
--cc=yoyang@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox