linux/net/sunrpc/clnt.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 *  linux/net/sunrpc/clnt.c
 *
 *  This file contains the high-level RPC interface.
 *  It is modeled as a finite state machine to support both synchronous
 *  and asynchronous requests.
 *
 *  -	RPC header generation and argument serialization.
 *  -	Credential refresh.
 *  -	TCP connect handling.
 *  -	Retry of operation when it is suspected the operation failed because
 *	of uid squashing on the server, or when the credentials were stale
 *	and need to be refreshed, or when a packet was damaged in transit.
 *	This may be have to be moved to the VFS layer.
 *
 *  Copyright (C) 1992,1993 Rick Sladkey <[email protected]>
 *  Copyright (C) 1995,1996 Olaf Kirch <[email protected]>
 */


#include <linux/module.h>
#include <linux/types.h>
#include <linux/kallsyms.h>
#include <linux/mm.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/slab.h>
#include <linux/rcupdate.h>
#include <linux/utsname.h>
#include <linux/workqueue.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/un.h>

#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/addr.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/sunrpc/metrics.h>
#include <linux/sunrpc/bc_xprt.h>
#include <trace/events/sunrpc.h>

#include "sunrpc.h"
#include "sysfs.h"
#include "netns.h"

#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
#define RPCDBG_FACILITY
#endif

/*
 * All RPC clients are linked into this list
 */

static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);


static void	call_start(struct rpc_task *task);
static void	call_reserve(struct rpc_task *task);
static void	call_reserveresult(struct rpc_task *task);
static void	call_allocate(struct rpc_task *task);
static void	call_encode(struct rpc_task *task);
static void	call_decode(struct rpc_task *task);
static void	call_bind(struct rpc_task *task);
static void	call_bind_status(struct rpc_task *task);
static void	call_transmit(struct rpc_task *task);
static void	call_status(struct rpc_task *task);
static void	call_transmit_status(struct rpc_task *task);
static void	call_refresh(struct rpc_task *task);
static void	call_refreshresult(struct rpc_task *task);
static void	call_connect(struct rpc_task *task);
static void	call_connect_status(struct rpc_task *task);

static int	rpc_encode_header(struct rpc_task *task,
				  struct xdr_stream *xdr);
static int	rpc_decode_header(struct rpc_task *task,
				  struct xdr_stream *xdr);
static int	rpc_ping(struct rpc_clnt *clnt);
static int	rpc_ping_noreply(struct rpc_clnt *clnt);
static void	rpc_check_timeout(struct rpc_task *task);

static void rpc_register_client(struct rpc_clnt *clnt)
{}

static void rpc_unregister_client(struct rpc_clnt *clnt)
{}

static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
{}

static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
{}

static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
				    struct rpc_clnt *clnt)
{}

static int
rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
{}

static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
{}

static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
				   struct super_block *sb)
{}

static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
				struct super_block *sb)
{}

static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
{}

static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
			    void *ptr)
{}

static struct notifier_block rpc_clients_block =;

int rpc_clients_notifier_register(void)
{}

void rpc_clients_notifier_unregister(void)
{}

static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt,
		const struct rpc_timeout *timeout)
{}

static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
{}

static int rpc_client_register(struct rpc_clnt *clnt,
			       rpc_authflavor_t pseudoflavor,
			       const char *client_name)
{}

static DEFINE_IDA(rpc_clids);

void rpc_cleanup_clids(void)
{}

static int rpc_alloc_clid(struct rpc_clnt *clnt)
{}

static void rpc_free_clid(struct rpc_clnt *clnt)
{}

static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
		struct rpc_xprt_switch *xps,
		struct rpc_xprt *xprt,
		struct rpc_clnt *parent)
{}

static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
					struct rpc_xprt *xprt)
{}

/**
 * rpc_create - create an RPC client and transport with one call
 * @args: rpc_clnt create argument structure
 *
 * Creates and initializes an RPC transport and an RPC client.
 *
 * It can ping the server in order to determine if it is up, and to see if
 * it supports this program and version.  RPC_CLNT_CREATE_NOPING disables
 * this behavior so asynchronous tasks can also use rpc_create.
 */
