📄 transport.c
字号:
/* * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the BSD-type * license below: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the Network Appliance, Inc. nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* * transport.c * * This file contains the top-level implementation of an RPC RDMA * transport. * * Naming convention: functions beginning with xprt_ are part of the * transport switch. All others are RPC RDMA internal. */#include <linux/module.h>#include <linux/init.h>#include <linux/seq_file.h>#include "xprt_rdma.h"#ifdef RPC_DEBUG# define RPCDBG_FACILITY RPCDBG_TRANS#endifMODULE_LICENSE("Dual BSD/GPL");MODULE_DESCRIPTION("RPC/RDMA Transport for Linux kernel NFS");MODULE_AUTHOR("Network Appliance, Inc.");/* * tunables */static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE;static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE;static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE;static unsigned int xprt_rdma_inline_write_padding;#if !RPCRDMA_PERSISTENT_REGISTRATIONstatic unsigned int xprt_rdma_memreg_strategy = RPCRDMA_REGISTER; /* FMR? */#elsestatic unsigned int xprt_rdma_memreg_strategy = RPCRDMA_ALLPHYSICAL;#endif#ifdef RPC_DEBUGstatic unsigned int min_slot_table_size = RPCRDMA_MIN_SLOT_TABLE;static unsigned int max_slot_table_size = RPCRDMA_MAX_SLOT_TABLE;static unsigned int zero;static unsigned int max_padding = PAGE_SIZE;static unsigned int min_memreg = RPCRDMA_BOUNCEBUFFERS;static unsigned int max_memreg = RPCRDMA_LAST - 1;static struct ctl_table_header *sunrpc_table_header;static ctl_table xr_tunables_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "rdma_slot_table_entries", .data = &xprt_rdma_slot_table_entries, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_minmax, .strategy = &sysctl_intvec, .extra1 = &min_slot_table_size, .extra2 = &max_slot_table_size }, { .ctl_name = CTL_UNNUMBERED, .procname = "rdma_max_inline_read", .data = &xprt_rdma_max_inline_read, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec, .strategy = &sysctl_intvec, }, { .ctl_name = CTL_UNNUMBERED, .procname = "rdma_max_inline_write", .data = &xprt_rdma_max_inline_write, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec, .strategy = &sysctl_intvec, }, { .ctl_name = CTL_UNNUMBERED, .procname = "rdma_inline_write_padding", .data = &xprt_rdma_inline_write_padding, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_minmax, .strategy = &sysctl_intvec, .extra1 = &zero, .extra2 = &max_padding, }, { .ctl_name = CTL_UNNUMBERED, .procname = "rdma_memreg_strategy", .data = &xprt_rdma_memreg_strategy, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_minmax, .strategy = &sysctl_intvec, .extra1 = &min_memreg, .extra2 = &max_memreg, }, { .ctl_name = 0, },};static ctl_table sunrpc_table[] = { { .ctl_name = CTL_SUNRPC, .procname = "sunrpc", .mode = 0555, .child = xr_tunables_table }, { .ctl_name = 0, },};#endifstatic struct rpc_xprt_ops xprt_rdma_procs; /* forward reference */static voidxprt_rdma_format_addresses(struct rpc_xprt *xprt){ struct sockaddr_in *addr = (struct sockaddr_in *) &rpcx_to_rdmad(xprt).addr; char *buf; buf = kzalloc(20, GFP_KERNEL); if (buf) snprintf(buf, 20, NIPQUAD_FMT, NIPQUAD(addr->sin_addr.s_addr)); xprt->address_strings[RPC_DISPLAY_ADDR] = buf; buf = kzalloc(8, GFP_KERNEL); if (buf) snprintf(buf, 8, "%u", ntohs(addr->sin_port)); xprt->address_strings[RPC_DISPLAY_PORT] = buf; xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; buf = kzalloc(48, GFP_KERNEL); if (buf) snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", NIPQUAD(addr->sin_addr.s_addr), ntohs(addr->sin_port), "rdma"); xprt->address_strings[RPC_DISPLAY_ALL] = buf; buf = kzalloc(10, GFP_KERNEL); if (buf) snprintf(buf, 10, "%02x%02x%02x%02x", NIPQUAD(addr->sin_addr.s_addr)); xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; buf = kzalloc(8, GFP_KERNEL); if (buf) snprintf(buf, 8, "%4hx", ntohs(addr->sin_port)); xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; buf = kzalloc(30, GFP_KERNEL); if (buf) snprintf(buf, 30, NIPQUAD_FMT".%u.%u", NIPQUAD(addr->sin_addr.s_addr), ntohs(addr->sin_port) >> 8, ntohs(addr->sin_port) & 0xff); xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; /* netid */ xprt->address_strings[RPC_DISPLAY_NETID] = "rdma";}static voidxprt_rdma_free_addresses(struct rpc_xprt *xprt){ kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); kfree(xprt->address_strings[RPC_DISPLAY_PORT]); kfree(xprt->address_strings[RPC_DISPLAY_ALL]); kfree(xprt->address_strings[RPC_DISPLAY_HEX_ADDR]); kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]); kfree(xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR]);}static voidxprt_rdma_connect_worker(struct work_struct *work){ struct rpcrdma_xprt *r_xprt = container_of(work, struct rpcrdma_xprt, rdma_connect.work); struct rpc_xprt *xprt = &r_xprt->xprt; int rc = 0; if (!xprt->shutdown) { xprt_clear_connected(xprt); dprintk("RPC: %s: %sconnect\n", __func__, r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); if (rc) goto out; } goto out_clear;out: xprt_wake_pending_tasks(xprt, rc);out_clear: dprintk("RPC: %s: exit\n", __func__); xprt_clear_connecting(xprt);}/* * xprt_rdma_destroy * * Destroy the xprt. * Free all memory associated with the object, including its own. * NOTE: none of the *destroy methods free memory for their top-level * objects, even though they may have allocated it (they do free * private memory). It's up to the caller to handle it. In this * case (RDMA transport), all structure memory is inlined with the * struct rpcrdma_xprt. */static voidxprt_rdma_destroy(struct rpc_xprt *xprt){ struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); int rc; dprintk("RPC: %s: called\n", __func__); cancel_delayed_work(&r_xprt->rdma_connect); flush_scheduled_work(); xprt_clear_connected(xprt); rpcrdma_buffer_destroy(&r_xprt->rx_buf); rc = rpcrdma_ep_destroy(&r_xprt->rx_ep, &r_xprt->rx_ia); if (rc) dprintk("RPC: %s: rpcrdma_ep_destroy returned %i\n", __func__, rc); rpcrdma_ia_close(&r_xprt->rx_ia); xprt_rdma_free_addresses(xprt); kfree(xprt->slot); xprt->slot = NULL; kfree(xprt); dprintk("RPC: %s: returning\n", __func__); module_put(THIS_MODULE);}/** * xprt_setup_rdma - Set up transport to use RDMA * * @args: rpc transport arguments */static struct rpc_xprt *xprt_setup_rdma(struct xprt_create *args){ struct rpcrdma_create_data_internal cdata; struct rpc_xprt *xprt; struct rpcrdma_xprt *new_xprt; struct rpcrdma_ep *new_ep; struct sockaddr_in *sin; int rc; if (args->addrlen > sizeof(xprt->addr)) { dprintk("RPC: %s: address too large\n", __func__); return ERR_PTR(-EBADF); } xprt = kzalloc(sizeof(struct rpcrdma_xprt), GFP_KERNEL); if (xprt == NULL) { dprintk("RPC: %s: couldn't allocate rpcrdma_xprt\n", __func__); return ERR_PTR(-ENOMEM); } xprt->max_reqs = xprt_rdma_slot_table_entries; xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL); if (xprt->slot == NULL) { dprintk("RPC: %s: couldn't allocate %d slots\n", __func__, xprt->max_reqs); kfree(xprt); return ERR_PTR(-ENOMEM); } /* 60 second timeout, no retries */ xprt_set_timeout(&xprt->timeout, 0, 60UL * HZ); xprt->bind_timeout = (60U * HZ); xprt->connect_timeout = (60U * HZ); xprt->reestablish_timeout = (5U * HZ); xprt->idle_timeout = (5U * 60 * HZ); xprt->resvport = 0; /* privileged port not needed */ xprt->tsh_size = 0; /* RPC-RDMA handles framing */ xprt->max_payload = RPCRDMA_MAX_DATA_SEGS * PAGE_SIZE; xprt->ops = &xprt_rdma_procs; /* * Set up RDMA-specific connect data. */ /* Put server RDMA address in local cdata */ memcpy(&cdata.addr, args->dstaddr, args->addrlen); /* Ensure xprt->addr holds valid server TCP (not RDMA) * address, for any side protocols which peek at it */ xprt->prot = IPPROTO_TCP; xprt->addrlen = args->addrlen; memcpy(&xprt->addr, &cdata.addr, xprt->addrlen); sin = (struct sockaddr_in *)&cdata.addr; if (ntohs(sin->sin_port) != 0) xprt_set_bound(xprt); dprintk("RPC: %s: %u.%u.%u.%u:%u\n", __func__, NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); /* Set max requests */ cdata.max_requests = xprt->max_reqs; /* Set some length limits */ cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */ cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */ cdata.inline_wsize = xprt_rdma_max_inline_write; if (cdata.inline_wsize > cdata.wsize) cdata.inline_wsize = cdata.wsize; cdata.inline_rsize = xprt_rdma_max_inline_read; if (cdata.inline_rsize > cdata.rsize) cdata.inline_rsize = cdata.rsize; cdata.padding = xprt_rdma_inline_write_padding; /* * Create new transport instance, which includes initialized * o ia * o endpoint * o buffers */ new_xprt = rpcx_to_rdmax(xprt); rc = rpcrdma_ia_open(new_xprt, (struct sockaddr *) &cdata.addr, xprt_rdma_memreg_strategy); if (rc) goto out1; /* * initialize and create ep */ new_xprt->rx_data = cdata; new_ep = &new_xprt->rx_ep; new_ep->rep_remote_addr = cdata.addr; rc = rpcrdma_ep_create(&new_xprt->rx_ep, &new_xprt->rx_ia, &new_xprt->rx_data); if (rc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -