11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/net/sunrpc/svc.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * High-level RPC service routines 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * 8bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Multiple threads pools and NUMAisation 9bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Copyright (c) 2006 Silicon Graphics, Inc. 10bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * by Greg Banks <gnb@melbourne.sgi.com> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/linkage.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/net.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 19a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks#include <linux/interrupt.h> 20a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks#include <linux/module.h> 219867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton#include <linux/kthread.h> 225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/types.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/xdr.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/stats.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/svcsock.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/clnt.h> 294d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga#include <linux/sunrpc/bc_xprt.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RPCDBG_FACILITY RPCDBG_SVCDSP 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 335247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskystatic void svc_unregister(const struct svc_serv *serv, struct net *net); 347252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever 3542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks#define svc_serv_is_pooled(serv) ((serv)->sv_function) 3642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 38bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Mode for mapping cpus to pools. 39bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 40bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksenum { 4142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks SVC_POOL_AUTO = -1, /* choose one of the others */ 42bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks SVC_POOL_GLOBAL, /* no mapping, just a single global pool 43bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * (legacy & UP mode) */ 44bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks SVC_POOL_PERCPU, /* one pool per cpu */ 45bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks SVC_POOL_PERNODE /* one pool per numa node */ 46bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks}; 4742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks#define SVC_POOL_DEFAULT SVC_POOL_GLOBAL 48bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 49bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 50bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Structure for mapping cpus to pools and vice versa. 51bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Setup once during sunrpc initialisation. 52bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 53bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstatic struct svc_pool_map { 5442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks int count; /* How many svc_servs use us */ 55bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks int mode; /* Note: int not enum to avoid 56bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * warnings about "enumeration value 57bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * not handled in switch" */ 58bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int npools; 59bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int *pool_to; /* maps pool id to cpu or node */ 60bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int *to_pool; /* maps cpu or node to pool id */ 61bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} svc_pool_map = { 6242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks .count = 0, 6342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks .mode = SVC_POOL_DEFAULT 64bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks}; 6542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksstatic DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */ 6642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 6742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksstatic int 6842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksparam_set_pool_mode(const char *val, struct kernel_param *kp) 6942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks{ 7042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks int *ip = (int *)kp->arg; 7142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks struct svc_pool_map *m = &svc_pool_map; 7242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks int err; 7342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 7442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_lock(&svc_pool_map_mutex); 7542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 7642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks err = -EBUSY; 7742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (m->count) 7842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks goto out; 7942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 8042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks err = 0; 8142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (!strncmp(val, "auto", 4)) 8242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks *ip = SVC_POOL_AUTO; 8342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks else if (!strncmp(val, "global", 6)) 8442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks *ip = SVC_POOL_GLOBAL; 8542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks else if (!strncmp(val, "percpu", 6)) 8642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks *ip = SVC_POOL_PERCPU; 8742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks else if (!strncmp(val, "pernode", 7)) 8842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks *ip = SVC_POOL_PERNODE; 8942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks else 9042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks err = -EINVAL; 9142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 9242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksout: 9342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_unlock(&svc_pool_map_mutex); 9442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks return err; 9542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks} 9642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 9742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksstatic int 9842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksparam_get_pool_mode(char *buf, struct kernel_param *kp) 9942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks{ 10042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks int *ip = (int *)kp->arg; 10142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 10242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks switch (*ip) 10342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks { 10442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks case SVC_POOL_AUTO: 10542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks return strlcpy(buf, "auto", 20); 10642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks case SVC_POOL_GLOBAL: 10742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks return strlcpy(buf, "global", 20); 10842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks case SVC_POOL_PERCPU: 10942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks return strlcpy(buf, "percpu", 20); 11042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks case SVC_POOL_PERNODE: 11142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks return strlcpy(buf, "pernode", 20); 11242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks default: 11342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks return sprintf(buf, "%d", *ip); 11442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks } 11542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks} 116bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 11742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksmodule_param_call(pool_mode, param_set_pool_mode, param_get_pool_mode, 11842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks &svc_pool_map.mode, 0644); 119bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 120bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 121bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Detect best pool mapping mode heuristically, 122bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * according to the machine's topology. 123bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 124bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstatic int 125bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Bankssvc_pool_map_choose_mode(void) 126bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 127bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int node; 128bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 12962bc62a873116805774ffd37d7f86aa4faa832b1Christoph Lameter if (nr_online_nodes > 1) { 130bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* 131bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Actually have multiple NUMA nodes, 132bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * so split pools on NUMA node boundaries 133bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 134bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return SVC_POOL_PERNODE; 135bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 136bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 13772c3368856c543ace033f6a5b9a3edf1f4043236H Hartley Sweeten node = first_online_node; 138bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks if (nr_cpus_node(node) > 2) { 139bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* 140bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Non-trivial SMP, or CONFIG_NUMA on 141bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * non-NUMA hardware, e.g. with a generic 142bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * x86_64 kernel on Xeons. In this case we 143bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * want to divide the pools on cpu boundaries. 144bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 145bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return SVC_POOL_PERCPU; 146bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 147bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 148bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* default: one global pool */ 149bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return SVC_POOL_GLOBAL; 150bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} 151bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 152bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 153bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Allocate the to_pool[] and pool_to[] arrays. 154bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Returns 0 on success or an errno. 155bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 156bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstatic int 157bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Bankssvc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools) 158bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 159bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->to_pool = kcalloc(maxpools, sizeof(unsigned int), GFP_KERNEL); 160bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks if (!m->to_pool) 161bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks goto fail; 162bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->pool_to = kcalloc(maxpools, sizeof(unsigned int), GFP_KERNEL); 163bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks if (!m->pool_to) 164bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks goto fail_free; 165bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 166bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return 0; 167bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 168bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksfail_free: 169bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks kfree(m->to_pool); 17061c8504c428edcebf23b97775a129c5b393a302bJ. Bruce Fields m->to_pool = NULL; 171bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksfail: 172bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return -ENOMEM; 173bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} 174bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 175bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 176bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Initialise the pool map for SVC_POOL_PERCPU mode. 177bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Returns number of pools or <0 on error. 178bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 179bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstatic int 180bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Bankssvc_pool_map_init_percpu(struct svc_pool_map *m) 181bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 18253b8a315b76a3f3c70a5644976c0095460eb13d8Christoph Lameter unsigned int maxpools = nr_cpu_ids; 183bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int pidx = 0; 184bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int cpu; 185bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks int err; 186bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 187bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks err = svc_pool_map_alloc_arrays(m, maxpools); 188bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks if (err) 189bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return err; 190bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 191bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks for_each_online_cpu(cpu) { 192bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks BUG_ON(pidx > maxpools); 193bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->to_pool[cpu] = pidx; 194bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->pool_to[pidx] = cpu; 195bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks pidx++; 196bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 197bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* cpus brought online later all get mapped to pool0, sorry */ 198bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 199bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return pidx; 200bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks}; 201bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 202bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 203bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 204bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Initialise the pool map for SVC_POOL_PERNODE mode. 205bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Returns number of pools or <0 on error. 206bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 207bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstatic int 208bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Bankssvc_pool_map_init_pernode(struct svc_pool_map *m) 209bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 21074c7aa8b8581e0ba8d6d17c623b9279aaabbb0cfChristoph Lameter unsigned int maxpools = nr_node_ids; 211bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int pidx = 0; 212bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int node; 213bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks int err; 214bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 215bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks err = svc_pool_map_alloc_arrays(m, maxpools); 216bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks if (err) 217bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return err; 218bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 219bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks for_each_node_with_cpus(node) { 220bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* some architectures (e.g. SN2) have cpuless nodes */ 221bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks BUG_ON(pidx > maxpools); 222bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->to_pool[node] = pidx; 223bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->pool_to[pidx] = node; 224bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks pidx++; 225bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 226bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* nodes brought online later all get mapped to pool0, sorry */ 227bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 228bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return pidx; 229bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} 230bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 231bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 232bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 23342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * Add a reference to the global map of cpus to pools (and 23442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * vice versa). Initialise the map if we're the first user. 23542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * Returns the number of pools. 236bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 237bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstatic unsigned int 23842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Bankssvc_pool_map_get(void) 239bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 240bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks struct svc_pool_map *m = &svc_pool_map; 241bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks int npools = -1; 242bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 24342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_lock(&svc_pool_map_mutex); 24442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 24542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (m->count++) { 24642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_unlock(&svc_pool_map_mutex); 247bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return m->npools; 24842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks } 249bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 25042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (m->mode == SVC_POOL_AUTO) 25142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks m->mode = svc_pool_map_choose_mode(); 252bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 253bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks switch (m->mode) { 254bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks case SVC_POOL_PERCPU: 255bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks npools = svc_pool_map_init_percpu(m); 256bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks break; 257bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks case SVC_POOL_PERNODE: 258bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks npools = svc_pool_map_init_pernode(m); 259bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks break; 260bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 261bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 262bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks if (npools < 0) { 263bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* default, or memory allocation failure */ 264bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks npools = 1; 265bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->mode = SVC_POOL_GLOBAL; 266bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 267bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks m->npools = npools; 268bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 26942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_unlock(&svc_pool_map_mutex); 270bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return m->npools; 271bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} 272bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 27342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 27442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks/* 27542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * Drop a reference to the global map of cpus to pools. 27642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * When the last reference is dropped, the map data is 27742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * freed; this allows the sysadmin to change the pool 27842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * mode using the pool_mode module option without 27942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * rebooting or re-loading sunrpc.ko. 28042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks */ 28142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banksstatic void 28242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Bankssvc_pool_map_put(void) 28342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks{ 28442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks struct svc_pool_map *m = &svc_pool_map; 28542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 28642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_lock(&svc_pool_map_mutex); 28742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 28842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (!--m->count) { 28942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks kfree(m->to_pool); 29061c8504c428edcebf23b97775a129c5b393a302bJ. Bruce Fields m->to_pool = NULL; 29142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks kfree(m->pool_to); 29261c8504c428edcebf23b97775a129c5b393a302bJ. Bruce Fields m->pool_to = NULL; 29342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks m->npools = 0; 29442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks } 29542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 29642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks mutex_unlock(&svc_pool_map_mutex); 29742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks} 29842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 29942a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 30011fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazetstatic int svc_pool_map_get_node(unsigned int pidx) 30111fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet{ 30211fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet const struct svc_pool_map *m = &svc_pool_map; 30311fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet 30411fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet if (m->count) { 30511fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet if (m->mode == SVC_POOL_PERCPU) 30611fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet return cpu_to_node(m->pool_to[pidx]); 30711fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet if (m->mode == SVC_POOL_PERNODE) 30811fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet return m->pool_to[pidx]; 30911fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet } 31011fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet return NUMA_NO_NODE; 31111fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet} 312bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 3139867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton * Set the given thread's cpus_allowed mask so that it 314bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * will only run on cpus in the given pool. 315bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 3169867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Laytonstatic inline void 3179867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Laytonsvc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx) 318bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 319bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks struct svc_pool_map *m = &svc_pool_map; 3209867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton unsigned int node = m->pool_to[pidx]; 321bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 322bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* 323bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * The caller checks for sv_nrpools > 1, which 32442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * implies that we've been initialized. 325bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 3261bd58aaff44485ec9e3640af350f6ba1b33e2becWeston Andros Adamson WARN_ON_ONCE(m->count == 0); 3271bd58aaff44485ec9e3640af350f6ba1b33e2becWeston Andros Adamson if (m->count == 0) 3281bd58aaff44485ec9e3640af350f6ba1b33e2becWeston Andros Adamson return; 329bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 3309867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton switch (m->mode) { 331bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks case SVC_POOL_PERCPU: 332c5f59f0833df945eef7ff35f3dc6ba61c5f293ddMike Travis { 333aa85ea5b89c36c51200d795dd788139bd9b8cf50Rusty Russell set_cpus_allowed_ptr(task, cpumask_of(node)); 3349867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton break; 335c5f59f0833df945eef7ff35f3dc6ba61c5f293ddMike Travis } 336bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks case SVC_POOL_PERNODE: 337c5f59f0833df945eef7ff35f3dc6ba61c5f293ddMike Travis { 338a70f730282019f487aa33a84e5ac9a5e89c5abd0Rusty Russell set_cpus_allowed_ptr(task, cpumask_of_node(node)); 3399867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton break; 340bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 341c5f59f0833df945eef7ff35f3dc6ba61c5f293ddMike Travis } 342bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} 343bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 344bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 345bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Use the mapping mode to choose a pool for a given CPU. 346bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * Used when enqueueing an incoming RPC. Always returns 347bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * a non-NULL pool pointer. 348bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 349bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banksstruct svc_pool * 350bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Bankssvc_pool_for_cpu(struct svc_serv *serv, int cpu) 351bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks{ 352bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks struct svc_pool_map *m = &svc_pool_map; 353bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks unsigned int pidx = 0; 354bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 355bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks /* 35642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks * An uninitialised map happens in a pure client when 357bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * lockd is brought up, so silently treat it the 358bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks * same as SVC_POOL_GLOBAL. 359bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks */ 36042a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (svc_serv_is_pooled(serv)) { 36142a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks switch (m->mode) { 36242a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks case SVC_POOL_PERCPU: 36342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks pidx = m->to_pool[cpu]; 36442a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks break; 36542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks case SVC_POOL_PERNODE: 36642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks pidx = m->to_pool[cpu_to_node(cpu)]; 36742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks break; 36842a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks } 369bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks } 370bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks return &serv->sv_pools[pidx % serv->sv_nrpools]; 371bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks} 372bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 373bb2224df5ffe4f864f5b696199b17db1ce77bc0aStanislav Kinsburskyint svc_rpcb_setup(struct svc_serv *serv, struct net *net) 374d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky{ 375d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky int err; 376d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky 377bee42f688c915b510a4aabae4f7a99457137d6f3Stanislav Kinsbursky err = rpcb_create_local(net); 378d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky if (err) 379d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky return err; 380d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky 381d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky /* Remove any stale portmap registrations */ 382bee42f688c915b510a4aabae4f7a99457137d6f3Stanislav Kinsbursky svc_unregister(serv, net); 383d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky return 0; 384d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky} 385bb2224df5ffe4f864f5b696199b17db1ce77bc0aStanislav KinsburskyEXPORT_SYMBOL_GPL(svc_rpcb_setup); 386d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky 3875ecebb7c7fd737cf387a552994df319c063973dbStanislav Kinsburskyvoid svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) 388d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky{ 3895ecebb7c7fd737cf387a552994df319c063973dbStanislav Kinsbursky svc_unregister(serv, net); 3905ecebb7c7fd737cf387a552994df319c063973dbStanislav Kinsbursky rpcb_put_local(net); 391d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky} 39216d0587090ab93206768f726f71d84ecf55e05c4Stanislav KinsburskyEXPORT_SYMBOL_GPL(svc_rpcb_cleanup); 393d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky 394d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsburskystatic int svc_uses_rpcbind(struct svc_serv *serv) 395d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky{ 396d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky struct svc_program *progp; 397d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky unsigned int i; 398d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky 399d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky for (progp = serv->sv_program; progp; progp = progp->pg_next) { 400d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky for (i = 0; i < progp->pg_nvers; i++) { 401d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky if (progp->pg_vers[i] == NULL) 402d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky continue; 403d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky if (progp->pg_vers[i]->vs_hidden == 0) 404d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky return 1; 405d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky } 406d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky } 407d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky 408d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky return 0; 409d99085605cd245d8f24858e9d0b06013e13aa044Stanislav Kinsbursky} 410bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 4119793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsburskyint svc_bind(struct svc_serv *serv, struct net *net) 4129793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky{ 4139793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky if (!svc_uses_rpcbind(serv)) 4149793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky return 0; 4159793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky return svc_rpcb_setup(serv, net); 4169793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky} 4179793f7c88937e7ac07305ab1af1a519225836823Stanislav KinsburskyEXPORT_SYMBOL_GPL(svc_bind); 4189793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky 419bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks/* 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Create an RPC service 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 422a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksstatic struct svc_serv * 423a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks__svc_create(struct svc_program *prog, unsigned int bufsize, int npools, 4245ecebb7c7fd737cf387a552994df319c063973dbStanislav Kinsbursky void (*shutdown)(struct svc_serv *serv, struct net *net)) 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_serv *serv; 427ea339d46b93c7b16e067a29aad1812f7a389815aChuck Lever unsigned int vers; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int xdrsize; 4293262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks unsigned int i; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4310da974f4f303a6842516b764507e3c0a03f41e5aPanagiotis Issaris if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL))) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4339ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher serv->sv_name = prog->pg_name; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_program = prog; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_nrthreads = 1; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats = prog->pg_stats; 437c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown if (bufsize > RPCSVC_MAXPAYLOAD) 438c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown bufsize = RPCSVC_MAXPAYLOAD; 439c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown serv->sv_max_payload = bufsize? bufsize : 4096; 440c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown serv->sv_max_mesg = roundup(serv->sv_max_payload + PAGE_SIZE, PAGE_SIZE); 441bc591ccff27e6a85d3a0d6fcb16cfadcc45267a8NeilBrown serv->sv_shutdown = shutdown; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xdrsize = 0; 4439ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher while (prog) { 4449ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher prog->pg_lovers = prog->pg_nvers-1; 4459ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher for (vers=0; vers<prog->pg_nvers ; vers++) 4469ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher if (prog->pg_vers[vers]) { 4479ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher prog->pg_hivers = vers; 4489ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher if (prog->pg_lovers > vers) 4499ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher prog->pg_lovers = vers; 4509ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher if (prog->pg_vers[vers]->vs_xdrsize > xdrsize) 4519ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher xdrsize = prog->pg_vers[vers]->vs_xdrsize; 4529ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher } 4539ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher prog = prog->pg_next; 4549ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher } 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_xdrsize = xdrsize; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&serv->sv_tempsocks); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&serv->sv_permsocks); 45836bdfc8bae51339aa27ef8e4ce148185293061aeGreg Banks init_timer(&serv->sv_temptimer); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&serv->sv_lock); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks serv->sv_nrpools = npools; 4623262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks serv->sv_pools = 463cd86128088554d64fea1679191509f00e6353c5bRobert P. J. Day kcalloc(serv->sv_nrpools, sizeof(struct svc_pool), 4643262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks GFP_KERNEL); 4653262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks if (!serv->sv_pools) { 4663262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks kfree(serv); 4673262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks return NULL; 4683262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks } 4693262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks 4703262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks for (i = 0; i < serv->sv_nrpools; i++) { 4713262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks struct svc_pool *pool = &serv->sv_pools[i]; 4723262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks 47346121cf7d85869bfe9588bac7ccf55aa0bc7f278Chuck Lever dprintk("svc: initialising pool %u for %s\n", 4743262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks i, serv->sv_name); 4753262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks 4763262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks pool->sp_id = i; 4773262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks INIT_LIST_HEAD(&pool->sp_threads); 4783262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks INIT_LIST_HEAD(&pool->sp_sockets); 479a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks INIT_LIST_HEAD(&pool->sp_all_threads); 4803262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks spin_lock_init(&pool->sp_lock); 4813262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks } 4823262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks 4839793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) 4849793f7c88937e7ac07305ab1af1a519225836823Stanislav Kinsbursky serv->sv_shutdown = svc_rpcb_cleanup; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return serv; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 489a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksstruct svc_serv * 490a74554429eada89a7ddb47317e6a2968d03e41a2Greg Bankssvc_create(struct svc_program *prog, unsigned int bufsize, 4915ecebb7c7fd737cf387a552994df319c063973dbStanislav Kinsbursky void (*shutdown)(struct svc_serv *serv, struct net *net)) 492a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks{ 49349a9072f29a1039f142ec98b44a72d7173651c02Chuck Lever return __svc_create(prog, bufsize, /*npools*/1, shutdown); 494a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks} 49524c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_create); 496a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 497a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksstruct svc_serv * 498a74554429eada89a7ddb47317e6a2968d03e41a2Greg Bankssvc_create_pooled(struct svc_program *prog, unsigned int bufsize, 4995ecebb7c7fd737cf387a552994df319c063973dbStanislav Kinsbursky void (*shutdown)(struct svc_serv *serv, struct net *net), 500a75c5d01e4235a7dd785548ac756f248b1b40107Jeff Layton svc_thread_fn func, struct module *mod) 501a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks{ 502a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks struct svc_serv *serv; 50342a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks unsigned int npools = svc_pool_map_get(); 504a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 50549a9072f29a1039f142ec98b44a72d7173651c02Chuck Lever serv = __svc_create(prog, bufsize, npools, shutdown); 506a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 507a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks if (serv != NULL) { 508a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks serv->sv_function = func; 509a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks serv->sv_module = mod; 510a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } 511a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 512a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks return serv; 513a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks} 51424c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_create_pooled); 515a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 516074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsburskyvoid svc_shutdown_net(struct svc_serv *serv, struct net *net) 517074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky{ 518074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky svc_close_net(serv, net); 519074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky 520074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky if (serv->sv_shutdown) 521074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky serv->sv_shutdown(serv, net); 522074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky} 523074d0f67cfe0af4927ce49560f403096b490c47fStanislav KinsburskyEXPORT_SYMBOL_GPL(svc_shutdown_net); 524074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 526bedbdd8bada194a690d2901801bf8451965086b3Neil Brown * Destroy an RPC service. Should be called with appropriate locking to 527bedbdd8bada194a690d2901801bf8451965086b3Neil Brown * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_destroy(struct svc_serv *serv) 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 53246121cf7d85869bfe9588bac7ccf55aa0bc7f278Chuck Lever dprintk("svc: svc_destroy(%s, %d)\n", 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_program->pg_name, 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_nrthreads); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serv->sv_nrthreads) { 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (--(serv->sv_nrthreads) != 0) { 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds svc_sock_update_bufs(serv); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("svc_destroy: no threads for serv=%p!\n", serv); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 54436bdfc8bae51339aa27ef8e4ce148185293061aeGreg Banks del_timer_sync(&serv->sv_temptimer); 545074d0f67cfe0af4927ce49560f403096b490c47fStanislav Kinsbursky 5467b147f1ff267d12e0d189ca3d4156ed5a76b8d99Stanislav Kinsbursky /* 5477b147f1ff267d12e0d189ca3d4156ed5a76b8d99Stanislav Kinsbursky * The last user is gone and thus all sockets have to be destroyed to 5487b147f1ff267d12e0d189ca3d4156ed5a76b8d99Stanislav Kinsbursky * the point. Check this. 5497b147f1ff267d12e0d189ca3d4156ed5a76b8d99Stanislav Kinsbursky */ 5507b147f1ff267d12e0d189ca3d4156ed5a76b8d99Stanislav Kinsbursky BUG_ON(!list_empty(&serv->sv_permsocks)); 5517b147f1ff267d12e0d189ca3d4156ed5a76b8d99Stanislav Kinsbursky BUG_ON(!list_empty(&serv->sv_tempsocks)); 552cda1fd4abd773216a888487af0170d0cc3d50454NeilBrown 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cache_clean_deferred(serv); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 55542a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks if (svc_serv_is_pooled(serv)) 55642a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks svc_pool_map_put(); 55742a7fc4a6598221f1a547a76cdd45a8ab4d90e93Greg Banks 5583262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks kfree(serv->sv_pools); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(serv); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 56124c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_destroy); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate an RPC server's buffer space. 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We allocate pages and place them in rq_argpages. 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 56811fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazetsvc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node) 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5700dc220f0815497858db539d27947f3ec83202aceChuck Lever unsigned int pages, arghi; 571cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki 572ba17686f62db88f6a591121e768a0c83a2a2647dAndy Adamson /* bc_xprt uses fore channel allocated buffers */ 573ba17686f62db88f6a591121e768a0c83a2a2647dAndy Adamson if (svc_is_backchannel(rqstp)) 574ba17686f62db88f6a591121e768a0c83a2a2647dAndy Adamson return 1; 575ba17686f62db88f6a591121e768a0c83a2a2647dAndy Adamson 576c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply. 577c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown * We assume one is at most one page 578c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown */ 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arghi = 0; 580b25cd058f25ea2054351bbe501956002cd8ed4c5Weston Andros Adamson WARN_ON_ONCE(pages > RPCSVC_MAXPAGES); 581b25cd058f25ea2054351bbe501956002cd8ed4c5Weston Andros Adamson if (pages > RPCSVC_MAXPAGES) 582b25cd058f25ea2054351bbe501956002cd8ed4c5Weston Andros Adamson pages = RPCSVC_MAXPAGES; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (pages) { 58411fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet struct page *p = alloc_pages_node(node, GFP_KERNEL, 0); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p) 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5874452435948424e5322c2a2fefbdc2cf3732cc45dNeilBrown rqstp->rq_pages[arghi++] = p; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pages--; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5900dc220f0815497858db539d27947f3ec83202aceChuck Lever return pages == 0; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Release an RPC server buffer 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_release_buffer(struct svc_rqst *rqstp) 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 59950c8bb13eaaf345caf2e7966667ba1d3e4d68af2Chuck Lever unsigned int i; 60050c8bb13eaaf345caf2e7966667ba1d3e4d68af2Chuck Lever 60150c8bb13eaaf345caf2e7966667ba1d3e4d68af2Chuck Lever for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++) 6024452435948424e5322c2a2fefbdc2cf3732cc45dNeilBrown if (rqstp->rq_pages[i]) 6034452435948424e5322c2a2fefbdc2cf3732cc45dNeilBrown put_page(rqstp->rq_pages[i]); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6060113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Laytonstruct svc_rqst * 60711fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazetsvc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_rqst *rqstp; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61111fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet rqstp = kzalloc_node(sizeof(*rqstp), GFP_KERNEL, node); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rqstp) 6130113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton goto out_enomem; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_nrthreads++; 6163262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks spin_lock_bh(&pool->sp_lock); 6173262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks pool->sp_nrthreads++; 618a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks list_add(&rqstp->rq_all, &pool->sp_all_threads); 6193262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks spin_unlock_bh(&pool->sp_lock); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rqstp->rq_server = serv; 6213262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks rqstp->rq_pool = pool; 622bfd241600a3b0db4fe43c859f1460d0a958d924aGreg Banks 62311fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); 6240113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton if (!rqstp->rq_argp) 6250113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton goto out_thread; 6260113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton 62711fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet rqstp->rq_resp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); 6280113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton if (!rqstp->rq_resp) 6290113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton goto out_thread; 6300113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton 63111fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node)) 6320113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton goto out_thread; 6330113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton 6340113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton return rqstp; 6350113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Laytonout_thread: 6360113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton svc_exit_thread(rqstp); 6370113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Laytonout_enomem: 6380113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton return ERR_PTR(-ENOMEM); 6390113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton} 64024c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_prepare_thread); 6410113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton 6420113ab34644649aceaac37ef4b7e5c7d5c183be3Jeff Layton/* 643a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * Choose a pool in which to create a new thread, for svc_set_num_threads 644a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks */ 645a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksstatic inline struct svc_pool * 646a74554429eada89a7ddb47317e6a2968d03e41a2Greg Bankschoose_pool(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state) 647a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks{ 648a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks if (pool != NULL) 649a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks return pool; 650a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 651cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki return &serv->sv_pools[(*state)++ % serv->sv_nrpools]; 652a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks} 653a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 654a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks/* 655a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * Choose a thread to kill, for svc_set_num_threads 656a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks */ 657a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksstatic inline struct task_struct * 658a74554429eada89a7ddb47317e6a2968d03e41a2Greg Bankschoose_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state) 659a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks{ 660a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks unsigned int i; 661a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks struct task_struct *task = NULL; 662a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 663a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks if (pool != NULL) { 664a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks spin_lock_bh(&pool->sp_lock); 665a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } else { 666a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks /* choose a pool in round-robin fashion */ 667cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki for (i = 0; i < serv->sv_nrpools; i++) { 668cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki pool = &serv->sv_pools[--(*state) % serv->sv_nrpools]; 669a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks spin_lock_bh(&pool->sp_lock); 670cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki if (!list_empty(&pool->sp_all_threads)) 671cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki goto found_pool; 672a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks spin_unlock_bh(&pool->sp_lock); 673cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki } 674a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks return NULL; 675a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } 676a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 677a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksfound_pool: 678a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks if (!list_empty(&pool->sp_all_threads)) { 679a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks struct svc_rqst *rqstp; 680a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 681a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks /* 682a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * Remove from the pool->sp_all_threads list 683a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * so we don't try to kill it again. 684a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks */ 685a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks rqstp = list_entry(pool->sp_all_threads.next, struct svc_rqst, rq_all); 686a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks list_del_init(&rqstp->rq_all); 687a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks task = rqstp->rq_task; 688cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki } 689a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks spin_unlock_bh(&pool->sp_lock); 690a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 691a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks return task; 692a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks} 693a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 694a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks/* 695a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * Create or destroy enough new threads to make the number 696a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * of threads the given number. If `pool' is non-NULL, applies 697a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * only to threads in that pool, otherwise round-robins between 69894cf3179ccfc69d727dd884fd0831d82ada6bb06J. Bruce Fields * all pools. Caller must ensure that mutual exclusion between this and 69994cf3179ccfc69d727dd884fd0831d82ada6bb06J. Bruce Fields * server startup or shutdown. 700a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * 701a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * Destroying threads relies on the service threads filling in 702a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * rqstp->rq_task, which only the nfs ones do. Assumes the serv 703a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * has been created using svc_create_pooled(). 704a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * 705a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * Based on code that used to be in nfsd_svc() but tweaked 706a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks * to be pool-aware. 707a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks */ 708a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banksint 709a74554429eada89a7ddb47317e6a2968d03e41a2Greg Bankssvc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) 710a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks{ 7119867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton struct svc_rqst *rqstp; 7129867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton struct task_struct *task; 7139867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton struct svc_pool *chosen_pool; 714a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks int error = 0; 715a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks unsigned int state = serv->sv_nrthreads-1; 71611fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet int node; 717a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 718a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks if (pool == NULL) { 719a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks /* The -1 assumes caller has done a svc_get() */ 720a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks nrservs -= (serv->sv_nrthreads-1); 721a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } else { 722a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks spin_lock_bh(&pool->sp_lock); 723a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks nrservs -= pool->sp_nrthreads; 724a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks spin_unlock_bh(&pool->sp_lock); 725a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } 726a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 727a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks /* create new threads */ 728a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks while (nrservs > 0) { 729a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks nrservs--; 7309867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton chosen_pool = choose_pool(serv, pool, &state); 7319867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton 73211fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet node = svc_pool_map_get_node(chosen_pool->sp_id); 73311fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet rqstp = svc_prepare_thread(serv, chosen_pool, node); 7349867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton if (IS_ERR(rqstp)) { 7359867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton error = PTR_ERR(rqstp); 7369867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton break; 7379867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton } 7389867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton 739a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks __module_get(serv->sv_module); 74011fd165c68b73434ca1273e21f21db5eecc90926Eric Dumazet task = kthread_create_on_node(serv->sv_function, rqstp, 741f170168b9a0b61ea1e647b082b38f605f1d3de3eKees Cook node, "%s", serv->sv_name); 7429867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton if (IS_ERR(task)) { 7439867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton error = PTR_ERR(task); 744a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks module_put(serv->sv_module); 7459867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton svc_exit_thread(rqstp); 746a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks break; 747a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } 7489867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton 7499867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton rqstp->rq_task = task; 7509867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton if (serv->sv_nrpools > 1) 7519867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton svc_pool_map_set_cpumask(task, chosen_pool->sp_id); 7529867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton 7539867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton svc_sock_update_bufs(serv); 7549867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton wake_up_process(task); 755a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } 756a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks /* destroy old threads */ 757a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks while (nrservs < 0 && 7589867d76ca16b3f455f9ca83861f4ce5c94a25928Jeff Layton (task = choose_victim(serv, pool, &state)) != NULL) { 759a75c5d01e4235a7dd785548ac756f248b1b40107Jeff Layton send_sig(SIGINT, task, 1); 760a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks nrservs++; 761a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks } 762a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 763a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks return error; 764a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks} 76524c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_set_num_threads); 766a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks 767a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks/* 768bedbdd8bada194a690d2901801bf8451965086b3Neil Brown * Called from a server thread as it's exiting. Caller must hold the BKL or 769bedbdd8bada194a690d2901801bf8451965086b3Neil Brown * the "service mutex", whichever is appropriate for the service. 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_exit_thread(struct svc_rqst *rqstp) 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_serv *serv = rqstp->rq_server; 7753262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks struct svc_pool *pool = rqstp->rq_pool; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds svc_release_buffer(rqstp); 778a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(rqstp->rq_resp); 779a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(rqstp->rq_argp); 780a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(rqstp->rq_auth_data); 7813262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks 7823262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks spin_lock_bh(&pool->sp_lock); 7833262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks pool->sp_nrthreads--; 784a74554429eada89a7ddb47317e6a2968d03e41a2Greg Banks list_del(&rqstp->rq_all); 7853262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks spin_unlock_bh(&pool->sp_lock); 7863262c816a3d7fb1eaabce633caa317887ed549aeGreg Banks 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(rqstp); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Release the server */ 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serv) 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds svc_destroy(serv); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 79324c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_exit_thread); 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7962c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * Register an "inet" protocol family netid with the local 7972c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * rpcbind daemon via an rpcbind v4 SET request. 798a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * 7992c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * No netconfig infrastructure is available in the kernel, so 8002c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * we map IP_ protocol numbers to netids by hand. 801a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * 8022c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * Returns zero on success; a negative errno value is returned 8032c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * if any error occurs. 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8055247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskystatic int __svc_rpcb_register4(struct net *net, const u32 program, 8065247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky const u32 version, 8072c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever const unsigned short protocol, 8082c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever const unsigned short port) 809a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever{ 810cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever const struct sockaddr_in sin = { 811a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever .sin_family = AF_INET, 812a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever .sin_addr.s_addr = htonl(INADDR_ANY), 813a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever .sin_port = htons(port), 814a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever }; 815cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever const char *netid; 816cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever int error; 8172c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 8182c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever switch (protocol) { 8192c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever case IPPROTO_UDP: 8202c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever netid = RPCBIND_NETID_UDP; 8212c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever break; 8222c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever case IPPROTO_TCP: 8232c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever netid = RPCBIND_NETID_TCP; 8242c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever break; 8252c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever default: 826ba5c35e0c7e30b095636cd58b0854fdbd3c32947Chuck Lever return -ENOPROTOOPT; 8272c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever } 8282c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 8295247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = rpcb_v4_register(net, program, version, 830cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever (const struct sockaddr *)&sin, netid); 831cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever 832cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever /* 833cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever * User space didn't support rpcbind v4, so retry this 834cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever * registration request with the legacy rpcbind v2 protocol. 835cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever */ 836cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever if (error == -EPROTONOSUPPORT) 8375247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = rpcb_register(net, program, version, protocol, port); 838cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever 839cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever return error; 8402c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever} 8412c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 842dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#if IS_ENABLED(CONFIG_IPV6) 8432c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever/* 8442c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * Register an "inet6" protocol family netid with the local 8452c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * rpcbind daemon via an rpcbind v4 SET request. 8462c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * 8472c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * No netconfig infrastructure is available in the kernel, so 8482c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * we map IP_ protocol numbers to netids by hand. 8492c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * 8502c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * Returns zero on success; a negative errno value is returned 8512c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * if any error occurs. 8522c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever */ 8535247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskystatic int __svc_rpcb_register6(struct net *net, const u32 program, 8545247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky const u32 version, 8552c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever const unsigned short protocol, 8562c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever const unsigned short port) 8572c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever{ 858cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever const struct sockaddr_in6 sin6 = { 859a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever .sin6_family = AF_INET6, 860a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever .sin6_addr = IN6ADDR_ANY_INIT, 861a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever .sin6_port = htons(port), 862a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever }; 863cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever const char *netid; 864cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever int error; 865a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever 8662c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever switch (protocol) { 8672c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever case IPPROTO_UDP: 8682c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever netid = RPCBIND_NETID_UDP6; 869a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever break; 8702c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever case IPPROTO_TCP: 871a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever netid = RPCBIND_NETID_TCP6; 872a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever break; 873a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever default: 874ba5c35e0c7e30b095636cd58b0854fdbd3c32947Chuck Lever return -ENOPROTOOPT; 8752c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever } 8762c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 8775247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = rpcb_v4_register(net, program, version, 878cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever (const struct sockaddr *)&sin6, netid); 879cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever 880cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever /* 881cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever * User space didn't support rpcbind version 4, so we won't 882cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever * use a PF_INET6 listener. 883cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever */ 884cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever if (error == -EPROTONOSUPPORT) 885cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever error = -EAFNOSUPPORT; 886cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever 887cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever return error; 8882c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever} 889dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#endif /* IS_ENABLED(CONFIG_IPV6) */ 8902c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 8912c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever/* 8922c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * Register a kernel RPC service via rpcbind version 4. 8932c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * 8942c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * Returns zero on success; a negative errno value is returned 8952c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever * if any error occurs. 8962c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever */ 8975247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskystatic int __svc_register(struct net *net, const char *progname, 898363f724cdd3d2ae554e261be995abdeb15f7bdd9Chuck Lever const u32 program, const u32 version, 8994b62e58cccff9c5e7ffc7023f7ec24c75fbd549bChuck Lever const int family, 9002c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever const unsigned short protocol, 9012c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever const unsigned short port) 9022c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever{ 903363f724cdd3d2ae554e261be995abdeb15f7bdd9Chuck Lever int error = -EAFNOSUPPORT; 9042c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 9052c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever switch (family) { 9064b62e58cccff9c5e7ffc7023f7ec24c75fbd549bChuck Lever case PF_INET: 9075247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = __svc_rpcb_register4(net, program, version, 9082c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever protocol, port); 909cadc0fa534e51e20fdffe1623913c163a18d71b1Chuck Lever break; 910dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#if IS_ENABLED(CONFIG_IPV6) 9114b62e58cccff9c5e7ffc7023f7ec24c75fbd549bChuck Lever case PF_INET6: 9125247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = __svc_rpcb_register6(net, program, version, 9132c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever protocol, port); 914dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#endif 915a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever } 916a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever 917363f724cdd3d2ae554e261be995abdeb15f7bdd9Chuck Lever return error; 918a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever} 9192c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever 920a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever/** 921a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * svc_register - register an RPC service with the local portmapper 922a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * @serv: svc_serv struct for the service to register 9235247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky * @net: net namespace for the service to register 9244b62e58cccff9c5e7ffc7023f7ec24c75fbd549bChuck Lever * @family: protocol family of service's listener socket 925a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * @proto: transport protocol number to advertise 926a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * @port: port to advertise 927a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever * 9284b62e58cccff9c5e7ffc7023f7ec24c75fbd549bChuck Lever * Service is registered for any address in the passed-in protocol family 929a26cfad6e0a308a2c68df1f1ef50aabd48b17e6dChuck Lever */ 9305247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskyint svc_register(const struct svc_serv *serv, struct net *net, 9315247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky const int family, const unsigned short proto, 9325247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky const unsigned short port) 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_program *progp; 9357e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee struct svc_version *vers; 936ea339d46b93c7b16e067a29aad1812f7a389815aChuck Lever unsigned int i; 93714aeb2118d6e9fd9ee988324c740a00c80979093Chuck Lever int error = 0; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9390af39507f60ee9f98b20f24af09c1a60655417acWeston Andros Adamson WARN_ON_ONCE(proto == 0 && port == 0); 9400af39507f60ee9f98b20f24af09c1a60655417acWeston Andros Adamson if (proto == 0 && port == 0) 9410af39507f60ee9f98b20f24af09c1a60655417acWeston Andros Adamson return -EINVAL; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 943bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch for (progp = serv->sv_program; progp; progp = progp->pg_next) { 944bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch for (i = 0; i < progp->pg_nvers; i++) { 9457e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee vers = progp->pg_vers[i]; 9467e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee if (vers == NULL) 947bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch continue; 948bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch 9492c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n", 950bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch progp->pg_name, 9512c7eb0b206b8408d92c518033a359f4374c75314Chuck Lever i, 952bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch proto == IPPROTO_UDP? "udp" : "tcp", 953bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch port, 9544b62e58cccff9c5e7ffc7023f7ec24c75fbd549bChuck Lever family, 9557e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee vers->vs_hidden ? 9567e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee " (but not telling portmap)" : ""); 957bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch 9587e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee if (vers->vs_hidden) 959bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch continue; 960bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch 9615247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = __svc_register(net, progp->pg_name, progp->pg_prog, 962363f724cdd3d2ae554e261be995abdeb15f7bdd9Chuck Lever i, family, proto, port); 9637e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee 9647e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee if (vers->vs_rpcb_optnl) { 9657e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee error = 0; 9667e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee continue; 9677e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee } 9687e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee 9697e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee if (error < 0) { 9707e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee printk(KERN_WARNING "svc: failed to register " 9717e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee "%sv%u RPC service (errno %d).\n", 9727e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee progp->pg_name, i, -error); 973bc5fea4299b8bda5f73c6f79dc35d388caf8bcedOlaf Kirch break; 9747e55b59b2f32afc83452ae250dfd6173c9a7b515Kinglong Mee } 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9787252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever return error; 9797252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever} 9807252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever 981d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever/* 982d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * If user space is running rpcbind, it should take the v4 UNSET 983d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * and clear everything for this [program, version]. If user space 984d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * is running portmap, it will reject the v4 UNSET, but won't have 985d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient 986d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * in this case to clear all existing entries for [program, version]. 987d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever */ 9885247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskystatic void __svc_unregister(struct net *net, const u32 program, const u32 version, 989f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever const char *progname) 990f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever{ 991f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever int error; 992f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever 9935247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = rpcb_v4_register(net, program, version, NULL, ""); 994f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever 995d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever /* 996d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * User space didn't support rpcbind v4, so retry this 997d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever * request with the legacy rpcbind v2 protocol. 998d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever */ 999d5a8620f7c8a5bcade730e2fa1224191f289fb00Chuck Lever if (error == -EPROTONOSUPPORT) 10005247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky error = rpcb_register(net, program, version, 0, 0); 1001f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever 1002f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever dprintk("svc: %s(%sv%u), error %d\n", 1003f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever __func__, progname, version, error); 1004f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever} 1005f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever 10067252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever/* 1007f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever * All netids, bind addresses and ports registered for [program, version] 1008f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever * are removed from the local rpcbind database (if the service is not 1009f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever * hidden) to make way for a new instance of the service. 10107252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever * 1011f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever * The result of unregistration is reported via dprintk for those who want 1012f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8Chuck Lever * verification of the result, but is otherwise not important. 10137252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever */ 10145247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsburskystatic void svc_unregister(const struct svc_serv *serv, struct net *net) 10157252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever{ 10167252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever struct svc_program *progp; 10177252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever unsigned long flags; 10187252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever unsigned int i; 10197252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever 10207252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever clear_thread_flag(TIF_SIGPENDING); 10217252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever 10227252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever for (progp = serv->sv_program; progp; progp = progp->pg_next) { 10237252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever for (i = 0; i < progp->pg_nvers; i++) { 10247252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever if (progp->pg_vers[i] == NULL) 10257252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever continue; 10267252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever if (progp->pg_vers[i]->vs_hidden) 10277252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever continue; 10287252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever 10297402ab19cdd5943c7dd4f3399afe3abda8077ef5Chuck Lever dprintk("svc: attempting to unregister %sv%u\n", 10307402ab19cdd5943c7dd4f3399afe3abda8077ef5Chuck Lever progp->pg_name, i); 10315247fab5c82779174d50590e0200bf532248a8a1Stanislav Kinsbursky __svc_unregister(net, progp->pg_prog, i, progp->pg_name); 10327252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever } 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10357252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever spin_lock_irqsave(¤t->sighand->siglock, flags); 10367252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever recalc_sigpending(); 10377252d575ab0e8771269a3d245c36a05ace5152bdChuck Lever spin_unlock_irqrestore(¤t->sighand->siglock, flags); 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10417032a3dd923f434132643321ad5faad128611f9eJ. Bruce Fields * dprintk the given error with the address of the client that caused it. 1042354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert */ 1043624ab4644819948e9dc87c114201e98f2e52490fJ. Bruce Fields#ifdef RPC_DEBUG 1044b9075fa968a0a4347aef35e235e2995c0e57ddddJoe Perchesstatic __printf(2, 3) 1045e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perchesvoid svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) 1046354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert{ 1047e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches struct va_format vaf; 1048354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert va_list args; 1049354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert char buf[RPC_MAX_ADDRBUFLEN]; 1050354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert 1051e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches va_start(args, fmt); 1052354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert 1053e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches vaf.fmt = fmt; 1054e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches vaf.va = &args; 1055354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert 10567032a3dd923f434132643321ad5faad128611f9eJ. Bruce Fields dprintk("svc: %s: %pV", svc_print_addr(rqstp, buf, sizeof(buf)), &vaf); 1057354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert 1058e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches va_end(args); 1059354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert} 1060624ab4644819948e9dc87c114201e98f2e52490fJ. Bruce Fields#else 1061624ab4644819948e9dc87c114201e98f2e52490fJ. Bruce Fieldsstatic __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {} 1062624ab4644819948e9dc87c114201e98f2e52490fJ. Bruce Fields#endif 1063354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert 1064354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert/* 10651cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga * Common routine for processing the RPC request. 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10671cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiagastatic int 10681cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiagasvc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_program *progp; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_version *versp = NULL; /* compiler food */ 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct svc_procedure *procp = NULL; 10736fb2b47fa16c81317ec282248e6cff521cca31c2NeilBrown struct svc_serv *serv = rqstp->rq_server; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kxdrproc_t xdr; 1075d8ed029d6000ba2e2908d9286409e4833c091b4cAlexey Dobriyan __be32 *statp; 10761cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga u32 prog, vers, proc; 1077d8ed029d6000ba2e2908d9286409e4833c091b4cAlexey Dobriyan __be32 auth_stat, rpc_stat; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int auth_res; 10798f8e05c5708d7e9017c47f395f8b1498f7f52922J.Bruce Fields __be32 *reply_statp; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpc_stat = rpc_success; 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (argv->iov_len < 6*4) 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_short_len; 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10865c04c46aec16b3267d8fe03af886f2d41e448cd0J. Bruce Fields /* Will be turned off only in gss privacy case: */ 1087f15a5cf912f05b572d1f9f3772fba019643f4837Kinglong Mee rqstp->rq_splice_ok = true; 10882f425878b6a71571341dcd3f9e9d1a6f6355da9cAndy Adamson /* Will be turned off only when NFSv4 Sessions are used */ 1089f15a5cf912f05b572d1f9f3772fba019643f4837Kinglong Mee rqstp->rq_usedeferral = true; 10909e701c610923aaeac8b38b9202a686d1cc9ee35dJ. Bruce Fields rqstp->rq_dropme = false; 1091e831fe65b10199e1e301a7316c66d6ced133712dTom Tucker 1092e831fe65b10199e1e301a7316c66d6ced133712dTom Tucker /* Setup reply header */ 1093e831fe65b10199e1e301a7316c66d6ced133712dTom Tucker rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds svc_putu32(resv, rqstp->rq_xid); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10977699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan vers = svc_getnl(argv); 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First words of reply: */ 11007699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 1); /* REPLY */ 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vers != 2) /* RPC version number */ 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_bad_rpc; 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Save position in case we later decide to reject: */ 11068f8e05c5708d7e9017c47f395f8b1498f7f52922J.Bruce Fields reply_statp = resv->iov_base + resv->iov_len; 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11087699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 0); /* ACCEPT */ 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11107699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan rqstp->rq_prog = prog = svc_getnl(argv); /* program number */ 11117699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan rqstp->rq_vers = vers = svc_getnl(argv); /* version number */ 11127699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan rqstp->rq_proc = proc = svc_getnl(argv); /* procedure number */ 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111480d188a643b0f550a2aaedf7bf4dd1abd86cfc45NeilBrown for (progp = serv->sv_program; progp; progp = progp->pg_next) 111580d188a643b0f550a2aaedf7bf4dd1abd86cfc45NeilBrown if (prog == progp->pg_prog) 111680d188a643b0f550a2aaedf7bf4dd1abd86cfc45NeilBrown break; 111780d188a643b0f550a2aaedf7bf4dd1abd86cfc45NeilBrown 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Decode auth data, and add verifier to reply buffer. 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We do this before anything else in order to get a decent 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * auth verifier. 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds auth_res = svc_authenticate(rqstp, &auth_stat); 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Also give the program a chance to reject this call: */ 112580d188a643b0f550a2aaedf7bf4dd1abd86cfc45NeilBrown if (auth_res == SVC_OK && progp) { 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds auth_stat = rpc_autherr_badcred; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds auth_res = progp->pg_authenticate(rqstp); 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (auth_res) { 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SVC_OK: 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SVC_GARBAGE: 1133dd35210e1e2cb46d6dba5c97f1bc3784c4f97998Harshula Jayasuriya goto err_garbage; 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SVC_SYSERR: 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpc_stat = rpc_system_err; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_bad; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SVC_DENIED: 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_bad_auth; 11391ebede86b8abbcf8833830e18e05391758cf2f28NeilBrown case SVC_CLOSE: 11401ebede86b8abbcf8833830e18e05391758cf2f28NeilBrown if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) 11411ebede86b8abbcf8833830e18e05391758cf2f28NeilBrown svc_close_xprt(rqstp->rq_xprt); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SVC_DROP: 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto dropit; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SVC_COMPLETE: 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 114780d188a643b0f550a2aaedf7bf4dd1abd86cfc45NeilBrown 11489ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher if (progp == NULL) 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_bad_prog; 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vers >= progp->pg_nvers || 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(versp = progp->pg_vers[vers])) 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_bad_vers; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds procp = versp->vs_proc + proc; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (proc >= versp->vs_nproc || !procp->pc_func) 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_bad_proc; 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rqstp->rq_procinfo = procp; 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Syntactic check complete */ 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpccnt++; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Build the reply header. */ 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds statp = resv->iov_base +resv->iov_len; 11657699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, RPC_SUCCESS); 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Bump per-procedure stats counter */ 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds procp->pc_count++; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize storage for argp and resp */ 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(rqstp->rq_argp, 0, procp->pc_argsize); 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(rqstp->rq_resp, 0, procp->pc_ressize); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1174cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki /* un-reserve some of the out-queue now that we have a 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * better idea of reply size 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (procp->pc_xdrressize) 1178cd123012d99fde4759500fee611e724e4f3016e3Jeff Layton svc_reserve_auth(rqstp, procp->pc_xdrressize<<2); 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Call the function that processes the request. */ 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!versp->vs_dispatch) { 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Decode arguments */ 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xdr = procp->pc_decode; 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (xdr && !xdr(rqstp, argv->iov_base, rqstp->rq_argp)) 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_garbage; 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Encode reply */ 11909e701c610923aaeac8b38b9202a686d1cc9ee35dJ. Bruce Fields if (rqstp->rq_dropme) { 1191d343fce148a4eee24a907a05c4101d3268045aaeNeilBrown if (procp->pc_release) 1192d343fce148a4eee24a907a05c4101d3268045aaeNeilBrown procp->pc_release(rqstp, NULL, rqstp->rq_resp); 1193d343fce148a4eee24a907a05c4101d3268045aaeNeilBrown goto dropit; 1194d343fce148a4eee24a907a05c4101d3268045aaeNeilBrown } 1195f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches if (*statp == rpc_success && 1196f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches (xdr = procp->pc_encode) && 1197f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) { 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("svc: failed to encode reply\n"); 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* serv->sv_stats->rpcsystemerr++; */ 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *statp = rpc_system_err; 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("svc: calling dispatcher\n"); 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!versp->vs_dispatch(rqstp, statp)) { 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Release reply info */ 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (procp->pc_release) 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds procp->pc_release(rqstp, NULL, rqstp->rq_resp); 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto dropit; 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check RPC status result */ 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*statp != rpc_success) 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resv->iov_len = ((void*)statp) - resv->iov_base + 4; 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Release reply info */ 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (procp->pc_release) 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds procp->pc_release(rqstp, NULL, rqstp->rq_resp); 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (procp->pc_encode == NULL) 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto dropit; 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sendit: 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (svc_authorise(rqstp)) 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto dropit; 12261cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga return 1; /* Caller can now send it */ 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dropit: 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds svc_authorise(rqstp); /* doesn't hurt to call this twice */ 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("svc: svc_process dropit\n"); 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_short_len: 1234354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert svc_printk(rqstp, "short len %Zd, dropping request\n", 1235354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert argv->iov_len); 123634e9a63b4f3e169b583f6ba2e26356ecbf932fbaNeilBrown 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto dropit; /* drop request */ 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_bad_rpc: 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpcbadfmt++; 12417699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 1); /* REJECT */ 12427699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 0); /* RPC_MISMATCH */ 12437699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 2); /* Only RPCv2 supported */ 12447699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 2); 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_bad_auth: 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat)); 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpcbadauth++; 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restore write pointer to location of accept status: */ 12518f8e05c5708d7e9017c47f395f8b1498f7f52922J.Bruce Fields xdr_ressize_check(rqstp, reply_statp); 12527699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 1); /* REJECT */ 12537699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, 1); /* AUTH_ERROR */ 12547699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, ntohl(auth_stat)); /* status */ 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_bad_prog: 12589ba02638e4be28dd4ff724202a640264427c62d1Andreas Gruenbacher dprintk("svc: unknown program %d\n", prog); 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpcbadfmt++; 12607699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, RPC_PROG_UNAVAIL); 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_bad_vers: 1264354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", 126534e9a63b4f3e169b583f6ba2e26356ecbf932fbaNeilBrown vers, prog, progp->pg_name); 126634e9a63b4f3e169b583f6ba2e26356ecbf932fbaNeilBrown 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpcbadfmt++; 12687699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, RPC_PROG_MISMATCH); 12697699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, progp->pg_lovers); 12707699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, progp->pg_hivers); 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_bad_proc: 1274354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert svc_printk(rqstp, "unknown procedure (%d)\n", proc); 127534e9a63b4f3e169b583f6ba2e26356ecbf932fbaNeilBrown 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpcbadfmt++; 12777699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, RPC_PROC_UNAVAIL); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_garbage: 1281354ecbb9dd89c21708b319da8c4ffd3dd6e6811dDr. David Alan Gilbert svc_printk(rqstp, "failed to decode args\n"); 128234e9a63b4f3e169b583f6ba2e26356ecbf932fbaNeilBrown 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpc_stat = rpc_garbage_args; 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_bad: 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serv->sv_stats->rpcbadfmt++; 12867699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan svc_putnl(resv, ntohl(rpc_stat)); 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto sendit; 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 128924c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_process); 12907adae489fe794e3e203ff168595f635d0b845e59Greg Banks 12917adae489fe794e3e203ff168595f635d0b845e59Greg Banks/* 12921cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga * Process the RPC request. 12931cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga */ 12941cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiagaint 12951cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiagasvc_process(struct svc_rqst *rqstp) 12961cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga{ 12971cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga struct kvec *argv = &rqstp->rq_arg.head[0]; 12981cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga struct kvec *resv = &rqstp->rq_res.head[0]; 12991cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga struct svc_serv *serv = rqstp->rq_server; 13001cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga u32 dir; 13011cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga 13021cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga /* 13031cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga * Setup response xdr_buf. 13041cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga * Initially it has just one page 13051cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga */ 1306afc59400d6c65bad66d4ad0b2daf879cbff8e23eJ. Bruce Fields rqstp->rq_next_page = &rqstp->rq_respages[1]; 13071cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga resv->iov_base = page_address(rqstp->rq_respages[0]); 13081cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga resv->iov_len = 0; 13091cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.pages = rqstp->rq_respages + 1; 13101cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.len = 0; 13111cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.page_base = 0; 13121cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.page_len = 0; 13131cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.buflen = PAGE_SIZE; 13141cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.tail[0].iov_base = NULL; 13151cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_res.tail[0].iov_len = 0; 13161cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga 13171cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga rqstp->rq_xid = svc_getu32(argv); 13181cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga 13191cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga dir = svc_getnl(argv); 13201cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga if (dir != 0) { 13211cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga /* direction != CALL */ 13221cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga svc_printk(rqstp, "bad direction %d, dropping request\n", dir); 13231cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga serv->sv_stats->rpcbadfmt++; 13241cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga svc_drop(rqstp); 13251cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga return 0; 13261cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga } 13271cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga 13284b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson /* Returns 1 for send, 0 for drop */ 13294b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson if (svc_process_common(rqstp, argv, resv)) 13304b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson return svc_send(rqstp); 13314b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson else { 13324b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson svc_drop(rqstp); 13334b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson return 0; 13344b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson } 13351cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga} 13361cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga 13379e00abc3c20904fd6a5d888bb7023925799ec8a5Trond Myklebust#if defined(CONFIG_SUNRPC_BACKCHANNEL) 13384d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga/* 13394d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga * Process a backchannel RPC request that arrived over an existing 13404d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga * outbound connection 13414d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga */ 13424d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiagaint 13434d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiagabc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, 13444d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga struct svc_rqst *rqstp) 13454d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga{ 13464d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga struct kvec *argv = &rqstp->rq_arg.head[0]; 13474d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga struct kvec *resv = &rqstp->rq_res.head[0]; 13484d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13494d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga /* Build the svc_rqst used by the common processing routine */ 13504a19de0f4b693139bb10b7cc3cfe1f618576ba67Andy Adamson rqstp->rq_xprt = serv->sv_bc_xprt; 13514d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga rqstp->rq_xid = req->rq_xid; 13524d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga rqstp->rq_prot = req->rq_xprt->prot; 13534d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga rqstp->rq_server = serv; 13544d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13554d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga rqstp->rq_addrlen = sizeof(req->rq_xprt->addr); 13564d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); 13574d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); 13584d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); 13594d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13604d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga /* reset result send buffer "put" position */ 13614d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga resv->iov_len = 0; 13624d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13634d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga if (rqstp->rq_prot != IPPROTO_TCP) { 13644d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga printk(KERN_ERR "No support for Non-TCP transports!\n"); 13654d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga BUG(); 13664d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga } 13674d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13684d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga /* 13694d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga * Skip the next two words because they've already been 13704d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga * processed in the trasport 13714d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga */ 13724d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga svc_getu32(argv); /* XID */ 13734d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga svc_getnl(argv); /* CALLDIR */ 13744d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13754b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson /* Returns 1 for send, 0 for drop */ 13764b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson if (svc_process_common(rqstp, argv, resv)) { 13774b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson memcpy(&req->rq_snd_buf, &rqstp->rq_res, 13784b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson sizeof(req->rq_snd_buf)); 13794b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson return bc_send(req); 13804b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson } else { 1381b3b02ae5865c2dcd506322e0fc6def59a042e72fTrond Myklebust /* drop request */ 1382b3b02ae5865c2dcd506322e0fc6def59a042e72fTrond Myklebust xprt_free_bc_request(req); 13834b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson return 0; 13844b5b3ba16be1b195d2e1161746637acd4b9fed4fAndy Adamson } 13854d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga} 13860d961aa934b799ca7369db582e52952cc50c656dTrond MyklebustEXPORT_SYMBOL_GPL(bc_svc_process); 13879e00abc3c20904fd6a5d888bb7023925799ec8a5Trond Myklebust#endif /* CONFIG_SUNRPC_BACKCHANNEL */ 13884d6bbb6233c9cf23822a2f66f8470c9f40854b77Ricardo Labiaga 13891cad7ea6fe98dc414bd3df55275c147bd15ebf97Ricardo Labiaga/* 13907adae489fe794e3e203ff168595f635d0b845e59Greg Banks * Return (transport-specific) limit on the rpc payload. 13917adae489fe794e3e203ff168595f635d0b845e59Greg Banks */ 13927adae489fe794e3e203ff168595f635d0b845e59Greg Banksu32 svc_max_payload(const struct svc_rqst *rqstp) 13937adae489fe794e3e203ff168595f635d0b845e59Greg Banks{ 1394490231558e058547da4ffab6d8ce8e28771749ccTom Tucker u32 max = rqstp->rq_xprt->xpt_class->xcl_max_payload; 13957adae489fe794e3e203ff168595f635d0b845e59Greg Banks 1396c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown if (rqstp->rq_server->sv_max_payload < max) 1397c6b0a9f87b82f25fa35206ec04b5160372eabab4NeilBrown max = rqstp->rq_server->sv_max_payload; 13987adae489fe794e3e203ff168595f635d0b845e59Greg Banks return max; 13997adae489fe794e3e203ff168595f635d0b845e59Greg Banks} 14007adae489fe794e3e203ff168595f635d0b845e59Greg BanksEXPORT_SYMBOL_GPL(svc_max_payload); 1401