struct rpc_clnt *rpc_create(struct rpc_create_args *args)
{}
EXPORT_SYMBOL_GPL();

/*
 * This function clones the RPC client structure. It allows us to share the
 * same transport while varying parameters such as the authentication
 * flavour.
 */
static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
					   struct rpc_clnt *clnt)
{}

/**
 * rpc_clone_client - Clone an RPC client structure
 *
 * @clnt: RPC client whose parameters are copied
 *
 * Returns a fresh RPC client or an ERR_PTR.
 */
struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth
 *
 * @clnt: RPC client whose parameters are copied
 * @flavor: security flavor for new client
 *
 * Returns a fresh RPC client or an ERR_PTR.
 */
struct rpc_clnt *
rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_switch_client_transport: switch the RPC transport on the fly
 * @clnt: pointer to a struct rpc_clnt
 * @args: pointer to the new transport arguments
 * @timeout: pointer to the new timeout parameters
 *
 * This function allows the caller to switch the RPC transport for the
 * rpc_clnt structure 'clnt' to allow it to connect to a mirrored NFS
 * server, for instance.  It assumes that the caller has ensured that
 * there are no active RPC tasks by using some form of locking.
 *
 * Returns zero if "clnt" is now using the new xprt.  Otherwise a
 * negative errno is returned, and "clnt" continues to use the old
 * xprt.
 */
int rpc_switch_client_transport(struct rpc_clnt *clnt,
		struct xprt_create *args,
		const struct rpc_timeout *timeout)
{}
EXPORT_SYMBOL_GPL();

static struct rpc_xprt_switch *rpc_clnt_xprt_switch_get(struct rpc_clnt *clnt)
{}

static
int _rpc_clnt_xprt_iter_init(struct rpc_clnt *clnt, struct rpc_xprt_iter *xpi,
			     void func(struct rpc_xprt_iter *xpi, struct rpc_xprt_switch *xps))
{}

static
int rpc_clnt_xprt_iter_init(struct rpc_clnt *clnt, struct rpc_xprt_iter *xpi)
{}

static
int rpc_clnt_xprt_iter_offline_init(struct rpc_clnt *clnt,
				    struct rpc_xprt_iter *xpi)
{}

/**
 * rpc_clnt_iterate_for_each_xprt - Apply a function to all transports
 * @clnt: pointer to client
 * @fn: function to apply
 * @data: void pointer to function data
 *
 * Iterates through the list of RPC transports currently attached to the
 * client and applies the function fn(clnt, xprt, data).
 *
 * On error, the iteration stops, and the function returns the error value.
 */
int rpc_clnt_iterate_for_each_xprt(struct rpc_clnt *clnt,
		int (*fn)(struct rpc_clnt *, struct rpc_xprt *, void *),
		void *data)
{}
EXPORT_SYMBOL_GPL();

/*
 * Kill all tasks for the given client.
 * XXX: kill their descendants as well?
 */
