VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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