⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -