linux/net/sunrpc/xprtrdma/svc_rdma.c
<<
>>
Prefs
   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}
 301