// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (c) 2014-2017 Oracle. All rights reserved. * 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/slab.h> #include <linux/seq_file.h> #include <linux/smp.h> #include <linux/sunrpc/addr.h> #include <linux/sunrpc/svc_rdma.h> #include "xprt_rdma.h" #include <trace/events/rpcrdma.h> /* * tunables */ static unsigned int xprt_rdma_slot_table_entries = …; unsigned int xprt_rdma_max_inline_read = …; unsigned int xprt_rdma_max_inline_write = …; unsigned int xprt_rdma_memreg_strategy = …; int xprt_rdma_pad_optimize; static struct xprt_class xprt_rdma; #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) static unsigned int min_slot_table_size = …; static unsigned int max_slot_table_size = …; static unsigned int min_inline_size = …; static unsigned int max_inline_size = …; static unsigned int max_padding = …; static unsigned int min_memreg = …; static unsigned int max_memreg = …; static unsigned int dummy; static struct ctl_table_header *sunrpc_table_header; static struct ctl_table xr_tunables_table[] = …; #endif static const struct rpc_xprt_ops xprt_rdma_procs; static void xprt_rdma_format_addresses4(struct rpc_xprt *xprt, struct sockaddr *sap) { … } static void xprt_rdma_format_addresses6(struct rpc_xprt *xprt, struct sockaddr *sap) { … } void xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap) { … } void xprt_rdma_free_addresses(struct rpc_xprt *xprt) { … } /** * xprt_rdma_connect_worker - establish connection in the background * @work: worker thread context * * Requester holds the xprt's send lock to prevent activity on this * transport while a fresh connection is being established. RPC tasks * sleep on the xprt's pending queue waiting for connect to complete. */ static void xprt_rdma_connect_worker(struct work_struct *work) { … } /** * xprt_rdma_inject_disconnect - inject a connection fault * @xprt: transport context * * If @xprt is connected, disconnect it to simulate spurious * connection loss. Caller must hold @xprt's send lock to * ensure that data structures and hardware resources are * stable during the rdma_disconnect() call. */ static void xprt_rdma_inject_disconnect(struct rpc_xprt *xprt) { … } /** * xprt_rdma_destroy - Full tear down of transport * @xprt: doomed transport context * * Caller guarantees there will be no more calls to us with * this @xprt. */ static void xprt_rdma_destroy(struct rpc_xprt *xprt) { … } /* 60 second timeout, no retries */ static const struct rpc_timeout xprt_rdma_default_timeout = …; /** * xprt_setup_rdma - Set up transport to use RDMA * * @args: rpc transport arguments */ static struct rpc_xprt * xprt_setup_rdma(struct xprt_create *args) { … } /** * xprt_rdma_close - close a transport connection * @xprt: transport context * * Called during autoclose or device removal. * * Caller holds @xprt's send lock to prevent activity on this * transport while the connection is torn down. */ void xprt_rdma_close(struct rpc_xprt *xprt) { … } /** * xprt_rdma_set_port - update server port with rpcbind result * @xprt: controlling RPC transport * @port: new port value * * Transport connect status is unchanged. */ static void xprt_rdma_set_port(struct rpc_xprt *xprt, u16 port) { … } /** * xprt_rdma_timer - invoked when an RPC times out * @xprt: controlling RPC transport * @task: RPC task that timed out * * Invoked when the transport is still connected, but an RPC * retransmit timeout occurs. * * Since RDMA connections don't have a keep-alive, forcibly * disconnect and retry to connect. This drives full * detection of the network path, and retransmissions of * all pending RPCs. */ static void xprt_rdma_timer(struct rpc_xprt *xprt, struct rpc_task *task) { … } /** * xprt_rdma_set_connect_timeout - set timeouts for establishing a connection * @xprt: controlling transport instance * @connect_timeout: reconnect timeout after client disconnects * @reconnect_timeout: reconnect timeout after server disconnects * */ static void xprt_rdma_set_connect_timeout(struct rpc_xprt *xprt, unsigned long connect_timeout, unsigned long reconnect_timeout) { … } /** * xprt_rdma_connect - schedule an attempt to reconnect * @xprt: transport state * @task: RPC scheduler context (unused) * */ static void xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task) { … } /** * xprt_rdma_alloc_slot - allocate an rpc_rqst * @xprt: controlling RPC transport * @task: RPC task requesting a fresh rpc_rqst * * tk_status values: * %0 if task->tk_rqstp points to a fresh rpc_rqst * %-EAGAIN if no rpc_rqst is available; queued on backlog */ static void xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) { … } /** * xprt_rdma_free_slot - release an rpc_rqst * @xprt: controlling RPC transport * @rqst: rpc_rqst to release * */ static void xprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst) { … } static bool rpcrdma_check_regbuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_regbuf *rb, size_t size, gfp_t flags) { … } /** * xprt_rdma_allocate - allocate transport resources for an RPC * @task: RPC task * * Return values: * 0: Success; rq_buffer points to RPC buffer to use * ENOMEM: Out of memory, call again later * EIO: A permanent error occurred, do not retry */ static int xprt_rdma_allocate(struct rpc_task *task) { … } /** * xprt_rdma_free - release resources allocated by xprt_rdma_allocate * @task: RPC task * * Caller guarantees rqst->rq_buffer is non-NULL. */ static void xprt_rdma_free(struct rpc_task *task) { … } /** * xprt_rdma_send_request - marshal and send an RPC request * @rqst: RPC message in rq_snd_buf * * Caller holds the transport's write lock. * * Returns: * %0 if the RPC message has been sent * %-ENOTCONN if the caller should reconnect and call again * %-EAGAIN if the caller should call again * %-ENOBUFS if the caller should call again after a delay * %-EMSGSIZE if encoding ran out of buffer space. The request * was not sent. Do not try to send this message again. * %-EIO if an I/O error occurred. The request was not sent. * Do not try to send this message again. */ static int xprt_rdma_send_request(struct rpc_rqst *rqst) { … } void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) { … } static int xprt_rdma_enable_swap(struct rpc_xprt *xprt) { … } static void xprt_rdma_disable_swap(struct rpc_xprt *xprt) { … } /* * Plumbing for rpc transport switch and kernel module */ static const struct rpc_xprt_ops xprt_rdma_procs = …; static struct xprt_class xprt_rdma = …; void xprt_rdma_cleanup(void) { … } int xprt_rdma_init(void) { … }