On 02/01/2012 10:44 AM, Jeff Layton wrote: > This program opens and "listens" on the new nfsd/cld rpc_pipefs pipe. > The code here doesn't actually do anything on stable storage yet. That > will be added in a later patch. > > The patch also adds a autoconf enable switch for the new daemon that > defaults to "no", and a test for the upcall description header file. > > Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> > --- > configure.ac | 14 +++ > utils/Makefile.am | 4 + > utils/nfsdcld/Makefile.am | 14 +++ > utils/nfsdcld/nfsdcld.c | 275 +++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 307 insertions(+), 0 deletions(-) > create mode 100644 utils/nfsdcld/Makefile.am > create mode 100644 utils/nfsdcld/nfsdcld.c > > diff --git a/configure.ac b/configure.ac > index 920e8da..d50e54e 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -185,6 +185,12 @@ else > AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mount" = "yes"]) > fi > > +AC_ARG_ENABLE(nfsdcld, > + [AC_HELP_STRING([--enable-nfsdcld], > + [Create nfsdcld NFSv4 clientid tracking daemon. <:@default=no@:>@])], > + enable_nfsdcld=$enableval, > + enable_nfsdcld="no") > + > dnl Check for TI-RPC library and headers > AC_LIBTIRPC > > @@ -260,6 +266,13 @@ if test "$enable_nfsv4" = yes; then > dnl check for the keyutils libraries and headers > AC_KEYUTILS > > + if test "$enable_nfsdcld" = "yes"; then > + AC_CHECK_HEADERS([linux/nfsd/cld.h], , > + AC_MSG_ERROR([Cannot find header needed for nfsdcld])) > + fi This adds a dependency on the kernel headers being present which is unprecedented for nfs-utils or any other package I'm aware of and I just don't think its a good idea... So I'm wondering if there is someway around creating this dependency... steved. > + > + AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) > + > dnl librpcsecgss already has a dependency on libgssapi, > dnl but we need to make sure we get the right version > if test "$enable_gss" = yes; then > @@ -460,6 +473,7 @@ AC_CONFIG_FILES([ > tools/nfs-iostat/Makefile > utils/Makefile > utils/blkmapd/Makefile > + utils/nfsdcld/Makefile > utils/exportfs/Makefile > utils/gssd/Makefile > utils/idmapd/Makefile > diff --git a/utils/Makefile.am b/utils/Makefile.am > index d074b85..5df7ca7 100644 > --- a/utils/Makefile.am > +++ b/utils/Makefile.am > @@ -21,6 +21,10 @@ if CONFIG_MOUNT > OPTDIRS += mount > endif > > +if CONFIG_NFSDCLD > +OPTDIRS += nfsdcld > +endif > + > SUBDIRS = \ > exportfs \ > mountd \ > diff --git a/utils/nfsdcld/Makefile.am b/utils/nfsdcld/Makefile.am > new file mode 100644 > index 0000000..ed7ed42 > --- /dev/null > +++ b/utils/nfsdcld/Makefile.am > @@ -0,0 +1,14 @@ > +## Process this file with automake to produce Makefile.in > + > +#man8_MANS = nfsdcld.man > +#EXTRA_DIST = $(man8_MANS) > + > +AM_CFLAGS += -D_LARGEFILE64_SOURCE > +sbin_PROGRAMS = nfsdcld > + > +nfsdcld_SOURCES = nfsdcld.c > + > +nfsdcld_LDADD = ../../support/nfs/libnfs.a $(LIBEVENT) > + > +MAINTAINERCLEANFILES = Makefile.in > + > diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c > new file mode 100644 > index 0000000..7a83fbe > --- /dev/null > +++ b/utils/nfsdcld/nfsdcld.c > @@ -0,0 +1,275 @@ > +/* > + * nfsdcld.c -- NFSv4 client name tracking daemon > + * > + * Copyright (C) 2011 Red Hat, Jeff Layton <jlayton@xxxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, > + * Boston, MA 02110-1301, USA. > + */ > + > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif /* HAVE_CONFIG_H */ > + > +#include <errno.h> > +#include <event.h> > +#include <stdbool.h> > +#include <getopt.h> > +#include <string.h> > +#include <sys/stat.h> > +#include <sys/types.h> > +#include <fcntl.h> > +#include <unistd.h> > +#include <linux/nfsd/cld.h> > + > +#include "xlog.h" > +#include "nfslib.h" > + > +#ifndef PIPEFS_DIR > +#define PIPEFS_DIR NFS_STATEDIR "/rpc_pipefs" > +#endif > + > +#define DEFAULT_CLD_PATH PIPEFS_DIR "/nfsd/cld" > + > +#define UPCALL_VERSION 1 > + > +/* private data structures */ > +struct cld_client { > + int cl_fd; > + struct event cl_event; > + struct cld_msg cl_msg; > +}; > + > +/* global variables */ > +static char *pipepath = DEFAULT_CLD_PATH; > + > +static struct option longopts[] = > +{ > + { "help", 0, NULL, 'h' }, > + { "foreground", 0, NULL, 'F' }, > + { "debug", 0, NULL, 'd' }, > + { "pipe", 1, NULL, 'p' }, > + { NULL, 0, 0, 0 }, > +}; > + > +/* forward declarations */ > +static void cldcb(int UNUSED(fd), short which, void *data); > + > +static void > +usage(char *progname) > +{ > + printf("Usage:\n"); > + printf("%s [ -hFd ] [ -p pipe ]\n", progname); > +} > + > +static int > +cld_pipe_open(struct cld_client *clnt) > +{ > + int fd; > + > + xlog(D_GENERAL, "%s: opening upcall pipe %s", __func__, pipepath); > + fd = open(pipepath, O_RDWR, 0); > + if (fd < 0) { > + xlog(L_ERROR, "%s: open of %s failed: %m", __func__, pipepath); > + return -errno; > + } > + > + if (clnt->cl_event.ev_flags & EVLIST_INIT) > + event_del(&clnt->cl_event); > + if (clnt->cl_fd >= 0) > + close(clnt->cl_fd); > + > + clnt->cl_fd = fd; > + event_set(&clnt->cl_event, clnt->cl_fd, EV_READ, cldcb, clnt); > + /* event_add is done by the caller */ > + return 0; > +} > + > +static int > +cld_pipe_init(struct cld_client *clnt) > +{ > + int ret; > + > + clnt->cl_fd = -1; > + ret = cld_pipe_open(clnt); > + if (ret) > + return ret; > + > + event_add(&clnt->cl_event, NULL); > + return 0; > +} > + > +static void > +cld_not_implemented(struct cld_client *clnt) > +{ > + int ret; > + ssize_t bsize, wsize; > + struct cld_msg *cmsg = &clnt->cl_msg; > + > + xlog(D_GENERAL, "%s: downcalling with not implemented error", __func__); > + > + /* set up reply */ > + cmsg->cm_status = -EOPNOTSUPP; > + > + bsize = sizeof(*cmsg); > + > + wsize = atomicio((void *)write, clnt->cl_fd, cmsg, bsize); > + if (wsize != bsize) > + xlog(L_ERROR, "%s: problem writing to cld pipe (%ld): %m", > + __func__, wsize); > + > + /* reopen pipe, just to be sure */ > + ret = cld_pipe_open(clnt); > + if (ret) { > + xlog(L_FATAL, "%s: unable to reopen pipe: %d", __func__, ret); > + exit(ret); > + } > +} > + > +static void > +cld_create(struct cld_client *clnt) > +{ > + int ret; > + ssize_t bsize, wsize; > + struct cld_msg *cmsg = &clnt->cl_msg; > + > + xlog(D_GENERAL, "%s: create client record", __func__); > + > + /* FIXME: create client record on storage here */ > + > + /* set up reply */ > + cmsg->cm_status = 0; > + > + bsize = sizeof(*cmsg); > + > + wsize = atomicio((void *)write, clnt->cl_fd, cmsg, bsize); > + if (wsize != bsize) { > + xlog(L_ERROR, "%s: problem writing to cld pipe (%ld): %m", > + __func__, wsize); > + ret = cld_pipe_open(clnt); > + if (ret) { > + xlog(L_FATAL, "%s: unable to reopen pipe: %d", > + __func__, ret); > + exit(ret); > + } > + } > +} > + > +static void > +cldcb(int UNUSED(fd), short which, void *data) > +{ > + ssize_t len; > + struct cld_client *clnt = data; > + struct cld_msg *cmsg = &clnt->cl_msg; > + > + if (which != EV_READ) > + goto out; > + > + len = atomicio(read, clnt->cl_fd, cmsg, sizeof(*cmsg)); > + if (len <= 0) { > + xlog(L_ERROR, "%s: pipe read failed: %m", __func__); > + cld_pipe_open(clnt); > + goto out; > + } > + > + if (cmsg->cm_vers != UPCALL_VERSION) { > + xlog(L_ERROR, "%s: unsupported upcall version: %hu", > + cmsg->cm_vers); > + cld_pipe_open(clnt); > + goto out; > + } > + > + switch(cmsg->cm_cmd) { > + case Cld_Create: > + cld_create(clnt); > + break; > + default: > + xlog(L_WARNING, "%s: command %u is not yet implemented", > + __func__, cmsg->cm_cmd); > + cld_not_implemented(clnt); > + } > +out: > + event_add(&clnt->cl_event, NULL); > +} > + > +int > +main(int argc, char **argv) > +{ > + char arg; > + int rc = 0; > + bool foreground = false; > + char *progname; > + struct cld_client clnt; > + > + memset(&clnt, 0, sizeof(clnt)); > + > + progname = strdup(basename(argv[0])); > + if (!progname) { > + fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]); > + return 1; > + } > + > + event_init(); > + xlog_syslog(0); > + xlog_stderr(1); > + > + /* process command-line options */ > + while ((arg = getopt_long(argc, argv, "hdFp:", longopts, > + NULL)) != EOF) { > + switch (arg) { > + case 'd': > + xlog_config(D_ALL, 1); > + break; > + case 'F': > + foreground = true; > + break; > + case 'p': > + pipepath = optarg; > + break; > + default: > + usage(progname); > + return 0; > + } > + } > + > + > + xlog_open(progname); > + if (!foreground) { > + xlog_syslog(1); > + xlog_stderr(0); > + rc = daemon(0, 0); > + if (rc) { > + xlog(L_ERROR, "Unable to daemonize: %m"); > + goto out; > + } > + } > + > + /* set up storage db */ > + > + /* set up event handler */ > + rc = cld_pipe_init(&clnt); > + if (rc) > + goto out; > + > + xlog(D_GENERAL, "%s: Starting event dispatch handler.", __func__); > + rc = event_dispatch(); > + if (rc < 0) > + xlog(L_ERROR, "%s: event_dispatch failed: %m", __func__); > + > + close(clnt.cl_fd); > +out: > + free(progname); > + return rc; > +} -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html