cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

svc_rdma.c (8299B)


      1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
      2/*
      3 * Copyright (c) 2015-2018 Oracle.  All rights reserved.
      4 * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
      5 *
      6 * This software is available to you under a choice of one of two
      7 * licenses.  You may choose to be licensed under the terms of the GNU
      8 * General Public License (GPL) Version 2, available from the file
      9 * COPYING in the main directory of this source tree, or the BSD-type
     10 * license below:
     11 *
     12 * Redistribution and use in source and binary forms, with or without
     13 * modification, are permitted provided that the following conditions
     14 * are met:
     15 *
     16 *      Redistributions of source code must retain the above copyright
     17 *      notice, this list of conditions and the following disclaimer.
     18 *
     19 *      Redistributions in binary form must reproduce the above
     20 *      copyright notice, this list of conditions and the following
     21 *      disclaimer in the documentation and/or other materials provided
     22 *      with the distribution.
     23 *
     24 *      Neither the name of the Network Appliance, Inc. nor the names of
     25 *      its contributors may be used to endorse or promote products
     26 *      derived from this software without specific prior written
     27 *      permission.
     28 *
     29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     40 *
     41 * Author: Tom Tucker <tom@opengridcomputing.com>
     42 */
     43
     44#include <linux/slab.h>
     45#include <linux/fs.h>
     46#include <linux/sysctl.h>
     47#include <linux/workqueue.h>
     48#include <linux/sunrpc/clnt.h>
     49#include <linux/sunrpc/sched.h>
     50#include <linux/sunrpc/svc_rdma.h>
     51
     52#define RPCDBG_FACILITY	RPCDBG_SVCXPRT
     53
     54/* RPC/RDMA parameters */
     55unsigned int svcrdma_ord = 16;	/* historical default */
     56static unsigned int min_ord = 1;
     57static unsigned int max_ord = 255;
     58unsigned int svcrdma_max_requests = RPCRDMA_MAX_REQUESTS;
     59unsigned int svcrdma_max_bc_requests = RPCRDMA_MAX_BC_REQUESTS;
     60static unsigned int min_max_requests = 4;
     61static unsigned int max_max_requests = 16384;
     62unsigned int svcrdma_max_req_size = RPCRDMA_DEF_INLINE_THRESH;
     63static unsigned int min_max_inline = RPCRDMA_DEF_INLINE_THRESH;
     64static unsigned int max_max_inline = RPCRDMA_MAX_INLINE_THRESH;
     65static unsigned int svcrdma_stat_unused;
     66static unsigned int zero;
     67
     68struct percpu_counter svcrdma_stat_read;
     69struct percpu_counter svcrdma_stat_recv;
     70struct percpu_counter svcrdma_stat_sq_starve;
     71struct percpu_counter svcrdma_stat_write;
     72
     73enum {
     74	SVCRDMA_COUNTER_BUFSIZ	= sizeof(unsigned long long),
     75};
     76
     77static int svcrdma_counter_handler(struct ctl_table *table, int write,
     78				   void *buffer, size_t *lenp, loff_t *ppos)
     79{
     80	struct percpu_counter *stat = (struct percpu_counter *)table->data;
     81	char tmp[SVCRDMA_COUNTER_BUFSIZ + 1];
     82	int len;
     83
     84	if (write) {
     85		percpu_counter_set(stat, 0);
     86		return 0;
     87	}
     88
     89	len = snprintf(tmp, SVCRDMA_COUNTER_BUFSIZ, "%lld\n",
     90		       percpu_counter_sum_positive(stat));
     91	if (len >= SVCRDMA_COUNTER_BUFSIZ)
     92		return -EFAULT;
     93	len = strlen(tmp);
     94	if (*ppos > len) {
     95		*lenp = 0;
     96		return 0;
     97	}
     98	len -= *ppos;
     99	if (len > *lenp)
    100		len = *lenp;
    101	if (len)
    102		memcpy(buffer, tmp, len);
    103	*lenp = len;
    104	*ppos += len;
    105
    106	return 0;
    107}
    108
    109static struct ctl_table_header *svcrdma_table_header;
    110static struct ctl_table svcrdma_parm_table[] = {
    111	{
    112		.procname	= "max_requests",
    113		.data		= &svcrdma_max_requests,
    114		.maxlen		= sizeof(unsigned int),
    115		.mode		= 0644,
    116		.proc_handler	= proc_dointvec_minmax,
    117		.extra1		= &min_max_requests,
    118		.extra2		= &max_max_requests
    119	},
    120	{
    121		.procname	= "max_req_size",
    122		.data		= &svcrdma_max_req_size,
    123		.maxlen		= sizeof(unsigned int),
    124		.mode		= 0644,
    125		.proc_handler	= proc_dointvec_minmax,
    126		.extra1		= &min_max_inline,
    127		.extra2		= &max_max_inline
    128	},
    129	{
    130		.procname	= "max_outbound_read_requests",
    131		.data		= &svcrdma_ord,
    132		.maxlen		= sizeof(unsigned int),
    133		.mode		= 0644,
    134		.proc_handler	= proc_dointvec_minmax,
    135		.extra1		= &min_ord,
    136		.extra2		= &max_ord,
    137	},
    138
    139	{
    140		.procname	= "rdma_stat_read",
    141		.data		= &svcrdma_stat_read,
    142		.maxlen		= SVCRDMA_COUNTER_BUFSIZ,
    143		.mode		= 0644,
    144		.proc_handler	= svcrdma_counter_handler,
    145	},
    146	{
    147		.procname	= "rdma_stat_recv",
    148		.data		= &svcrdma_stat_recv,
    149		.maxlen		= SVCRDMA_COUNTER_BUFSIZ,
    150		.mode		= 0644,
    151		.proc_handler	= svcrdma_counter_handler,
    152	},
    153	{
    154		.procname	= "rdma_stat_write",
    155		.data		= &svcrdma_stat_write,
    156		.maxlen		= SVCRDMA_COUNTER_BUFSIZ,
    157		.mode		= 0644,
    158		.proc_handler	= svcrdma_counter_handler,
    159	},
    160	{
    161		.procname	= "rdma_stat_sq_starve",
    162		.data		= &svcrdma_stat_sq_starve,
    163		.maxlen		= SVCRDMA_COUNTER_BUFSIZ,
    164		.mode		= 0644,
    165		.proc_handler	= svcrdma_counter_handler,
    166	},
    167	{
    168		.procname	= "rdma_stat_rq_starve",
    169		.data		= &svcrdma_stat_unused,
    170		.maxlen		= sizeof(unsigned int),
    171		.mode		= 0644,
    172		.proc_handler	= proc_dointvec_minmax,
    173		.extra1		= &zero,
    174		.extra2		= &zero,
    175	},
    176	{
    177		.procname	= "rdma_stat_rq_poll",
    178		.data		= &svcrdma_stat_unused,
    179		.maxlen		= sizeof(unsigned int),
    180		.mode		= 0644,
    181		.proc_handler	= proc_dointvec_minmax,
    182		.extra1		= &zero,
    183		.extra2		= &zero,
    184	},
    185	{
    186		.procname	= "rdma_stat_rq_prod",
    187		.data		= &svcrdma_stat_unused,
    188		.maxlen		= sizeof(unsigned int),
    189		.mode		= 0644,
    190		.proc_handler	= proc_dointvec_minmax,
    191		.extra1		= &zero,
    192		.extra2		= &zero,
    193	},
    194	{
    195		.procname	= "rdma_stat_sq_poll",
    196		.data		= &svcrdma_stat_unused,
    197		.maxlen		= sizeof(unsigned int),
    198		.mode		= 0644,
    199		.proc_handler	= proc_dointvec_minmax,
    200		.extra1		= &zero,
    201		.extra2		= &zero,
    202	},
    203	{
    204		.procname	= "rdma_stat_sq_prod",
    205		.data		= &svcrdma_stat_unused,
    206		.maxlen		= sizeof(unsigned int),
    207		.mode		= 0644,
    208		.proc_handler	= proc_dointvec_minmax,
    209		.extra1		= &zero,
    210		.extra2		= &zero,
    211	},
    212	{ },
    213};
    214
    215static struct ctl_table svcrdma_table[] = {
    216	{
    217		.procname	= "svc_rdma",
    218		.mode		= 0555,
    219		.child		= svcrdma_parm_table
    220	},
    221	{ },
    222};
    223
    224static struct ctl_table svcrdma_root_table[] = {
    225	{
    226		.procname	= "sunrpc",
    227		.mode		= 0555,
    228		.child		= svcrdma_table
    229	},
    230	{ },
    231};
    232
    233static void svc_rdma_proc_cleanup(void)
    234{
    235	if (!svcrdma_table_header)
    236		return;
    237	unregister_sysctl_table(svcrdma_table_header);
    238	svcrdma_table_header = NULL;
    239
    240	percpu_counter_destroy(&svcrdma_stat_write);
    241	percpu_counter_destroy(&svcrdma_stat_sq_starve);
    242	percpu_counter_destroy(&svcrdma_stat_recv);
    243	percpu_counter_destroy(&svcrdma_stat_read);
    244}
    245
    246static int svc_rdma_proc_init(void)
    247{
    248	int rc;
    249
    250	if (svcrdma_table_header)
    251		return 0;
    252
    253	rc = percpu_counter_init(&svcrdma_stat_read, 0, GFP_KERNEL);
    254	if (rc)
    255		goto out_err;
    256	rc = percpu_counter_init(&svcrdma_stat_recv, 0, GFP_KERNEL);
    257	if (rc)
    258		goto out_err;
    259	rc = percpu_counter_init(&svcrdma_stat_sq_starve, 0, GFP_KERNEL);
    260	if (rc)
    261		goto out_err;
    262	rc = percpu_counter_init(&svcrdma_stat_write, 0, GFP_KERNEL);
    263	if (rc)
    264		goto out_err;
    265
    266	svcrdma_table_header = register_sysctl_table(svcrdma_root_table);
    267	return 0;
    268
    269out_err:
    270	percpu_counter_destroy(&svcrdma_stat_sq_starve);
    271	percpu_counter_destroy(&svcrdma_stat_recv);
    272	percpu_counter_destroy(&svcrdma_stat_read);
    273	return rc;
    274}
    275
    276void svc_rdma_cleanup(void)
    277{
    278	dprintk("SVCRDMA Module Removed, deregister RPC RDMA transport\n");
    279	svc_unreg_xprt_class(&svc_rdma_class);
    280	svc_rdma_proc_cleanup();
    281}
    282
    283int svc_rdma_init(void)
    284{
    285	int rc;
    286
    287	dprintk("SVCRDMA Module Init, register RPC RDMA transport\n");
    288	dprintk("\tsvcrdma_ord      : %d\n", svcrdma_ord);
    289	dprintk("\tmax_requests     : %u\n", svcrdma_max_requests);
    290	dprintk("\tmax_bc_requests  : %u\n", svcrdma_max_bc_requests);
    291	dprintk("\tmax_inline       : %d\n", svcrdma_max_req_size);
    292
    293	rc = svc_rdma_proc_init();
    294	if (rc)
    295		return rc;
    296
    297	/* Register RDMA with the SVC transport switch */
    298	svc_reg_xprt_class(&svc_rdma_class);
    299	return 0;
    300}