xref: /openbmc/linux/fs/lockd/mon.c (revision 03eb1dcbb799304b58730f4dba65812f49fb305e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * linux/fs/lockd/mon.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * The kernel statd client.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #include <linux/types.h>
101da177e4SLinus Torvalds #include <linux/utsname.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h>
130896a725S\"Talpey, Thomas\ #include <linux/sunrpc/xprtsock.h>
141da177e4SLinus Torvalds #include <linux/sunrpc/svc.h>
151da177e4SLinus Torvalds #include <linux/lockd/lockd.h>
161da177e4SLinus Torvalds #include <linux/lockd/sm_inter.h>
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds #define NLMDBG_FACILITY		NLMDBG_MONITOR
2036e8e668SChuck Lever #define NSM_PROGRAM		100024
2136e8e668SChuck Lever #define NSM_VERSION		1
2236e8e668SChuck Lever 
2336e8e668SChuck Lever enum {
2436e8e668SChuck Lever 	NSMPROC_NULL,
2536e8e668SChuck Lever 	NSMPROC_STAT,
2636e8e668SChuck Lever 	NSMPROC_MON,
2736e8e668SChuck Lever 	NSMPROC_UNMON,
2836e8e668SChuck Lever 	NSMPROC_UNMON_ALL,
2936e8e668SChuck Lever 	NSMPROC_SIMU_CRASH,
3036e8e668SChuck Lever 	NSMPROC_NOTIFY,
3136e8e668SChuck Lever };
321da177e4SLinus Torvalds 
339c1bfd03SChuck Lever struct nsm_args {
349c1bfd03SChuck Lever 	__be32			addr;		/* remote address */
359c1bfd03SChuck Lever 	u32			prog;		/* RPC callback info */
369c1bfd03SChuck Lever 	u32			vers;
379c1bfd03SChuck Lever 	u32			proc;
389c1bfd03SChuck Lever 
399c1bfd03SChuck Lever 	char			*mon_name;
409c1bfd03SChuck Lever };
419c1bfd03SChuck Lever 
429c1bfd03SChuck Lever struct nsm_res {
439c1bfd03SChuck Lever 	u32			status;
449c1bfd03SChuck Lever 	u32			state;
459c1bfd03SChuck Lever };
469c1bfd03SChuck Lever 
471da177e4SLinus Torvalds static struct rpc_clnt *	nsm_create(void);
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds static struct rpc_program	nsm_program;
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds /*
521da177e4SLinus Torvalds  * Local NSM state
531da177e4SLinus Torvalds  */
54460f5cacSOlaf Kirch int				nsm_local_state;
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds /*
5736e8e668SChuck Lever  * Common procedure for NSMPROC_MON/NSMPROC_UNMON calls
581da177e4SLinus Torvalds  */
591da177e4SLinus Torvalds static int
609502c522SOlaf Kirch nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
611da177e4SLinus Torvalds {
621da177e4SLinus Torvalds 	struct rpc_clnt	*clnt;
631da177e4SLinus Torvalds 	int		status;
64a4846750SChuck Lever 	struct nsm_args args = {
65a4846750SChuck Lever 		.addr		= nsm_addr_in(nsm)->sin_addr.s_addr,
66a4846750SChuck Lever 		.prog		= NLM_PROGRAM,
67a4846750SChuck Lever 		.vers		= 3,
68a4846750SChuck Lever 		.proc		= NLMPROC_NSM_NOTIFY,
6929ed1407SChuck Lever 		.mon_name	= nsm->sm_mon_name,
70a4846750SChuck Lever 	};
71dead28daSChuck Lever 	struct rpc_message msg = {
72dead28daSChuck Lever 		.rpc_argp	= &args,
73dead28daSChuck Lever 		.rpc_resp	= res,
74dead28daSChuck Lever 	};
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 	clnt = nsm_create();
771da177e4SLinus Torvalds 	if (IS_ERR(clnt)) {
781da177e4SLinus Torvalds 		status = PTR_ERR(clnt);
795acf4315SChuck Lever 		dprintk("lockd: failed to create NSM upcall transport, "
805acf4315SChuck Lever 				"status=%d\n", status);
811da177e4SLinus Torvalds 		goto out;
821da177e4SLinus Torvalds 	}
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds 	memset(res, 0, sizeof(*res));
851da177e4SLinus Torvalds 
86dead28daSChuck Lever 	msg.rpc_proc = &clnt->cl_procinfo[proc];
87dead28daSChuck Lever 	status = rpc_call_sync(clnt, &msg, 0);
881da177e4SLinus Torvalds 	if (status < 0)
895acf4315SChuck Lever 		dprintk("lockd: NSM upcall RPC failed, status=%d\n",
901da177e4SLinus Torvalds 				status);
911da177e4SLinus Torvalds 	else
921da177e4SLinus Torvalds 		status = 0;
9390c5755fSTrond Myklebust 	rpc_shutdown_client(clnt);
941da177e4SLinus Torvalds  out:
951da177e4SLinus Torvalds 	return status;
961da177e4SLinus Torvalds }
971da177e4SLinus Torvalds 
981e49323cSChuck Lever /**
991e49323cSChuck Lever  * nsm_monitor - Notify a peer in case we reboot
1001e49323cSChuck Lever  * @host: pointer to nlm_host of peer to notify
1011e49323cSChuck Lever  *
1021e49323cSChuck Lever  * If this peer is not already monitored, this function sends an
1031e49323cSChuck Lever  * upcall to the local rpc.statd to record the name/address of
1041e49323cSChuck Lever  * the peer to notify in case we reboot.
1051e49323cSChuck Lever  *
1061e49323cSChuck Lever  * Returns zero if the peer is monitored by the local rpc.statd;
1071e49323cSChuck Lever  * otherwise a negative errno value is returned.
1081da177e4SLinus Torvalds  */
1091e49323cSChuck Lever int nsm_monitor(const struct nlm_host *host)
1101da177e4SLinus Torvalds {
1118dead0dbSOlaf Kirch 	struct nsm_handle *nsm = host->h_nsmhandle;
1121da177e4SLinus Torvalds 	struct nsm_res	res;
1131da177e4SLinus Torvalds 	int		status;
1141da177e4SLinus Torvalds 
1159fee4902SChuck Lever 	dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
1168dead0dbSOlaf Kirch 
1178dead0dbSOlaf Kirch 	if (nsm->sm_monitored)
118977faf39SOlaf Kirch 		return 0;
1191da177e4SLinus Torvalds 
12029ed1407SChuck Lever 	/*
12129ed1407SChuck Lever 	 * Choose whether to record the caller_name or IP address of
12229ed1407SChuck Lever 	 * this peer in the local rpc.statd's database.
12329ed1407SChuck Lever 	 */
12429ed1407SChuck Lever 	nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
12529ed1407SChuck Lever 
12636e8e668SChuck Lever 	status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
1275d254b11SChuck Lever 	if (res.status != 0)
1285d254b11SChuck Lever 		status = -EIO;
1295d254b11SChuck Lever 	if (status < 0)
1309fee4902SChuck Lever 		printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
1311da177e4SLinus Torvalds 	else
1328dead0dbSOlaf Kirch 		nsm->sm_monitored = 1;
1331da177e4SLinus Torvalds 	return status;
1341da177e4SLinus Torvalds }
1351da177e4SLinus Torvalds 
136356c3eb4SChuck Lever /**
137356c3eb4SChuck Lever  * nsm_unmonitor - Unregister peer notification
138356c3eb4SChuck Lever  * @host: pointer to nlm_host of peer to stop monitoring
139356c3eb4SChuck Lever  *
140356c3eb4SChuck Lever  * If this peer is monitored, this function sends an upcall to
141356c3eb4SChuck Lever  * tell the local rpc.statd not to send this peer a notification
142356c3eb4SChuck Lever  * when we reboot.
1431da177e4SLinus Torvalds  */
144356c3eb4SChuck Lever void nsm_unmonitor(const struct nlm_host *host)
1451da177e4SLinus Torvalds {
1468dead0dbSOlaf Kirch 	struct nsm_handle *nsm = host->h_nsmhandle;
1471da177e4SLinus Torvalds 	struct nsm_res	res;
148356c3eb4SChuck Lever 	int status;
1491da177e4SLinus Torvalds 
1509502c522SOlaf Kirch 	if (atomic_read(&nsm->sm_count) == 1
1519502c522SOlaf Kirch 	 && nsm->sm_monitored && !nsm->sm_sticky) {
1529fee4902SChuck Lever 		dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
1539502c522SOlaf Kirch 
15436e8e668SChuck Lever 		status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res);
1550c7aef45SChuck Lever 		if (res.status != 0)
1560c7aef45SChuck Lever 			status = -EIO;
1571da177e4SLinus Torvalds 		if (status < 0)
1589502c522SOlaf Kirch 			printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
1599fee4902SChuck Lever 					nsm->sm_name);
1609502c522SOlaf Kirch 		else
1618dead0dbSOlaf Kirch 			nsm->sm_monitored = 0;
162977faf39SOlaf Kirch 	}
1631da177e4SLinus Torvalds }
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds /*
1661da177e4SLinus Torvalds  * Create NSM client for the local host
1671da177e4SLinus Torvalds  */
1681da177e4SLinus Torvalds static struct rpc_clnt *
1691da177e4SLinus Torvalds nsm_create(void)
1701da177e4SLinus Torvalds {
171e1ec7892SChuck Lever 	struct sockaddr_in	sin = {
172e1ec7892SChuck Lever 		.sin_family	= AF_INET,
173e1ec7892SChuck Lever 		.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
174e1ec7892SChuck Lever 		.sin_port	= 0,
175e1ec7892SChuck Lever 	};
176e1ec7892SChuck Lever 	struct rpc_create_args args = {
1770896a725S\"Talpey, Thomas\ 		.protocol	= XPRT_TRANSPORT_UDP,
178e1ec7892SChuck Lever 		.address	= (struct sockaddr *)&sin,
179e1ec7892SChuck Lever 		.addrsize	= sizeof(sin),
180e1ec7892SChuck Lever 		.servername	= "localhost",
181e1ec7892SChuck Lever 		.program	= &nsm_program,
18236e8e668SChuck Lever 		.version	= NSM_VERSION,
183e1ec7892SChuck Lever 		.authflavor	= RPC_AUTH_NULL,
184e1ec7892SChuck Lever 	};
1851da177e4SLinus Torvalds 
186e1ec7892SChuck Lever 	return rpc_create(&args);
1871da177e4SLinus Torvalds }
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds /*
1901da177e4SLinus Torvalds  * XDR functions for NSM.
1912ca7754dSChuck Lever  *
1922ca7754dSChuck Lever  * See http://www.opengroup.org/ for details on the Network
1932ca7754dSChuck Lever  * Status Monitor wire protocol.
1941da177e4SLinus Torvalds  */
1951da177e4SLinus Torvalds 
196*03eb1dcbSChuck Lever static int encode_nsm_string(struct xdr_stream *xdr, const char *string)
197099bd05fSChuck Lever {
198*03eb1dcbSChuck Lever 	const u32 len = strlen(string);
199*03eb1dcbSChuck Lever 	__be32 *p;
200099bd05fSChuck Lever 
201*03eb1dcbSChuck Lever 	if (unlikely(len > SM_MAXSTRLEN))
202*03eb1dcbSChuck Lever 		return -EIO;
203*03eb1dcbSChuck Lever 	p = xdr_reserve_space(xdr, sizeof(u32) + len);
204*03eb1dcbSChuck Lever 	if (unlikely(p == NULL))
205*03eb1dcbSChuck Lever 		return -EIO;
206*03eb1dcbSChuck Lever 	xdr_encode_opaque(p, string, len);
207*03eb1dcbSChuck Lever 	return 0;
208099bd05fSChuck Lever }
209099bd05fSChuck Lever 
21049695174SChuck Lever /*
21149695174SChuck Lever  * "mon_name" specifies the host to be monitored.
21249695174SChuck Lever  */
213*03eb1dcbSChuck Lever static int encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
21449695174SChuck Lever {
215*03eb1dcbSChuck Lever 	return encode_nsm_string(xdr, argp->mon_name);
21649695174SChuck Lever }
21749695174SChuck Lever 
218850c95fdSChuck Lever /*
219850c95fdSChuck Lever  * The "my_id" argument specifies the hostname and RPC procedure
220850c95fdSChuck Lever  * to be called when the status manager receives notification
22136e8e668SChuck Lever  * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
222850c95fdSChuck Lever  * has changed.
223850c95fdSChuck Lever  */
224*03eb1dcbSChuck Lever static int encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
225850c95fdSChuck Lever {
226*03eb1dcbSChuck Lever 	int status;
227*03eb1dcbSChuck Lever 	__be32 *p;
228850c95fdSChuck Lever 
229*03eb1dcbSChuck Lever 	status = encode_nsm_string(xdr, utsname()->nodename);
230*03eb1dcbSChuck Lever 	if (unlikely(status != 0))
231*03eb1dcbSChuck Lever 		return status;
232*03eb1dcbSChuck Lever 	p = xdr_reserve_space(xdr, 3 * sizeof(u32));
233*03eb1dcbSChuck Lever 	if (unlikely(p == NULL))
234*03eb1dcbSChuck Lever 		return -EIO;
235850c95fdSChuck Lever 	*p++ = htonl(argp->prog);
236850c95fdSChuck Lever 	*p++ = htonl(argp->vers);
237850c95fdSChuck Lever 	*p++ = htonl(argp->proc);
238*03eb1dcbSChuck Lever 	return 0;
239850c95fdSChuck Lever }
240850c95fdSChuck Lever 
241ea72a7f1SChuck Lever /*
242ea72a7f1SChuck Lever  * The "mon_id" argument specifies the non-private arguments
24336e8e668SChuck Lever  * of an NSMPROC_MON or NSMPROC_UNMON call.
244ea72a7f1SChuck Lever  */
245*03eb1dcbSChuck Lever static int encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
246ea72a7f1SChuck Lever {
247*03eb1dcbSChuck Lever 	int status;
248ea72a7f1SChuck Lever 
249*03eb1dcbSChuck Lever 	status = encode_mon_name(xdr, argp);
250*03eb1dcbSChuck Lever 	if (unlikely(status != 0))
251*03eb1dcbSChuck Lever 		return status;
252*03eb1dcbSChuck Lever 	return encode_my_id(xdr, argp);
253ea72a7f1SChuck Lever }
254ea72a7f1SChuck Lever 
2550490a54aSChuck Lever /*
2560490a54aSChuck Lever  * The "priv" argument may contain private information required
25736e8e668SChuck Lever  * by the NSMPROC_MON call. This information will be supplied in the
25836e8e668SChuck Lever  * NLMPROC_SM_NOTIFY call.
2590490a54aSChuck Lever  *
2600490a54aSChuck Lever  * Linux provides the raw IP address of the monitored host,
2610490a54aSChuck Lever  * left in network byte order.
2620490a54aSChuck Lever  */
263*03eb1dcbSChuck Lever static int encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
2640490a54aSChuck Lever {
265*03eb1dcbSChuck Lever 	__be32 *p;
266*03eb1dcbSChuck Lever 
267*03eb1dcbSChuck Lever 	p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
268*03eb1dcbSChuck Lever 	if (unlikely(p == NULL))
269*03eb1dcbSChuck Lever 		return -EIO;
2700490a54aSChuck Lever 	*p++ = argp->addr;
2710490a54aSChuck Lever 	*p++ = 0;
2720490a54aSChuck Lever 	*p++ = 0;
2730490a54aSChuck Lever 	*p++ = 0;
2741da177e4SLinus Torvalds 	return 0;
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds 
277*03eb1dcbSChuck Lever static int xdr_enc_mon(struct rpc_rqst *req, __be32 *p,
278*03eb1dcbSChuck Lever 		       const struct nsm_args *argp)
2791da177e4SLinus Torvalds {
280*03eb1dcbSChuck Lever 	struct xdr_stream xdr;
281*03eb1dcbSChuck Lever 	int status;
282*03eb1dcbSChuck Lever 
283*03eb1dcbSChuck Lever 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
284*03eb1dcbSChuck Lever 	status = encode_mon_id(&xdr, argp);
285*03eb1dcbSChuck Lever 	if (unlikely(status))
286*03eb1dcbSChuck Lever 		return status;
287*03eb1dcbSChuck Lever 	return encode_priv(&xdr, argp);
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds 
290*03eb1dcbSChuck Lever static int xdr_enc_unmon(struct rpc_rqst *req, __be32 *p,
291*03eb1dcbSChuck Lever 			 const struct nsm_args *argp)
2921da177e4SLinus Torvalds {
293*03eb1dcbSChuck Lever 	struct xdr_stream xdr;
294*03eb1dcbSChuck Lever 
295*03eb1dcbSChuck Lever 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
296*03eb1dcbSChuck Lever 	return encode_mon_id(&xdr, argp);
297*03eb1dcbSChuck Lever }
298*03eb1dcbSChuck Lever 
299*03eb1dcbSChuck Lever static int xdr_dec_stat_res(struct rpc_rqst *rqstp, __be32 *p,
300*03eb1dcbSChuck Lever 			    struct nsm_res *resp)
301*03eb1dcbSChuck Lever {
302*03eb1dcbSChuck Lever 	struct xdr_stream xdr;
303*03eb1dcbSChuck Lever 
304*03eb1dcbSChuck Lever 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
305*03eb1dcbSChuck Lever 	p = xdr_inline_decode(&xdr, 2 * sizeof(u32));
306*03eb1dcbSChuck Lever 	if (unlikely(p == NULL))
307*03eb1dcbSChuck Lever 		return -EIO;
3081da177e4SLinus Torvalds 	resp->status = ntohl(*p++);
309*03eb1dcbSChuck Lever 	resp->state = ntohl(*p);
310*03eb1dcbSChuck Lever 
311*03eb1dcbSChuck Lever 	dprintk("lockd: xdr_dec_stat_res status %d state %d\n",
3121da177e4SLinus Torvalds 			resp->status, resp->state);
3131da177e4SLinus Torvalds 	return 0;
3141da177e4SLinus Torvalds }
3151da177e4SLinus Torvalds 
316*03eb1dcbSChuck Lever static int xdr_dec_stat(struct rpc_rqst *rqstp, __be32 *p,
317*03eb1dcbSChuck Lever 			struct nsm_res *resp)
3181da177e4SLinus Torvalds {
319*03eb1dcbSChuck Lever 	struct xdr_stream xdr;
320*03eb1dcbSChuck Lever 
321*03eb1dcbSChuck Lever 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
322*03eb1dcbSChuck Lever 	p = xdr_inline_decode(&xdr, sizeof(u32));
323*03eb1dcbSChuck Lever 	if (unlikely(p == NULL))
324*03eb1dcbSChuck Lever 		return -EIO;
325*03eb1dcbSChuck Lever 	resp->state = ntohl(*p);
326*03eb1dcbSChuck Lever 
327*03eb1dcbSChuck Lever 	dprintk("lockd: xdr_dec_stat state %d\n", resp->state);
3281da177e4SLinus Torvalds 	return 0;
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds #define SM_my_name_sz	(1+XDR_QUADLEN(SM_MAXSTRLEN))
3322ca7754dSChuck Lever #define SM_my_id_sz	(SM_my_name_sz+3)
3332ca7754dSChuck Lever #define SM_mon_name_sz	(1+XDR_QUADLEN(SM_MAXSTRLEN))
3342ca7754dSChuck Lever #define SM_mon_id_sz	(SM_mon_name_sz+SM_my_id_sz)
3350490a54aSChuck Lever #define SM_priv_sz	(XDR_QUADLEN(SM_PRIV_SIZE))
3360490a54aSChuck Lever #define SM_mon_sz	(SM_mon_id_sz+SM_priv_sz)
3371da177e4SLinus Torvalds #define SM_monres_sz	2
3381da177e4SLinus Torvalds #define SM_unmonres_sz	1
3391da177e4SLinus Torvalds 
3401da177e4SLinus Torvalds static struct rpc_procinfo	nsm_procedures[] = {
34136e8e668SChuck Lever [NSMPROC_MON] = {
34236e8e668SChuck Lever 		.p_proc		= NSMPROC_MON,
343*03eb1dcbSChuck Lever 		.p_encode	= (kxdrproc_t)xdr_enc_mon,
344*03eb1dcbSChuck Lever 		.p_decode	= (kxdrproc_t)xdr_dec_stat_res,
3452bea90d4SChuck Lever 		.p_arglen	= SM_mon_sz,
3462bea90d4SChuck Lever 		.p_replen	= SM_monres_sz,
34736e8e668SChuck Lever 		.p_statidx	= NSMPROC_MON,
348cc0175c1SChuck Lever 		.p_name		= "MONITOR",
3491da177e4SLinus Torvalds 	},
35036e8e668SChuck Lever [NSMPROC_UNMON] = {
35136e8e668SChuck Lever 		.p_proc		= NSMPROC_UNMON,
352*03eb1dcbSChuck Lever 		.p_encode	= (kxdrproc_t)xdr_enc_unmon,
353*03eb1dcbSChuck Lever 		.p_decode	= (kxdrproc_t)xdr_dec_stat,
3542bea90d4SChuck Lever 		.p_arglen	= SM_mon_id_sz,
3552bea90d4SChuck Lever 		.p_replen	= SM_unmonres_sz,
35636e8e668SChuck Lever 		.p_statidx	= NSMPROC_UNMON,
357cc0175c1SChuck Lever 		.p_name		= "UNMONITOR",
3581da177e4SLinus Torvalds 	},
3591da177e4SLinus Torvalds };
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds static struct rpc_version	nsm_version1 = {
3621da177e4SLinus Torvalds 		.number		= 1,
363e8c96f8cSTobias Klauser 		.nrprocs	= ARRAY_SIZE(nsm_procedures),
3641da177e4SLinus Torvalds 		.procs		= nsm_procedures
3651da177e4SLinus Torvalds };
3661da177e4SLinus Torvalds 
3671da177e4SLinus Torvalds static struct rpc_version *	nsm_version[] = {
3681da177e4SLinus Torvalds 	[1] = &nsm_version1,
3691da177e4SLinus Torvalds };
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds static struct rpc_stat		nsm_stats;
3721da177e4SLinus Torvalds 
3731da177e4SLinus Torvalds static struct rpc_program	nsm_program = {
3741da177e4SLinus Torvalds 		.name		= "statd",
37536e8e668SChuck Lever 		.number		= NSM_PROGRAM,
376e8c96f8cSTobias Klauser 		.nrvers		= ARRAY_SIZE(nsm_version),
3771da177e4SLinus Torvalds 		.version	= nsm_version,
3781da177e4SLinus Torvalds 		.stats		= &nsm_stats
3791da177e4SLinus Torvalds };
380