void rpc_killall_tasks(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_cancel_tasks - try to cancel a set of RPC tasks
 * @clnt: Pointer to RPC client
 * @error: RPC task error value to set
 * @fnmatch: Pointer to selector function
 * @data: User data
 *
 * Uses @fnmatch to define a set of RPC tasks that are to be cancelled.
 * The argument @error must be a negative error value.
 */
unsigned long rpc_cancel_tasks(struct rpc_clnt *clnt, int error,
			       bool (*fnmatch)(const struct rpc_task *,
					       const void *),
			       const void *data)
{}
EXPORT_SYMBOL_GPL();

static int rpc_clnt_disconnect_xprt(struct rpc_clnt *clnt,
				    struct rpc_xprt *xprt, void *dummy)
{}

void rpc_clnt_disconnect(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/*
 * Properly shut down an RPC client, terminating all outstanding
 * requests.
 */
void rpc_shutdown_client(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/*
 * Free an RPC client
 */
static void rpc_free_client_work(struct work_struct *work)
{}
static struct rpc_clnt *
rpc_free_client(struct rpc_clnt *clnt)
{}

/*
 * Free an RPC client
 */
static struct rpc_clnt *
rpc_free_auth(struct rpc_clnt *clnt)
{}

/*
 * Release reference to the RPC client
 */
void
rpc_release_client(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_bind_new_program - bind a new RPC program to an existing client
 * @old: old rpc_client
 * @program: rpc program to set
 * @vers: rpc program version
 *
 * Clones the rpc client and sets up a new RPC program. This is mainly
 * of use for enabling different RPC programs to share the same transport.
 * The Sun NFSv2/v3 ACL protocol can do this.
 */
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
				      const struct rpc_program *program,
				      u32 vers)
{}
EXPORT_SYMBOL_GPL();

struct rpc_xprt *
rpc_task_get_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
{}

static void
rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
{}

void rpc_task_release_transport(struct rpc_task *task)
{}
EXPORT_SYMBOL_GPL();

void rpc_task_release_client(struct rpc_task *task)
{}

static struct rpc_xprt *
rpc_task_get_first_xprt(struct rpc_clnt *clnt)
{}

static struct rpc_xprt *
rpc_task_get_next_xprt(struct rpc_clnt *clnt)
{}

static
void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
{}

static
void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
{}

static void
rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg)
{}

/*
 * Default callback for async RPC calls
 */
static void
rpc_default_callback(struct rpc_task *task, void *data)
{}

static const struct rpc_call_ops rpc_default_ops =;

/**
 * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
 * @task_setup_data: pointer to task initialisation data
 */
struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_call_sync - Perform a synchronous RPC call
 * @clnt: pointer to RPC client
 * @msg: RPC call parameters
 * @flags: RPC call flags
 */
int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_call_async - Perform an asynchronous RPC call
 * @clnt: pointer to RPC client
 * @msg: RPC call parameters
 * @flags: RPC call flags
 * @tk_ops: RPC call ops
 * @data: user call data
 */
int
rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
	       const struct rpc_call_ops *tk_ops, void *data)
{}
EXPORT_SYMBOL_GPL();

#if defined(CONFIG_SUNRPC_BACKCHANNEL)
static void call_bc_encode(struct rpc_task *task);

/**
 * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
 * rpc_execute against it
 * @req: RPC request
 * @timeout: timeout values to use for this task
 */
struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
		struct rpc_timeout *timeout)
{}
#endif /* CONFIG_SUNRPC_BACKCHANNEL */

/**
 * rpc_prepare_reply_pages - Prepare to receive a reply data payload into pages
 * @req: RPC request to prepare
 * @pages: vector of struct page pointers
 * @base: offset in first page where receive should start, in bytes
 * @len: expected size of the upper layer data payload, in bytes
 * @hdrsize: expected size of upper layer reply header, in XDR words
 *
 */
void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages,
			     unsigned int base, unsigned int len,
			     unsigned int hdrsize)
{}
EXPORT_SYMBOL_GPL();

void
rpc_call_start(struct rpc_task *task)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_peeraddr - extract remote peer address from clnt's xprt
 * @clnt: RPC client structure
 * @buf: target buffer
 * @bufsize: length of target buffer
 *
 * Returns the number of bytes that are actually in the stored address.
 */
size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_peeraddr2str - return remote peer address in printable format
 * @clnt: RPC client structure
 * @format: address format
 *
 * NB: the lifetime of the memory referenced by the returned pointer is
 * the same as the rpc_xprt itself.  As long as the caller uses this
 * pointer, it must hold the RCU read lock.
 */
const char *rpc_peeraddr2str(struct rpc_clnt *clnt,
			     enum rpc_display_format_t format)
{}
EXPORT_SYMBOL_GPL();

static const struct sockaddr_in rpc_inaddr_loopback =;

static const struct sockaddr_in6 rpc_in6addr_loopback =;

