xref: /openbmc/linux/net/sunrpc/svc.c (revision 37902c6313090235c847af89c5515591261ee338)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * linux/net/sunrpc/svc.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * High-level RPC service routines
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
8bfd24160SGreg Banks  *
9bfd24160SGreg Banks  * Multiple threads pools and NUMAisation
10bfd24160SGreg Banks  * Copyright (c) 2006 Silicon Graphics, Inc.
11bfd24160SGreg Banks  * by Greg Banks <gnb@melbourne.sgi.com>
121da177e4SLinus Torvalds  */
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <linux/linkage.h>
153f07c014SIngo Molnar #include <linux/sched/signal.h>
161da177e4SLinus Torvalds #include <linux/errno.h>
171da177e4SLinus Torvalds #include <linux/net.h>
181da177e4SLinus Torvalds #include <linux/in.h>
191da177e4SLinus Torvalds #include <linux/mm.h>
20a7455442SGreg Banks #include <linux/interrupt.h>
21a7455442SGreg Banks #include <linux/module.h>
229867d76cSJeff Layton #include <linux/kthread.h>
235a0e3ad6STejun Heo #include <linux/slab.h>
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #include <linux/sunrpc/types.h>
261da177e4SLinus Torvalds #include <linux/sunrpc/xdr.h>
271da177e4SLinus Torvalds #include <linux/sunrpc/stats.h>
281da177e4SLinus Torvalds #include <linux/sunrpc/svcsock.h>
291da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h>
304d6bbb62SRicardo Labiaga #include <linux/sunrpc/bc_xprt.h>
311da177e4SLinus Torvalds 
32860a0d9eSJeff Layton #include <trace/events/sunrpc.h>
33860a0d9eSJeff Layton 
343a126180SChuck Lever #include "fail.h"
353a126180SChuck Lever 
361da177e4SLinus Torvalds #define RPCDBG_FACILITY	RPCDBG_SVCDSP
371da177e4SLinus Torvalds 
385247fab5SStanislav Kinsbursky static void svc_unregister(const struct svc_serv *serv, struct net *net);
397252d575SChuck Lever 
4042a7fc4aSGreg Banks #define SVC_POOL_DEFAULT	SVC_POOL_GLOBAL
41bfd24160SGreg Banks 
42bfd24160SGreg Banks /*
43cf0e124eSNeilBrown  * Mode for mapping cpus to pools.
44cf0e124eSNeilBrown  */
45cf0e124eSNeilBrown enum {
46cf0e124eSNeilBrown 	SVC_POOL_AUTO = -1,	/* choose one of the others */
47cf0e124eSNeilBrown 	SVC_POOL_GLOBAL,	/* no mapping, just a single global pool
48cf0e124eSNeilBrown 				 * (legacy & UP mode) */
49cf0e124eSNeilBrown 	SVC_POOL_PERCPU,	/* one pool per cpu */
50cf0e124eSNeilBrown 	SVC_POOL_PERNODE	/* one pool per numa node */
51cf0e124eSNeilBrown };
52cf0e124eSNeilBrown 
53cf0e124eSNeilBrown /*
54bfd24160SGreg Banks  * Structure for mapping cpus to pools and vice versa.
55bfd24160SGreg Banks  * Setup once during sunrpc initialisation.
56bfd24160SGreg Banks  */
57cf0e124eSNeilBrown 
58cf0e124eSNeilBrown struct svc_pool_map {
59cf0e124eSNeilBrown 	int count;			/* How many svc_servs use us */
60cf0e124eSNeilBrown 	int mode;			/* Note: int not enum to avoid
61cf0e124eSNeilBrown 					 * warnings about "enumeration value
62cf0e124eSNeilBrown 					 * not handled in switch" */
63cf0e124eSNeilBrown 	unsigned int npools;
64cf0e124eSNeilBrown 	unsigned int *pool_to;		/* maps pool id to cpu or node */
65cf0e124eSNeilBrown 	unsigned int *to_pool;		/* maps cpu or node to pool id */
66cf0e124eSNeilBrown };
67cf0e124eSNeilBrown 
68cf0e124eSNeilBrown static struct svc_pool_map svc_pool_map = {
6942a7fc4aSGreg Banks 	.mode = SVC_POOL_DEFAULT
70bfd24160SGreg Banks };
71d70bc0c6SJeff Layton 
7242a7fc4aSGreg Banks static DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */
73bfd24160SGreg Banks 
7442a7fc4aSGreg Banks static int
75e4dca7b7SKees Cook param_set_pool_mode(const char *val, const struct kernel_param *kp)
7642a7fc4aSGreg Banks {
7742a7fc4aSGreg Banks 	int *ip = (int *)kp->arg;
7842a7fc4aSGreg Banks 	struct svc_pool_map *m = &svc_pool_map;
7942a7fc4aSGreg Banks 	int err;
8042a7fc4aSGreg Banks 
8142a7fc4aSGreg Banks 	mutex_lock(&svc_pool_map_mutex);
8242a7fc4aSGreg Banks 
8342a7fc4aSGreg Banks 	err = -EBUSY;
8442a7fc4aSGreg Banks 	if (m->count)
8542a7fc4aSGreg Banks 		goto out;
8642a7fc4aSGreg Banks 
8742a7fc4aSGreg Banks 	err = 0;
8842a7fc4aSGreg Banks 	if (!strncmp(val, "auto", 4))
8942a7fc4aSGreg Banks 		*ip = SVC_POOL_AUTO;
9042a7fc4aSGreg Banks 	else if (!strncmp(val, "global", 6))
9142a7fc4aSGreg Banks 		*ip = SVC_POOL_GLOBAL;
9242a7fc4aSGreg Banks 	else if (!strncmp(val, "percpu", 6))
9342a7fc4aSGreg Banks 		*ip = SVC_POOL_PERCPU;
9442a7fc4aSGreg Banks 	else if (!strncmp(val, "pernode", 7))
9542a7fc4aSGreg Banks 		*ip = SVC_POOL_PERNODE;
9642a7fc4aSGreg Banks 	else
9742a7fc4aSGreg Banks 		err = -EINVAL;
9842a7fc4aSGreg Banks 
9942a7fc4aSGreg Banks out:
10042a7fc4aSGreg Banks 	mutex_unlock(&svc_pool_map_mutex);
10142a7fc4aSGreg Banks 	return err;
10242a7fc4aSGreg Banks }
10342a7fc4aSGreg Banks 
10442a7fc4aSGreg Banks static int
105e4dca7b7SKees Cook param_get_pool_mode(char *buf, const struct kernel_param *kp)
10642a7fc4aSGreg Banks {
10742a7fc4aSGreg Banks 	int *ip = (int *)kp->arg;
10842a7fc4aSGreg Banks 
10942a7fc4aSGreg Banks 	switch (*ip)
11042a7fc4aSGreg Banks 	{
11142a7fc4aSGreg Banks 	case SVC_POOL_AUTO:
112746c6237SXiongfeng Wang 		return strlcpy(buf, "auto\n", 20);
11342a7fc4aSGreg Banks 	case SVC_POOL_GLOBAL:
114746c6237SXiongfeng Wang 		return strlcpy(buf, "global\n", 20);
11542a7fc4aSGreg Banks 	case SVC_POOL_PERCPU:
116746c6237SXiongfeng Wang 		return strlcpy(buf, "percpu\n", 20);
11742a7fc4aSGreg Banks 	case SVC_POOL_PERNODE:
118746c6237SXiongfeng Wang 		return strlcpy(buf, "pernode\n", 20);
11942a7fc4aSGreg Banks 	default:
120746c6237SXiongfeng Wang 		return sprintf(buf, "%d\n", *ip);
12142a7fc4aSGreg Banks 	}
12242a7fc4aSGreg Banks }
12342a7fc4aSGreg Banks 
12442a7fc4aSGreg Banks module_param_call(pool_mode, param_set_pool_mode, param_get_pool_mode,
12542a7fc4aSGreg Banks 		 &svc_pool_map.mode, 0644);
126bfd24160SGreg Banks 
127bfd24160SGreg Banks /*
128bfd24160SGreg Banks  * Detect best pool mapping mode heuristically,
129bfd24160SGreg Banks  * according to the machine's topology.
130bfd24160SGreg Banks  */
131bfd24160SGreg Banks static int
132bfd24160SGreg Banks svc_pool_map_choose_mode(void)
133bfd24160SGreg Banks {
134bfd24160SGreg Banks 	unsigned int node;
135bfd24160SGreg Banks 
13662bc62a8SChristoph Lameter 	if (nr_online_nodes > 1) {
137bfd24160SGreg Banks 		/*
138bfd24160SGreg Banks 		 * Actually have multiple NUMA nodes,
139bfd24160SGreg Banks 		 * so split pools on NUMA node boundaries
140bfd24160SGreg Banks 		 */
141bfd24160SGreg Banks 		return SVC_POOL_PERNODE;
142bfd24160SGreg Banks 	}
143bfd24160SGreg Banks 
14472c33688SH Hartley Sweeten 	node = first_online_node;
145bfd24160SGreg Banks 	if (nr_cpus_node(node) > 2) {
146bfd24160SGreg Banks 		/*
147bfd24160SGreg Banks 		 * Non-trivial SMP, or CONFIG_NUMA on
148bfd24160SGreg Banks 		 * non-NUMA hardware, e.g. with a generic
149bfd24160SGreg Banks 		 * x86_64 kernel on Xeons.  In this case we
150bfd24160SGreg Banks 		 * want to divide the pools on cpu boundaries.
151bfd24160SGreg Banks 		 */
152bfd24160SGreg Banks 		return SVC_POOL_PERCPU;
153bfd24160SGreg Banks 	}
154bfd24160SGreg Banks 
155bfd24160SGreg Banks 	/* default: one global pool */
156bfd24160SGreg Banks 	return SVC_POOL_GLOBAL;
157bfd24160SGreg Banks }
158bfd24160SGreg Banks 
159bfd24160SGreg Banks /*
160bfd24160SGreg Banks  * Allocate the to_pool[] and pool_to[] arrays.
161bfd24160SGreg Banks  * Returns 0 on success or an errno.
162bfd24160SGreg Banks  */
163bfd24160SGreg Banks static int
164bfd24160SGreg Banks svc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools)
165bfd24160SGreg Banks {
166bfd24160SGreg Banks 	m->to_pool = kcalloc(maxpools, sizeof(unsigned int), GFP_KERNEL);
167bfd24160SGreg Banks 	if (!m->to_pool)
168bfd24160SGreg Banks 		goto fail;
169bfd24160SGreg Banks 	m->pool_to = kcalloc(maxpools, sizeof(unsigned int), GFP_KERNEL);
170bfd24160SGreg Banks 	if (!m->pool_to)
171bfd24160SGreg Banks 		goto fail_free;
172bfd24160SGreg Banks 
173bfd24160SGreg Banks 	return 0;
174bfd24160SGreg Banks 
175bfd24160SGreg Banks fail_free:
176bfd24160SGreg Banks 	kfree(m->to_pool);
17761c8504cSJ. Bruce Fields 	m->to_pool = NULL;
178bfd24160SGreg Banks fail:
179bfd24160SGreg Banks 	return -ENOMEM;
180bfd24160SGreg Banks }
181bfd24160SGreg Banks 
182bfd24160SGreg Banks /*
183bfd24160SGreg Banks  * Initialise the pool map for SVC_POOL_PERCPU mode.
184bfd24160SGreg Banks  * Returns number of pools or <0 on error.
185bfd24160SGreg Banks  */
186bfd24160SGreg Banks static int
187bfd24160SGreg Banks svc_pool_map_init_percpu(struct svc_pool_map *m)
188bfd24160SGreg Banks {
18953b8a315SChristoph Lameter 	unsigned int maxpools = nr_cpu_ids;
190bfd24160SGreg Banks 	unsigned int pidx = 0;
191bfd24160SGreg Banks 	unsigned int cpu;
192bfd24160SGreg Banks 	int err;
193bfd24160SGreg Banks 
194bfd24160SGreg Banks 	err = svc_pool_map_alloc_arrays(m, maxpools);
195bfd24160SGreg Banks 	if (err)
196bfd24160SGreg Banks 		return err;
197bfd24160SGreg Banks 
198bfd24160SGreg Banks 	for_each_online_cpu(cpu) {
199eb63192bSDan Carpenter 		BUG_ON(pidx >= maxpools);
200bfd24160SGreg Banks 		m->to_pool[cpu] = pidx;
201bfd24160SGreg Banks 		m->pool_to[pidx] = cpu;
202bfd24160SGreg Banks 		pidx++;
203bfd24160SGreg Banks 	}
204bfd24160SGreg Banks 	/* cpus brought online later all get mapped to pool0, sorry */
205bfd24160SGreg Banks 
206bfd24160SGreg Banks 	return pidx;
207bfd24160SGreg Banks };
208bfd24160SGreg Banks 
209bfd24160SGreg Banks 
210bfd24160SGreg Banks /*
211bfd24160SGreg Banks  * Initialise the pool map for SVC_POOL_PERNODE mode.
212bfd24160SGreg Banks  * Returns number of pools or <0 on error.
213bfd24160SGreg Banks  */
214bfd24160SGreg Banks static int
215bfd24160SGreg Banks svc_pool_map_init_pernode(struct svc_pool_map *m)
216bfd24160SGreg Banks {
21774c7aa8bSChristoph Lameter 	unsigned int maxpools = nr_node_ids;
218bfd24160SGreg Banks 	unsigned int pidx = 0;
219bfd24160SGreg Banks 	unsigned int node;
220bfd24160SGreg Banks 	int err;
221bfd24160SGreg Banks 
222bfd24160SGreg Banks 	err = svc_pool_map_alloc_arrays(m, maxpools);
223bfd24160SGreg Banks 	if (err)
224bfd24160SGreg Banks 		return err;
225bfd24160SGreg Banks 
226bfd24160SGreg Banks 	for_each_node_with_cpus(node) {
227bfd24160SGreg Banks 		/* some architectures (e.g. SN2) have cpuless nodes */
228bfd24160SGreg Banks 		BUG_ON(pidx > maxpools);
229bfd24160SGreg Banks 		m->to_pool[node] = pidx;
230bfd24160SGreg Banks 		m->pool_to[pidx] = node;
231bfd24160SGreg Banks 		pidx++;
232bfd24160SGreg Banks 	}
233bfd24160SGreg Banks 	/* nodes brought online later all get mapped to pool0, sorry */
234bfd24160SGreg Banks 
235bfd24160SGreg Banks 	return pidx;
236bfd24160SGreg Banks }
237bfd24160SGreg Banks 
238bfd24160SGreg Banks 
239bfd24160SGreg Banks /*
24042a7fc4aSGreg Banks  * Add a reference to the global map of cpus to pools (and
24193aa619eSNeilBrown  * vice versa) if pools are in use.
24293aa619eSNeilBrown  * Initialise the map if we're the first user.
24393aa619eSNeilBrown  * Returns the number of pools. If this is '1', no reference
24493aa619eSNeilBrown  * was taken.
245bfd24160SGreg Banks  */
246cf0e124eSNeilBrown static unsigned int
24742a7fc4aSGreg Banks svc_pool_map_get(void)
248bfd24160SGreg Banks {
249bfd24160SGreg Banks 	struct svc_pool_map *m = &svc_pool_map;
250bfd24160SGreg Banks 	int npools = -1;
251bfd24160SGreg Banks 
25242a7fc4aSGreg Banks 	mutex_lock(&svc_pool_map_mutex);
253bfd24160SGreg Banks 
25442a7fc4aSGreg Banks 	if (m->count++) {
25542a7fc4aSGreg Banks 		mutex_unlock(&svc_pool_map_mutex);
25693aa619eSNeilBrown 		WARN_ON_ONCE(m->npools <= 1);
25742a7fc4aSGreg Banks 		return m->npools;
25842a7fc4aSGreg Banks 	}
25942a7fc4aSGreg Banks 
26042a7fc4aSGreg Banks 	if (m->mode == SVC_POOL_AUTO)
261bfd24160SGreg Banks 		m->mode = svc_pool_map_choose_mode();
262bfd24160SGreg Banks 
263bfd24160SGreg Banks 	switch (m->mode) {
264bfd24160SGreg Banks 	case SVC_POOL_PERCPU:
265bfd24160SGreg Banks 		npools = svc_pool_map_init_percpu(m);
266bfd24160SGreg Banks 		break;
267bfd24160SGreg Banks 	case SVC_POOL_PERNODE:
268bfd24160SGreg Banks 		npools = svc_pool_map_init_pernode(m);
269bfd24160SGreg Banks 		break;
270bfd24160SGreg Banks 	}
271bfd24160SGreg Banks 
27293aa619eSNeilBrown 	if (npools <= 0) {
273bfd24160SGreg Banks 		/* default, or memory allocation failure */
274bfd24160SGreg Banks 		npools = 1;
275bfd24160SGreg Banks 		m->mode = SVC_POOL_GLOBAL;
276bfd24160SGreg Banks 	}
277bfd24160SGreg Banks 	m->npools = npools;
278bfd24160SGreg Banks 
27993aa619eSNeilBrown 	if (npools == 1)
28093aa619eSNeilBrown 		/* service is unpooled, so doesn't hold a reference */
28193aa619eSNeilBrown 		m->count--;
28293aa619eSNeilBrown 
28342a7fc4aSGreg Banks 	mutex_unlock(&svc_pool_map_mutex);
28493aa619eSNeilBrown 	return npools;
285bfd24160SGreg Banks }
28642a7fc4aSGreg Banks 
28742a7fc4aSGreg Banks /*
28893aa619eSNeilBrown  * Drop a reference to the global map of cpus to pools, if
28993aa619eSNeilBrown  * pools were in use, i.e. if npools > 1.
29042a7fc4aSGreg Banks  * When the last reference is dropped, the map data is
29142a7fc4aSGreg Banks  * freed; this allows the sysadmin to change the pool
29242a7fc4aSGreg Banks  * mode using the pool_mode module option without
29342a7fc4aSGreg Banks  * rebooting or re-loading sunrpc.ko.
29442a7fc4aSGreg Banks  */
295cf0e124eSNeilBrown static void
29693aa619eSNeilBrown svc_pool_map_put(int npools)
29742a7fc4aSGreg Banks {
29842a7fc4aSGreg Banks 	struct svc_pool_map *m = &svc_pool_map;
29942a7fc4aSGreg Banks 
30093aa619eSNeilBrown 	if (npools <= 1)
30193aa619eSNeilBrown 		return;
30242a7fc4aSGreg Banks 	mutex_lock(&svc_pool_map_mutex);
30342a7fc4aSGreg Banks 
30442a7fc4aSGreg Banks 	if (!--m->count) {
30542a7fc4aSGreg Banks 		kfree(m->to_pool);
30661c8504cSJ. Bruce Fields 		m->to_pool = NULL;
30742a7fc4aSGreg Banks 		kfree(m->pool_to);
30861c8504cSJ. Bruce Fields 		m->pool_to = NULL;
30942a7fc4aSGreg Banks 		m->npools = 0;
31042a7fc4aSGreg Banks 	}
31142a7fc4aSGreg Banks 
31242a7fc4aSGreg Banks 	mutex_unlock(&svc_pool_map_mutex);
31342a7fc4aSGreg Banks }
31442a7fc4aSGreg Banks 
31511fd165cSEric Dumazet static int svc_pool_map_get_node(unsigned int pidx)
31611fd165cSEric Dumazet {
31711fd165cSEric Dumazet 	const struct svc_pool_map *m = &svc_pool_map;
31811fd165cSEric Dumazet 
31911fd165cSEric Dumazet 	if (m->count) {
32011fd165cSEric Dumazet 		if (m->mode == SVC_POOL_PERCPU)
32111fd165cSEric Dumazet 			return cpu_to_node(m->pool_to[pidx]);
32211fd165cSEric Dumazet 		if (m->mode == SVC_POOL_PERNODE)
32311fd165cSEric Dumazet 			return m->pool_to[pidx];
32411fd165cSEric Dumazet 	}
32511fd165cSEric Dumazet 	return NUMA_NO_NODE;
32611fd165cSEric Dumazet }
327bfd24160SGreg Banks /*
3289867d76cSJeff Layton  * Set the given thread's cpus_allowed mask so that it
329bfd24160SGreg Banks  * will only run on cpus in the given pool.
330bfd24160SGreg Banks  */
3319867d76cSJeff Layton static inline void
3329867d76cSJeff Layton svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx)
333bfd24160SGreg Banks {
334bfd24160SGreg Banks 	struct svc_pool_map *m = &svc_pool_map;
3359867d76cSJeff Layton 	unsigned int node = m->pool_to[pidx];
336bfd24160SGreg Banks 
337bfd24160SGreg Banks 	/*
338bfd24160SGreg Banks 	 * The caller checks for sv_nrpools > 1, which
33942a7fc4aSGreg Banks 	 * implies that we've been initialized.
340bfd24160SGreg Banks 	 */
3411bd58aafSWeston Andros Adamson 	WARN_ON_ONCE(m->count == 0);
3421bd58aafSWeston Andros Adamson 	if (m->count == 0)
3431bd58aafSWeston Andros Adamson 		return;
344bfd24160SGreg Banks 
3459867d76cSJeff Layton 	switch (m->mode) {
346bfd24160SGreg Banks 	case SVC_POOL_PERCPU:
347c5f59f08SMike Travis 	{
348aa85ea5bSRusty Russell 		set_cpus_allowed_ptr(task, cpumask_of(node));
3499867d76cSJeff Layton 		break;
350c5f59f08SMike Travis 	}
351bfd24160SGreg Banks 	case SVC_POOL_PERNODE:
352c5f59f08SMike Travis 	{
353a70f7302SRusty Russell 		set_cpus_allowed_ptr(task, cpumask_of_node(node));
3549867d76cSJeff Layton 		break;
355bfd24160SGreg Banks 	}
356bfd24160SGreg Banks 	}
357c5f59f08SMike Travis }
358bfd24160SGreg Banks 
359bfd24160SGreg Banks /*
360bfd24160SGreg Banks  * Use the mapping mode to choose a pool for a given CPU.
361bfd24160SGreg Banks  * Used when enqueueing an incoming RPC.  Always returns
362bfd24160SGreg Banks  * a non-NULL pool pointer.
363bfd24160SGreg Banks  */
364bfd24160SGreg Banks struct svc_pool *
365bfd24160SGreg Banks svc_pool_for_cpu(struct svc_serv *serv, int cpu)
366bfd24160SGreg Banks {
367bfd24160SGreg Banks 	struct svc_pool_map *m = &svc_pool_map;
368bfd24160SGreg Banks 	unsigned int pidx = 0;
369bfd24160SGreg Banks 
37093aa619eSNeilBrown 	if (serv->sv_nrpools <= 1)
37193aa619eSNeilBrown 		return serv->sv_pools;
37293aa619eSNeilBrown 
373bfd24160SGreg Banks 	switch (m->mode) {
374bfd24160SGreg Banks 	case SVC_POOL_PERCPU:
375bfd24160SGreg Banks 		pidx = m->to_pool[cpu];
376bfd24160SGreg Banks 		break;
377bfd24160SGreg Banks 	case SVC_POOL_PERNODE:
378bfd24160SGreg Banks 		pidx = m->to_pool[cpu_to_node(cpu)];
379bfd24160SGreg Banks 		break;
380bfd24160SGreg Banks 	}
38193aa619eSNeilBrown 
382bfd24160SGreg Banks 	return &serv->sv_pools[pidx % serv->sv_nrpools];
383bfd24160SGreg Banks }
384bfd24160SGreg Banks 
385bb2224dfSStanislav Kinsbursky int svc_rpcb_setup(struct svc_serv *serv, struct net *net)
386d9908560SStanislav Kinsbursky {
387d9908560SStanislav Kinsbursky 	int err;
388d9908560SStanislav Kinsbursky 
389bee42f68SStanislav Kinsbursky 	err = rpcb_create_local(net);
390d9908560SStanislav Kinsbursky 	if (err)
391d9908560SStanislav Kinsbursky 		return err;
392d9908560SStanislav Kinsbursky 
393d9908560SStanislav Kinsbursky 	/* Remove any stale portmap registrations */
394bee42f68SStanislav Kinsbursky 	svc_unregister(serv, net);
395d9908560SStanislav Kinsbursky 	return 0;
396d9908560SStanislav Kinsbursky }
397bb2224dfSStanislav Kinsbursky EXPORT_SYMBOL_GPL(svc_rpcb_setup);
398d9908560SStanislav Kinsbursky 
3995ecebb7cSStanislav Kinsbursky void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net)
400d9908560SStanislav Kinsbursky {
4015ecebb7cSStanislav Kinsbursky 	svc_unregister(serv, net);
4025ecebb7cSStanislav Kinsbursky 	rpcb_put_local(net);
403d9908560SStanislav Kinsbursky }
40416d05870SStanislav Kinsbursky EXPORT_SYMBOL_GPL(svc_rpcb_cleanup);
405d9908560SStanislav Kinsbursky 
406d9908560SStanislav Kinsbursky static int svc_uses_rpcbind(struct svc_serv *serv)
407d9908560SStanislav Kinsbursky {
408d9908560SStanislav Kinsbursky 	struct svc_program	*progp;
409d9908560SStanislav Kinsbursky 	unsigned int		i;
410d9908560SStanislav Kinsbursky 
411d9908560SStanislav Kinsbursky 	for (progp = serv->sv_program; progp; progp = progp->pg_next) {
412d9908560SStanislav Kinsbursky 		for (i = 0; i < progp->pg_nvers; i++) {
413d9908560SStanislav Kinsbursky 			if (progp->pg_vers[i] == NULL)
414d9908560SStanislav Kinsbursky 				continue;
41505a45a2dSJeff Layton 			if (!progp->pg_vers[i]->vs_hidden)
416d9908560SStanislav Kinsbursky 				return 1;
417d9908560SStanislav Kinsbursky 		}
418d9908560SStanislav Kinsbursky 	}
419d9908560SStanislav Kinsbursky 
420d9908560SStanislav Kinsbursky 	return 0;
421d9908560SStanislav Kinsbursky }
422bfd24160SGreg Banks 
4239793f7c8SStanislav Kinsbursky int svc_bind(struct svc_serv *serv, struct net *net)
4249793f7c8SStanislav Kinsbursky {
4259793f7c8SStanislav Kinsbursky 	if (!svc_uses_rpcbind(serv))
4269793f7c8SStanislav Kinsbursky 		return 0;
4279793f7c8SStanislav Kinsbursky 	return svc_rpcb_setup(serv, net);
4289793f7c8SStanislav Kinsbursky }
4299793f7c8SStanislav Kinsbursky EXPORT_SYMBOL_GPL(svc_bind);
4309793f7c8SStanislav Kinsbursky 
431d0025268STrond Myklebust #if defined(CONFIG_SUNRPC_BACKCHANNEL)
432d0025268STrond Myklebust static void
433d0025268STrond Myklebust __svc_init_bc(struct svc_serv *serv)
434d0025268STrond Myklebust {
435d0025268STrond Myklebust 	INIT_LIST_HEAD(&serv->sv_cb_list);
436d0025268STrond Myklebust 	spin_lock_init(&serv->sv_cb_lock);
437d0025268STrond Myklebust 	init_waitqueue_head(&serv->sv_cb_waitq);
438d0025268STrond Myklebust }
439d0025268STrond Myklebust #else
440d0025268STrond Myklebust static void
441d0025268STrond Myklebust __svc_init_bc(struct svc_serv *serv)
442d0025268STrond Myklebust {
443d0025268STrond Myklebust }
444d0025268STrond Myklebust #endif
445d0025268STrond Myklebust 
446bfd24160SGreg Banks /*
4471da177e4SLinus Torvalds  * Create an RPC service
4481da177e4SLinus Torvalds  */
449a7455442SGreg Banks static struct svc_serv *
450a7455442SGreg Banks __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
451*37902c63SChuck Lever 	     int (*threadfn)(void *data))
4521da177e4SLinus Torvalds {
4531da177e4SLinus Torvalds 	struct svc_serv	*serv;
454ea339d46SChuck Lever 	unsigned int vers;
4551da177e4SLinus Torvalds 	unsigned int xdrsize;
4563262c816SGreg Banks 	unsigned int i;
4571da177e4SLinus Torvalds 
4580da974f4SPanagiotis Issaris 	if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL)))
4591da177e4SLinus Torvalds 		return NULL;
4609ba02638SAndreas Gruenbacher 	serv->sv_name      = prog->pg_name;
4611da177e4SLinus Torvalds 	serv->sv_program   = prog;
462ec52361dSNeilBrown 	kref_init(&serv->sv_refcnt);
4631da177e4SLinus Torvalds 	serv->sv_stats     = prog->pg_stats;
464c6b0a9f8SNeilBrown 	if (bufsize > RPCSVC_MAXPAYLOAD)
465c6b0a9f8SNeilBrown 		bufsize = RPCSVC_MAXPAYLOAD;
466c6b0a9f8SNeilBrown 	serv->sv_max_payload = bufsize? bufsize : 4096;
467c6b0a9f8SNeilBrown 	serv->sv_max_mesg  = roundup(serv->sv_max_payload + PAGE_SIZE, PAGE_SIZE);
468*37902c63SChuck Lever 	serv->sv_threadfn = threadfn;
4691da177e4SLinus Torvalds 	xdrsize = 0;
4709ba02638SAndreas Gruenbacher 	while (prog) {
4719ba02638SAndreas Gruenbacher 		prog->pg_lovers = prog->pg_nvers-1;
4721da177e4SLinus Torvalds 		for (vers=0; vers<prog->pg_nvers ; vers++)
4731da177e4SLinus Torvalds 			if (prog->pg_vers[vers]) {
4741da177e4SLinus Torvalds 				prog->pg_hivers = vers;
4751da177e4SLinus Torvalds 				if (prog->pg_lovers > vers)
4761da177e4SLinus Torvalds 					prog->pg_lovers = vers;
4771da177e4SLinus Torvalds 				if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
4781da177e4SLinus Torvalds 					xdrsize = prog->pg_vers[vers]->vs_xdrsize;
4791da177e4SLinus Torvalds 			}
4809ba02638SAndreas Gruenbacher 		prog = prog->pg_next;
4819ba02638SAndreas Gruenbacher 	}
4821da177e4SLinus Torvalds 	serv->sv_xdrsize   = xdrsize;
4831da177e4SLinus Torvalds 	INIT_LIST_HEAD(&serv->sv_tempsocks);
4841da177e4SLinus Torvalds 	INIT_LIST_HEAD(&serv->sv_permsocks);
485ff861c4dSKees Cook 	timer_setup(&serv->sv_temptimer, NULL, 0);
4861da177e4SLinus Torvalds 	spin_lock_init(&serv->sv_lock);
4871da177e4SLinus Torvalds 
488d0025268STrond Myklebust 	__svc_init_bc(serv);
489d0025268STrond Myklebust 
490a7455442SGreg Banks 	serv->sv_nrpools = npools;
4913262c816SGreg Banks 	serv->sv_pools =
492cd861280SRobert P. J. Day 		kcalloc(serv->sv_nrpools, sizeof(struct svc_pool),
4933262c816SGreg Banks 			GFP_KERNEL);
4943262c816SGreg Banks 	if (!serv->sv_pools) {
4953262c816SGreg Banks 		kfree(serv);
4963262c816SGreg Banks 		return NULL;
4973262c816SGreg Banks 	}
4983262c816SGreg Banks 
4993262c816SGreg Banks 	for (i = 0; i < serv->sv_nrpools; i++) {
5003262c816SGreg Banks 		struct svc_pool *pool = &serv->sv_pools[i];
5013262c816SGreg Banks 
50246121cf7SChuck Lever 		dprintk("svc: initialising pool %u for %s\n",
5033262c816SGreg Banks 				i, serv->sv_name);
5043262c816SGreg Banks 
5053262c816SGreg Banks 		pool->sp_id = i;
5063262c816SGreg Banks 		INIT_LIST_HEAD(&pool->sp_sockets);
507a7455442SGreg Banks 		INIT_LIST_HEAD(&pool->sp_all_threads);
5083262c816SGreg Banks 		spin_lock_init(&pool->sp_lock);
5093262c816SGreg Banks 	}
5103262c816SGreg Banks 
5111da177e4SLinus Torvalds 	return serv;
5121da177e4SLinus Torvalds }
5131da177e4SLinus Torvalds 
514*37902c63SChuck Lever /**
515*37902c63SChuck Lever  * svc_create - Create an RPC service
516*37902c63SChuck Lever  * @prog: the RPC program the new service will handle
517*37902c63SChuck Lever  * @bufsize: maximum message size for @prog
518*37902c63SChuck Lever  * @threadfn: a function to service RPC requests for @prog
519*37902c63SChuck Lever  *
520*37902c63SChuck Lever  * Returns an instantiated struct svc_serv object or NULL.
521*37902c63SChuck Lever  */
522*37902c63SChuck Lever struct svc_serv *svc_create(struct svc_program *prog, unsigned int bufsize,
523*37902c63SChuck Lever 			    int (*threadfn)(void *data))
524a7455442SGreg Banks {
525*37902c63SChuck Lever 	return __svc_create(prog, bufsize, 1, threadfn);
526a7455442SGreg Banks }
52724c3767eSTrond Myklebust EXPORT_SYMBOL_GPL(svc_create);
528a7455442SGreg Banks 
529*37902c63SChuck Lever /**
530*37902c63SChuck Lever  * svc_create_pooled - Create an RPC service with pooled threads
531*37902c63SChuck Lever  * @prog: the RPC program the new service will handle
532*37902c63SChuck Lever  * @bufsize: maximum message size for @prog
533*37902c63SChuck Lever  * @threadfn: a function to service RPC requests for @prog
534*37902c63SChuck Lever  *
535*37902c63SChuck Lever  * Returns an instantiated struct svc_serv object or NULL.
536*37902c63SChuck Lever  */
537*37902c63SChuck Lever struct svc_serv *svc_create_pooled(struct svc_program *prog,
538*37902c63SChuck Lever 				   unsigned int bufsize,
539*37902c63SChuck Lever 				   int (*threadfn)(void *data))
540a7455442SGreg Banks {
541a7455442SGreg Banks 	struct svc_serv *serv;
54242a7fc4aSGreg Banks 	unsigned int npools = svc_pool_map_get();
543a7455442SGreg Banks 
544*37902c63SChuck Lever 	serv = __svc_create(prog, bufsize, npools, threadfn);
545067f96efSJeff Layton 	if (!serv)
546067f96efSJeff Layton 		goto out_err;
547a7455442SGreg Banks 	return serv;
548067f96efSJeff Layton out_err:
54993aa619eSNeilBrown 	svc_pool_map_put(npools);
550067f96efSJeff Layton 	return NULL;
551a7455442SGreg Banks }
55224c3767eSTrond Myklebust EXPORT_SYMBOL_GPL(svc_create_pooled);
553a7455442SGreg Banks 
5541da177e4SLinus Torvalds /*
555bedbdd8bSNeil Brown  * Destroy an RPC service. Should be called with appropriate locking to
5562a36395fSNeilBrown  * protect sv_permsocks and sv_tempsocks.
5571da177e4SLinus Torvalds  */
5581da177e4SLinus Torvalds void
559ec52361dSNeilBrown svc_destroy(struct kref *ref)
5601da177e4SLinus Torvalds {
561ec52361dSNeilBrown 	struct svc_serv *serv = container_of(ref, struct svc_serv, sv_refcnt);
5621da177e4SLinus Torvalds 
563ec52361dSNeilBrown 	dprintk("svc: svc_destroy(%s)\n", serv->sv_program->pg_name);
56436bdfc8bSGreg Banks 	del_timer_sync(&serv->sv_temptimer);
565074d0f67SStanislav Kinsbursky 
5667b147f1fSStanislav Kinsbursky 	/*
5677b147f1fSStanislav Kinsbursky 	 * The last user is gone and thus all sockets have to be destroyed to
5687b147f1fSStanislav Kinsbursky 	 * the point. Check this.
5697b147f1fSStanislav Kinsbursky 	 */
5707b147f1fSStanislav Kinsbursky 	BUG_ON(!list_empty(&serv->sv_permsocks));
5717b147f1fSStanislav Kinsbursky 	BUG_ON(!list_empty(&serv->sv_tempsocks));
572cda1fd4aSNeilBrown 
5731da177e4SLinus Torvalds 	cache_clean_deferred(serv);
5741da177e4SLinus Torvalds 
57593aa619eSNeilBrown 	svc_pool_map_put(serv->sv_nrpools);
57642a7fc4aSGreg Banks 
5773262c816SGreg Banks 	kfree(serv->sv_pools);
5781da177e4SLinus Torvalds 	kfree(serv);
5791da177e4SLinus Torvalds }
58024c3767eSTrond Myklebust EXPORT_SYMBOL_GPL(svc_destroy);
5811da177e4SLinus Torvalds 
5821da177e4SLinus Torvalds /*
5831da177e4SLinus Torvalds  * Allocate an RPC server's buffer space.
5844ff923ceSChuck Lever  * We allocate pages and place them in rq_pages.
5851da177e4SLinus Torvalds  */
5861da177e4SLinus Torvalds static int
58711fd165cSEric Dumazet svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node)
5881da177e4SLinus Torvalds {
5890dc220f0SChuck Lever 	unsigned int pages, arghi;
5901da177e4SLinus Torvalds 
591ba17686fSAndy Adamson 	/* bc_xprt uses fore channel allocated buffers */
592ba17686fSAndy Adamson 	if (svc_is_backchannel(rqstp))
593ba17686fSAndy Adamson 		return 1;
594ba17686fSAndy Adamson 
595c6b0a9f8SNeilBrown 	pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
596c6b0a9f8SNeilBrown 				       * We assume one is at most one page
597c6b0a9f8SNeilBrown 				       */
5981da177e4SLinus Torvalds 	arghi = 0;
599b25cd058SWeston Andros Adamson 	WARN_ON_ONCE(pages > RPCSVC_MAXPAGES);
600b25cd058SWeston Andros Adamson 	if (pages > RPCSVC_MAXPAGES)
601b25cd058SWeston Andros Adamson 		pages = RPCSVC_MAXPAGES;
6021da177e4SLinus Torvalds 	while (pages) {
60311fd165cSEric Dumazet 		struct page *p = alloc_pages_node(node, GFP_KERNEL, 0);
6041da177e4SLinus Torvalds 		if (!p)
6051da177e4SLinus Torvalds 			break;
60644524359SNeilBrown 		rqstp->rq_pages[arghi++] = p;
6071da177e4SLinus Torvalds 		pages--;
6081da177e4SLinus Torvalds 	}
6090dc220f0SChuck Lever 	return pages == 0;
6101da177e4SLinus Torvalds }
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds /*
6131da177e4SLinus Torvalds  * Release an RPC server buffer
6141da177e4SLinus Torvalds  */
6151da177e4SLinus Torvalds static void
6161da177e4SLinus Torvalds svc_release_buffer(struct svc_rqst *rqstp)
6171da177e4SLinus Torvalds {
61850c8bb13SChuck Lever 	unsigned int i;
61950c8bb13SChuck Lever 
62044524359SNeilBrown 	for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++)
62144524359SNeilBrown 		if (rqstp->rq_pages[i])
62244524359SNeilBrown 			put_page(rqstp->rq_pages[i]);
6231da177e4SLinus Torvalds }
6241da177e4SLinus Torvalds 
6250113ab34SJeff Layton struct svc_rqst *
6261b6dc1dfSJeff Layton svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node)
6270113ab34SJeff Layton {
6280113ab34SJeff Layton 	struct svc_rqst	*rqstp;
6290113ab34SJeff Layton 
63011fd165cSEric Dumazet 	rqstp = kzalloc_node(sizeof(*rqstp), GFP_KERNEL, node);
6310113ab34SJeff Layton 	if (!rqstp)
6321b6dc1dfSJeff Layton 		return rqstp;
6330113ab34SJeff Layton 
634b1691bc0SJeff Layton 	__set_bit(RQ_BUSY, &rqstp->rq_flags);
635b1691bc0SJeff Layton 	spin_lock_init(&rqstp->rq_lock);
636b1691bc0SJeff Layton 	rqstp->rq_server = serv;
637b1691bc0SJeff Layton 	rqstp->rq_pool = pool;
6381b6dc1dfSJeff Layton 
6395191955dSChuck Lever 	rqstp->rq_scratch_page = alloc_pages_node(node, GFP_KERNEL, 0);
6405191955dSChuck Lever 	if (!rqstp->rq_scratch_page)
6415191955dSChuck Lever 		goto out_enomem;
6425191955dSChuck Lever 
6431b6dc1dfSJeff Layton 	rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node);
6441b6dc1dfSJeff Layton 	if (!rqstp->rq_argp)
6451b6dc1dfSJeff Layton 		goto out_enomem;
6461b6dc1dfSJeff Layton 
6471b6dc1dfSJeff Layton 	rqstp->rq_resp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node);
6481b6dc1dfSJeff Layton 	if (!rqstp->rq_resp)
6491b6dc1dfSJeff Layton 		goto out_enomem;
6501b6dc1dfSJeff Layton 
6511b6dc1dfSJeff Layton 	if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node))
6521b6dc1dfSJeff Layton 		goto out_enomem;
6531b6dc1dfSJeff Layton 
6541b6dc1dfSJeff Layton 	return rqstp;
6551b6dc1dfSJeff Layton out_enomem:
6561b6dc1dfSJeff Layton 	svc_rqst_free(rqstp);
6571b6dc1dfSJeff Layton 	return NULL;
6581b6dc1dfSJeff Layton }
6591b6dc1dfSJeff Layton EXPORT_SYMBOL_GPL(svc_rqst_alloc);
6601b6dc1dfSJeff Layton 
6616b044fbaSNeilBrown static struct svc_rqst *
6621b6dc1dfSJeff Layton svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
6631b6dc1dfSJeff Layton {
6641b6dc1dfSJeff Layton 	struct svc_rqst	*rqstp;
6651b6dc1dfSJeff Layton 
6661b6dc1dfSJeff Layton 	rqstp = svc_rqst_alloc(serv, pool, node);
6671b6dc1dfSJeff Layton 	if (!rqstp)
6681b6dc1dfSJeff Layton 		return ERR_PTR(-ENOMEM);
6691b6dc1dfSJeff Layton 
670ec52361dSNeilBrown 	svc_get(serv);
6712a36395fSNeilBrown 	spin_lock_bh(&serv->sv_lock);
6722a36395fSNeilBrown 	serv->sv_nrthreads += 1;
6732a36395fSNeilBrown 	spin_unlock_bh(&serv->sv_lock);
6742a36395fSNeilBrown 
6750113ab34SJeff Layton 	spin_lock_bh(&pool->sp_lock);
6760113ab34SJeff Layton 	pool->sp_nrthreads++;
67781244386SJeff Layton 	list_add_rcu(&rqstp->rq_all, &pool->sp_all_threads);
6780113ab34SJeff Layton 	spin_unlock_bh(&pool->sp_lock);
6790113ab34SJeff Layton 	return rqstp;
6800113ab34SJeff Layton }
6810113ab34SJeff Layton 
6821da177e4SLinus Torvalds /*
683a7455442SGreg Banks  * Choose a pool in which to create a new thread, for svc_set_num_threads
684a7455442SGreg Banks  */
685a7455442SGreg Banks static inline struct svc_pool *
686a7455442SGreg Banks choose_pool(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state)
687a7455442SGreg Banks {
688a7455442SGreg Banks 	if (pool != NULL)
689a7455442SGreg Banks 		return pool;
690a7455442SGreg Banks 
691a7455442SGreg Banks 	return &serv->sv_pools[(*state)++ % serv->sv_nrpools];
692a7455442SGreg Banks }
693a7455442SGreg Banks 
694a7455442SGreg Banks /*
695a7455442SGreg Banks  * Choose a thread to kill, for svc_set_num_threads
696a7455442SGreg Banks  */
697a7455442SGreg Banks static inline struct task_struct *
698a7455442SGreg Banks choose_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state)
699a7455442SGreg Banks {
700a7455442SGreg Banks 	unsigned int i;
701a7455442SGreg Banks 	struct task_struct *task = NULL;
702a7455442SGreg Banks 
703a7455442SGreg Banks 	if (pool != NULL) {
704a7455442SGreg Banks 		spin_lock_bh(&pool->sp_lock);
705a7455442SGreg Banks 	} else {
706a7455442SGreg Banks 		/* choose a pool in round-robin fashion */
707a7455442SGreg Banks 		for (i = 0; i < serv->sv_nrpools; i++) {
708a7455442SGreg Banks 			pool = &serv->sv_pools[--(*state) % serv->sv_nrpools];
709a7455442SGreg Banks 			spin_lock_bh(&pool->sp_lock);
710a7455442SGreg Banks 			if (!list_empty(&pool->sp_all_threads))
711a7455442SGreg Banks 				goto found_pool;
712a7455442SGreg Banks 			spin_unlock_bh(&pool->sp_lock);
713a7455442SGreg Banks 		}
714a7455442SGreg Banks 		return NULL;
715a7455442SGreg Banks 	}
716a7455442SGreg Banks 
717a7455442SGreg Banks found_pool:
718a7455442SGreg Banks 	if (!list_empty(&pool->sp_all_threads)) {
719a7455442SGreg Banks 		struct svc_rqst *rqstp;
720a7455442SGreg Banks 
721a7455442SGreg Banks 		/*
722a7455442SGreg Banks 		 * Remove from the pool->sp_all_threads list
723a7455442SGreg Banks 		 * so we don't try to kill it again.
724a7455442SGreg Banks 		 */
725a7455442SGreg Banks 		rqstp = list_entry(pool->sp_all_threads.next, struct svc_rqst, rq_all);
72681244386SJeff Layton 		set_bit(RQ_VICTIM, &rqstp->rq_flags);
72781244386SJeff Layton 		list_del_rcu(&rqstp->rq_all);
728a7455442SGreg Banks 		task = rqstp->rq_task;
729a7455442SGreg Banks 	}
730a7455442SGreg Banks 	spin_unlock_bh(&pool->sp_lock);
731a7455442SGreg Banks 
732a7455442SGreg Banks 	return task;
733a7455442SGreg Banks }
734a7455442SGreg Banks 
7359e0d8768STrond Myklebust /* create new threads */
7369e0d8768STrond Myklebust static int
7379e0d8768STrond Myklebust svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
7389e0d8768STrond Myklebust {
7399e0d8768STrond Myklebust 	struct svc_rqst	*rqstp;
7409e0d8768STrond Myklebust 	struct task_struct *task;
7419e0d8768STrond Myklebust 	struct svc_pool *chosen_pool;
7429e0d8768STrond Myklebust 	unsigned int state = serv->sv_nrthreads-1;
7439e0d8768STrond Myklebust 	int node;
7449e0d8768STrond Myklebust 
7459e0d8768STrond Myklebust 	do {
7469e0d8768STrond Myklebust 		nrservs--;
7479e0d8768STrond Myklebust 		chosen_pool = choose_pool(serv, pool, &state);
7489e0d8768STrond Myklebust 
7499e0d8768STrond Myklebust 		node = svc_pool_map_get_node(chosen_pool->sp_id);
7509e0d8768STrond Myklebust 		rqstp = svc_prepare_thread(serv, chosen_pool, node);
7519e0d8768STrond Myklebust 		if (IS_ERR(rqstp))
7529e0d8768STrond Myklebust 			return PTR_ERR(rqstp);
7539e0d8768STrond Myklebust 
754*37902c63SChuck Lever 		task = kthread_create_on_node(serv->sv_threadfn, rqstp,
7559e0d8768STrond Myklebust 					      node, "%s", serv->sv_name);
7569e0d8768STrond Myklebust 		if (IS_ERR(task)) {
7579e0d8768STrond Myklebust 			svc_exit_thread(rqstp);
7589e0d8768STrond Myklebust 			return PTR_ERR(task);
7599e0d8768STrond Myklebust 		}
7609e0d8768STrond Myklebust 
7619e0d8768STrond Myklebust 		rqstp->rq_task = task;
7629e0d8768STrond Myklebust 		if (serv->sv_nrpools > 1)
7639e0d8768STrond Myklebust 			svc_pool_map_set_cpumask(task, chosen_pool->sp_id);
7649e0d8768STrond Myklebust 
7659e0d8768STrond Myklebust 		svc_sock_update_bufs(serv);
7669e0d8768STrond Myklebust 		wake_up_process(task);
7679e0d8768STrond Myklebust 	} while (nrservs > 0);
7689e0d8768STrond Myklebust 
7699e0d8768STrond Myklebust 	return 0;
7709e0d8768STrond Myklebust }
7719e0d8768STrond Myklebust 
772a7455442SGreg Banks /*
773a7455442SGreg Banks  * Create or destroy enough new threads to make the number
774a7455442SGreg Banks  * of threads the given number.  If `pool' is non-NULL, applies
775a7455442SGreg Banks  * only to threads in that pool, otherwise round-robins between
77694cf3179SJ. Bruce Fields  * all pools.  Caller must ensure that mutual exclusion between this and
77794cf3179SJ. Bruce Fields  * server startup or shutdown.
778a7455442SGreg Banks  */
779a7455442SGreg Banks 
780ed6473ddSTrond Myklebust /* destroy old threads */
781ed6473ddSTrond Myklebust static int
782ed6473ddSTrond Myklebust svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
783ed6473ddSTrond Myklebust {
784ed6473ddSTrond Myklebust 	struct task_struct *task;
785ed6473ddSTrond Myklebust 	unsigned int state = serv->sv_nrthreads-1;
786ed6473ddSTrond Myklebust 
787ed6473ddSTrond Myklebust 	/* destroy old threads */
788ed6473ddSTrond Myklebust 	do {
789ed6473ddSTrond Myklebust 		task = choose_victim(serv, pool, &state);
790ed6473ddSTrond Myklebust 		if (task == NULL)
791ed6473ddSTrond Myklebust 			break;
792ed6473ddSTrond Myklebust 		kthread_stop(task);
793ed6473ddSTrond Myklebust 		nrservs++;
794ed6473ddSTrond Myklebust 	} while (nrservs < 0);
795ed6473ddSTrond Myklebust 	return 0;
796ed6473ddSTrond Myklebust }
797ed6473ddSTrond Myklebust 
798ed6473ddSTrond Myklebust int
7993ebdbe52SNeilBrown svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
800ed6473ddSTrond Myklebust {
801ed6473ddSTrond Myklebust 	if (pool == NULL) {
802ec52361dSNeilBrown 		nrservs -= serv->sv_nrthreads;
803ed6473ddSTrond Myklebust 	} else {
804ed6473ddSTrond Myklebust 		spin_lock_bh(&pool->sp_lock);
805ed6473ddSTrond Myklebust 		nrservs -= pool->sp_nrthreads;
806ed6473ddSTrond Myklebust 		spin_unlock_bh(&pool->sp_lock);
807ed6473ddSTrond Myklebust 	}
808ed6473ddSTrond Myklebust 
809ed6473ddSTrond Myklebust 	if (nrservs > 0)
810ed6473ddSTrond Myklebust 		return svc_start_kthreads(serv, pool, nrservs);
811ed6473ddSTrond Myklebust 	if (nrservs < 0)
812ed6473ddSTrond Myklebust 		return svc_stop_kthreads(serv, pool, nrservs);
813ed6473ddSTrond Myklebust 	return 0;
814ed6473ddSTrond Myklebust }
8153ebdbe52SNeilBrown EXPORT_SYMBOL_GPL(svc_set_num_threads);
816ed6473ddSTrond Myklebust 
8172f0f88f4SChuck Lever /**
8182f0f88f4SChuck Lever  * svc_rqst_replace_page - Replace one page in rq_pages[]
8192f0f88f4SChuck Lever  * @rqstp: svc_rqst with pages to replace
8202f0f88f4SChuck Lever  * @page: replacement page
8212f0f88f4SChuck Lever  *
8222f0f88f4SChuck Lever  * When replacing a page in rq_pages, batch the release of the
8232f0f88f4SChuck Lever  * replaced pages to avoid hammering the page allocator.
8242f0f88f4SChuck Lever  */
8252f0f88f4SChuck Lever void svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page)
8262f0f88f4SChuck Lever {
8272f0f88f4SChuck Lever 	if (*rqstp->rq_next_page) {
8282f0f88f4SChuck Lever 		if (!pagevec_space(&rqstp->rq_pvec))
8292f0f88f4SChuck Lever 			__pagevec_release(&rqstp->rq_pvec);
8302f0f88f4SChuck Lever 		pagevec_add(&rqstp->rq_pvec, *rqstp->rq_next_page);
8312f0f88f4SChuck Lever 	}
8322f0f88f4SChuck Lever 
8332f0f88f4SChuck Lever 	get_page(page);
8342f0f88f4SChuck Lever 	*(rqstp->rq_next_page++) = page;
8352f0f88f4SChuck Lever }
8362f0f88f4SChuck Lever EXPORT_SYMBOL_GPL(svc_rqst_replace_page);
8372f0f88f4SChuck Lever 
838a7455442SGreg Banks /*
8393c519914SJeff Layton  * Called from a server thread as it's exiting. Caller must hold the "service
8403c519914SJeff Layton  * mutex" for the service.
8411da177e4SLinus Torvalds  */
8421da177e4SLinus Torvalds void
8431b6dc1dfSJeff Layton svc_rqst_free(struct svc_rqst *rqstp)
8441da177e4SLinus Torvalds {
8451da177e4SLinus Torvalds 	svc_release_buffer(rqstp);
846b9f83ffaSYunjian Wang 	if (rqstp->rq_scratch_page)
8475191955dSChuck Lever 		put_page(rqstp->rq_scratch_page);
8481da177e4SLinus Torvalds 	kfree(rqstp->rq_resp);
8491da177e4SLinus Torvalds 	kfree(rqstp->rq_argp);
8501da177e4SLinus Torvalds 	kfree(rqstp->rq_auth_data);
8511b6dc1dfSJeff Layton 	kfree_rcu(rqstp, rq_rcu_head);
8521b6dc1dfSJeff Layton }
8531b6dc1dfSJeff Layton EXPORT_SYMBOL_GPL(svc_rqst_free);
8541b6dc1dfSJeff Layton 
8551b6dc1dfSJeff Layton void
8561b6dc1dfSJeff Layton svc_exit_thread(struct svc_rqst *rqstp)
8571b6dc1dfSJeff Layton {
8581b6dc1dfSJeff Layton 	struct svc_serv	*serv = rqstp->rq_server;
8591b6dc1dfSJeff Layton 	struct svc_pool	*pool = rqstp->rq_pool;
8603262c816SGreg Banks 
8613262c816SGreg Banks 	spin_lock_bh(&pool->sp_lock);
8623262c816SGreg Banks 	pool->sp_nrthreads--;
86381244386SJeff Layton 	if (!test_and_set_bit(RQ_VICTIM, &rqstp->rq_flags))
86481244386SJeff Layton 		list_del_rcu(&rqstp->rq_all);
8653262c816SGreg Banks 	spin_unlock_bh(&pool->sp_lock);
8663262c816SGreg Banks 
8672a36395fSNeilBrown 	spin_lock_bh(&serv->sv_lock);
868ec52361dSNeilBrown 	serv->sv_nrthreads -= 1;
8692a36395fSNeilBrown 	spin_unlock_bh(&serv->sv_lock);
870ec52361dSNeilBrown 	svc_sock_update_bufs(serv);
871ec52361dSNeilBrown 
8721b6dc1dfSJeff Layton 	svc_rqst_free(rqstp);
8731da177e4SLinus Torvalds 
874ec52361dSNeilBrown 	svc_put(serv);
8751da177e4SLinus Torvalds }
87624c3767eSTrond Myklebust EXPORT_SYMBOL_GPL(svc_exit_thread);
8771da177e4SLinus Torvalds 
8781da177e4SLinus Torvalds /*
8792c7eb0b2SChuck Lever  * Register an "inet" protocol family netid with the local
8802c7eb0b2SChuck Lever  * rpcbind daemon via an rpcbind v4 SET request.
881a26cfad6SChuck Lever  *
8822c7eb0b2SChuck Lever  * No netconfig infrastructure is available in the kernel, so
8832c7eb0b2SChuck Lever  * we map IP_ protocol numbers to netids by hand.
884a26cfad6SChuck Lever  *
8852c7eb0b2SChuck Lever  * Returns zero on success; a negative errno value is returned
8862c7eb0b2SChuck Lever  * if any error occurs.
8871da177e4SLinus Torvalds  */
8885247fab5SStanislav Kinsbursky static int __svc_rpcb_register4(struct net *net, const u32 program,
8895247fab5SStanislav Kinsbursky 				const u32 version,
890a26cfad6SChuck Lever 				const unsigned short protocol,
891a26cfad6SChuck Lever 				const unsigned short port)
892a26cfad6SChuck Lever {
893cadc0fa5SChuck Lever 	const struct sockaddr_in sin = {
894a26cfad6SChuck Lever 		.sin_family		= AF_INET,
895a26cfad6SChuck Lever 		.sin_addr.s_addr	= htonl(INADDR_ANY),
896a26cfad6SChuck Lever 		.sin_port		= htons(port),
897a26cfad6SChuck Lever 	};
898cadc0fa5SChuck Lever 	const char *netid;
899cadc0fa5SChuck Lever 	int error;
9002c7eb0b2SChuck Lever 
9012c7eb0b2SChuck Lever 	switch (protocol) {
9022c7eb0b2SChuck Lever 	case IPPROTO_UDP:
9032c7eb0b2SChuck Lever 		netid = RPCBIND_NETID_UDP;
9042c7eb0b2SChuck Lever 		break;
9052c7eb0b2SChuck Lever 	case IPPROTO_TCP:
9062c7eb0b2SChuck Lever 		netid = RPCBIND_NETID_TCP;
9072c7eb0b2SChuck Lever 		break;
9082c7eb0b2SChuck Lever 	default:
909ba5c35e0SChuck Lever 		return -ENOPROTOOPT;
9102c7eb0b2SChuck Lever 	}
9112c7eb0b2SChuck Lever 
9125247fab5SStanislav Kinsbursky 	error = rpcb_v4_register(net, program, version,
913cadc0fa5SChuck Lever 					(const struct sockaddr *)&sin, netid);
914cadc0fa5SChuck Lever 
915cadc0fa5SChuck Lever 	/*
916cadc0fa5SChuck Lever 	 * User space didn't support rpcbind v4, so retry this
917cadc0fa5SChuck Lever 	 * registration request with the legacy rpcbind v2 protocol.
918cadc0fa5SChuck Lever 	 */
919cadc0fa5SChuck Lever 	if (error == -EPROTONOSUPPORT)
9205247fab5SStanislav Kinsbursky 		error = rpcb_register(net, program, version, protocol, port);
921cadc0fa5SChuck Lever 
922cadc0fa5SChuck Lever 	return error;
9232c7eb0b2SChuck Lever }
9242c7eb0b2SChuck Lever 
925dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
9262c7eb0b2SChuck Lever /*
9272c7eb0b2SChuck Lever  * Register an "inet6" protocol family netid with the local
9282c7eb0b2SChuck Lever  * rpcbind daemon via an rpcbind v4 SET request.
9292c7eb0b2SChuck Lever  *
9302c7eb0b2SChuck Lever  * No netconfig infrastructure is available in the kernel, so
9312c7eb0b2SChuck Lever  * we map IP_ protocol numbers to netids by hand.
9322c7eb0b2SChuck Lever  *
9332c7eb0b2SChuck Lever  * Returns zero on success; a negative errno value is returned
9342c7eb0b2SChuck Lever  * if any error occurs.
9352c7eb0b2SChuck Lever  */
9365247fab5SStanislav Kinsbursky static int __svc_rpcb_register6(struct net *net, const u32 program,
9375247fab5SStanislav Kinsbursky 				const u32 version,
9382c7eb0b2SChuck Lever 				const unsigned short protocol,
9392c7eb0b2SChuck Lever 				const unsigned short port)
9402c7eb0b2SChuck Lever {
941cadc0fa5SChuck Lever 	const struct sockaddr_in6 sin6 = {
942a26cfad6SChuck Lever 		.sin6_family		= AF_INET6,
943a26cfad6SChuck Lever 		.sin6_addr		= IN6ADDR_ANY_INIT,
944a26cfad6SChuck Lever 		.sin6_port		= htons(port),
945a26cfad6SChuck Lever 	};
946cadc0fa5SChuck Lever 	const char *netid;
947cadc0fa5SChuck Lever 	int error;
948a26cfad6SChuck Lever 
9492c7eb0b2SChuck Lever 	switch (protocol) {
9502c7eb0b2SChuck Lever 	case IPPROTO_UDP:
9512c7eb0b2SChuck Lever 		netid = RPCBIND_NETID_UDP6;
9522c7eb0b2SChuck Lever 		break;
9532c7eb0b2SChuck Lever 	case IPPROTO_TCP:
9542c7eb0b2SChuck Lever 		netid = RPCBIND_NETID_TCP6;
9552c7eb0b2SChuck Lever 		break;
9562c7eb0b2SChuck Lever 	default:
957ba5c35e0SChuck Lever 		return -ENOPROTOOPT;
9582c7eb0b2SChuck Lever 	}
9592c7eb0b2SChuck Lever 
9605247fab5SStanislav Kinsbursky 	error = rpcb_v4_register(net, program, version,
961cadc0fa5SChuck Lever 					(const struct sockaddr *)&sin6, netid);
962cadc0fa5SChuck Lever 
963cadc0fa5SChuck Lever 	/*
964cadc0fa5SChuck Lever 	 * User space didn't support rpcbind version 4, so we won't
965cadc0fa5SChuck Lever 	 * use a PF_INET6 listener.
966cadc0fa5SChuck Lever 	 */
967cadc0fa5SChuck Lever 	if (error == -EPROTONOSUPPORT)
968cadc0fa5SChuck Lever 		error = -EAFNOSUPPORT;
969cadc0fa5SChuck Lever 
970cadc0fa5SChuck Lever 	return error;
9712c7eb0b2SChuck Lever }
972dfd56b8bSEric Dumazet #endif	/* IS_ENABLED(CONFIG_IPV6) */
9732c7eb0b2SChuck Lever 
9742c7eb0b2SChuck Lever /*
9752c7eb0b2SChuck Lever  * Register a kernel RPC service via rpcbind version 4.
9762c7eb0b2SChuck Lever  *
9772c7eb0b2SChuck Lever  * Returns zero on success; a negative errno value is returned
9782c7eb0b2SChuck Lever  * if any error occurs.
9792c7eb0b2SChuck Lever  */
9805247fab5SStanislav Kinsbursky static int __svc_register(struct net *net, const char *progname,
981363f724cSChuck Lever 			  const u32 program, const u32 version,
9824b62e58cSChuck Lever 			  const int family,
9832c7eb0b2SChuck Lever 			  const unsigned short protocol,
9842c7eb0b2SChuck Lever 			  const unsigned short port)
9852c7eb0b2SChuck Lever {
986363f724cSChuck Lever 	int error = -EAFNOSUPPORT;
9872c7eb0b2SChuck Lever 
988a26cfad6SChuck Lever 	switch (family) {
9894b62e58cSChuck Lever 	case PF_INET:
9905247fab5SStanislav Kinsbursky 		error = __svc_rpcb_register4(net, program, version,
9912c7eb0b2SChuck Lever 						protocol, port);
992cadc0fa5SChuck Lever 		break;
993dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
9944b62e58cSChuck Lever 	case PF_INET6:
9955247fab5SStanislav Kinsbursky 		error = __svc_rpcb_register6(net, program, version,
9962c7eb0b2SChuck Lever 						protocol, port);
997dfd56b8bSEric Dumazet #endif
9982c7eb0b2SChuck Lever 	}
9992c7eb0b2SChuck Lever 
1000b4af5932SChuck Lever 	trace_svc_register(progname, version, protocol, port, family, error);
1001a26cfad6SChuck Lever 	return error;
1002a26cfad6SChuck Lever }
1003a26cfad6SChuck Lever 
1004642ee6b2STrond Myklebust int svc_rpcbind_set_version(struct net *net,
1005642ee6b2STrond Myklebust 			    const struct svc_program *progp,
1006642ee6b2STrond Myklebust 			    u32 version, int family,
1007642ee6b2STrond Myklebust 			    unsigned short proto,
1008642ee6b2STrond Myklebust 			    unsigned short port)
1009642ee6b2STrond Myklebust {
1010642ee6b2STrond Myklebust 	return __svc_register(net, progp->pg_name, progp->pg_prog,
1011642ee6b2STrond Myklebust 				version, family, proto, port);
1012642ee6b2STrond Myklebust 
1013642ee6b2STrond Myklebust }
1014642ee6b2STrond Myklebust EXPORT_SYMBOL_GPL(svc_rpcbind_set_version);
1015642ee6b2STrond Myklebust 
1016642ee6b2STrond Myklebust int svc_generic_rpcbind_set(struct net *net,
1017642ee6b2STrond Myklebust 			    const struct svc_program *progp,
1018642ee6b2STrond Myklebust 			    u32 version, int family,
1019642ee6b2STrond Myklebust 			    unsigned short proto,
1020642ee6b2STrond Myklebust 			    unsigned short port)
1021642ee6b2STrond Myklebust {
1022642ee6b2STrond Myklebust 	const struct svc_version *vers = progp->pg_vers[version];
1023642ee6b2STrond Myklebust 	int error;
1024642ee6b2STrond Myklebust 
1025642ee6b2STrond Myklebust 	if (vers == NULL)
1026642ee6b2STrond Myklebust 		return 0;
1027642ee6b2STrond Myklebust 
1028642ee6b2STrond Myklebust 	if (vers->vs_hidden) {
1029b4af5932SChuck Lever 		trace_svc_noregister(progp->pg_name, version, proto,
1030b4af5932SChuck Lever 				     port, family, 0);
1031642ee6b2STrond Myklebust 		return 0;
1032642ee6b2STrond Myklebust 	}
1033642ee6b2STrond Myklebust 
1034642ee6b2STrond Myklebust 	/*
1035642ee6b2STrond Myklebust 	 * Don't register a UDP port if we need congestion
1036642ee6b2STrond Myklebust 	 * control.
1037642ee6b2STrond Myklebust 	 */
1038642ee6b2STrond Myklebust 	if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP)
1039642ee6b2STrond Myklebust 		return 0;
1040642ee6b2STrond Myklebust 
1041642ee6b2STrond Myklebust 	error = svc_rpcbind_set_version(net, progp, version,
1042642ee6b2STrond Myklebust 					family, proto, port);
1043642ee6b2STrond Myklebust 
1044642ee6b2STrond Myklebust 	return (vers->vs_rpcb_optnl) ? 0 : error;
1045642ee6b2STrond Myklebust }
1046642ee6b2STrond Myklebust EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set);
1047642ee6b2STrond Myklebust 
1048a26cfad6SChuck Lever /**
1049a26cfad6SChuck Lever  * svc_register - register an RPC service with the local portmapper
1050a26cfad6SChuck Lever  * @serv: svc_serv struct for the service to register
10515247fab5SStanislav Kinsbursky  * @net: net namespace for the service to register
10524b62e58cSChuck Lever  * @family: protocol family of service's listener socket
1053a26cfad6SChuck Lever  * @proto: transport protocol number to advertise
1054a26cfad6SChuck Lever  * @port: port to advertise
1055a26cfad6SChuck Lever  *
10564b62e58cSChuck Lever  * Service is registered for any address in the passed-in protocol family
1057a26cfad6SChuck Lever  */
10585247fab5SStanislav Kinsbursky int svc_register(const struct svc_serv *serv, struct net *net,
10595247fab5SStanislav Kinsbursky 		 const int family, const unsigned short proto,
10605247fab5SStanislav Kinsbursky 		 const unsigned short port)
10611da177e4SLinus Torvalds {
10621da177e4SLinus Torvalds 	struct svc_program	*progp;
1063ea339d46SChuck Lever 	unsigned int		i;
106414aeb211SChuck Lever 	int			error = 0;
10651da177e4SLinus Torvalds 
10660af39507SWeston Andros Adamson 	WARN_ON_ONCE(proto == 0 && port == 0);
10670af39507SWeston Andros Adamson 	if (proto == 0 && port == 0)
10680af39507SWeston Andros Adamson 		return -EINVAL;
10691da177e4SLinus Torvalds 
1070bc5fea42SOlaf Kirch 	for (progp = serv->sv_program; progp; progp = progp->pg_next) {
10711da177e4SLinus Torvalds 		for (i = 0; i < progp->pg_nvers; i++) {
1072bc5fea42SOlaf Kirch 
1073642ee6b2STrond Myklebust 			error = progp->pg_rpcbind_set(net, progp, i,
1074642ee6b2STrond Myklebust 					family, proto, port);
10757e55b59bSKinglong Mee 			if (error < 0) {
10767e55b59bSKinglong Mee 				printk(KERN_WARNING "svc: failed to register "
10777e55b59bSKinglong Mee 					"%sv%u RPC service (errno %d).\n",
10787e55b59bSKinglong Mee 					progp->pg_name, i, -error);
10791da177e4SLinus Torvalds 				break;
10801da177e4SLinus Torvalds 			}
1081bc5fea42SOlaf Kirch 		}
10827e55b59bSKinglong Mee 	}
10831da177e4SLinus Torvalds 
10847252d575SChuck Lever 	return error;
10857252d575SChuck Lever }
10867252d575SChuck Lever 
1087d5a8620fSChuck Lever /*
1088d5a8620fSChuck Lever  * If user space is running rpcbind, it should take the v4 UNSET
1089d5a8620fSChuck Lever  * and clear everything for this [program, version].  If user space
1090d5a8620fSChuck Lever  * is running portmap, it will reject the v4 UNSET, but won't have
1091d5a8620fSChuck Lever  * any "inet6" entries anyway.  So a PMAP_UNSET should be sufficient
1092d5a8620fSChuck Lever  * in this case to clear all existing entries for [program, version].
1093d5a8620fSChuck Lever  */
10945247fab5SStanislav Kinsbursky static void __svc_unregister(struct net *net, const u32 program, const u32 version,
1095f6fb3f6fSChuck Lever 			     const char *progname)
1096f6fb3f6fSChuck Lever {
1097f6fb3f6fSChuck Lever 	int error;
1098f6fb3f6fSChuck Lever 
10995247fab5SStanislav Kinsbursky 	error = rpcb_v4_register(net, program, version, NULL, "");
1100d5a8620fSChuck Lever 
1101d5a8620fSChuck Lever 	/*
1102d5a8620fSChuck Lever 	 * User space didn't support rpcbind v4, so retry this
1103d5a8620fSChuck Lever 	 * request with the legacy rpcbind v2 protocol.
1104d5a8620fSChuck Lever 	 */
1105d5a8620fSChuck Lever 	if (error == -EPROTONOSUPPORT)
11065247fab5SStanislav Kinsbursky 		error = rpcb_register(net, program, version, 0, 0);
1107d5a8620fSChuck Lever 
1108b4af5932SChuck Lever 	trace_svc_unregister(progname, version, error);
1109f6fb3f6fSChuck Lever }
1110f6fb3f6fSChuck Lever 
11117252d575SChuck Lever /*
1112f6fb3f6fSChuck Lever  * All netids, bind addresses and ports registered for [program, version]
1113f6fb3f6fSChuck Lever  * are removed from the local rpcbind database (if the service is not
1114f6fb3f6fSChuck Lever  * hidden) to make way for a new instance of the service.
11157252d575SChuck Lever  *
1116f6fb3f6fSChuck Lever  * The result of unregistration is reported via dprintk for those who want
1117f6fb3f6fSChuck Lever  * verification of the result, but is otherwise not important.
11187252d575SChuck Lever  */
11195247fab5SStanislav Kinsbursky static void svc_unregister(const struct svc_serv *serv, struct net *net)
11207252d575SChuck Lever {
11217252d575SChuck Lever 	struct svc_program *progp;
11227252d575SChuck Lever 	unsigned long flags;
11237252d575SChuck Lever 	unsigned int i;
11247252d575SChuck Lever 
11257252d575SChuck Lever 	clear_thread_flag(TIF_SIGPENDING);
11267252d575SChuck Lever 
11277252d575SChuck Lever 	for (progp = serv->sv_program; progp; progp = progp->pg_next) {
11287252d575SChuck Lever 		for (i = 0; i < progp->pg_nvers; i++) {
11297252d575SChuck Lever 			if (progp->pg_vers[i] == NULL)
11307252d575SChuck Lever 				continue;
11317252d575SChuck Lever 			if (progp->pg_vers[i]->vs_hidden)
11327252d575SChuck Lever 				continue;
11335247fab5SStanislav Kinsbursky 			__svc_unregister(net, progp->pg_prog, i, progp->pg_name);
11347252d575SChuck Lever 		}
11357252d575SChuck Lever 	}
11367252d575SChuck Lever 
11371da177e4SLinus Torvalds 	spin_lock_irqsave(&current->sighand->siglock, flags);
11381da177e4SLinus Torvalds 	recalc_sigpending();
11391da177e4SLinus Torvalds 	spin_unlock_irqrestore(&current->sighand->siglock, flags);
11401da177e4SLinus Torvalds }
11411da177e4SLinus Torvalds 
11421da177e4SLinus Torvalds /*
11437032a3ddSJ. Bruce Fields  * dprintk the given error with the address of the client that caused it.
1144354ecbb9SDr. David Alan Gilbert  */
1145f895b252SJeff Layton #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
1146b9075fa9SJoe Perches static __printf(2, 3)
1147e87cc472SJoe Perches void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
1148354ecbb9SDr. David Alan Gilbert {
1149e87cc472SJoe Perches 	struct va_format vaf;
1150354ecbb9SDr. David Alan Gilbert 	va_list args;
1151354ecbb9SDr. David Alan Gilbert 	char 	buf[RPC_MAX_ADDRBUFLEN];
1152354ecbb9SDr. David Alan Gilbert 
1153354ecbb9SDr. David Alan Gilbert 	va_start(args, fmt);
1154354ecbb9SDr. David Alan Gilbert 
1155e87cc472SJoe Perches 	vaf.fmt = fmt;
1156e87cc472SJoe Perches 	vaf.va = &args;
1157e87cc472SJoe Perches 
11587032a3ddSJ. Bruce Fields 	dprintk("svc: %s: %pV", svc_print_addr(rqstp, buf, sizeof(buf)), &vaf);
1159e87cc472SJoe Perches 
1160e87cc472SJoe Perches 	va_end(args);
1161354ecbb9SDr. David Alan Gilbert }
1162624ab464SJ. Bruce Fields #else
1163624ab464SJ. Bruce Fields static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
1164624ab464SJ. Bruce Fields #endif
1165354ecbb9SDr. David Alan Gilbert 
11668e5b6773STrond Myklebust __be32
11678e5b6773STrond Myklebust svc_generic_init_request(struct svc_rqst *rqstp,
11688e5b6773STrond Myklebust 		const struct svc_program *progp,
11698e5b6773STrond Myklebust 		struct svc_process_info *ret)
11708e5b6773STrond Myklebust {
11718e5b6773STrond Myklebust 	const struct svc_version *versp = NULL;	/* compiler food */
11728e5b6773STrond Myklebust 	const struct svc_procedure *procp = NULL;
11738e5b6773STrond Myklebust 
11748e5b6773STrond Myklebust 	if (rqstp->rq_vers >= progp->pg_nvers )
11758e5b6773STrond Myklebust 		goto err_bad_vers;
11768e5b6773STrond Myklebust 	versp = progp->pg_vers[rqstp->rq_vers];
11778e5b6773STrond Myklebust 	if (!versp)
11788e5b6773STrond Myklebust 		goto err_bad_vers;
11798e5b6773STrond Myklebust 
11808e5b6773STrond Myklebust 	/*
11818e5b6773STrond Myklebust 	 * Some protocol versions (namely NFSv4) require some form of
11828e5b6773STrond Myklebust 	 * congestion control.  (See RFC 7530 section 3.1 paragraph 2)
11838e5b6773STrond Myklebust 	 * In other words, UDP is not allowed. We mark those when setting
11848e5b6773STrond Myklebust 	 * up the svc_xprt, and verify that here.
11858e5b6773STrond Myklebust 	 *
11868e5b6773STrond Myklebust 	 * The spec is not very clear about what error should be returned
11878e5b6773STrond Myklebust 	 * when someone tries to access a server that is listening on UDP
11888e5b6773STrond Myklebust 	 * for lower versions. RPC_PROG_MISMATCH seems to be the closest
11898e5b6773STrond Myklebust 	 * fit.
11908e5b6773STrond Myklebust 	 */
11918e5b6773STrond Myklebust 	if (versp->vs_need_cong_ctrl && rqstp->rq_xprt &&
11928e5b6773STrond Myklebust 	    !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
11938e5b6773STrond Myklebust 		goto err_bad_vers;
11948e5b6773STrond Myklebust 
11958e5b6773STrond Myklebust 	if (rqstp->rq_proc >= versp->vs_nproc)
11968e5b6773STrond Myklebust 		goto err_bad_proc;
11978e5b6773STrond Myklebust 	rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc];
11988e5b6773STrond Myklebust 	if (!procp)
11998e5b6773STrond Myklebust 		goto err_bad_proc;
12008e5b6773STrond Myklebust 
12018e5b6773STrond Myklebust 	/* Initialize storage for argp and resp */
12028e5b6773STrond Myklebust 	memset(rqstp->rq_argp, 0, procp->pc_argsize);
12038e5b6773STrond Myklebust 	memset(rqstp->rq_resp, 0, procp->pc_ressize);
12048e5b6773STrond Myklebust 
12058e5b6773STrond Myklebust 	/* Bump per-procedure stats counter */
12068e5b6773STrond Myklebust 	versp->vs_count[rqstp->rq_proc]++;
12078e5b6773STrond Myklebust 
12088e5b6773STrond Myklebust 	ret->dispatch = versp->vs_dispatch;
12098e5b6773STrond Myklebust 	return rpc_success;
12108e5b6773STrond Myklebust err_bad_vers:
12118e5b6773STrond Myklebust 	ret->mismatch.lovers = progp->pg_lovers;
12128e5b6773STrond Myklebust 	ret->mismatch.hivers = progp->pg_hivers;
12138e5b6773STrond Myklebust 	return rpc_prog_mismatch;
12148e5b6773STrond Myklebust err_bad_proc:
12158e5b6773STrond Myklebust 	return rpc_proc_unavail;
12168e5b6773STrond Myklebust }
12178e5b6773STrond Myklebust EXPORT_SYMBOL_GPL(svc_generic_init_request);
12188e5b6773STrond Myklebust 
1219354ecbb9SDr. David Alan Gilbert /*
12201cad7ea6SRicardo Labiaga  * Common routine for processing the RPC request.
12211da177e4SLinus Torvalds  */
12221cad7ea6SRicardo Labiaga static int
12231cad7ea6SRicardo Labiaga svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
12241da177e4SLinus Torvalds {
12251da177e4SLinus Torvalds 	struct svc_program	*progp;
1226860bda29SChristoph Hellwig 	const struct svc_procedure *procp = NULL;
12276fb2b47fSNeilBrown 	struct svc_serv		*serv = rqstp->rq_server;
12288e5b6773STrond Myklebust 	struct svc_process_info process;
1229d8ed029dSAlexey Dobriyan 	__be32			*statp;
12308e5b6773STrond Myklebust 	u32			prog, vers;
1231438623a0SChuck Lever 	__be32			rpc_stat;
12325b747a59SChuck Lever 	int			auth_res, rc;
12338f8e05c5SJ.Bruce Fields 	__be32			*reply_statp;
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds 	rpc_stat = rpc_success;
12361da177e4SLinus Torvalds 
12371da177e4SLinus Torvalds 	if (argv->iov_len < 6*4)
12381da177e4SLinus Torvalds 		goto err_short_len;
12391da177e4SLinus Torvalds 
124006eb8a56SChuck Lever 	/* Will be turned off by GSS integrity and privacy services */
1241779fb0f3SJeff Layton 	set_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
12422f425878SAndy Adamson 	/* Will be turned off only when NFSv4 Sessions are used */
124330660e04SJeff Layton 	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
124478b65eb3SJeff Layton 	clear_bit(RQ_DROPME, &rqstp->rq_flags);
1245e831fe65STom Tucker 
12461da177e4SLinus Torvalds 	svc_putu32(resv, rqstp->rq_xid);
12471da177e4SLinus Torvalds 
124876994313SAlexey Dobriyan 	vers = svc_getnl(argv);
12491da177e4SLinus Torvalds 
12501da177e4SLinus Torvalds 	/* First words of reply: */
125176994313SAlexey Dobriyan 	svc_putnl(resv, 1);		/* REPLY */
12521da177e4SLinus Torvalds 
12531da177e4SLinus Torvalds 	if (vers != 2)		/* RPC version number */
12541da177e4SLinus Torvalds 		goto err_bad_rpc;
12551da177e4SLinus Torvalds 
12561da177e4SLinus Torvalds 	/* Save position in case we later decide to reject: */
12578f8e05c5SJ.Bruce Fields 	reply_statp = resv->iov_base + resv->iov_len;
12581da177e4SLinus Torvalds 
125976994313SAlexey Dobriyan 	svc_putnl(resv, 0);		/* ACCEPT */
12601da177e4SLinus Torvalds 
126176994313SAlexey Dobriyan 	rqstp->rq_prog = prog = svc_getnl(argv);	/* program number */
12628e5b6773STrond Myklebust 	rqstp->rq_vers = svc_getnl(argv);	/* version number */
12638e5b6773STrond Myklebust 	rqstp->rq_proc = svc_getnl(argv);	/* procedure number */
12641da177e4SLinus Torvalds 
126580d188a6SNeilBrown 	for (progp = serv->sv_program; progp; progp = progp->pg_next)
126680d188a6SNeilBrown 		if (prog == progp->pg_prog)
126780d188a6SNeilBrown 			break;
126880d188a6SNeilBrown 
12691da177e4SLinus Torvalds 	/*
12701da177e4SLinus Torvalds 	 * Decode auth data, and add verifier to reply buffer.
12711da177e4SLinus Torvalds 	 * We do this before anything else in order to get a decent
12721da177e4SLinus Torvalds 	 * auth verifier.
12731da177e4SLinus Torvalds 	 */
1274438623a0SChuck Lever 	auth_res = svc_authenticate(rqstp);
12751da177e4SLinus Torvalds 	/* Also give the program a chance to reject this call: */
12765c2465dfSChuck Lever 	if (auth_res == SVC_OK && progp)
12771da177e4SLinus Torvalds 		auth_res = progp->pg_authenticate(rqstp);
1278ff27e9f7SChuck Lever 	if (auth_res != SVC_OK)
1279438623a0SChuck Lever 		trace_svc_authenticate(rqstp, auth_res);
12801da177e4SLinus Torvalds 	switch (auth_res) {
12811da177e4SLinus Torvalds 	case SVC_OK:
12821da177e4SLinus Torvalds 		break;
12831da177e4SLinus Torvalds 	case SVC_GARBAGE:
1284dd35210eSHarshula Jayasuriya 		goto err_garbage;
12851da177e4SLinus Torvalds 	case SVC_SYSERR:
12861da177e4SLinus Torvalds 		rpc_stat = rpc_system_err;
12871da177e4SLinus Torvalds 		goto err_bad;
12881da177e4SLinus Torvalds 	case SVC_DENIED:
12891da177e4SLinus Torvalds 		goto err_bad_auth;
12901ebede86SNeilBrown 	case SVC_CLOSE:
12914d712ef1SChuck Lever 		goto close;
12921da177e4SLinus Torvalds 	case SVC_DROP:
12931da177e4SLinus Torvalds 		goto dropit;
12941da177e4SLinus Torvalds 	case SVC_COMPLETE:
12951da177e4SLinus Torvalds 		goto sendit;
12961da177e4SLinus Torvalds 	}
12971da177e4SLinus Torvalds 
12989ba02638SAndreas Gruenbacher 	if (progp == NULL)
12991da177e4SLinus Torvalds 		goto err_bad_prog;
13001da177e4SLinus Torvalds 
13018e5b6773STrond Myklebust 	rpc_stat = progp->pg_init_request(rqstp, progp, &process);
13028e5b6773STrond Myklebust 	switch (rpc_stat) {
13038e5b6773STrond Myklebust 	case rpc_success:
13048e5b6773STrond Myklebust 		break;
13058e5b6773STrond Myklebust 	case rpc_prog_unavail:
13068e5b6773STrond Myklebust 		goto err_bad_prog;
13078e5b6773STrond Myklebust 	case rpc_prog_mismatch:
13081da177e4SLinus Torvalds 		goto err_bad_vers;
13098e5b6773STrond Myklebust 	case rpc_proc_unavail:
13101da177e4SLinus Torvalds 		goto err_bad_proc;
13118e5b6773STrond Myklebust 	}
13128e5b6773STrond Myklebust 
13138e5b6773STrond Myklebust 	procp = rqstp->rq_procinfo;
13148e5b6773STrond Myklebust 	/* Should this check go into the dispatcher? */
13158e5b6773STrond Myklebust 	if (!procp || !procp->pc_func)
13168e5b6773STrond Myklebust 		goto err_bad_proc;
13171da177e4SLinus Torvalds 
13181da177e4SLinus Torvalds 	/* Syntactic check complete */
13191da177e4SLinus Torvalds 	serv->sv_stats->rpccnt++;
13200b9547bfSChuck Lever 	trace_svc_process(rqstp, progp->pg_name);
13211da177e4SLinus Torvalds 
13221da177e4SLinus Torvalds 	/* Build the reply header. */
13231da177e4SLinus Torvalds 	statp = resv->iov_base +resv->iov_len;
132476994313SAlexey Dobriyan 	svc_putnl(resv, RPC_SUCCESS);
13251da177e4SLinus Torvalds 
13261da177e4SLinus Torvalds 	/* un-reserve some of the out-queue now that we have a
13271da177e4SLinus Torvalds 	 * better idea of reply size
13281da177e4SLinus Torvalds 	 */
13291da177e4SLinus Torvalds 	if (procp->pc_xdrressize)
1330cd123012SJeff Layton 		svc_reserve_auth(rqstp, procp->pc_xdrressize<<2);
13311da177e4SLinus Torvalds 
13321da177e4SLinus Torvalds 	/* Call the function that processes the request. */
13335b747a59SChuck Lever 	rc = process.dispatch(rqstp, statp);
13345b747a59SChuck Lever 	if (procp->pc_release)
13355b747a59SChuck Lever 		procp->pc_release(rqstp);
13365b747a59SChuck Lever 	if (!rc)
13375b747a59SChuck Lever 		goto dropit;
13389082e1d9SChuck Lever 	if (rqstp->rq_auth_stat != rpc_auth_ok)
13395b747a59SChuck Lever 		goto err_bad_auth;
13409082e1d9SChuck Lever 
13411da177e4SLinus Torvalds 	/* Check RPC status result */
13421da177e4SLinus Torvalds 	if (*statp != rpc_success)
13431da177e4SLinus Torvalds 		resv->iov_len = ((void*)statp)  - resv->iov_base + 4;
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds 	if (procp->pc_encode == NULL)
13461da177e4SLinus Torvalds 		goto dropit;
13471da177e4SLinus Torvalds 
13481da177e4SLinus Torvalds  sendit:
13491da177e4SLinus Torvalds 	if (svc_authorise(rqstp))
1350f1442d63SDaniel Kobras 		goto close_xprt;
13511cad7ea6SRicardo Labiaga 	return 1;		/* Caller can now send it */
13521da177e4SLinus Torvalds 
13531da177e4SLinus Torvalds  dropit:
13541da177e4SLinus Torvalds 	svc_authorise(rqstp);	/* doesn't hurt to call this twice */
13551da177e4SLinus Torvalds 	dprintk("svc: svc_process dropit\n");
13561da177e4SLinus Torvalds 	return 0;
13571da177e4SLinus Torvalds 
13584d712ef1SChuck Lever  close:
1359f1442d63SDaniel Kobras 	svc_authorise(rqstp);
1360f1442d63SDaniel Kobras close_xprt:
1361d4b09acfSVasily Averin 	if (rqstp->rq_xprt && test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
13624355d767SChuck Lever 		svc_xprt_close(rqstp->rq_xprt);
13634d712ef1SChuck Lever 	dprintk("svc: svc_process close\n");
13644d712ef1SChuck Lever 	return 0;
13654d712ef1SChuck Lever 
13661da177e4SLinus Torvalds err_short_len:
13675b5e0928SAlexey Dobriyan 	svc_printk(rqstp, "short len %zd, dropping request\n",
1368354ecbb9SDr. David Alan Gilbert 			argv->iov_len);
1369f1442d63SDaniel Kobras 	goto close_xprt;
13701da177e4SLinus Torvalds 
13711da177e4SLinus Torvalds err_bad_rpc:
13721da177e4SLinus Torvalds 	serv->sv_stats->rpcbadfmt++;
137376994313SAlexey Dobriyan 	svc_putnl(resv, 1);	/* REJECT */
137476994313SAlexey Dobriyan 	svc_putnl(resv, 0);	/* RPC_MISMATCH */
137576994313SAlexey Dobriyan 	svc_putnl(resv, 2);	/* Only RPCv2 supported */
137676994313SAlexey Dobriyan 	svc_putnl(resv, 2);
13771da177e4SLinus Torvalds 	goto sendit;
13781da177e4SLinus Torvalds 
13791da177e4SLinus Torvalds err_bad_auth:
1380438623a0SChuck Lever 	dprintk("svc: authentication failed (%d)\n",
1381438623a0SChuck Lever 		be32_to_cpu(rqstp->rq_auth_stat));
13821da177e4SLinus Torvalds 	serv->sv_stats->rpcbadauth++;
13831da177e4SLinus Torvalds 	/* Restore write pointer to location of accept status: */
13848f8e05c5SJ.Bruce Fields 	xdr_ressize_check(rqstp, reply_statp);
138576994313SAlexey Dobriyan 	svc_putnl(resv, 1);	/* REJECT */
138676994313SAlexey Dobriyan 	svc_putnl(resv, 1);	/* AUTH_ERROR */
1387438623a0SChuck Lever 	svc_putu32(resv, rqstp->rq_auth_stat);	/* status */
13881da177e4SLinus Torvalds 	goto sendit;
13891da177e4SLinus Torvalds 
13901da177e4SLinus Torvalds err_bad_prog:
13919ba02638SAndreas Gruenbacher 	dprintk("svc: unknown program %d\n", prog);
13921da177e4SLinus Torvalds 	serv->sv_stats->rpcbadfmt++;
139376994313SAlexey Dobriyan 	svc_putnl(resv, RPC_PROG_UNAVAIL);
13941da177e4SLinus Torvalds 	goto sendit;
13951da177e4SLinus Torvalds 
13961da177e4SLinus Torvalds err_bad_vers:
1397354ecbb9SDr. David Alan Gilbert 	svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n",
13988e5b6773STrond Myklebust 		       rqstp->rq_vers, rqstp->rq_prog, progp->pg_name);
139934e9a63bSNeilBrown 
14001da177e4SLinus Torvalds 	serv->sv_stats->rpcbadfmt++;
140176994313SAlexey Dobriyan 	svc_putnl(resv, RPC_PROG_MISMATCH);
14028e5b6773STrond Myklebust 	svc_putnl(resv, process.mismatch.lovers);
14038e5b6773STrond Myklebust 	svc_putnl(resv, process.mismatch.hivers);
14041da177e4SLinus Torvalds 	goto sendit;
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds err_bad_proc:
14078e5b6773STrond Myklebust 	svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc);
140834e9a63bSNeilBrown 
14091da177e4SLinus Torvalds 	serv->sv_stats->rpcbadfmt++;
141076994313SAlexey Dobriyan 	svc_putnl(resv, RPC_PROC_UNAVAIL);
14111da177e4SLinus Torvalds 	goto sendit;
14121da177e4SLinus Torvalds 
14131da177e4SLinus Torvalds err_garbage:
1414354ecbb9SDr. David Alan Gilbert 	svc_printk(rqstp, "failed to decode args\n");
141534e9a63bSNeilBrown 
14161da177e4SLinus Torvalds 	rpc_stat = rpc_garbage_args;
14171da177e4SLinus Torvalds err_bad:
14181da177e4SLinus Torvalds 	serv->sv_stats->rpcbadfmt++;
141976994313SAlexey Dobriyan 	svc_putnl(resv, ntohl(rpc_stat));
14201da177e4SLinus Torvalds 	goto sendit;
14211da177e4SLinus Torvalds }
14227adae489SGreg Banks 
14237adae489SGreg Banks /*
14241cad7ea6SRicardo Labiaga  * Process the RPC request.
14251cad7ea6SRicardo Labiaga  */
14261cad7ea6SRicardo Labiaga int
14271cad7ea6SRicardo Labiaga svc_process(struct svc_rqst *rqstp)
14281cad7ea6SRicardo Labiaga {
14291cad7ea6SRicardo Labiaga 	struct kvec		*argv = &rqstp->rq_arg.head[0];
14301cad7ea6SRicardo Labiaga 	struct kvec		*resv = &rqstp->rq_res.head[0];
14311cad7ea6SRicardo Labiaga 	struct svc_serv		*serv = rqstp->rq_server;
14321cad7ea6SRicardo Labiaga 	u32			dir;
14331cad7ea6SRicardo Labiaga 
14343a126180SChuck Lever #if IS_ENABLED(CONFIG_FAIL_SUNRPC)
14353a126180SChuck Lever 	if (!fail_sunrpc.ignore_server_disconnect &&
14363a126180SChuck Lever 	    should_fail(&fail_sunrpc.attr, 1))
14373a126180SChuck Lever 		svc_xprt_deferred_close(rqstp->rq_xprt);
14383a126180SChuck Lever #endif
14393a126180SChuck Lever 
14401cad7ea6SRicardo Labiaga 	/*
14411cad7ea6SRicardo Labiaga 	 * Setup response xdr_buf.
14421cad7ea6SRicardo Labiaga 	 * Initially it has just one page
14431cad7ea6SRicardo Labiaga 	 */
1444afc59400SJ. Bruce Fields 	rqstp->rq_next_page = &rqstp->rq_respages[1];
14451cad7ea6SRicardo Labiaga 	resv->iov_base = page_address(rqstp->rq_respages[0]);
14461cad7ea6SRicardo Labiaga 	resv->iov_len = 0;
14471cad7ea6SRicardo Labiaga 	rqstp->rq_res.pages = rqstp->rq_respages + 1;
14481cad7ea6SRicardo Labiaga 	rqstp->rq_res.len = 0;
14491cad7ea6SRicardo Labiaga 	rqstp->rq_res.page_base = 0;
14501cad7ea6SRicardo Labiaga 	rqstp->rq_res.page_len = 0;
14511cad7ea6SRicardo Labiaga 	rqstp->rq_res.buflen = PAGE_SIZE;
14521cad7ea6SRicardo Labiaga 	rqstp->rq_res.tail[0].iov_base = NULL;
14531cad7ea6SRicardo Labiaga 	rqstp->rq_res.tail[0].iov_len = 0;
14541cad7ea6SRicardo Labiaga 
14551cad7ea6SRicardo Labiaga 	dir  = svc_getnl(argv);
14561cad7ea6SRicardo Labiaga 	if (dir != 0) {
14571cad7ea6SRicardo Labiaga 		/* direction != CALL */
14581cad7ea6SRicardo Labiaga 		svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
14591cad7ea6SRicardo Labiaga 		serv->sv_stats->rpcbadfmt++;
1460860a0d9eSJeff Layton 		goto out_drop;
14611cad7ea6SRicardo Labiaga 	}
14621cad7ea6SRicardo Labiaga 
14634b5b3ba1SAndy Adamson 	/* Returns 1 for send, 0 for drop */
14640b9547bfSChuck Lever 	if (likely(svc_process_common(rqstp, argv, resv)))
14650b9547bfSChuck Lever 		return svc_send(rqstp);
1466860a0d9eSJeff Layton 
1467860a0d9eSJeff Layton out_drop:
14684b5b3ba1SAndy Adamson 	svc_drop(rqstp);
14694b5b3ba1SAndy Adamson 	return 0;
14704b5b3ba1SAndy Adamson }
14713f87d5d6SChuck Lever EXPORT_SYMBOL_GPL(svc_process);
14721cad7ea6SRicardo Labiaga 
14739e00abc3STrond Myklebust #if defined(CONFIG_SUNRPC_BACKCHANNEL)
14744d6bbb62SRicardo Labiaga /*
14754d6bbb62SRicardo Labiaga  * Process a backchannel RPC request that arrived over an existing
14764d6bbb62SRicardo Labiaga  * outbound connection
14774d6bbb62SRicardo Labiaga  */
14784d6bbb62SRicardo Labiaga int
14794d6bbb62SRicardo Labiaga bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
14804d6bbb62SRicardo Labiaga 	       struct svc_rqst *rqstp)
14814d6bbb62SRicardo Labiaga {
14824d6bbb62SRicardo Labiaga 	struct kvec	*argv = &rqstp->rq_arg.head[0];
14834d6bbb62SRicardo Labiaga 	struct kvec	*resv = &rqstp->rq_res.head[0];
1484632dda83SChuck Lever 	struct rpc_task *task;
14850d2a970dSTrond Myklebust 	int proc_error;
1486632dda83SChuck Lever 	int error;
1487632dda83SChuck Lever 
1488632dda83SChuck Lever 	dprintk("svc: %s(%p)\n", __func__, req);
14894d6bbb62SRicardo Labiaga 
14904d6bbb62SRicardo Labiaga 	/* Build the svc_rqst used by the common processing routine */
14914d6bbb62SRicardo Labiaga 	rqstp->rq_xid = req->rq_xid;
14924d6bbb62SRicardo Labiaga 	rqstp->rq_prot = req->rq_xprt->prot;
14934d6bbb62SRicardo Labiaga 	rqstp->rq_server = serv;
1494d4b09acfSVasily Averin 	rqstp->rq_bc_net = req->rq_xprt->xprt_net;
14954d6bbb62SRicardo Labiaga 
14964d6bbb62SRicardo Labiaga 	rqstp->rq_addrlen = sizeof(req->rq_xprt->addr);
14974d6bbb62SRicardo Labiaga 	memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
14984d6bbb62SRicardo Labiaga 	memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
14994d6bbb62SRicardo Labiaga 	memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
1500756b9b37STrond Myklebust 
1501756b9b37STrond Myklebust 	/* Adjust the argument buffer length */
150238b7631fSBenjamin Coddington 	rqstp->rq_arg.len = req->rq_private_buf.len;
1503756b9b37STrond Myklebust 	if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
1504756b9b37STrond Myklebust 		rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
1505756b9b37STrond Myklebust 		rqstp->rq_arg.page_len = 0;
1506756b9b37STrond Myklebust 	} else if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len +
1507756b9b37STrond Myklebust 			rqstp->rq_arg.page_len)
1508756b9b37STrond Myklebust 		rqstp->rq_arg.page_len = rqstp->rq_arg.len -
1509756b9b37STrond Myklebust 			rqstp->rq_arg.head[0].iov_len;
1510756b9b37STrond Myklebust 	else
1511756b9b37STrond Myklebust 		rqstp->rq_arg.len = rqstp->rq_arg.head[0].iov_len +
1512756b9b37STrond Myklebust 			rqstp->rq_arg.page_len;
15134d6bbb62SRicardo Labiaga 
15144d6bbb62SRicardo Labiaga 	/* reset result send buffer "put" position */
15154d6bbb62SRicardo Labiaga 	resv->iov_len = 0;
15164d6bbb62SRicardo Labiaga 
15174d6bbb62SRicardo Labiaga 	/*
15184d6bbb62SRicardo Labiaga 	 * Skip the next two words because they've already been
1519632dda83SChuck Lever 	 * processed in the transport
15204d6bbb62SRicardo Labiaga 	 */
15214d6bbb62SRicardo Labiaga 	svc_getu32(argv);	/* XID */
15224d6bbb62SRicardo Labiaga 	svc_getnl(argv);	/* CALLDIR */
15234d6bbb62SRicardo Labiaga 
1524632dda83SChuck Lever 	/* Parse and execute the bc call */
15250d2a970dSTrond Myklebust 	proc_error = svc_process_common(rqstp, argv, resv);
15260d2a970dSTrond Myklebust 
15277402a4feSTrond Myklebust 	atomic_dec(&req->rq_xprt->bc_slot_count);
15280d2a970dSTrond Myklebust 	if (!proc_error) {
1529632dda83SChuck Lever 		/* Processing error: drop the request */
1530b3b02ae5STrond Myklebust 		xprt_free_bc_request(req);
15318f7766c8SVasily Averin 		error = -EINVAL;
15328f7766c8SVasily Averin 		goto out;
15334b5b3ba1SAndy Adamson 	}
1534632dda83SChuck Lever 	/* Finally, send the reply synchronously */
1535632dda83SChuck Lever 	memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf));
15360f419791STrond Myklebust 	task = rpc_run_bc_task(req);
1537632dda83SChuck Lever 	if (IS_ERR(task)) {
1538632dda83SChuck Lever 		error = PTR_ERR(task);
1539632dda83SChuck Lever 		goto out;
1540632dda83SChuck Lever 	}
1541632dda83SChuck Lever 
1542632dda83SChuck Lever 	WARN_ON_ONCE(atomic_read(&task->tk_count) != 1);
1543632dda83SChuck Lever 	error = task->tk_status;
1544632dda83SChuck Lever 	rpc_put_task(task);
1545632dda83SChuck Lever 
1546632dda83SChuck Lever out:
1547632dda83SChuck Lever 	dprintk("svc: %s(), error=%d\n", __func__, error);
1548632dda83SChuck Lever 	return error;
15494d6bbb62SRicardo Labiaga }
15500d961aa9STrond Myklebust EXPORT_SYMBOL_GPL(bc_svc_process);
15519e00abc3STrond Myklebust #endif /* CONFIG_SUNRPC_BACKCHANNEL */
15524d6bbb62SRicardo Labiaga 
15531cad7ea6SRicardo Labiaga /*
15547adae489SGreg Banks  * Return (transport-specific) limit on the rpc payload.
15557adae489SGreg Banks  */
15567adae489SGreg Banks u32 svc_max_payload(const struct svc_rqst *rqstp)
15577adae489SGreg Banks {
155849023155STom Tucker 	u32 max = rqstp->rq_xprt->xpt_class->xcl_max_payload;
15597adae489SGreg Banks 
1560c6b0a9f8SNeilBrown 	if (rqstp->rq_server->sv_max_payload < max)
1561c6b0a9f8SNeilBrown 		max = rqstp->rq_server->sv_max_payload;
15627adae489SGreg Banks 	return max;
15637adae489SGreg Banks }
15647adae489SGreg Banks EXPORT_SYMBOL_GPL(svc_max_payload);
15658154ef27SChuck Lever 
15668154ef27SChuck Lever /**
15675c117207SChuck Lever  * svc_proc_name - Return RPC procedure name in string form
15685c117207SChuck Lever  * @rqstp: svc_rqst to operate on
15695c117207SChuck Lever  *
15705c117207SChuck Lever  * Return value:
15715c117207SChuck Lever  *   Pointer to a NUL-terminated string
15725c117207SChuck Lever  */
15735c117207SChuck Lever const char *svc_proc_name(const struct svc_rqst *rqstp)
15745c117207SChuck Lever {
15755c117207SChuck Lever 	if (rqstp && rqstp->rq_procinfo)
15765c117207SChuck Lever 		return rqstp->rq_procinfo->pc_name;
15775c117207SChuck Lever 	return "unknown";
15785c117207SChuck Lever }
15795c117207SChuck Lever 
15805c117207SChuck Lever 
15815c117207SChuck Lever /**
158203493bcaSChuck Lever  * svc_encode_result_payload - mark a range of bytes as a result payload
158341205539SChuck Lever  * @rqstp: svc_rqst to operate on
158441205539SChuck Lever  * @offset: payload's byte offset in rqstp->rq_res
158541205539SChuck Lever  * @length: size of payload, in bytes
158641205539SChuck Lever  *
158741205539SChuck Lever  * Returns zero on success, or a negative errno if a permanent
158841205539SChuck Lever  * error occurred.
158941205539SChuck Lever  */
159003493bcaSChuck Lever int svc_encode_result_payload(struct svc_rqst *rqstp, unsigned int offset,
159141205539SChuck Lever 			      unsigned int length)
159241205539SChuck Lever {
159303493bcaSChuck Lever 	return rqstp->rq_xprt->xpt_ops->xpo_result_payload(rqstp, offset,
159403493bcaSChuck Lever 							   length);
159541205539SChuck Lever }
159603493bcaSChuck Lever EXPORT_SYMBOL_GPL(svc_encode_result_payload);
159741205539SChuck Lever 
159841205539SChuck Lever /**
15998154ef27SChuck Lever  * svc_fill_write_vector - Construct data argument for VFS write call
16008154ef27SChuck Lever  * @rqstp: svc_rqst to operate on
1601dae9a6caSChuck Lever  * @payload: xdr_buf containing only the write data payload
16028154ef27SChuck Lever  *
16033fd9557aSChuck Lever  * Fills in rqstp::rq_vec, and returns the number of elements.
16048154ef27SChuck Lever  */
1605dae9a6caSChuck Lever unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
1606dae9a6caSChuck Lever 				   struct xdr_buf *payload)
16078154ef27SChuck Lever {
1608dae9a6caSChuck Lever 	struct page **pages = payload->pages;
1609dae9a6caSChuck Lever 	struct kvec *first = payload->head;
16108154ef27SChuck Lever 	struct kvec *vec = rqstp->rq_vec;
1611dae9a6caSChuck Lever 	size_t total = payload->len;
16128154ef27SChuck Lever 	unsigned int i;
16138154ef27SChuck Lever 
16148154ef27SChuck Lever 	/* Some types of transport can present the write payload
16158154ef27SChuck Lever 	 * entirely in rq_arg.pages. In this case, @first is empty.
16168154ef27SChuck Lever 	 */
16178154ef27SChuck Lever 	i = 0;
16188154ef27SChuck Lever 	if (first->iov_len) {
16198154ef27SChuck Lever 		vec[i].iov_base = first->iov_base;
16208154ef27SChuck Lever 		vec[i].iov_len = min_t(size_t, total, first->iov_len);
16218154ef27SChuck Lever 		total -= vec[i].iov_len;
16228154ef27SChuck Lever 		++i;
16238154ef27SChuck Lever 	}
16248154ef27SChuck Lever 
16258154ef27SChuck Lever 	while (total) {
16268154ef27SChuck Lever 		vec[i].iov_base = page_address(*pages);
16278154ef27SChuck Lever 		vec[i].iov_len = min_t(size_t, total, PAGE_SIZE);
16288154ef27SChuck Lever 		total -= vec[i].iov_len;
16298154ef27SChuck Lever 		++i;
16308154ef27SChuck Lever 		++pages;
16318154ef27SChuck Lever 	}
16328154ef27SChuck Lever 
16338154ef27SChuck Lever 	WARN_ON_ONCE(i > ARRAY_SIZE(rqstp->rq_vec));
16348154ef27SChuck Lever 	return i;
16358154ef27SChuck Lever }
16368154ef27SChuck Lever EXPORT_SYMBOL_GPL(svc_fill_write_vector);
163738a70315SChuck Lever 
163838a70315SChuck Lever /**
163938a70315SChuck Lever  * svc_fill_symlink_pathname - Construct pathname argument for VFS symlink call
164038a70315SChuck Lever  * @rqstp: svc_rqst to operate on
164138a70315SChuck Lever  * @first: buffer containing first section of pathname
164211b4d66eSChuck Lever  * @p: buffer containing remaining section of pathname
164338a70315SChuck Lever  * @total: total length of the pathname argument
164438a70315SChuck Lever  *
164511b4d66eSChuck Lever  * The VFS symlink API demands a NUL-terminated pathname in mapped memory.
164611b4d66eSChuck Lever  * Returns pointer to a NUL-terminated string, or an ERR_PTR. Caller must free
164711b4d66eSChuck Lever  * the returned string.
164838a70315SChuck Lever  */
164938a70315SChuck Lever char *svc_fill_symlink_pathname(struct svc_rqst *rqstp, struct kvec *first,
165011b4d66eSChuck Lever 				void *p, size_t total)
165138a70315SChuck Lever {
165238a70315SChuck Lever 	size_t len, remaining;
165311b4d66eSChuck Lever 	char *result, *dst;
165438a70315SChuck Lever 
165511b4d66eSChuck Lever 	result = kmalloc(total + 1, GFP_KERNEL);
165611b4d66eSChuck Lever 	if (!result)
165711b4d66eSChuck Lever 		return ERR_PTR(-ESERVERFAULT);
165811b4d66eSChuck Lever 
165938a70315SChuck Lever 	dst = result;
166038a70315SChuck Lever 	remaining = total;
166138a70315SChuck Lever 
166238a70315SChuck Lever 	len = min_t(size_t, total, first->iov_len);
166311b4d66eSChuck Lever 	if (len) {
166438a70315SChuck Lever 		memcpy(dst, first->iov_base, len);
166538a70315SChuck Lever 		dst += len;
166638a70315SChuck Lever 		remaining -= len;
166711b4d66eSChuck Lever 	}
166838a70315SChuck Lever 
166938a70315SChuck Lever 	if (remaining) {
167038a70315SChuck Lever 		len = min_t(size_t, remaining, PAGE_SIZE);
167111b4d66eSChuck Lever 		memcpy(dst, p, len);
167238a70315SChuck Lever 		dst += len;
167338a70315SChuck Lever 	}
167438a70315SChuck Lever 
167538a70315SChuck Lever 	*dst = '\0';
167638a70315SChuck Lever 
167711b4d66eSChuck Lever 	/* Sanity check: Linux doesn't allow the pathname argument to
167838a70315SChuck Lever 	 * contain a NUL byte.
167938a70315SChuck Lever 	 */
168011b4d66eSChuck Lever 	if (strlen(result) != total) {
168111b4d66eSChuck Lever 		kfree(result);
168238a70315SChuck Lever 		return ERR_PTR(-EINVAL);
168311b4d66eSChuck Lever 	}
168438a70315SChuck Lever 	return result;
168538a70315SChuck Lever }
168638a70315SChuck Lever EXPORT_SYMBOL_GPL(svc_fill_symlink_pathname);
1687