2 * nfsdcld.c -- NFSv4 client name tracking daemon
4 * Copyright (C) 2011 Red Hat, Jeff Layton <jlayton@redhat.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
24 #endif /* HAVE_CONFIG_H */
32 #include <sys/types.h>
41 #define PIPEFS_DIR NFS_STATEDIR "/rpc_pipefs"
44 #define DEFAULT_CLD_PATH PIPEFS_DIR "/nfsd/cld"
46 #define UPCALL_VERSION 1
48 /* private data structures */
51 struct event cl_event;
52 struct cld_msg cl_msg;
55 /* global variables */
56 static char *pipepath = DEFAULT_CLD_PATH;
58 static struct option longopts[] =
60 { "help", 0, NULL, 'h' },
61 { "foreground", 0, NULL, 'F' },
62 { "debug", 0, NULL, 'd' },
63 { "pipe", 1, NULL, 'p' },
67 /* forward declarations */
68 static void cldcb(int UNUSED(fd), short which, void *data);
73 printf("Usage: %s [ -hFd ] [ -p pipe ]\n", progname);
77 cld_pipe_open(struct cld_client *clnt)
81 xlog(D_GENERAL, "%s: opening upcall pipe %s", __func__, pipepath);
82 fd = open(pipepath, O_RDWR, 0);
84 xlog(L_ERROR, "%s: open of %s failed: %m", __func__, pipepath);
88 if (clnt->cl_event.ev_flags & EVLIST_INIT)
89 event_del(&clnt->cl_event);
94 event_set(&clnt->cl_event, clnt->cl_fd, EV_READ, cldcb, clnt);
95 /* event_add is done by the caller */
100 cld_pipe_init(struct cld_client *clnt)
105 ret = cld_pipe_open(clnt);
109 event_add(&clnt->cl_event, NULL);
114 cld_not_implemented(struct cld_client *clnt)
117 ssize_t bsize, wsize;
118 struct cld_msg *cmsg = &clnt->cl_msg;
120 xlog(D_GENERAL, "%s: downcalling with not implemented error", __func__);
123 cmsg->cm_status = -EOPNOTSUPP;
125 bsize = sizeof(*cmsg);
127 wsize = atomicio((void *)write, clnt->cl_fd, cmsg, bsize);
129 xlog(L_ERROR, "%s: problem writing to cld pipe (%ld): %m",
132 /* reopen pipe, just to be sure */
133 ret = cld_pipe_open(clnt);
135 xlog(L_FATAL, "%s: unable to reopen pipe: %d", __func__, ret);
141 cld_create(struct cld_client *clnt)
144 ssize_t bsize, wsize;
145 struct cld_msg *cmsg = &clnt->cl_msg;
147 xlog(D_GENERAL, "%s: create client record", __func__);
149 /* FIXME: create client record on storage here */
154 bsize = sizeof(*cmsg);
156 wsize = atomicio((void *)write, clnt->cl_fd, cmsg, bsize);
157 if (wsize != bsize) {
158 xlog(L_ERROR, "%s: problem writing to cld pipe (%ld): %m",
160 ret = cld_pipe_open(clnt);
162 xlog(L_FATAL, "%s: unable to reopen pipe: %d",
170 cldcb(int UNUSED(fd), short which, void *data)
173 struct cld_client *clnt = data;
174 struct cld_msg *cmsg = &clnt->cl_msg;
176 if (which != EV_READ)
179 len = atomicio(read, clnt->cl_fd, cmsg, sizeof(*cmsg));
181 xlog(L_ERROR, "%s: pipe read failed: %m", __func__);
186 if (cmsg->cm_vers != UPCALL_VERSION) {
187 xlog(L_ERROR, "%s: unsupported upcall version: %hu",
193 switch(cmsg->cm_cmd) {
198 xlog(L_WARNING, "%s: command %u is not yet implemented",
199 __func__, cmsg->cm_cmd);
200 cld_not_implemented(clnt);
203 event_add(&clnt->cl_event, NULL);
207 main(int argc, char **argv)
211 bool foreground = false;
213 struct cld_client clnt;
215 memset(&clnt, 0, sizeof(clnt));
217 progname = strdup(basename(argv[0]));
219 fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
227 /* process command-line options */
228 while ((arg = getopt_long(argc, argv, "hdFp:", longopts,
232 xlog_config(D_ALL, 1);
253 xlog(L_ERROR, "Unable to daemonize: %m");
258 /* set up storage db */
260 /* set up event handler */
261 rc = cld_pipe_init(&clnt);
265 xlog(D_GENERAL, "%s: Starting event dispatch handler.", __func__);
266 rc = event_dispatch();
268 xlog(L_ERROR, "%s: event_dispatch failed: %m", __func__);