/*
 * Try a getsockname() on a connected datagram socket.  Using a
 * connected datagram socket prevents leaving a socket in TIME_WAIT.
 * This conserves the ephemeral port number space.
 *
 * Returns zero and fills in "buf" if successful; otherwise, a
 * negative errno is returned.
 */
static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen,
			struct sockaddr *buf)
{}

/*
 * Scraping a connected socket failed, so we don't have a useable
 * local address.  Fallback: generate an address that will prevent
 * the server from calling us back.
 *
 * Returns zero and fills in "buf" if successful; otherwise, a
 * negative errno is returned.
 */
static int rpc_anyaddr(int family, struct sockaddr *buf, size_t buflen)
{}

/**
 * rpc_localaddr - discover local endpoint address for an RPC client
 * @clnt: RPC client structure
 * @buf: target buffer
 * @buflen: size of target buffer, in bytes
 *
 * Returns zero and fills in "buf" and "buflen" if successful;
 * otherwise, a negative errno is returned.
 *
 * This works even if the underlying transport is not currently connected,
 * or if the upper layer never previously provided a source address.
 *
 * The result of this function call is transient: multiple calls in
 * succession may give different results, depending on how local
 * networking configuration changes over time.
 */
int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen)
{}
EXPORT_SYMBOL_GPL();

void
rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_net_ns - Get the network namespace for this RPC client
 * @clnt: RPC client to query
 *
 */
