^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/lockd/mon.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * The kernel statd client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sunrpc/clnt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/sunrpc/addr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sunrpc/xprtsock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/sunrpc/svc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/lockd/lockd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "netns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define NLMDBG_FACILITY NLMDBG_MONITOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define NSM_PROGRAM 100024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define NSM_VERSION 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) NSMPROC_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) NSMPROC_STAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) NSMPROC_MON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) NSMPROC_UNMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) NSMPROC_UNMON_ALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) NSMPROC_SIMU_CRASH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) NSMPROC_NOTIFY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct nsm_args {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct nsm_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 prog; /* RPC callback info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 vers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 proc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) char *mon_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const char *nodename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct nsm_res {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct rpc_program nsm_program;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static DEFINE_SPINLOCK(nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Local NSM state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u32 __read_mostly nsm_local_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) bool __read_mostly nsm_use_hostnames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return (struct sockaddr *)&nsm->sm_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static struct rpc_clnt *nsm_create(struct net *net, const char *nodename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct sockaddr_in sin = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .sin_family = AF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct rpc_create_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .net = net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .protocol = XPRT_TRANSPORT_TCP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .address = (struct sockaddr *)&sin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .addrsize = sizeof(sin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .servername = "rpc.statd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .nodename = nodename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .program = &nsm_program,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .version = NSM_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .authflavor = RPC_AUTH_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .flags = RPC_CLNT_CREATE_NOPING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .cred = current_cred(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return rpc_create(&args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) const struct nlm_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct rpc_clnt *clnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct nsm_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .priv = &nsm->sm_priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .prog = NLM_PROGRAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .vers = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .proc = NLMPROC_NSM_NOTIFY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .mon_name = nsm->sm_mon_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .nodename = host->nodename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct rpc_message msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .rpc_argp = &args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .rpc_resp = res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) memset(res, 0, sizeof(*res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) clnt = nsm_create(host->net, host->nodename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (IS_ERR(clnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dprintk("lockd: failed to create NSM upcall transport, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) "status=%ld, net=%x\n", PTR_ERR(clnt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) host->net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return PTR_ERR(clnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) msg.rpc_proc = &clnt->cl_procinfo[proc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (status == -ECONNREFUSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dprintk("lockd: NSM upcall RPC failed, status=%d, forcing rebind\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) rpc_force_rebind(clnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dprintk("lockd: NSM upcall RPC failed, status=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rpc_shutdown_client(clnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * nsm_monitor - Notify a peer in case we reboot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * @host: pointer to nlm_host of peer to notify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * If this peer is not already monitored, this function sends an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * upcall to the local rpc.statd to record the name/address of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * the peer to notify in case we reboot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Returns zero if the peer is monitored by the local rpc.statd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * otherwise a negative errno value is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int nsm_monitor(const struct nlm_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct nsm_handle *nsm = host->h_nsmhandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct nsm_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (nsm->sm_monitored)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Choose whether to record the caller_name or IP address of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * this peer in the local rpc.statd's database.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (unlikely(res.status != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (unlikely(status < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pr_notice_ratelimited("lockd: cannot monitor %s\n", nsm->sm_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) nsm->sm_monitored = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (unlikely(nsm_local_state != res.state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) nsm_local_state = res.state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dprintk("lockd: NSM state changed to %d\n", nsm_local_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * nsm_unmonitor - Unregister peer notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * @host: pointer to nlm_host of peer to stop monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * If this peer is monitored, this function sends an upcall to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * tell the local rpc.statd not to send this peer a notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * when we reboot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) void nsm_unmonitor(const struct nlm_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct nsm_handle *nsm = host->h_nsmhandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct nsm_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (refcount_read(&nsm->sm_count) == 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) && nsm->sm_monitored && !nsm->sm_sticky) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (res.status != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) nsm->sm_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) nsm->sm_monitored = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static struct nsm_handle *nsm_lookup_hostname(const struct list_head *nsm_handles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) const char *hostname, const size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct nsm_handle *nsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) list_for_each_entry(nsm, nsm_handles, sm_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (strlen(nsm->sm_name) == len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) memcmp(nsm->sm_name, hostname, len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return nsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static struct nsm_handle *nsm_lookup_addr(const struct list_head *nsm_handles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) const struct sockaddr *sap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct nsm_handle *nsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) list_for_each_entry(nsm, nsm_handles, sm_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (rpc_cmp_addr(nsm_addr(nsm), sap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return nsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static struct nsm_handle *nsm_lookup_priv(const struct list_head *nsm_handles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) const struct nsm_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct nsm_handle *nsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) list_for_each_entry(nsm, nsm_handles, sm_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (memcmp(nsm->sm_priv.data, priv->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) sizeof(priv->data)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return nsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * Construct a unique cookie to match this nsm_handle to this monitored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * host. It is passed to the local rpc.statd via NSMPROC_MON, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * The NSM protocol requires that these cookies be unique while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * system is running. We prefer a stronger requirement of making them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * unique across reboots. If user space bugs cause a stale cookie to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * be sent to the kernel, it could cause the wrong host to lose its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * lock state if cookies were not unique across reboots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * The cookies are exposed only to local user space via loopback. They
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * do not appear on the physical network. If we want greater security
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * for some reason, nsm_init_private() could perform a one-way hash to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * obscure the contents of the cookie.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static void nsm_init_private(struct nsm_handle *nsm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u64 *p = (u64 *)&nsm->sm_priv.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) s64 ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ns = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) put_unaligned(ns, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) put_unaligned((unsigned long)nsm, p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) const size_t salen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) const char *hostname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) const size_t hostname_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct nsm_handle *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (unlikely(new == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) refcount_set(&new->sm_count, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) new->sm_name = (char *)(new + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) memcpy(nsm_addr(new), sap, salen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) new->sm_addrlen = salen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) nsm_init_private(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (rpc_ntop(nsm_addr(new), new->sm_addrbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) sizeof(new->sm_addrbuf)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) (void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) "unsupported address family");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) memcpy(new->sm_name, hostname, hostname_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) new->sm_name[hostname_len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * nsm_get_handle - Find or create a cached nsm_handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @net: network namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * @sap: pointer to socket address of handle to find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * @salen: length of socket address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * @hostname: pointer to C string containing hostname to find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * @hostname_len: length of C string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Behavior is modulated by the global nsm_use_hostnames variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Returns a cached nsm_handle after bumping its ref count, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * returns a fresh nsm_handle if a handle that matches @sap and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @hostname cannot be found in the handle cache. Returns NULL if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * an error occurs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct nsm_handle *nsm_get_handle(const struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) const size_t salen, const char *hostname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) const size_t hostname_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct nsm_handle *cached, *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct lockd_net *ln = net_generic(net, lockd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (printk_ratelimit()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) printk(KERN_WARNING "Invalid hostname \"%.*s\" "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "in NFS lock request\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) (int)hostname_len, hostname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) spin_lock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (nsm_use_hostnames && hostname != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) cached = nsm_lookup_hostname(&ln->nsm_handles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) hostname, hostname_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) cached = nsm_lookup_addr(&ln->nsm_handles, sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (cached != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) refcount_inc(&cached->sm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) spin_unlock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dprintk("lockd: found nsm_handle for %s (%s), "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "cnt %d\n", cached->sm_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) cached->sm_addrbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) refcount_read(&cached->sm_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (new != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) list_add(&new->sm_link, &ln->nsm_handles);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) spin_unlock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dprintk("lockd: created nsm_handle for %s (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) new->sm_name, new->sm_addrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) spin_unlock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) new = nsm_create_handle(sap, salen, hostname, hostname_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (unlikely(new == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * @net: network namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * @info: pointer to NLMPROC_SM_NOTIFY arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * Returns a matching nsm_handle if found in the nsm cache. The returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * nsm_handle's reference count is bumped. Otherwise returns NULL if some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * error occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct nsm_handle *nsm_reboot_lookup(const struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) const struct nlm_reboot *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct nsm_handle *cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct lockd_net *ln = net_generic(net, lockd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) spin_lock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) cached = nsm_lookup_priv(&ln->nsm_handles, &info->priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (unlikely(cached == NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) spin_unlock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dprintk("lockd: never saw rebooted peer '%.*s' before\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) info->len, info->mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) refcount_inc(&cached->sm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) spin_unlock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) cached->sm_name, cached->sm_addrbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) refcount_read(&cached->sm_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * nsm_release - Release an NSM handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * @nsm: pointer to handle to be released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) void nsm_release(struct nsm_handle *nsm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (refcount_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) list_del(&nsm->sm_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) spin_unlock(&nsm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) nsm->sm_name, nsm->sm_addrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) kfree(nsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * XDR functions for NSM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * See https://www.opengroup.org/ for details on the Network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * Status Monitor wire protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static void encode_nsm_string(struct xdr_stream *xdr, const char *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) const u32 len = strlen(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) p = xdr_reserve_space(xdr, 4 + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) xdr_encode_opaque(p, string, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * "mon_name" specifies the host to be monitored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static void encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) encode_nsm_string(xdr, argp->mon_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * The "my_id" argument specifies the hostname and RPC procedure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * to be called when the status manager receives notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * has changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) encode_nsm_string(xdr, argp->nodename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) p = xdr_reserve_space(xdr, 4 + 4 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) *p++ = cpu_to_be32(argp->prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) *p++ = cpu_to_be32(argp->vers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) *p = cpu_to_be32(argp->proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * The "mon_id" argument specifies the non-private arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * of an NSMPROC_MON or NSMPROC_UNMON call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static void encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) encode_mon_name(xdr, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) encode_my_id(xdr, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * The "priv" argument may contain private information required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * by the NSMPROC_MON call. This information will be supplied in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * NLMPROC_SM_NOTIFY call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static void nsm_xdr_enc_mon(struct rpc_rqst *req, struct xdr_stream *xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) const void *argp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) encode_mon_id(xdr, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) encode_priv(xdr, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static void nsm_xdr_enc_unmon(struct rpc_rqst *req, struct xdr_stream *xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) const void *argp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) encode_mon_id(xdr, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int nsm_xdr_dec_stat_res(struct rpc_rqst *rqstp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct xdr_stream *xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct nsm_res *resp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) p = xdr_inline_decode(xdr, 4 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (unlikely(p == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) resp->status = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) resp->state = be32_to_cpup(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) dprintk("lockd: %s status %d state %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) __func__, resp->status, resp->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static int nsm_xdr_dec_stat(struct rpc_rqst *rqstp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct xdr_stream *xdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct nsm_res *resp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) p = xdr_inline_decode(xdr, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (unlikely(p == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) resp->state = be32_to_cpup(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) dprintk("lockd: %s state %d\n", __func__, resp->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) #define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #define SM_my_id_sz (SM_my_name_sz+3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) #define SM_mon_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) #define SM_mon_id_sz (SM_mon_name_sz+SM_my_id_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) #define SM_priv_sz (XDR_QUADLEN(SM_PRIV_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) #define SM_mon_sz (SM_mon_id_sz+SM_priv_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) #define SM_monres_sz 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #define SM_unmonres_sz 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static const struct rpc_procinfo nsm_procedures[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) [NSMPROC_MON] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .p_proc = NSMPROC_MON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .p_encode = nsm_xdr_enc_mon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .p_decode = nsm_xdr_dec_stat_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .p_arglen = SM_mon_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) .p_replen = SM_monres_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) .p_statidx = NSMPROC_MON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) .p_name = "MONITOR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) [NSMPROC_UNMON] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .p_proc = NSMPROC_UNMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .p_encode = nsm_xdr_enc_unmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .p_decode = nsm_xdr_dec_stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .p_arglen = SM_mon_id_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .p_replen = SM_unmonres_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .p_statidx = NSMPROC_UNMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .p_name = "UNMONITOR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static unsigned int nsm_version1_counts[ARRAY_SIZE(nsm_procedures)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static const struct rpc_version nsm_version1 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .number = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .nrprocs = ARRAY_SIZE(nsm_procedures),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .procs = nsm_procedures,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) .counts = nsm_version1_counts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static const struct rpc_version *nsm_version[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) [1] = &nsm_version1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static struct rpc_stat nsm_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static const struct rpc_program nsm_program = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .name = "statd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .number = NSM_PROGRAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .nrvers = ARRAY_SIZE(nsm_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .version = nsm_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .stats = &nsm_stats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };