linux/net/sunrpc/svc_xprt.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/net/sunrpc/svc_xprt.c
 *
 * Author: Tom Tucker <[email protected]>
 */

#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/errno.h>
#include <linux/freezer.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <linux/sunrpc/addr.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svc_xprt.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/xprt.h>
#include <linux/sunrpc/bc_xprt.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <trace/events/sunrpc.h>

#define RPCDBG_FACILITY

static unsigned int svc_rpc_per_connection_limit __read_mostly;
module_param(svc_rpc_per_connection_limit, uint, 0644);


static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
static int svc_deferred_recv(struct svc_rqst *rqstp);
static struct cache_deferred_req *svc_defer(struct cache_req *req);
static void svc_age_temp_xprts(struct timer_list *t);
static void svc_delete_xprt(struct svc_xprt *xprt);

/* apparently the "standard" is that clients close
 * idle connections after 5 minutes, servers after
 * 6 minutes
 *   http://nfsv4bat.org/Documents/ConnectAThon/1996/nfstcp.pdf
 */
static int svc_conn_age_period =;

/* List of registered transport classes */
static DEFINE_SPINLOCK(svc_xprt_class_lock);
static LIST_HEAD(svc_xprt_class_list);

/* SMP locking strategy:
 *
 *	svc_serv->sv_lock protects sv_tempsocks, sv_permsocks, sv_tmpcnt.
 *	when both need to be taken (rare), svc_serv->sv_lock is first.
 *	The "service mutex" protects svc_serv->sv_nrthread.
 *	svc_sock->sk_lock protects the svc_sock->sk_deferred list
 *             and the ->sk_info_authunix cache.
 *
 *	The XPT_BUSY bit in xprt->xpt_flags prevents a transport being
 *	enqueued multiply. During normal transport processing this bit
 *	is set by svc_xprt_enqueue and cleared by svc_xprt_received.
 *	Providers should not manipulate this bit directly.
 *
 *	Some flags can be set to certain values at any time
 *	providing that certain rules are followed:
 *
 *	XPT_CONN, XPT_DATA:
 *		- Can be set or cleared at any time.
 *		- After a set, svc_xprt_enqueue must be called to enqueue
 *		  the transport for processing.
 *		- After a clear, the transport must be read/accepted.
 *		  If this succeeds, it must be set again.
 *	XPT_CLOSE:
 *		- Can set at any time. It is never cleared.
 *      XPT_DEAD:
 *		- Can only be set while XPT_BUSY is held which ensures
 *		  that no other thread will be using the transport or will
 *		  try to set XPT_DEAD.
 */

/**
 * svc_reg_xprt_class - Register a server-side RPC transport class
 * @xcl: New transport class to be registered
 *
 * Returns zero on success; otherwise a negative errno is returned.
 */
int svc_reg_xprt_class(struct svc_xprt_class *xcl)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_unreg_xprt_class - Unregister a server-side RPC transport class
 * @xcl: Transport class to be unregistered
 *
 */
void svc_unreg_xprt_class(struct svc_xprt_class *xcl)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_print_xprts - Format the transport list for printing
 * @buf: target buffer for formatted address
 * @maxlen: length of target buffer
 *
 * Fills in @buf with a string containing a list of transport names, each name
 * terminated with '\n'. If the buffer is too small, some entries may be
 * missing, but it is guaranteed that all lines in the output buffer are
 * complete.
 *
 * Returns positive length of the filled-in string.
 */
int svc_print_xprts(char *buf, int maxlen)
{}

/**
 * svc_xprt_deferred_close - Close a transport
 * @xprt: transport instance
 *
 * Used in contexts that need to defer the work of shutting down
 * the transport to an nfsd thread.
 */
void svc_xprt_deferred_close(struct svc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

static void svc_xprt_free(struct kref *kref)
{}

void svc_xprt_put(struct svc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

/*
 * Called by transport drivers to initialize the transport independent
 * portion of the transport instance.
 */
void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl,
		   struct svc_xprt *xprt, struct svc_serv *serv)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_xprt_received - start next receiver thread
 * @xprt: controlling transport
 *
 * The caller must hold the XPT_BUSY bit and must
 * not thereafter touch transport data.
 *
 * Note: XPT_DATA only gets cleared when a read-attempt finds no (or
 * insufficient) data.
 */
void svc_xprt_received(struct svc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
{}

static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
			    struct net *net, struct sockaddr *sap,
			    size_t len, int flags, const struct cred *cred)
{}

/**
 * svc_xprt_create_from_sa - Add a new listener to @serv from socket address
 * @serv: target RPC service
 * @xprt_name: transport class name
 * @net: network namespace
 * @sap: socket address pointer
 * @flags: SVC_SOCK flags
 * @cred: credential to bind to this transport
 *
 * Return local xprt port on success or %-EPROTONOSUPPORT on failure
 */
int svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name,
			    struct net *net, struct sockaddr *sap,
			    int flags, const struct cred *cred)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_xprt_create - Add a new listener to @serv
 * @serv: target RPC service
 * @xprt_name: transport class name
 * @net: network namespace
 * @family: network address family
 * @port: listener port
 * @flags: SVC_SOCK flags
 * @cred: credential to bind to this transport
 *
 * Return local xprt port on success or %-EPROTONOSUPPORT on failure
 */
int svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
		    struct net *net, const int family,
		    const unsigned short port, int flags,
		    const struct cred *cred)
{}
EXPORT_SYMBOL_GPL();

/*
 * Copy the local and remote xprt addresses to the rqstp structure
 */
void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_print_addr - Format rq_addr field for printing
 * @rqstp: svc_rqst struct containing address to print
 * @buf: target buffer for formatted address
 * @len: length of target buffer
 *
 */
char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)
{}
EXPORT_SYMBOL_GPL();

static bool svc_xprt_slots_in_range(struct svc_xprt *xprt)
{}

static bool svc_xprt_reserve_slot(struct svc_rqst *rqstp, struct svc_xprt *xprt)
{}

static void svc_xprt_release_slot(struct svc_rqst *rqstp)
{}

static bool svc_xprt_ready(struct svc_xprt *xprt)
{}

/**
 * svc_xprt_enqueue - Queue a transport on an idle nfsd thread
 * @xprt: transport with data pending
 *
 */
void svc_xprt_enqueue(struct svc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

/*
 * Dequeue the first transport, if there is one.
 */
static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
{}

/**
 * svc_reserve - change the space reserved for the reply to a request.
 * @rqstp:  The request in question
 * @space: new max space to reserve
 *
 * Each request reserves some space on the output queue of the transport
 * to make sure the reply fits.  This function reduces that reserved
 * space to be the amount of space used already, plus @space.
 *
 */
void svc_reserve(struct svc_rqst *rqstp, int space)
{}
EXPORT_SYMBOL_GPL();

static void free_deferred(struct svc_xprt *xprt, struct svc_deferred_req *dr)
{}

static void svc_xprt_release(struct svc_rqst *rqstp)
{}

/**
 * svc_wake_up - Wake up a service thread for non-transport work
 * @serv: RPC service
 *
 * Some svc_serv's will have occasional work to do, even when a xprt is not
 * waiting to be serviced. This function is there to "kick" a task in one of
 * those services so that it can wake up and do that work. Note that we only
 * bother with pool 0 as we don't need to wake up more than one thread for
 * this purpose.
 */
void svc_wake_up(struct svc_serv *serv)
{}
EXPORT_SYMBOL_GPL();

int svc_port_is_privileged(struct sockaddr *sin)
{}

/*
 * Make sure that we don't have too many active connections. If we have,
 * something must be dropped. It's not clear what will happen if we allow
 * "too many" connections, but when dealing with network-facing software,
 * we have to code defensively. Here we do that by imposing hard limits.
 *
 * There's no point in trying to do random drop here for DoS
 * prevention. The NFS clients does 1 reconnect in 15 seconds. An
 * attacker can easily beat that.
 *
 * The only somewhat efficient mechanism would be if drop old
 * connections from the same IP first. But right now we don't even
 * record the client IP in svc_sock.
 *
 * single-threaded services that expect a lot of clients will probably
 * need to set sv_maxconn to override the default value which is based
 * on the number of threads
 */
static void svc_check_conn_limits(struct svc_serv *serv)
{}

static bool svc_alloc_arg(struct svc_rqst *rqstp)
{}

static bool
svc_thread_should_sleep(struct svc_rqst *rqstp)
{}

static void svc_thread_wait_for_work(struct svc_rqst *rqstp)
{}

static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt)
{}

static void svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
{}

static void svc_thread_wake_next(struct svc_rqst *rqstp)
{}

/**
 * svc_recv - Receive and process the next request on any transport
 * @rqstp: an idle RPC service thread
 *
 * This code is carefully organised not to touch any cachelines in
 * the shared svc_serv structure, only cachelines in the local
 * svc_pool.
 */
void svc_recv(struct svc_rqst *rqstp)
{}
EXPORT_SYMBOL_GPL();

/*
 * Drop request
 */
void svc_drop(struct svc_rqst *rqstp)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_send - Return reply to client
 * @rqstp: RPC transaction context
 *
 */
void svc_send(struct svc_rqst *rqstp)
{}

/*
 * Timer function to close old temporary transports, using
 * a mark-and-sweep algorithm.
 */
static void svc_age_temp_xprts(struct timer_list *t)
{}

/* Close temporary transports whose xpt_local matches server_addr immediately
 * instead of waiting for them to be picked up by the timer.
 *
 * This is meant to be called from a notifier_block that runs when an ip
 * address is deleted.
 */
void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
{}
EXPORT_SYMBOL_GPL();

static void call_xpt_users(struct svc_xprt *xprt)
{}

/*
 * Remove a dead transport
 */
static void svc_delete_xprt(struct svc_xprt *xprt)
{}

/**
 * svc_xprt_close - Close a client connection
 * @xprt: transport to disconnect
 *
 */
void svc_xprt_close(struct svc_xprt *xprt)
{}
EXPORT_SYMBOL_GPL();

static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
{}

static void svc_clean_up_xprts(struct svc_serv *serv, struct net *net)
{}

/**
 * svc_xprt_destroy_all - Destroy transports associated with @serv
 * @serv: RPC service to be shut down
 * @net: target network namespace
 *
 * Server threads may still be running (especially in the case where the
 * service is still running in other network namespaces).
 *
 * So we shut down sockets the same way we would on a running server, by
 * setting XPT_CLOSE, enqueuing, and letting a thread pick it up to do
 * the close.  In the case there are no such other threads,
 * threads running, svc_clean_up_xprts() does a simple version of a
 * server's main event loop, and in the case where there are other
 * threads, we may need to wait a little while and then check again to
 * see if they're done.
 */
void svc_xprt_destroy_all(struct svc_serv *serv, struct net *net)
{}
EXPORT_SYMBOL_GPL();

/*
 * Handle defer and revisit of requests
 */

static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
{}

/*
 * Save the request off for later processing. The request buffer looks
 * like this:
 *
 * <xprt-header><rpc-header><rpc-pagelist><rpc-tail>
 *
 * This code can only handle requests that consist of an xprt-header
 * and rpc-header.
 */
static struct cache_deferred_req *svc_defer(struct cache_req *req)
{}

/*
 * recv data from a deferred request into an active one
 */
static noinline int svc_deferred_recv(struct svc_rqst *rqstp)
{}


static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt)
{}

/**
 * svc_find_listener - find an RPC transport instance
 * @serv: pointer to svc_serv to search
 * @xcl_name: C string containing transport's class name
 * @net: owner net pointer
 * @sa: sockaddr containing address
 *
 * Return the transport instance pointer for the endpoint accepting
 * connections/peer traffic from the specified transport class,
 * and matching sockaddr.
 */
struct svc_xprt *svc_find_listener(struct svc_serv *serv, const char *xcl_name,
				   struct net *net, const struct sockaddr *sa)
{}
EXPORT_SYMBOL_GPL();

/**
 * svc_find_xprt - find an RPC transport instance
 * @serv: pointer to svc_serv to search
 * @xcl_name: C string containing transport's class name
 * @net: owner net pointer
 * @af: Address family of transport's local address
 * @port: transport's IP port number
 *
 * Return the transport instance pointer for the endpoint accepting
 * connections/peer traffic from the specified transport class,
 * address family and port.
 *
 * Specifying 0 for the address family or port is effectively a
 * wild-card, and will result in matching the first transport in the
 * service's list that has a matching class name.
 */
struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
			       struct net *net, const sa_family_t af,
			       const unsigned short port)
{}
EXPORT_SYMBOL_GPL();

static int svc_one_xprt_name(const struct svc_xprt *xprt,
			     char *pos, int remaining)
{}

/**
 * svc_xprt_names - format a buffer with a list of transport names
 * @serv: pointer to an RPC service
 * @buf: pointer to a buffer to be filled in
 * @buflen: length of buffer to be filled in
 *
 * Fills in @buf with a string containing a list of transport names,
 * each name terminated with '\n'.
 *
 * Returns positive length of the filled-in string on success; otherwise
 * a negative errno value is returned if an error occurs.
 */
int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen)
{}
EXPORT_SYMBOL_GPL();

/*----------------------------------------------------------------------------*/

static void *svc_pool_stats_start(struct seq_file *m, loff_t *pos)
{}

static void *svc_pool_stats_next(struct seq_file *m, void *p, loff_t *pos)
{}

static void svc_pool_stats_stop(struct seq_file *m, void *p)
{}

static int svc_pool_stats_show(struct seq_file *m, void *p)
{}

static const struct seq_operations svc_pool_stats_seq_ops =;

int svc_pool_stats_open(struct svc_info *info, struct file *file)
{}
EXPORT_SYMBOL();

/*----------------------------------------------------------------------------*/