^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/nfs/callback.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004 Trond Myklebust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * NFSv4 callback handling
^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/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sunrpc/svc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sunrpc/svcsock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/nfs_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sunrpc/svcauth_gss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/sunrpc/bc_xprt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/inet_sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "nfs4_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "callback.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "netns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define NFSDBG_FACILITY NFSDBG_CALLBACK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct nfs_callback_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned int users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct svc_serv *serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static DEFINE_MUTEX(nfs_callback_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static struct svc_program nfs4_callback_program;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct cred *cred = current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct nfs_net *nn = net_generic(net, nfs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ret = svc_create_xprt(serv, "tcp", net, PF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) nn->nfs_callback_tcpport = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) nn->nfs_callback_tcpport, PF_INET, net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) nn->nfs_callback_tcpport6 = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } else if (ret != -EAFNOSUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return (ret) ? ret : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * This is the NFSv4 callback kernel thread.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) nfs4_callback_svc(void *vrqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct svc_rqst *rqstp = vrqstp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) while (!kthread_freezable_should_stop(NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) flush_signals(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Listen for a request on the socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (err == -EAGAIN || err == -EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) svc_process(rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) svc_exit_thread(rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) module_put_and_exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #if defined(CONFIG_NFS_V4_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * The callback service for NFSv4.1 callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) nfs41_callback_svc(void *vrqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct svc_rqst *rqstp = vrqstp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct svc_serv *serv = rqstp->rq_server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct rpc_rqst *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) DEFINE_WAIT(wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) set_freezable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) while (!kthread_freezable_should_stop(NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) flush_signals(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) spin_lock_bh(&serv->sv_cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!list_empty(&serv->sv_cb_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) req = list_first_entry(&serv->sv_cb_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct rpc_rqst, rq_bc_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) list_del(&req->rq_bc_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) spin_unlock_bh(&serv->sv_cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) finish_wait(&serv->sv_cb_waitq, &wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dprintk("Invoking bc_svc_process()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) error = bc_svc_process(serv, req, rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dprintk("bc_svc_process() returned w/ error code= %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) spin_unlock_bh(&serv->sv_cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) finish_wait(&serv->sv_cb_waitq, &wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) svc_exit_thread(rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) module_put_and_exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct svc_serv *serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (minorversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Save the svc_serv in the transport so that it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * be referenced when the session backchannel is initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) xprt->bc_serv = serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct svc_serv *serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #endif /* CONFIG_NFS_V4_1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct svc_serv *serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int nrservs = nfs_callback_nr_threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) nfs_callback_bc_serv(minorversion, xprt, serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) nrservs = NFS4_MIN_NR_CALLBACK_THREADS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (serv->sv_nrthreads-1 == nrservs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = serv->sv_ops->svo_setup(serv, NULL, nrservs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) serv->sv_ops->svo_setup(serv, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dprintk("nfs_callback_up: service started\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct nfs_net *nn = net_generic(net, nfs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (--nn->cb_users[minorversion])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dprintk("NFS: destroy per-net callback data; net=%x\n", net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) svc_shutdown_net(serv, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct net *net, struct rpc_xprt *xprt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct nfs_net *nn = net_generic(net, nfs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (nn->cb_users[minorversion]++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dprintk("NFS: create per-net callback data; net=%x\n", net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ret = svc_bind(serv, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) printk(KERN_WARNING "NFS: bind callback service failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto err_bind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = nfs4_callback_up_net(serv, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) else if (xprt->ops->bc_setup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) set_bc_enabled(serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ret = -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) printk(KERN_ERR "NFS: callback service start failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) goto err_socks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) err_socks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) svc_rpcb_cleanup(serv, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) err_bind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) nn->cb_users[minorversion]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dprintk("NFS: Couldn't create callback socket: err = %d; "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "net = %x\n", ret, net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct svc_serv_ops nfs40_cb_sv_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .svo_function = nfs4_callback_svc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .svo_enqueue_xprt = svc_xprt_do_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .svo_setup = svc_set_num_threads_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .svo_module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #if defined(CONFIG_NFS_V4_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static const struct svc_serv_ops nfs41_cb_sv_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .svo_function = nfs41_callback_svc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .svo_enqueue_xprt = svc_xprt_do_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .svo_setup = svc_set_num_threads_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .svo_module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static const struct svc_serv_ops *nfs4_cb_sv_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) [0] = &nfs40_cb_sv_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) [1] = &nfs41_cb_sv_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static const struct svc_serv_ops *nfs4_cb_sv_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) [0] = &nfs40_cb_sv_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) [1] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static struct svc_serv *nfs_callback_create_svc(int minorversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) const struct svc_serv_ops *sv_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct svc_serv *serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Check whether we're already up and running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (cb_info->serv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Note: increase service usage, because later in case of error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * svc_destroy() will be called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) svc_get(cb_info->serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return cb_info->serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) switch (minorversion) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sv_ops = nfs4_cb_sv_ops[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sv_ops = nfs4_cb_sv_ops[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (sv_ops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return ERR_PTR(-ENOTSUPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * Sanity check: if there's no task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * we should be the first user ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (cb_info->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) cb_info->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!serv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) cb_info->serv = serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* As there is only one thread we need to over-ride the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * default maximum of 80 connections
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) serv->sv_maxconn = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dprintk("nfs_callback_create_svc: service created\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * Bring up the callback thread if it is not already up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct svc_serv *serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct net *net = xprt->xprt_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mutex_lock(&nfs_callback_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) serv = nfs_callback_create_svc(minorversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (IS_ERR(serv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = PTR_ERR(serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) goto err_create;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ret = nfs_callback_up_net(minorversion, serv, net, xprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) goto err_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = nfs_callback_start_svc(minorversion, xprt, serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto err_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) cb_info->users++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * svc_create creates the svc_serv with sv_nrthreads == 1, and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * svc_prepare_thread increments that. So we need to call svc_destroy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * on both success and failure so that the refcount is 1 when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * thread exits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) err_net:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (!cb_info->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) cb_info->serv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) svc_destroy(serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err_create:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) mutex_unlock(&nfs_callback_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) err_start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) nfs_callback_down_net(minorversion, serv, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dprintk("NFS: Couldn't create server thread; err = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) goto err_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^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) * Kill the callback thread if it's no longer being used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) void nfs_callback_down(int minorversion, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct svc_serv *serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) mutex_lock(&nfs_callback_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) serv = cb_info->serv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) nfs_callback_down_net(minorversion, serv, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) cb_info->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (cb_info->users == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) svc_get(serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) serv->sv_ops->svo_setup(serv, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) svc_destroy(serv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) dprintk("nfs_callback_down: service destroyed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) cb_info->serv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) mutex_unlock(&nfs_callback_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Boolean check of RPC_AUTH_GSS principal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) char *p = rqstp->rq_cred.cr_principal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (clp->cl_minorversion != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * It might just be a normal user principal, in which case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * userspace won't bother to tell us the name at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (p == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Did we get the acceptor from userland during the SETCLIENID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * negotiation?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (clp->cl_acceptor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return !strcmp(p, clp->cl_acceptor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * Otherwise try to verify it using the cl_hostname. Note that this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * doesn't work if a non-canonical hostname was used in the devname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (memcmp(p, "nfs@", 4) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (strcmp(p, clp->cl_hostname) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * pg_authenticate method for nfsv4 callback threads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * The authflavor has been negotiated, so an incorrect flavor is a server
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * bug. Deny packets with incorrect authflavor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * All other checking done after NFS decoding where the nfs_client can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * found in nfs4_callback_compound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int nfs_callback_authenticate(struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) switch (rqstp->rq_authop->flavour) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case RPC_AUTH_NULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (rqstp->rq_proc != CB_NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case RPC_AUTH_GSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* No RPC_AUTH_GSS support yet in NFSv4.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (svc_is_backchannel(rqstp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return SVC_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Define NFS4 callback program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static const struct svc_version *nfs4_callback_version[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) [1] = &nfs4_callback_version1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) [4] = &nfs4_callback_version4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static struct svc_stat nfs4_callback_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static struct svc_program nfs4_callback_program = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .pg_prog = NFS4_CALLBACK, /* RPC service number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .pg_vers = nfs4_callback_version, /* version table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .pg_name = "NFSv4 callback", /* service name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .pg_class = "nfs", /* authentication class */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .pg_stats = &nfs4_callback_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .pg_authenticate = nfs_callback_authenticate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .pg_init_request = svc_generic_init_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .pg_rpcbind_set = svc_generic_rpcbind_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) };