struct net *rpc_net_ns(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_max_payload - Get maximum payload size for a transport, in bytes
 * @clnt: RPC client to query
 *
 * For stream transports, this is one RPC record fragment (see RFC
 * 1831), as we don't support multi-record requests yet.  For datagram
 * transports, this is the size of an IP packet minus the IP, UDP, and
 * RPC header sizes.
 */
size_t rpc_max_payload(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_max_bc_payload - Get maximum backchannel payload size, in bytes
 * @clnt: RPC client to query
 */
size_t rpc_max_bc_payload(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

unsigned int rpc_num_bc_slots(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_force_rebind - force transport to check that remote port is unchanged
 * @clnt: client to rebind
 *
 */
void rpc_force_rebind(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

static int
__rpc_restart_call(struct rpc_task *task, void (*action)(struct rpc_task *))
{}

/*
 * Restart an (async) RPC call. Usually called from within the
 * exit handler.
 */
int
rpc_restart_call(struct rpc_task *task)
{}
EXPORT_SYMBOL_GPL();

/*
 * Restart an (async) RPC call from the call_prepare state.
 * Usually called from within the exit handler.
 */
int
rpc_restart_call_prepare(struct rpc_task *task)
{}
EXPORT_SYMBOL_GPL();

const char
*rpc_proc_name(const struct rpc_task *task)
{}

static void
__rpc_call_rpcerror(struct rpc_task *task, int tk_status, int rpc_status)
{}

static void
rpc_call_rpcerror(struct rpc_task *task, int status)
{}

/*
 * 0.  Initial state
 *
 *     Other FSM states can be visited zero or more times, but
 *     this state is visited exactly once for each RPC.
 */
static void
call_start(struct rpc_task *task)
{}

/*
 * 1.	Reserve an RPC call slot
 */
static void
call_reserve(struct rpc_task *task)
{}

static void call_retry_reserve(struct rpc_task *task);

/*
 * 1b.	Grok the result of xprt_reserve()
 */
static void
call_reserveresult(struct rpc_task *task)
{}

/*
 * 1c.	Retry reserving an RPC call slot
 */
static void
call_retry_reserve(struct rpc_task *task)
{}

/*
 * 2.	Bind and/or refresh the credentials
 */
static void
call_refresh(struct rpc_task *task)
{}

/*
 * 2a.	Process the results of a credential refresh
 */
static void
call_refreshresult(struct rpc_task *task)
{}

/*
 * 2b.	Allocate the buffer. For details, see sched.c:rpc_malloc.
 *	(Note: buffer memory is freed in xprt_release).
 */
static void
call_allocate(struct rpc_task *task)
{}

static int
rpc_task_need_encode(struct rpc_task *task)
{}

static void
rpc_xdr_encode(struct rpc_task *task)
{}

/*
 * 3.	Encode arguments of an RPC call
 */
static void
call_encode(struct rpc_task *task)
{}

/*
 * Helpers to check if the task was already transmitted, and
 * to take action when that is the case.
 */
static bool
rpc_task_transmitted(struct rpc_task *task)
{}

static void
rpc_task_handle_transmitted(struct rpc_task *task)
{}

/*
 * 4.	Get the server port number if not yet set
 */
static void
call_bind(struct rpc_task *task)
{}

/*
 * 4a.	Sort out bind result
 */
static void
call_bind_status(struct rpc_task *task)
{}

/*
 * 4b.	Connect to the RPC server
 */
static void
call_connect(struct rpc_task *task)
{}

/*
 * 4c.	Sort out connect result
 */
static void
call_connect_status(struct rpc_task *task)
{}

/*
 * 5.	Transmit the RPC request, and wait for reply
 */
static void
call_transmit(struct rpc_task *task)
{}

/*
 * 5a.	Handle cleanup after a transmission
 */
static void
call_transmit_status(struct rpc_task *task)
{}

#if defined(CONFIG_SUNRPC_BACKCHANNEL)
static void call_bc_transmit(struct rpc_task *task);
static void call_bc_transmit_status(struct rpc_task *task);

static void
call_bc_encode(struct rpc_task *task)
{}

/*
 * 5b.	Send the backchannel RPC reply.  On error, drop the reply.  In
 * addition, disconnect on connectivity errors.
 */
static void
call_bc_transmit(struct rpc_task *task)
{}

static void
call_bc_transmit_status(struct rpc_task *task)
{}
#endif /* CONFIG_SUNRPC_BACKCHANNEL */

/*
 * 6.	Sort out the RPC call status
 */
static void
call_status(struct rpc_task *task)
{}

static bool
rpc_check_connected(const struct rpc_rqst *req)
{}

static void
rpc_check_timeout(struct rpc_task *task)
{}

/*
 * 7.	Decode the RPC reply
 */
static void
call_decode(struct rpc_task *task)
{}

static int
rpc_encode_header(struct rpc_task *task, struct xdr_stream *xdr)
{}

static noinline int
rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
{}

static void rpcproc_encode_null(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
		const void *obj)
{}

static int rpcproc_decode_null(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
		void *obj)
{}

static const struct rpc_procinfo rpcproc_null =;

static const struct rpc_procinfo rpcproc_null_noreply =;

static void
rpc_null_call_prepare(struct rpc_task *task, void *data)
{}

static const struct rpc_call_ops rpc_null_ops =;

static
struct rpc_task *rpc_call_null_helper(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt, struct rpc_cred *cred, int flags,
		const struct rpc_call_ops *ops, void *data)
{}

struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
{}
EXPORT_SYMBOL_GPL();

static int rpc_ping(struct rpc_clnt *clnt)
{}

static int rpc_ping_noreply(struct rpc_clnt *clnt)
{}

struct rpc_cb_add_xprt_calldata {};

static void rpc_cb_add_xprt_done(struct rpc_task *task, void *calldata)
{}

static void rpc_cb_add_xprt_release(void *calldata)
{}

static const struct rpc_call_ops rpc_cb_add_xprt_call_ops =;

/**
 * rpc_clnt_test_and_add_xprt - Test and add a new transport to a rpc_clnt
 * @clnt: pointer to struct rpc_clnt
 * @xps: pointer to struct rpc_xprt_switch,
 * @xprt: pointer struct rpc_xprt
 * @in_max_connect: pointer to the max_connect value for the passed in xprt transport
 */
int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
		struct rpc_xprt_switch *xps, struct rpc_xprt *xprt,
		void *in_max_connect)
{}
EXPORT_SYMBOL_GPL();

static int rpc_clnt_add_xprt_helper(struct rpc_clnt *clnt,
				    struct rpc_xprt *xprt,
				    struct rpc_add_xprt_test *data)
{}

/**
 * rpc_clnt_setup_test_and_add_xprt()
 *
 * This is an rpc_clnt_add_xprt setup() function which returns 1 so:
 *   1) caller of the test function must dereference the rpc_xprt_switch
 *   and the rpc_xprt.
 *   2) test function must call rpc_xprt_switch_add_xprt, usually in
 *   the rpc_call_done routine.
 *
 * Upon success (return of 1), the test function adds the new
 * transport to the rpc_clnt xprt switch
 *
 * @clnt: struct rpc_clnt to get the new transport
 * @xps:  the rpc_xprt_switch to hold the new transport
 * @xprt: the rpc_xprt to test
 * @data: a struct rpc_add_xprt_test pointer that holds the test function
 *        and test function call data
 */
int rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *clnt,
				     struct rpc_xprt_switch *xps,
				     struct rpc_xprt *xprt,
				     void *data)
{}
EXPORT_SYMBOL_GPL();

/**
 * rpc_clnt_add_xprt - Add a new transport to a rpc_clnt
 * @clnt: pointer to struct rpc_clnt
 * @xprtargs: pointer to struct xprt_create
 * @setup: callback to test and/or set up the connection
 * @data: pointer to setup function data
 *
 * Creates a new transport using the parameters set in args and
 * adds it to clnt.
 * If ping is set, then test that connectivity succeeds before
 * adding the new transport.
 *
 */
int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
		struct xprt_create *xprtargs,
		int (*setup)(struct rpc_clnt *,
			struct rpc_xprt_switch *,
			struct rpc_xprt *,
			void *),
		void *data)
{}
EXPORT_SYMBOL_GPL();

static int rpc_xprt_probe_trunked(struct rpc_clnt *clnt,
				  struct rpc_xprt *xprt,
				  struct rpc_add_xprt_test *data)
{}

/* rpc_clnt_probe_trunked_xprt -- probe offlined transport for session trunking
 * @clnt rpc_clnt structure
 *
 * For each offlined transport found in the rpc_clnt structure call
 * the function rpc_xprt_probe_trunked() which will determine if this
 * transport still belongs to the trunking group.
 */
void rpc_clnt_probe_trunked_xprts(struct rpc_clnt *clnt,
				  struct rpc_add_xprt_test *data)
{}
EXPORT_SYMBOL_GPL();

static int rpc_xprt_offline(struct rpc_clnt *clnt,
			    struct rpc_xprt *xprt,
			    void *data)
{}

/* rpc_clnt_manage_trunked_xprts -- offline trunked transports
 * @clnt rpc_clnt structure
 *
 * For each active transport found in the rpc_clnt structure call
 * the function rpc_xprt_offline() which will identify trunked transports
 * and will mark them offline.
 */
void rpc_clnt_manage_trunked_xprts(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

struct connect_timeout_data {};

static int
rpc_xprt_set_connect_timeout(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt,
		void *data)
{}

void
rpc_set_connect_timeout(struct rpc_clnt *clnt,
		unsigned long connect_timeout,
		unsigned long reconnect_timeout)
{}
EXPORT_SYMBOL_GPL();

void rpc_clnt_xprt_set_online(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
{}

void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

void rpc_clnt_xprt_switch_remove_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt,
				   const struct sockaddr *sap)
{}
EXPORT_SYMBOL_GPL();

#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
static void rpc_show_header(void)
{}

static void rpc_show_task(const struct rpc_clnt *clnt,
			  const struct rpc_task *task)
{}

void rpc_show_tasks(struct net *net)
{}
#endif

#if IS_ENABLED(CONFIG_SUNRPC_SWAP)
static int
rpc_clnt_swap_activate_callback(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt,
		void *dummy)
{}

int
rpc_clnt_swap_activate(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();

static int
rpc_clnt_swap_deactivate_callback(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt,
		void *dummy)
{}

void
rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
{}
EXPORT_SYMBOL_GPL();
#endif /* CONFIG_SUNRPC_SWAP */