mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-08 17:18:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
170
include/linux/sunrpc/addr.h
Normal file
170
include/linux/sunrpc/addr.h
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/addr.h
|
||||
*
|
||||
* Various routines for copying and comparing sockaddrs and for
|
||||
* converting them to and from presentation format.
|
||||
*/
|
||||
#ifndef _LINUX_SUNRPC_ADDR_H
|
||||
#define _LINUX_SUNRPC_ADDR_H
|
||||
|
||||
#include <linux/socket.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
size_t rpc_ntop(const struct sockaddr *, char *, const size_t);
|
||||
size_t rpc_pton(struct net *, const char *, const size_t,
|
||||
struct sockaddr *, const size_t);
|
||||
char * rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t);
|
||||
size_t rpc_uaddr2sockaddr(struct net *, const char *, const size_t,
|
||||
struct sockaddr *, const size_t);
|
||||
|
||||
static inline unsigned short rpc_get_port(const struct sockaddr *sap)
|
||||
{
|
||||
switch (sap->sa_family) {
|
||||
case AF_INET:
|
||||
return ntohs(((struct sockaddr_in *)sap)->sin_port);
|
||||
case AF_INET6:
|
||||
return ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rpc_set_port(struct sockaddr *sap,
|
||||
const unsigned short port)
|
||||
{
|
||||
switch (sap->sa_family) {
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)sap)->sin_port = htons(port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define IPV6_SCOPE_DELIMITER '%'
|
||||
#define IPV6_SCOPE_ID_LEN sizeof("%nnnnnnnnnn")
|
||||
|
||||
static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1,
|
||||
const struct sockaddr *sap2)
|
||||
{
|
||||
const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1;
|
||||
const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2;
|
||||
|
||||
return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
static inline bool __rpc_copy_addr4(struct sockaddr *dst,
|
||||
const struct sockaddr *src)
|
||||
{
|
||||
const struct sockaddr_in *ssin = (struct sockaddr_in *) src;
|
||||
struct sockaddr_in *dsin = (struct sockaddr_in *) dst;
|
||||
|
||||
dsin->sin_family = ssin->sin_family;
|
||||
dsin->sin_addr.s_addr = ssin->sin_addr.s_addr;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
|
||||
const struct sockaddr *sap2)
|
||||
{
|
||||
const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1;
|
||||
const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
|
||||
|
||||
if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
|
||||
return false;
|
||||
else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL)
|
||||
return sin1->sin6_scope_id == sin2->sin6_scope_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool __rpc_copy_addr6(struct sockaddr *dst,
|
||||
const struct sockaddr *src)
|
||||
{
|
||||
const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src;
|
||||
struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst;
|
||||
|
||||
dsin6->sin6_family = ssin6->sin6_family;
|
||||
dsin6->sin6_addr = ssin6->sin6_addr;
|
||||
dsin6->sin6_scope_id = ssin6->sin6_scope_id;
|
||||
return true;
|
||||
}
|
||||
#else /* !(IS_ENABLED(CONFIG_IPV6) */
|
||||
static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
|
||||
const struct sockaddr *sap2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __rpc_copy_addr6(struct sockaddr *dst,
|
||||
const struct sockaddr *src)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* !(IS_ENABLED(CONFIG_IPV6) */
|
||||
|
||||
/**
|
||||
* rpc_cmp_addr - compare the address portion of two sockaddrs.
|
||||
* @sap1: first sockaddr
|
||||
* @sap2: second sockaddr
|
||||
*
|
||||
* Just compares the family and address portion. Ignores port, but
|
||||
* compares the scope if it's a link-local address.
|
||||
*
|
||||
* Returns true if the addrs are equal, false if they aren't.
|
||||
*/
|
||||
static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
|
||||
const struct sockaddr *sap2)
|
||||
{
|
||||
if (sap1->sa_family == sap2->sa_family) {
|
||||
switch (sap1->sa_family) {
|
||||
case AF_INET:
|
||||
return __rpc_cmp_addr4(sap1, sap2);
|
||||
case AF_INET6:
|
||||
return __rpc_cmp_addr6(sap1, sap2);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpc_copy_addr - copy the address portion of one sockaddr to another
|
||||
* @dst: destination sockaddr
|
||||
* @src: source sockaddr
|
||||
*
|
||||
* Just copies the address portion and family. Ignores port, scope, etc.
|
||||
* Caller is responsible for making certain that dst is large enough to hold
|
||||
* the address in src. Returns true if address family is supported. Returns
|
||||
* false otherwise.
|
||||
*/
|
||||
static inline bool rpc_copy_addr(struct sockaddr *dst,
|
||||
const struct sockaddr *src)
|
||||
{
|
||||
switch (src->sa_family) {
|
||||
case AF_INET:
|
||||
return __rpc_copy_addr4(dst, src);
|
||||
case AF_INET6:
|
||||
return __rpc_copy_addr6(dst, src);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpc_get_scope_id - return scopeid for a given sockaddr
|
||||
* @sa: sockaddr to get scopeid from
|
||||
*
|
||||
* Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if
|
||||
* not an AF_INET6 address.
|
||||
*/
|
||||
static inline u32 rpc_get_scope_id(const struct sockaddr *sa)
|
||||
{
|
||||
if (sa->sa_family != AF_INET6)
|
||||
return 0;
|
||||
|
||||
return ((struct sockaddr_in6 *) sa)->sin6_scope_id;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_SUNRPC_ADDR_H */
|
198
include/linux/sunrpc/auth.h
Normal file
198
include/linux/sunrpc/auth.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/auth.h
|
||||
*
|
||||
* Declarations for the RPC client authentication machinery.
|
||||
*
|
||||
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_AUTH_H
|
||||
#define _LINUX_SUNRPC_AUTH_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/sunrpc/sched.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/uidgid.h>
|
||||
|
||||
/* size of the nodename buffer */
|
||||
#define UNX_MAXNODENAME 32
|
||||
|
||||
struct rpcsec_gss_info;
|
||||
|
||||
/* auth_cred ac_flags bits */
|
||||
enum {
|
||||
RPC_CRED_NO_CRKEY_TIMEOUT = 0, /* underlying cred has no key timeout */
|
||||
RPC_CRED_KEY_EXPIRE_SOON = 1, /* underlying cred key will expire soon */
|
||||
RPC_CRED_NOTIFY_TIMEOUT = 2, /* nofity generic cred when underlying
|
||||
key will expire soon */
|
||||
};
|
||||
|
||||
/* Work around the lack of a VFS credential */
|
||||
struct auth_cred {
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
struct group_info *group_info;
|
||||
const char *principal;
|
||||
unsigned long ac_flags;
|
||||
unsigned char machine_cred : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Client user credentials
|
||||
*/
|
||||
struct rpc_auth;
|
||||
struct rpc_credops;
|
||||
struct rpc_cred {
|
||||
struct hlist_node cr_hash; /* hash chain */
|
||||
struct list_head cr_lru; /* lru garbage collection */
|
||||
struct rcu_head cr_rcu;
|
||||
struct rpc_auth * cr_auth;
|
||||
const struct rpc_credops *cr_ops;
|
||||
#ifdef RPC_DEBUG
|
||||
unsigned long cr_magic; /* 0x0f4aa4f0 */
|
||||
#endif
|
||||
unsigned long cr_expire; /* when to gc */
|
||||
unsigned long cr_flags; /* various flags */
|
||||
atomic_t cr_count; /* ref count */
|
||||
|
||||
kuid_t cr_uid;
|
||||
|
||||
/* per-flavor data */
|
||||
};
|
||||
#define RPCAUTH_CRED_NEW 0
|
||||
#define RPCAUTH_CRED_UPTODATE 1
|
||||
#define RPCAUTH_CRED_HASHED 2
|
||||
#define RPCAUTH_CRED_NEGATIVE 3
|
||||
|
||||
#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0
|
||||
|
||||
/*
|
||||
* Client authentication handle
|
||||
*/
|
||||
struct rpc_cred_cache;
|
||||
struct rpc_authops;
|
||||
struct rpc_auth {
|
||||
unsigned int au_cslack; /* call cred size estimate */
|
||||
/* guess at number of u32's auth adds before
|
||||
* reply data; normally the verifier size: */
|
||||
unsigned int au_rslack;
|
||||
/* for gss, used to calculate au_rslack: */
|
||||
unsigned int au_verfsize;
|
||||
|
||||
unsigned int au_flags; /* various flags */
|
||||
const struct rpc_authops *au_ops; /* operations */
|
||||
rpc_authflavor_t au_flavor; /* pseudoflavor (note may
|
||||
* differ from the flavor in
|
||||
* au_ops->au_flavor in gss
|
||||
* case) */
|
||||
atomic_t au_count; /* Reference counter */
|
||||
|
||||
struct rpc_cred_cache * au_credcache;
|
||||
/* per-flavor data */
|
||||
};
|
||||
|
||||
struct rpc_auth_create_args {
|
||||
rpc_authflavor_t pseudoflavor;
|
||||
const char *target_name;
|
||||
};
|
||||
|
||||
/* Flags for rpcauth_lookupcred() */
|
||||
#define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */
|
||||
#define RPCAUTH_LOOKUP_RCU 0x02 /* lock-less lookup */
|
||||
|
||||
/*
|
||||
* Client authentication ops
|
||||
*/
|
||||
struct rpc_authops {
|
||||
struct module *owner;
|
||||
rpc_authflavor_t au_flavor; /* flavor (RPC_AUTH_*) */
|
||||
char * au_name;
|
||||
struct rpc_auth * (*create)(struct rpc_auth_create_args *, struct rpc_clnt *);
|
||||
void (*destroy)(struct rpc_auth *);
|
||||
|
||||
struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
|
||||
struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
|
||||
int (*list_pseudoflavors)(rpc_authflavor_t *, int);
|
||||
rpc_authflavor_t (*info2flavor)(struct rpcsec_gss_info *);
|
||||
int (*flavor2info)(rpc_authflavor_t,
|
||||
struct rpcsec_gss_info *);
|
||||
int (*key_timeout)(struct rpc_auth *,
|
||||
struct rpc_cred *);
|
||||
};
|
||||
|
||||
struct rpc_credops {
|
||||
const char * cr_name; /* Name of the auth flavour */
|
||||
int (*cr_init)(struct rpc_auth *, struct rpc_cred *);
|
||||
void (*crdestroy)(struct rpc_cred *);
|
||||
|
||||
int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
|
||||
struct rpc_cred * (*crbind)(struct rpc_task *, struct rpc_cred *, int);
|
||||
__be32 * (*crmarshal)(struct rpc_task *, __be32 *);
|
||||
int (*crrefresh)(struct rpc_task *);
|
||||
__be32 * (*crvalidate)(struct rpc_task *, __be32 *);
|
||||
int (*crwrap_req)(struct rpc_task *, kxdreproc_t,
|
||||
void *, __be32 *, void *);
|
||||
int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t,
|
||||
void *, __be32 *, void *);
|
||||
int (*crkey_timeout)(struct rpc_cred *);
|
||||
bool (*crkey_to_expire)(struct rpc_cred *);
|
||||
char * (*crstringify_acceptor)(struct rpc_cred *);
|
||||
};
|
||||
|
||||
extern const struct rpc_authops authunix_ops;
|
||||
extern const struct rpc_authops authnull_ops;
|
||||
|
||||
int __init rpc_init_authunix(void);
|
||||
int __init rpc_init_generic_auth(void);
|
||||
int __init rpcauth_init_module(void);
|
||||
void rpcauth_remove_module(void);
|
||||
void rpc_destroy_generic_auth(void);
|
||||
void rpc_destroy_authunix(void);
|
||||
|
||||
struct rpc_cred * rpc_lookup_cred(void);
|
||||
struct rpc_cred * rpc_lookup_cred_nonblock(void);
|
||||
struct rpc_cred * rpc_lookup_machine_cred(const char *service_name);
|
||||
int rpcauth_register(const struct rpc_authops *);
|
||||
int rpcauth_unregister(const struct rpc_authops *);
|
||||
struct rpc_auth * rpcauth_create(struct rpc_auth_create_args *,
|
||||
struct rpc_clnt *);
|
||||
void rpcauth_release(struct rpc_auth *);
|
||||
rpc_authflavor_t rpcauth_get_pseudoflavor(rpc_authflavor_t,
|
||||
struct rpcsec_gss_info *);
|
||||
int rpcauth_get_gssinfo(rpc_authflavor_t,
|
||||
struct rpcsec_gss_info *);
|
||||
int rpcauth_list_flavors(rpc_authflavor_t *, int);
|
||||
struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
|
||||
void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
|
||||
struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
|
||||
struct rpc_cred * rpcauth_generic_bind_cred(struct rpc_task *, struct rpc_cred *, int);
|
||||
void put_rpccred(struct rpc_cred *);
|
||||
__be32 * rpcauth_marshcred(struct rpc_task *, __be32 *);
|
||||
__be32 * rpcauth_checkverf(struct rpc_task *, __be32 *);
|
||||
int rpcauth_wrap_req(struct rpc_task *task, kxdreproc_t encode, void *rqstp, __be32 *data, void *obj);
|
||||
int rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, __be32 *data, void *obj);
|
||||
int rpcauth_refreshcred(struct rpc_task *);
|
||||
void rpcauth_invalcred(struct rpc_task *);
|
||||
int rpcauth_uptodatecred(struct rpc_task *);
|
||||
int rpcauth_init_credcache(struct rpc_auth *);
|
||||
void rpcauth_destroy_credcache(struct rpc_auth *);
|
||||
void rpcauth_clear_credcache(struct rpc_cred_cache *);
|
||||
int rpcauth_key_timeout_notify(struct rpc_auth *,
|
||||
struct rpc_cred *);
|
||||
bool rpcauth_cred_key_to_expire(struct rpc_cred *);
|
||||
char * rpcauth_stringify_acceptor(struct rpc_cred *);
|
||||
|
||||
static inline
|
||||
struct rpc_cred * get_rpccred(struct rpc_cred *cred)
|
||||
{
|
||||
atomic_inc(&cred->cr_count);
|
||||
return cred;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SUNRPC_AUTH_H */
|
92
include/linux/sunrpc/auth_gss.h
Normal file
92
include/linux/sunrpc/auth_gss.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/auth_gss.h
|
||||
*
|
||||
* Declarations for RPCSEC_GSS
|
||||
*
|
||||
* Dug Song <dugsong@monkey.org>
|
||||
* Andy Adamson <andros@umich.edu>
|
||||
* Bruce Fields <bfields@umich.edu>
|
||||
* Copyright (c) 2000 The Regents of the University of Michigan
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_AUTH_GSS_H
|
||||
#define _LINUX_SUNRPC_AUTH_GSS_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/sunrpc/auth.h>
|
||||
#include <linux/sunrpc/svc.h>
|
||||
#include <linux/sunrpc/gss_api.h>
|
||||
|
||||
#define RPC_GSS_VERSION 1
|
||||
|
||||
#define MAXSEQ 0x80000000 /* maximum legal sequence number, from rfc 2203 */
|
||||
|
||||
enum rpc_gss_proc {
|
||||
RPC_GSS_PROC_DATA = 0,
|
||||
RPC_GSS_PROC_INIT = 1,
|
||||
RPC_GSS_PROC_CONTINUE_INIT = 2,
|
||||
RPC_GSS_PROC_DESTROY = 3
|
||||
};
|
||||
|
||||
enum rpc_gss_svc {
|
||||
RPC_GSS_SVC_NONE = 1,
|
||||
RPC_GSS_SVC_INTEGRITY = 2,
|
||||
RPC_GSS_SVC_PRIVACY = 3
|
||||
};
|
||||
|
||||
/* on-the-wire gss cred: */
|
||||
struct rpc_gss_wire_cred {
|
||||
u32 gc_v; /* version */
|
||||
u32 gc_proc; /* control procedure */
|
||||
u32 gc_seq; /* sequence number */
|
||||
u32 gc_svc; /* service */
|
||||
struct xdr_netobj gc_ctx; /* context handle */
|
||||
};
|
||||
|
||||
/* on-the-wire gss verifier: */
|
||||
struct rpc_gss_wire_verf {
|
||||
u32 gv_flavor;
|
||||
struct xdr_netobj gv_verf;
|
||||
};
|
||||
|
||||
/* return from gss NULL PROC init sec context */
|
||||
struct rpc_gss_init_res {
|
||||
struct xdr_netobj gr_ctx; /* context handle */
|
||||
u32 gr_major; /* major status */
|
||||
u32 gr_minor; /* minor status */
|
||||
u32 gr_win; /* sequence window */
|
||||
struct xdr_netobj gr_token; /* token */
|
||||
};
|
||||
|
||||
/* The gss_cl_ctx struct holds all the information the rpcsec_gss client
|
||||
* code needs to know about a single security context. In particular,
|
||||
* gc_gss_ctx is the context handle that is used to do gss-api calls, while
|
||||
* gc_wire_ctx is the context handle that is used to identify the context on
|
||||
* the wire when communicating with a server. */
|
||||
|
||||
struct gss_cl_ctx {
|
||||
atomic_t count;
|
||||
enum rpc_gss_proc gc_proc;
|
||||
u32 gc_seq;
|
||||
spinlock_t gc_seq_lock;
|
||||
struct gss_ctx *gc_gss_ctx;
|
||||
struct xdr_netobj gc_wire_ctx;
|
||||
struct xdr_netobj gc_acceptor;
|
||||
u32 gc_win;
|
||||
unsigned long gc_expiry;
|
||||
struct rcu_head gc_rcu;
|
||||
};
|
||||
|
||||
struct gss_upcall_msg;
|
||||
struct gss_cred {
|
||||
struct rpc_cred gc_base;
|
||||
enum rpc_gss_svc gc_service;
|
||||
struct gss_cl_ctx __rcu *gc_ctx;
|
||||
struct gss_upcall_msg *gc_upcall;
|
||||
const char *gc_principal;
|
||||
unsigned long gc_upcall_timestamp;
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SUNRPC_AUTH_GSS_H */
|
||||
|
68
include/linux/sunrpc/bc_xprt.h
Normal file
68
include/linux/sunrpc/bc_xprt.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/******************************************************************************
|
||||
|
||||
(c) 2008 NetApp. All Rights Reserved.
|
||||
|
||||
NetApp provides this source code under the GPL v2 License.
|
||||
The GPL v2 license is available at
|
||||
http://opensource.org/licenses/gpl-license.php.
|
||||
|
||||
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.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Functions to create and manage the backchannel
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_BC_XPRT_H
|
||||
#define _LINUX_SUNRPC_BC_XPRT_H
|
||||
|
||||
#include <linux/sunrpc/svcsock.h>
|
||||
#include <linux/sunrpc/xprt.h>
|
||||
#include <linux/sunrpc/sched.h>
|
||||
|
||||
#ifdef CONFIG_SUNRPC_BACKCHANNEL
|
||||
struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid);
|
||||
void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied);
|
||||
void xprt_free_bc_request(struct rpc_rqst *req);
|
||||
int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
|
||||
void xprt_destroy_backchannel(struct rpc_xprt *, unsigned int max_reqs);
|
||||
int bc_send(struct rpc_rqst *req);
|
||||
|
||||
/*
|
||||
* Determine if a shared backchannel is in use
|
||||
*/
|
||||
static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
|
||||
{
|
||||
if (rqstp->rq_server->sv_bc_xprt)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_SUNRPC_BACKCHANNEL */
|
||||
static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
|
||||
unsigned int min_reqs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void xprt_free_bc_request(struct rpc_rqst *req)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
|
||||
#endif /* _LINUX_SUNRPC_BC_XPRT_H */
|
||||
|
298
include/linux/sunrpc/cache.h
Normal file
298
include/linux/sunrpc/cache.h
Normal file
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* include/linux/sunrpc/cache.h
|
||||
*
|
||||
* Generic code for various authentication-related caches
|
||||
* used by sunrpc clients and servers.
|
||||
*
|
||||
* Copyright (C) 2002 Neil Brown <neilb@cse.unsw.edu.au>
|
||||
*
|
||||
* Released under terms in GPL version 2. See COPYING.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_CACHE_H_
|
||||
#define _LINUX_SUNRPC_CACHE_H_
|
||||
|
||||
#include <linux/kref.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
/*
|
||||
* Each cache requires:
|
||||
* - A 'struct cache_detail' which contains information specific to the cache
|
||||
* for common code to use.
|
||||
* - An item structure that must contain a "struct cache_head"
|
||||
* - A lookup function defined using DefineCacheLookup
|
||||
* - A 'put' function that can release a cache item. It will only
|
||||
* be called after cache_put has succeed, so there are guarantee
|
||||
* to be no references.
|
||||
* - A function to calculate a hash of an item's key.
|
||||
*
|
||||
* as well as assorted code fragments (e.g. compare keys) and numbers
|
||||
* (e.g. hash size, goal_age, etc).
|
||||
*
|
||||
* Each cache must be registered so that it can be cleaned regularly.
|
||||
* When the cache is unregistered, it is flushed completely.
|
||||
*
|
||||
* Entries have a ref count and a 'hashed' flag which counts the existence
|
||||
* in the hash table.
|
||||
* We only expire entries when refcount is zero.
|
||||
* Existence in the cache is counted the refcount.
|
||||
*/
|
||||
|
||||
/* Every cache item has a common header that is used
|
||||
* for expiring and refreshing entries.
|
||||
*
|
||||
*/
|
||||
struct cache_head {
|
||||
struct cache_head * next;
|
||||
time_t expiry_time; /* After time time, don't use the data */
|
||||
time_t last_refresh; /* If CACHE_PENDING, this is when upcall
|
||||
* was sent, else this is when update was received
|
||||
*/
|
||||
struct kref ref;
|
||||
unsigned long flags;
|
||||
};
|
||||
#define CACHE_VALID 0 /* Entry contains valid data */
|
||||
#define CACHE_NEGATIVE 1 /* Negative entry - there is no match for the key */
|
||||
#define CACHE_PENDING 2 /* An upcall has been sent but no reply received yet*/
|
||||
#define CACHE_CLEANED 3 /* Entry has been cleaned from cache */
|
||||
|
||||
#define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */
|
||||
|
||||
struct cache_detail_procfs {
|
||||
struct proc_dir_entry *proc_ent;
|
||||
struct proc_dir_entry *flush_ent, *channel_ent, *content_ent;
|
||||
};
|
||||
|
||||
struct cache_detail_pipefs {
|
||||
struct dentry *dir;
|
||||
};
|
||||
|
||||
struct cache_detail {
|
||||
struct module * owner;
|
||||
int hash_size;
|
||||
struct cache_head ** hash_table;
|
||||
rwlock_t hash_lock;
|
||||
|
||||
atomic_t inuse; /* active user-space update or lookup */
|
||||
|
||||
char *name;
|
||||
void (*cache_put)(struct kref *);
|
||||
|
||||
int (*cache_upcall)(struct cache_detail *,
|
||||
struct cache_head *);
|
||||
|
||||
void (*cache_request)(struct cache_detail *cd,
|
||||
struct cache_head *ch,
|
||||
char **bpp, int *blen);
|
||||
|
||||
int (*cache_parse)(struct cache_detail *,
|
||||
char *buf, int len);
|
||||
|
||||
int (*cache_show)(struct seq_file *m,
|
||||
struct cache_detail *cd,
|
||||
struct cache_head *h);
|
||||
void (*warn_no_listener)(struct cache_detail *cd,
|
||||
int has_died);
|
||||
|
||||
struct cache_head * (*alloc)(void);
|
||||
int (*match)(struct cache_head *orig, struct cache_head *new);
|
||||
void (*init)(struct cache_head *orig, struct cache_head *new);
|
||||
void (*update)(struct cache_head *orig, struct cache_head *new);
|
||||
|
||||
/* fields below this comment are for internal use
|
||||
* and should not be touched by cache owners
|
||||
*/
|
||||
time_t flush_time; /* flush all cache items with last_refresh
|
||||
* earlier than this */
|
||||
struct list_head others;
|
||||
time_t nextcheck;
|
||||
int entries;
|
||||
|
||||
/* fields for communication over channel */
|
||||
struct list_head queue;
|
||||
|
||||
atomic_t readers; /* how many time is /chennel open */
|
||||
time_t last_close; /* if no readers, when did last close */
|
||||
time_t last_warn; /* when we last warned about no readers */
|
||||
|
||||
union {
|
||||
struct cache_detail_procfs procfs;
|
||||
struct cache_detail_pipefs pipefs;
|
||||
} u;
|
||||
struct net *net;
|
||||
};
|
||||
|
||||
|
||||
/* this must be embedded in any request structure that
|
||||
* identifies an object that will want a callback on
|
||||
* a cache fill
|
||||
*/
|
||||
struct cache_req {
|
||||
struct cache_deferred_req *(*defer)(struct cache_req *req);
|
||||
int thread_wait; /* How long (jiffies) we can block the
|
||||
* current thread to wait for updates.
|
||||
*/
|
||||
};
|
||||
/* this must be embedded in a deferred_request that is being
|
||||
* delayed awaiting cache-fill
|
||||
*/
|
||||
struct cache_deferred_req {
|
||||
struct hlist_node hash; /* on hash chain */
|
||||
struct list_head recent; /* on fifo */
|
||||
struct cache_head *item; /* cache item we wait on */
|
||||
void *owner; /* we might need to discard all defered requests
|
||||
* owned by someone */
|
||||
void (*revisit)(struct cache_deferred_req *req,
|
||||
int too_many);
|
||||
};
|
||||
|
||||
/*
|
||||
* timestamps kept in the cache are expressed in seconds
|
||||
* since boot. This is the best for measuring differences in
|
||||
* real time.
|
||||
*/
|
||||
static inline time_t seconds_since_boot(void)
|
||||
{
|
||||
struct timespec boot;
|
||||
getboottime(&boot);
|
||||
return get_seconds() - boot.tv_sec;
|
||||
}
|
||||
|
||||
static inline time_t convert_to_wallclock(time_t sinceboot)
|
||||
{
|
||||
struct timespec boot;
|
||||
getboottime(&boot);
|
||||
return boot.tv_sec + sinceboot;
|
||||
}
|
||||
|
||||
extern const struct file_operations cache_file_operations_pipefs;
|
||||
extern const struct file_operations content_file_operations_pipefs;
|
||||
extern const struct file_operations cache_flush_operations_pipefs;
|
||||
|
||||
extern struct cache_head *
|
||||
sunrpc_cache_lookup(struct cache_detail *detail,
|
||||
struct cache_head *key, int hash);
|
||||
extern struct cache_head *
|
||||
sunrpc_cache_update(struct cache_detail *detail,
|
||||
struct cache_head *new, struct cache_head *old, int hash);
|
||||
|
||||
extern int
|
||||
sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h);
|
||||
|
||||
|
||||
extern void cache_clean_deferred(void *owner);
|
||||
|
||||
static inline struct cache_head *cache_get(struct cache_head *h)
|
||||
{
|
||||
kref_get(&h->ref);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
|
||||
{
|
||||
if (atomic_read(&h->ref.refcount) <= 2 &&
|
||||
h->expiry_time < cd->nextcheck)
|
||||
cd->nextcheck = h->expiry_time;
|
||||
kref_put(&h->ref, cd->cache_put);
|
||||
}
|
||||
|
||||
static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
|
||||
{
|
||||
return (h->expiry_time < seconds_since_boot()) ||
|
||||
(detail->flush_time > h->last_refresh);
|
||||
}
|
||||
|
||||
extern int cache_check(struct cache_detail *detail,
|
||||
struct cache_head *h, struct cache_req *rqstp);
|
||||
extern void cache_flush(void);
|
||||
extern void cache_purge(struct cache_detail *detail);
|
||||
#define NEVER (0x7FFFFFFF)
|
||||
extern void __init cache_initialize(void);
|
||||
extern int cache_register_net(struct cache_detail *cd, struct net *net);
|
||||
extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
|
||||
|
||||
extern struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net);
|
||||
extern void cache_destroy_net(struct cache_detail *cd, struct net *net);
|
||||
|
||||
extern void sunrpc_init_cache_detail(struct cache_detail *cd);
|
||||
extern void sunrpc_destroy_cache_detail(struct cache_detail *cd);
|
||||
extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
|
||||
umode_t, struct cache_detail *);
|
||||
extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
|
||||
|
||||
extern void qword_add(char **bpp, int *lp, char *str);
|
||||
extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
|
||||
extern int qword_get(char **bpp, char *dest, int bufsize);
|
||||
|
||||
static inline int get_int(char **bpp, int *anint)
|
||||
{
|
||||
char buf[50];
|
||||
char *ep;
|
||||
int rv;
|
||||
int len = qword_get(bpp, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
if (len == 0)
|
||||
return -ENOENT;
|
||||
|
||||
rv = simple_strtol(buf, &ep, 0);
|
||||
if (*ep)
|
||||
return -EINVAL;
|
||||
|
||||
*anint = rv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_uint(char **bpp, unsigned int *anint)
|
||||
{
|
||||
char buf[50];
|
||||
int len = qword_get(bpp, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
if (len == 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (kstrtouint(buf, 0, anint))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_time(char **bpp, time_t *time)
|
||||
{
|
||||
char buf[50];
|
||||
long long ll;
|
||||
int len = qword_get(bpp, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
if (len == 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (kstrtoll(buf, 0, &ll))
|
||||
return -EINVAL;
|
||||
|
||||
*time = (time_t)ll;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline time_t get_expiry(char **bpp)
|
||||
{
|
||||
time_t rv;
|
||||
struct timespec boot;
|
||||
|
||||
if (get_time(bpp, &rv))
|
||||
return 0;
|
||||
if (rv < 0)
|
||||
return 0;
|
||||
getboottime(&boot);
|
||||
return rv - boot.tv_sec;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_SUNRPC_CACHE_H_ */
|
181
include/linux/sunrpc/clnt.h
Normal file
181
include/linux/sunrpc/clnt.h
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/clnt.h
|
||||
*
|
||||
* Declarations for the high-level RPC client interface
|
||||
*
|
||||
* Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_CLNT_H
|
||||
#define _LINUX_SUNRPC_CLNT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
#include <linux/sunrpc/sched.h>
|
||||
#include <linux/sunrpc/xprt.h>
|
||||
#include <linux/sunrpc/auth.h>
|
||||
#include <linux/sunrpc/stats.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/timer.h>
|
||||
#include <linux/sunrpc/rpc_pipe_fs.h>
|
||||
#include <asm/signal.h>
|
||||
#include <linux/path.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
struct rpc_inode;
|
||||
|
||||
/*
|
||||
* The high-level client handle
|
||||
*/
|
||||
struct rpc_clnt {
|
||||
atomic_t cl_count; /* Number of references */
|
||||
unsigned int cl_clid; /* client id */
|
||||
struct list_head cl_clients; /* Global list of clients */
|
||||
struct list_head cl_tasks; /* List of tasks */
|
||||
spinlock_t cl_lock; /* spinlock */
|
||||
struct rpc_xprt __rcu * cl_xprt; /* transport */
|
||||
struct rpc_procinfo * cl_procinfo; /* procedure info */
|
||||
u32 cl_prog, /* RPC program number */
|
||||
cl_vers, /* RPC version number */
|
||||
cl_maxproc; /* max procedure number */
|
||||
|
||||
struct rpc_auth * cl_auth; /* authenticator */
|
||||
struct rpc_stat * cl_stats; /* per-program statistics */
|
||||
struct rpc_iostats * cl_metrics; /* per-client statistics */
|
||||
|
||||
unsigned int cl_softrtry : 1,/* soft timeouts */
|
||||
cl_discrtry : 1,/* disconnect before retry */
|
||||
cl_noretranstimeo: 1,/* No retransmit timeouts */
|
||||
cl_autobind : 1,/* use getport() */
|
||||
cl_chatty : 1;/* be verbose */
|
||||
|
||||
struct rpc_rtt * cl_rtt; /* RTO estimator data */
|
||||
const struct rpc_timeout *cl_timeout; /* Timeout strategy */
|
||||
|
||||
int cl_nodelen; /* nodename length */
|
||||
char cl_nodename[UNX_MAXNODENAME+1];
|
||||
struct rpc_pipe_dir_head cl_pipedir_objects;
|
||||
struct rpc_clnt * cl_parent; /* Points to parent of clones */
|
||||
struct rpc_rtt cl_rtt_default;
|
||||
struct rpc_timeout cl_timeout_default;
|
||||
const struct rpc_program *cl_program;
|
||||
};
|
||||
|
||||
/*
|
||||
* General RPC program info
|
||||
*/
|
||||
#define RPC_MAXVERSION 4
|
||||
struct rpc_program {
|
||||
const char * name; /* protocol name */
|
||||
u32 number; /* program number */
|
||||
unsigned int nrvers; /* number of versions */
|
||||
const struct rpc_version ** version; /* version array */
|
||||
struct rpc_stat * stats; /* statistics */
|
||||
const char * pipe_dir_name; /* path to rpc_pipefs dir */
|
||||
};
|
||||
|
||||
struct rpc_version {
|
||||
u32 number; /* version number */
|
||||
unsigned int nrprocs; /* number of procs */
|
||||
struct rpc_procinfo * procs; /* procedure array */
|
||||
};
|
||||
|
||||
/*
|
||||
* Procedure information
|
||||
*/
|
||||
struct rpc_procinfo {
|
||||
u32 p_proc; /* RPC procedure number */
|
||||
kxdreproc_t p_encode; /* XDR encode function */
|
||||
kxdrdproc_t p_decode; /* XDR decode function */
|
||||
unsigned int p_arglen; /* argument hdr length (u32) */
|
||||
unsigned int p_replen; /* reply hdr length (u32) */
|
||||
unsigned int p_count; /* call count */
|
||||
unsigned int p_timer; /* Which RTT timer to use */
|
||||
u32 p_statidx; /* Which procedure to account */
|
||||
const char * p_name; /* name of procedure */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct rpc_create_args {
|
||||
struct net *net;
|
||||
int protocol;
|
||||
struct sockaddr *address;
|
||||
size_t addrsize;
|
||||
struct sockaddr *saddress;
|
||||
const struct rpc_timeout *timeout;
|
||||
const char *servername;
|
||||
const char *nodename;
|
||||
const struct rpc_program *program;
|
||||
u32 prognumber; /* overrides program->number */
|
||||
u32 version;
|
||||
rpc_authflavor_t authflavor;
|
||||
unsigned long flags;
|
||||
char *client_name;
|
||||
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
|
||||
};
|
||||
|
||||
/* Values for "flags" field */
|
||||
#define RPC_CLNT_CREATE_HARDRTRY (1UL << 0)
|
||||
#define RPC_CLNT_CREATE_AUTOBIND (1UL << 2)
|
||||
#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3)
|
||||
#define RPC_CLNT_CREATE_NOPING (1UL << 4)
|
||||
#define RPC_CLNT_CREATE_DISCRTRY (1UL << 5)
|
||||
#define RPC_CLNT_CREATE_QUIET (1UL << 6)
|
||||
#define RPC_CLNT_CREATE_INFINITE_SLOTS (1UL << 7)
|
||||
#define RPC_CLNT_CREATE_NO_IDLE_TIMEOUT (1UL << 8)
|
||||
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
|
||||
|
||||
struct rpc_clnt *rpc_create(struct rpc_create_args *args);
|
||||
struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
|
||||
struct rpc_xprt *xprt);
|
||||
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
|
||||
const struct rpc_program *, u32);
|
||||
void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt);
|
||||
struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
|
||||
struct rpc_clnt *rpc_clone_client_set_auth(struct rpc_clnt *,
|
||||
rpc_authflavor_t);
|
||||
int rpc_switch_client_transport(struct rpc_clnt *,
|
||||
struct xprt_create *,
|
||||
const struct rpc_timeout *);
|
||||
|
||||
void rpc_shutdown_client(struct rpc_clnt *);
|
||||
void rpc_release_client(struct rpc_clnt *);
|
||||
void rpc_task_release_client(struct rpc_task *);
|
||||
|
||||
int rpcb_create_local(struct net *);
|
||||
void rpcb_put_local(struct net *);
|
||||
int rpcb_register(struct net *, u32, u32, int, unsigned short);
|
||||
int rpcb_v4_register(struct net *net, const u32 program,
|
||||
const u32 version,
|
||||
const struct sockaddr *address,
|
||||
const char *netid);
|
||||
void rpcb_getport_async(struct rpc_task *);
|
||||
|
||||
void rpc_call_start(struct rpc_task *);
|
||||
int rpc_call_async(struct rpc_clnt *clnt,
|
||||
const struct rpc_message *msg, int flags,
|
||||
const struct rpc_call_ops *tk_ops,
|
||||
void *calldata);
|
||||
int rpc_call_sync(struct rpc_clnt *clnt,
|
||||
const struct rpc_message *msg, int flags);
|
||||
struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
|
||||
int flags);
|
||||
int rpc_restart_call_prepare(struct rpc_task *);
|
||||
int rpc_restart_call(struct rpc_task *);
|
||||
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
|
||||
int rpc_protocol(struct rpc_clnt *);
|
||||
struct net * rpc_net_ns(struct rpc_clnt *);
|
||||
size_t rpc_max_payload(struct rpc_clnt *);
|
||||
unsigned long rpc_get_timeout(struct rpc_clnt *clnt);
|
||||
void rpc_force_rebind(struct rpc_clnt *);
|
||||
size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
|
||||
const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
|
||||
int rpc_localaddr(struct rpc_clnt *, struct sockaddr *, size_t);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SUNRPC_CLNT_H */
|
73
include/linux/sunrpc/debug.h
Normal file
73
include/linux/sunrpc/debug.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/debug.h
|
||||
*
|
||||
* Debugging support for sunrpc module
|
||||
*
|
||||
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
#ifndef _LINUX_SUNRPC_DEBUG_H_
|
||||
#define _LINUX_SUNRPC_DEBUG_H_
|
||||
|
||||
#include <uapi/linux/sunrpc/debug.h>
|
||||
|
||||
|
||||
/*
|
||||
* Enable RPC debugging/profiling.
|
||||
*/
|
||||
#ifdef CONFIG_SUNRPC_DEBUG
|
||||
#define RPC_DEBUG
|
||||
#endif
|
||||
#ifdef CONFIG_TRACEPOINTS
|
||||
#define RPC_TRACEPOINTS
|
||||
#endif
|
||||
/* #define RPC_PROFILE */
|
||||
|
||||
/*
|
||||
* Debugging macros etc
|
||||
*/
|
||||
#ifdef RPC_DEBUG
|
||||
extern unsigned int rpc_debug;
|
||||
extern unsigned int nfs_debug;
|
||||
extern unsigned int nfsd_debug;
|
||||
extern unsigned int nlm_debug;
|
||||
#endif
|
||||
|
||||
#define dprintk(args...) dfprintk(FACILITY, ## args)
|
||||
#define dprintk_rcu(args...) dfprintk_rcu(FACILITY, ## args)
|
||||
|
||||
#undef ifdebug
|
||||
#ifdef RPC_DEBUG
|
||||
# define ifdebug(fac) if (unlikely(rpc_debug & RPCDBG_##fac))
|
||||
|
||||
# define dfprintk(fac, args...) \
|
||||
do { \
|
||||
ifdebug(fac) \
|
||||
printk(KERN_DEFAULT args); \
|
||||
} while (0)
|
||||
|
||||
# define dfprintk_rcu(fac, args...) \
|
||||
do { \
|
||||
ifdebug(fac) { \
|
||||
rcu_read_lock(); \
|
||||
printk(KERN_DEFAULT args); \
|
||||
rcu_read_unlock(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
# define RPC_IFDEBUG(x) x
|
||||
#else
|
||||
# define ifdebug(fac) if (0)
|
||||
# define dfprintk(fac, args...) do {} while (0)
|
||||
# define dfprintk_rcu(fac, args...) do {} while (0)
|
||||
# define RPC_IFDEBUG(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sysctl interface for RPC debugging
|
||||
*/
|
||||
#ifdef RPC_DEBUG
|
||||
void rpc_register_sysctl(void);
|
||||
void rpc_unregister_sysctl(void);
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_SUNRPC_DEBUG_H_ */
|
162
include/linux/sunrpc/gss_api.h
Normal file
162
include/linux/sunrpc/gss_api.h
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/gss_api.h
|
||||
*
|
||||
* Somewhat simplified version of the gss api.
|
||||
*
|
||||
* Dug Song <dugsong@monkey.org>
|
||||
* Andy Adamson <andros@umich.edu>
|
||||
* Bruce Fields <bfields@umich.edu>
|
||||
* Copyright (c) 2000 The Regents of the University of Michigan
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_GSS_API_H
|
||||
#define _LINUX_SUNRPC_GSS_API_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
/* The mechanism-independent gss-api context: */
|
||||
struct gss_ctx {
|
||||
struct gss_api_mech *mech_type;
|
||||
void *internal_ctx_id;
|
||||
};
|
||||
|
||||
#define GSS_C_NO_BUFFER ((struct xdr_netobj) 0)
|
||||
#define GSS_C_NO_CONTEXT ((struct gss_ctx *) 0)
|
||||
#define GSS_C_QOP_DEFAULT (0)
|
||||
|
||||
/*XXX arbitrary length - is this set somewhere? */
|
||||
#define GSS_OID_MAX_LEN 32
|
||||
struct rpcsec_gss_oid {
|
||||
unsigned int len;
|
||||
u8 data[GSS_OID_MAX_LEN];
|
||||
};
|
||||
|
||||
/* From RFC 3530 */
|
||||
struct rpcsec_gss_info {
|
||||
struct rpcsec_gss_oid oid;
|
||||
u32 qop;
|
||||
u32 service;
|
||||
};
|
||||
|
||||
/* gss-api prototypes; note that these are somewhat simplified versions of
|
||||
* the prototypes specified in RFC 2744. */
|
||||
int gss_import_sec_context(
|
||||
const void* input_token,
|
||||
size_t bufsize,
|
||||
struct gss_api_mech *mech,
|
||||
struct gss_ctx **ctx_id,
|
||||
time_t *endtime,
|
||||
gfp_t gfp_mask);
|
||||
u32 gss_get_mic(
|
||||
struct gss_ctx *ctx_id,
|
||||
struct xdr_buf *message,
|
||||
struct xdr_netobj *mic_token);
|
||||
u32 gss_verify_mic(
|
||||
struct gss_ctx *ctx_id,
|
||||
struct xdr_buf *message,
|
||||
struct xdr_netobj *mic_token);
|
||||
u32 gss_wrap(
|
||||
struct gss_ctx *ctx_id,
|
||||
int offset,
|
||||
struct xdr_buf *outbuf,
|
||||
struct page **inpages);
|
||||
u32 gss_unwrap(
|
||||
struct gss_ctx *ctx_id,
|
||||
int offset,
|
||||
struct xdr_buf *inbuf);
|
||||
u32 gss_delete_sec_context(
|
||||
struct gss_ctx **ctx_id);
|
||||
|
||||
rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 qop,
|
||||
u32 service);
|
||||
u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
|
||||
char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
|
||||
|
||||
struct pf_desc {
|
||||
u32 pseudoflavor;
|
||||
u32 qop;
|
||||
u32 service;
|
||||
char *name;
|
||||
char *auth_domain_name;
|
||||
};
|
||||
|
||||
/* Different mechanisms (e.g., krb5 or spkm3) may implement gss-api, and
|
||||
* mechanisms may be dynamically registered or unregistered by modules. */
|
||||
|
||||
/* Each mechanism is described by the following struct: */
|
||||
struct gss_api_mech {
|
||||
struct list_head gm_list;
|
||||
struct module *gm_owner;
|
||||
struct rpcsec_gss_oid gm_oid;
|
||||
char *gm_name;
|
||||
const struct gss_api_ops *gm_ops;
|
||||
/* pseudoflavors supported by this mechanism: */
|
||||
int gm_pf_num;
|
||||
struct pf_desc * gm_pfs;
|
||||
/* Should the following be a callback operation instead? */
|
||||
const char *gm_upcall_enctypes;
|
||||
};
|
||||
|
||||
/* and must provide the following operations: */
|
||||
struct gss_api_ops {
|
||||
int (*gss_import_sec_context)(
|
||||
const void *input_token,
|
||||
size_t bufsize,
|
||||
struct gss_ctx *ctx_id,
|
||||
time_t *endtime,
|
||||
gfp_t gfp_mask);
|
||||
u32 (*gss_get_mic)(
|
||||
struct gss_ctx *ctx_id,
|
||||
struct xdr_buf *message,
|
||||
struct xdr_netobj *mic_token);
|
||||
u32 (*gss_verify_mic)(
|
||||
struct gss_ctx *ctx_id,
|
||||
struct xdr_buf *message,
|
||||
struct xdr_netobj *mic_token);
|
||||
u32 (*gss_wrap)(
|
||||
struct gss_ctx *ctx_id,
|
||||
int offset,
|
||||
struct xdr_buf *outbuf,
|
||||
struct page **inpages);
|
||||
u32 (*gss_unwrap)(
|
||||
struct gss_ctx *ctx_id,
|
||||
int offset,
|
||||
struct xdr_buf *buf);
|
||||
void (*gss_delete_sec_context)(
|
||||
void *internal_ctx_id);
|
||||
};
|
||||
|
||||
int gss_mech_register(struct gss_api_mech *);
|
||||
void gss_mech_unregister(struct gss_api_mech *);
|
||||
|
||||
/* returns a mechanism descriptor given an OID, and increments the mechanism's
|
||||
* reference count. */
|
||||
struct gss_api_mech * gss_mech_get_by_OID(struct rpcsec_gss_oid *);
|
||||
|
||||
/* Given a GSS security tuple, look up a pseudoflavor */
|
||||
rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *);
|
||||
|
||||
/* Given a pseudoflavor, look up a GSS security tuple */
|
||||
int gss_mech_flavor2info(rpc_authflavor_t, struct rpcsec_gss_info *);
|
||||
|
||||
/* Returns a reference to a mechanism, given a name like "krb5" etc. */
|
||||
struct gss_api_mech *gss_mech_get_by_name(const char *);
|
||||
|
||||
/* Similar, but get by pseudoflavor. */
|
||||
struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32);
|
||||
|
||||
/* Fill in an array with a list of supported pseudoflavors */
|
||||
int gss_mech_list_pseudoflavors(rpc_authflavor_t *, int);
|
||||
|
||||
struct gss_api_mech * gss_mech_get(struct gss_api_mech *);
|
||||
|
||||
/* For every successful gss_mech_get or gss_mech_get_by_* call there must be a
|
||||
* corresponding call to gss_mech_put. */
|
||||
void gss_mech_put(struct gss_api_mech *);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SUNRPC_GSS_API_H */
|
||||
|
81
include/linux/sunrpc/gss_asn1.h
Normal file
81
include/linux/sunrpc/gss_asn1.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/gss_asn1.h
|
||||
*
|
||||
* minimal asn1 for generic encoding/decoding of gss tokens
|
||||
*
|
||||
* Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
|
||||
* lib/gssapi/krb5/gssapiP_krb5.h, and others
|
||||
*
|
||||
* Copyright (c) 2000 The Regents of the University of Michigan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Andy Adamson <andros@umich.edu>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 1995 by the Massachusetts Institute of Technology.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Export of this software from the United States of America may
|
||||
* require a specific license from the United States Government.
|
||||
* It is the responsibility of any person or organization contemplating
|
||||
* export to obtain such a license before exporting.
|
||||
*
|
||||
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||
* distribute this software and its documentation for any purpose and
|
||||
* without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both that copyright notice and
|
||||
* this permission notice appear in supporting documentation, and that
|
||||
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||
* to distribution of the software without specific, written prior
|
||||
* permission. Furthermore if you modify this software you must label
|
||||
* your software as modified software and not distribute it in such a
|
||||
* fashion that it might be confused with the original M.I.T. software.
|
||||
* M.I.T. makes no representations about the suitability of
|
||||
* this software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/sunrpc/gss_api.h>
|
||||
|
||||
#define SIZEOF_INT 4
|
||||
|
||||
/* from gssapi_err_generic.h */
|
||||
#define G_BAD_SERVICE_NAME (-2045022976L)
|
||||
#define G_BAD_STRING_UID (-2045022975L)
|
||||
#define G_NOUSER (-2045022974L)
|
||||
#define G_VALIDATE_FAILED (-2045022973L)
|
||||
#define G_BUFFER_ALLOC (-2045022972L)
|
||||
#define G_BAD_MSG_CTX (-2045022971L)
|
||||
#define G_WRONG_SIZE (-2045022970L)
|
||||
#define G_BAD_USAGE (-2045022969L)
|
||||
#define G_UNKNOWN_QOP (-2045022968L)
|
||||
#define G_NO_HOSTNAME (-2045022967L)
|
||||
#define G_BAD_HOSTNAME (-2045022966L)
|
||||
#define G_WRONG_MECH (-2045022965L)
|
||||
#define G_BAD_TOK_HEADER (-2045022964L)
|
||||
#define G_BAD_DIRECTION (-2045022963L)
|
||||
#define G_TOK_TRUNC (-2045022962L)
|
||||
#define G_REFLECT (-2045022961L)
|
||||
#define G_WRONG_TOKID (-2045022960L)
|
||||
|
||||
#define g_OID_equal(o1,o2) \
|
||||
(((o1)->len == (o2)->len) && \
|
||||
(memcmp((o1)->data,(o2)->data,(int) (o1)->len) == 0))
|
||||
|
||||
u32 g_verify_token_header(
|
||||
struct xdr_netobj *mech,
|
||||
int *body_size,
|
||||
unsigned char **buf_in,
|
||||
int toksize);
|
||||
|
||||
int g_token_size(
|
||||
struct xdr_netobj *mech,
|
||||
unsigned int body_size);
|
||||
|
||||
void g_make_token_header(
|
||||
struct xdr_netobj *mech,
|
||||
int body_size,
|
||||
unsigned char **buf);
|
167
include/linux/sunrpc/gss_err.h
Normal file
167
include/linux/sunrpc/gss_err.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* linux/include/sunrpc/gss_err.h
|
||||
*
|
||||
* Adapted from MIT Kerberos 5-1.2.1 include/gssapi/gssapi.h
|
||||
*
|
||||
* Copyright (c) 2002 The Regents of the University of Michigan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Andy Adamson <andros@umich.edu>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 1993 by OpenVision Technologies, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appears in all copies and
|
||||
* that both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of OpenVision not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. OpenVision makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_GSS_ERR_H
|
||||
#define _LINUX_SUNRPC_GSS_ERR_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
typedef unsigned int OM_uint32;
|
||||
|
||||
/*
|
||||
* Flag bits for context-level services.
|
||||
*/
|
||||
#define GSS_C_DELEG_FLAG 1
|
||||
#define GSS_C_MUTUAL_FLAG 2
|
||||
#define GSS_C_REPLAY_FLAG 4
|
||||
#define GSS_C_SEQUENCE_FLAG 8
|
||||
#define GSS_C_CONF_FLAG 16
|
||||
#define GSS_C_INTEG_FLAG 32
|
||||
#define GSS_C_ANON_FLAG 64
|
||||
#define GSS_C_PROT_READY_FLAG 128
|
||||
#define GSS_C_TRANS_FLAG 256
|
||||
|
||||
/*
|
||||
* Credential usage options
|
||||
*/
|
||||
#define GSS_C_BOTH 0
|
||||
#define GSS_C_INITIATE 1
|
||||
#define GSS_C_ACCEPT 2
|
||||
|
||||
/*
|
||||
* Status code types for gss_display_status
|
||||
*/
|
||||
#define GSS_C_GSS_CODE 1
|
||||
#define GSS_C_MECH_CODE 2
|
||||
|
||||
|
||||
/*
|
||||
* Expiration time of 2^32-1 seconds means infinite lifetime for a
|
||||
* credential or security context
|
||||
*/
|
||||
#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
|
||||
|
||||
|
||||
/* Major status codes */
|
||||
|
||||
#define GSS_S_COMPLETE 0
|
||||
|
||||
/*
|
||||
* Some "helper" definitions to make the status code macros obvious.
|
||||
*/
|
||||
#define GSS_C_CALLING_ERROR_OFFSET 24
|
||||
#define GSS_C_ROUTINE_ERROR_OFFSET 16
|
||||
#define GSS_C_SUPPLEMENTARY_OFFSET 0
|
||||
#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
|
||||
#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
|
||||
#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul)
|
||||
|
||||
/*
|
||||
* The macros that test status codes for error conditions. Note that the
|
||||
* GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now
|
||||
* evaluates its argument only once.
|
||||
*/
|
||||
#define GSS_CALLING_ERROR(x) \
|
||||
((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
|
||||
#define GSS_ROUTINE_ERROR(x) \
|
||||
((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
|
||||
#define GSS_SUPPLEMENTARY_INFO(x) \
|
||||
((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
|
||||
#define GSS_ERROR(x) \
|
||||
((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
|
||||
(GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
|
||||
|
||||
/*
|
||||
* Now the actual status code definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calling errors:
|
||||
*/
|
||||
#define GSS_S_CALL_INACCESSIBLE_READ \
|
||||
(((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET)
|
||||
#define GSS_S_CALL_INACCESSIBLE_WRITE \
|
||||
(((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET)
|
||||
#define GSS_S_CALL_BAD_STRUCTURE \
|
||||
(((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET)
|
||||
|
||||
/*
|
||||
* Routine errors:
|
||||
*/
|
||||
#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_DEFECTIVE_CREDENTIAL \
|
||||
(((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_CREDENTIALS_EXPIRED \
|
||||
(((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_CONTEXT_EXPIRED \
|
||||
(((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_DUPLICATE_ELEMENT \
|
||||
(((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
#define GSS_S_NAME_NOT_MN \
|
||||
(((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
||||
|
||||
/*
|
||||
* Supplementary info bits:
|
||||
*/
|
||||
#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
|
||||
#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
|
||||
#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
|
||||
#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
|
||||
#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
|
||||
|
||||
/* XXXX these are not part of the GSSAPI C bindings! (but should be) */
|
||||
|
||||
#define GSS_CALLING_ERROR_FIELD(x) \
|
||||
(((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK)
|
||||
#define GSS_ROUTINE_ERROR_FIELD(x) \
|
||||
(((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK)
|
||||
#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \
|
||||
(((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK)
|
||||
|
||||
/* XXXX This is a necessary evil until the spec is fixed */
|
||||
#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __LINUX_SUNRPC_GSS_ERR_H */
|
331
include/linux/sunrpc/gss_krb5.h
Normal file
331
include/linux/sunrpc/gss_krb5.h
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/gss_krb5_types.h
|
||||
*
|
||||
* Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
|
||||
* lib/gssapi/krb5/gssapiP_krb5.h, and others
|
||||
*
|
||||
* Copyright (c) 2000-2008 The Regents of the University of Michigan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Andy Adamson <andros@umich.edu>
|
||||
* Bruce Fields <bfields@umich.edu>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 1995 by the Massachusetts Institute of Technology.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Export of this software from the United States of America may
|
||||
* require a specific license from the United States Government.
|
||||
* It is the responsibility of any person or organization contemplating
|
||||
* export to obtain such a license before exporting.
|
||||
*
|
||||
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||
* distribute this software and its documentation for any purpose and
|
||||
* without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both that copyright notice and
|
||||
* this permission notice appear in supporting documentation, and that
|
||||
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||
* to distribution of the software without specific, written prior
|
||||
* permission. Furthermore if you modify this software you must label
|
||||
* your software as modified software and not distribute it in such a
|
||||
* fashion that it might be confused with the original M.I.T. software.
|
||||
* M.I.T. makes no representations about the suitability of
|
||||
* this software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/sunrpc/auth_gss.h>
|
||||
#include <linux/sunrpc/gss_err.h>
|
||||
#include <linux/sunrpc/gss_asn1.h>
|
||||
|
||||
/* Length of constant used in key derivation */
|
||||
#define GSS_KRB5_K5CLENGTH (5)
|
||||
|
||||
/* Maximum key length (in bytes) for the supported crypto algorithms*/
|
||||
#define GSS_KRB5_MAX_KEYLEN (32)
|
||||
|
||||
/* Maximum checksum function output for the supported crypto algorithms */
|
||||
#define GSS_KRB5_MAX_CKSUM_LEN (20)
|
||||
|
||||
/* Maximum blocksize for the supported crypto algorithms */
|
||||
#define GSS_KRB5_MAX_BLOCKSIZE (16)
|
||||
|
||||
struct krb5_ctx;
|
||||
|
||||
struct gss_krb5_enctype {
|
||||
const u32 etype; /* encryption (key) type */
|
||||
const u32 ctype; /* checksum type */
|
||||
const char *name; /* "friendly" name */
|
||||
const char *encrypt_name; /* crypto encrypt name */
|
||||
const char *cksum_name; /* crypto checksum name */
|
||||
const u16 signalg; /* signing algorithm */
|
||||
const u16 sealalg; /* sealing algorithm */
|
||||
const u32 blocksize; /* encryption blocksize */
|
||||
const u32 conflen; /* confounder length
|
||||
(normally the same as
|
||||
the blocksize) */
|
||||
const u32 cksumlength; /* checksum length */
|
||||
const u32 keyed_cksum; /* is it a keyed cksum? */
|
||||
const u32 keybytes; /* raw key len, in bytes */
|
||||
const u32 keylength; /* final key len, in bytes */
|
||||
u32 (*encrypt) (struct crypto_blkcipher *tfm,
|
||||
void *iv, void *in, void *out,
|
||||
int length); /* encryption function */
|
||||
u32 (*decrypt) (struct crypto_blkcipher *tfm,
|
||||
void *iv, void *in, void *out,
|
||||
int length); /* decryption function */
|
||||
u32 (*mk_key) (const struct gss_krb5_enctype *gk5e,
|
||||
struct xdr_netobj *in,
|
||||
struct xdr_netobj *out); /* complete key generation */
|
||||
u32 (*encrypt_v2) (struct krb5_ctx *kctx, u32 offset,
|
||||
struct xdr_buf *buf,
|
||||
struct page **pages); /* v2 encryption function */
|
||||
u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset,
|
||||
struct xdr_buf *buf, u32 *headskip,
|
||||
u32 *tailskip); /* v2 decryption function */
|
||||
};
|
||||
|
||||
/* krb5_ctx flags definitions */
|
||||
#define KRB5_CTX_FLAG_INITIATOR 0x00000001
|
||||
#define KRB5_CTX_FLAG_CFX 0x00000002
|
||||
#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
|
||||
|
||||
struct krb5_ctx {
|
||||
int initiate; /* 1 = initiating, 0 = accepting */
|
||||
u32 enctype;
|
||||
u32 flags;
|
||||
const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
|
||||
struct crypto_blkcipher *enc;
|
||||
struct crypto_blkcipher *seq;
|
||||
struct crypto_blkcipher *acceptor_enc;
|
||||
struct crypto_blkcipher *initiator_enc;
|
||||
struct crypto_blkcipher *acceptor_enc_aux;
|
||||
struct crypto_blkcipher *initiator_enc_aux;
|
||||
u8 Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */
|
||||
u8 cksum[GSS_KRB5_MAX_KEYLEN];
|
||||
s32 endtime;
|
||||
u32 seq_send;
|
||||
u64 seq_send64;
|
||||
struct xdr_netobj mech_used;
|
||||
u8 initiator_sign[GSS_KRB5_MAX_KEYLEN];
|
||||
u8 acceptor_sign[GSS_KRB5_MAX_KEYLEN];
|
||||
u8 initiator_seal[GSS_KRB5_MAX_KEYLEN];
|
||||
u8 acceptor_seal[GSS_KRB5_MAX_KEYLEN];
|
||||
u8 initiator_integ[GSS_KRB5_MAX_KEYLEN];
|
||||
u8 acceptor_integ[GSS_KRB5_MAX_KEYLEN];
|
||||
};
|
||||
|
||||
extern spinlock_t krb5_seq_lock;
|
||||
|
||||
/* The length of the Kerberos GSS token header */
|
||||
#define GSS_KRB5_TOK_HDR_LEN (16)
|
||||
|
||||
#define KG_TOK_MIC_MSG 0x0101
|
||||
#define KG_TOK_WRAP_MSG 0x0201
|
||||
|
||||
#define KG2_TOK_INITIAL 0x0101
|
||||
#define KG2_TOK_RESPONSE 0x0202
|
||||
#define KG2_TOK_MIC 0x0404
|
||||
#define KG2_TOK_WRAP 0x0504
|
||||
|
||||
#define KG2_TOKEN_FLAG_SENTBYACCEPTOR 0x01
|
||||
#define KG2_TOKEN_FLAG_SEALED 0x02
|
||||
#define KG2_TOKEN_FLAG_ACCEPTORSUBKEY 0x04
|
||||
|
||||
#define KG2_RESP_FLAG_ERROR 0x0001
|
||||
#define KG2_RESP_FLAG_DELEG_OK 0x0002
|
||||
|
||||
enum sgn_alg {
|
||||
SGN_ALG_DES_MAC_MD5 = 0x0000,
|
||||
SGN_ALG_MD2_5 = 0x0001,
|
||||
SGN_ALG_DES_MAC = 0x0002,
|
||||
SGN_ALG_3 = 0x0003, /* not published */
|
||||
SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */
|
||||
SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004
|
||||
};
|
||||
enum seal_alg {
|
||||
SEAL_ALG_NONE = 0xffff,
|
||||
SEAL_ALG_DES = 0x0000,
|
||||
SEAL_ALG_1 = 0x0001, /* not published */
|
||||
SEAL_ALG_MICROSOFT_RC4 = 0x0010,/* microsoft w2k; no support */
|
||||
SEAL_ALG_DES3KD = 0x0002
|
||||
};
|
||||
|
||||
#define CKSUMTYPE_CRC32 0x0001
|
||||
#define CKSUMTYPE_RSA_MD4 0x0002
|
||||
#define CKSUMTYPE_RSA_MD4_DES 0x0003
|
||||
#define CKSUMTYPE_DESCBC 0x0004
|
||||
#define CKSUMTYPE_RSA_MD5 0x0007
|
||||
#define CKSUMTYPE_RSA_MD5_DES 0x0008
|
||||
#define CKSUMTYPE_NIST_SHA 0x0009
|
||||
#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c
|
||||
#define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f
|
||||
#define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010
|
||||
#define CKSUMTYPE_HMAC_MD5_ARCFOUR -138 /* Microsoft md5 hmac cksumtype */
|
||||
|
||||
/* from gssapi_err_krb5.h */
|
||||
#define KG_CCACHE_NOMATCH (39756032L)
|
||||
#define KG_KEYTAB_NOMATCH (39756033L)
|
||||
#define KG_TGT_MISSING (39756034L)
|
||||
#define KG_NO_SUBKEY (39756035L)
|
||||
#define KG_CONTEXT_ESTABLISHED (39756036L)
|
||||
#define KG_BAD_SIGN_TYPE (39756037L)
|
||||
#define KG_BAD_LENGTH (39756038L)
|
||||
#define KG_CTX_INCOMPLETE (39756039L)
|
||||
#define KG_CONTEXT (39756040L)
|
||||
#define KG_CRED (39756041L)
|
||||
#define KG_ENC_DESC (39756042L)
|
||||
#define KG_BAD_SEQ (39756043L)
|
||||
#define KG_EMPTY_CCACHE (39756044L)
|
||||
#define KG_NO_CTYPES (39756045L)
|
||||
|
||||
/* per Kerberos v5 protocol spec crypto types from the wire.
|
||||
* these get mapped to linux kernel crypto routines.
|
||||
*/
|
||||
#define ENCTYPE_NULL 0x0000
|
||||
#define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */
|
||||
#define ENCTYPE_DES_CBC_MD4 0x0002 /* DES cbc mode with RSA-MD4 */
|
||||
#define ENCTYPE_DES_CBC_MD5 0x0003 /* DES cbc mode with RSA-MD5 */
|
||||
#define ENCTYPE_DES_CBC_RAW 0x0004 /* DES cbc mode raw */
|
||||
/* XXX deprecated? */
|
||||
#define ENCTYPE_DES3_CBC_SHA 0x0005 /* DES-3 cbc mode with NIST-SHA */
|
||||
#define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */
|
||||
#define ENCTYPE_DES_HMAC_SHA1 0x0008
|
||||
#define ENCTYPE_DES3_CBC_SHA1 0x0010
|
||||
#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011
|
||||
#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012
|
||||
#define ENCTYPE_ARCFOUR_HMAC 0x0017
|
||||
#define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018
|
||||
#define ENCTYPE_UNKNOWN 0x01ff
|
||||
|
||||
/*
|
||||
* Constants used for key derivation
|
||||
*/
|
||||
/* for 3DES */
|
||||
#define KG_USAGE_SEAL (22)
|
||||
#define KG_USAGE_SIGN (23)
|
||||
#define KG_USAGE_SEQ (24)
|
||||
|
||||
/* from rfc3961 */
|
||||
#define KEY_USAGE_SEED_CHECKSUM (0x99)
|
||||
#define KEY_USAGE_SEED_ENCRYPTION (0xAA)
|
||||
#define KEY_USAGE_SEED_INTEGRITY (0x55)
|
||||
|
||||
/* from rfc4121 */
|
||||
#define KG_USAGE_ACCEPTOR_SEAL (22)
|
||||
#define KG_USAGE_ACCEPTOR_SIGN (23)
|
||||
#define KG_USAGE_INITIATOR_SEAL (24)
|
||||
#define KG_USAGE_INITIATOR_SIGN (25)
|
||||
|
||||
/*
|
||||
* This compile-time check verifies that we will not exceed the
|
||||
* slack space allotted by the client and server auth_gss code
|
||||
* before they call gss_wrap().
|
||||
*/
|
||||
#define GSS_KRB5_MAX_SLACK_NEEDED \
|
||||
(GSS_KRB5_TOK_HDR_LEN /* gss token header */ \
|
||||
+ GSS_KRB5_MAX_CKSUM_LEN /* gss token checksum */ \
|
||||
+ GSS_KRB5_MAX_BLOCKSIZE /* confounder */ \
|
||||
+ GSS_KRB5_MAX_BLOCKSIZE /* possible padding */ \
|
||||
+ GSS_KRB5_TOK_HDR_LEN /* encrypted hdr in v2 token */\
|
||||
+ GSS_KRB5_MAX_CKSUM_LEN /* encryption hmac */ \
|
||||
+ 4 + 4 /* RPC verifier */ \
|
||||
+ GSS_KRB5_TOK_HDR_LEN \
|
||||
+ GSS_KRB5_MAX_CKSUM_LEN)
|
||||
|
||||
u32
|
||||
make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
struct xdr_buf *body, int body_offset, u8 *cksumkey,
|
||||
unsigned int usage, struct xdr_netobj *cksumout);
|
||||
|
||||
u32
|
||||
make_checksum_v2(struct krb5_ctx *, char *header, int hdrlen,
|
||||
struct xdr_buf *body, int body_offset, u8 *key,
|
||||
unsigned int usage, struct xdr_netobj *cksum);
|
||||
|
||||
u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
|
||||
struct xdr_netobj *);
|
||||
|
||||
u32 gss_verify_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
|
||||
struct xdr_netobj *);
|
||||
|
||||
u32
|
||||
gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
|
||||
struct xdr_buf *outbuf, struct page **pages);
|
||||
|
||||
u32
|
||||
gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset,
|
||||
struct xdr_buf *buf);
|
||||
|
||||
|
||||
u32
|
||||
krb5_encrypt(struct crypto_blkcipher *key,
|
||||
void *iv, void *in, void *out, int length);
|
||||
|
||||
u32
|
||||
krb5_decrypt(struct crypto_blkcipher *key,
|
||||
void *iv, void *in, void *out, int length);
|
||||
|
||||
int
|
||||
gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *outbuf,
|
||||
int offset, struct page **pages);
|
||||
|
||||
int
|
||||
gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf,
|
||||
int offset);
|
||||
|
||||
s32
|
||||
krb5_make_seq_num(struct krb5_ctx *kctx,
|
||||
struct crypto_blkcipher *key,
|
||||
int direction,
|
||||
u32 seqnum, unsigned char *cksum, unsigned char *buf);
|
||||
|
||||
s32
|
||||
krb5_get_seq_num(struct krb5_ctx *kctx,
|
||||
unsigned char *cksum,
|
||||
unsigned char *buf, int *direction, u32 *seqnum);
|
||||
|
||||
int
|
||||
xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen);
|
||||
|
||||
u32
|
||||
krb5_derive_key(const struct gss_krb5_enctype *gk5e,
|
||||
const struct xdr_netobj *inkey,
|
||||
struct xdr_netobj *outkey,
|
||||
const struct xdr_netobj *in_constant,
|
||||
gfp_t gfp_mask);
|
||||
|
||||
u32
|
||||
gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
|
||||
struct xdr_netobj *randombits,
|
||||
struct xdr_netobj *key);
|
||||
|
||||
u32
|
||||
gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e,
|
||||
struct xdr_netobj *randombits,
|
||||
struct xdr_netobj *key);
|
||||
|
||||
u32
|
||||
gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
|
||||
struct xdr_buf *buf,
|
||||
struct page **pages);
|
||||
|
||||
u32
|
||||
gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset,
|
||||
struct xdr_buf *buf, u32 *plainoffset,
|
||||
u32 *plainlen);
|
||||
|
||||
int
|
||||
krb5_rc4_setup_seq_key(struct krb5_ctx *kctx,
|
||||
struct crypto_blkcipher *cipher,
|
||||
unsigned char *cksum);
|
||||
|
||||
int
|
||||
krb5_rc4_setup_enc_key(struct krb5_ctx *kctx,
|
||||
struct crypto_blkcipher *cipher,
|
||||
s32 seqnum);
|
||||
void
|
||||
gss_krb5_make_confounder(char *p, u32 conflen);
|
4
include/linux/sunrpc/gss_krb5_enctypes.h
Normal file
4
include/linux/sunrpc/gss_krb5_enctypes.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
* Dumb way to share this static piece of information with nfsd
|
||||
*/
|
||||
#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2"
|
92
include/linux/sunrpc/metrics.h
Normal file
92
include/linux/sunrpc/metrics.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/metrics.h
|
||||
*
|
||||
* Declarations for RPC client per-operation metrics
|
||||
*
|
||||
* Copyright (C) 2005 Chuck Lever <cel@netapp.com>
|
||||
*
|
||||
* RPC client per-operation statistics provide latency and retry
|
||||
* information about each type of RPC procedure in a given RPC program.
|
||||
* These statistics are not for detailed problem diagnosis, but simply
|
||||
* to indicate whether the problem is local or remote.
|
||||
*
|
||||
* These counters are not meant to be human-readable, but are meant to be
|
||||
* integrated into system monitoring tools such as "sar" and "iostat". As
|
||||
* such, the counters are sampled by the tools over time, and are never
|
||||
* zeroed after a file system is mounted. Moving averages can be computed
|
||||
* by the tools by taking the difference between two instantaneous samples
|
||||
* and dividing that by the time between the samples.
|
||||
*
|
||||
* The counters are maintained in a single array per RPC client, indexed
|
||||
* by procedure number. There is no need to maintain separate counter
|
||||
* arrays per-CPU because these counters are always modified behind locks.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_METRICS_H
|
||||
#define _LINUX_SUNRPC_METRICS_H
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#define RPC_IOSTATS_VERS "1.0"
|
||||
|
||||
struct rpc_iostats {
|
||||
/*
|
||||
* These counters give an idea about how many request
|
||||
* transmissions are required, on average, to complete that
|
||||
* particular procedure. Some procedures may require more
|
||||
* than one transmission because the server is unresponsive,
|
||||
* the client is retransmitting too aggressively, or the
|
||||
* requests are large and the network is congested.
|
||||
*/
|
||||
unsigned long om_ops, /* count of operations */
|
||||
om_ntrans, /* count of RPC transmissions */
|
||||
om_timeouts; /* count of major timeouts */
|
||||
|
||||
/*
|
||||
* These count how many bytes are sent and received for a
|
||||
* given RPC procedure type. This indicates how much load a
|
||||
* particular procedure is putting on the network. These
|
||||
* counts include the RPC and ULP headers, and the request
|
||||
* payload.
|
||||
*/
|
||||
unsigned long long om_bytes_sent, /* count of bytes out */
|
||||
om_bytes_recv; /* count of bytes in */
|
||||
|
||||
/*
|
||||
* The length of time an RPC request waits in queue before
|
||||
* transmission, the network + server latency of the request,
|
||||
* and the total time the request spent from init to release
|
||||
* are measured.
|
||||
*/
|
||||
ktime_t om_queue, /* queued for xmit */
|
||||
om_rtt, /* RPC RTT */
|
||||
om_execute; /* RPC execution */
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct rpc_task;
|
||||
struct rpc_clnt;
|
||||
|
||||
/*
|
||||
* EXPORTed functions for managing rpc_iostats structures
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
struct rpc_iostats * rpc_alloc_iostats(struct rpc_clnt *);
|
||||
void rpc_count_iostats(const struct rpc_task *,
|
||||
struct rpc_iostats *);
|
||||
void rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
|
||||
void rpc_free_iostats(struct rpc_iostats *);
|
||||
|
||||
#else /* CONFIG_PROC_FS */
|
||||
|
||||
static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
|
||||
static inline void rpc_count_iostats(const struct rpc_task *task,
|
||||
struct rpc_iostats *stats) {}
|
||||
static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
|
||||
static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
#endif /* _LINUX_SUNRPC_METRICS_H */
|
214
include/linux/sunrpc/msg_prot.h
Normal file
214
include/linux/sunrpc/msg_prot.h
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/msg_prot.h
|
||||
*
|
||||
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_MSGPROT_H_
|
||||
#define _LINUX_SUNRPC_MSGPROT_H_
|
||||
|
||||
#ifdef __KERNEL__ /* user programs should get these from the rpc header files */
|
||||
|
||||
#define RPC_VERSION 2
|
||||
|
||||
/* size of an XDR encoding unit in bytes, i.e. 32bit */
|
||||
#define XDR_UNIT (4)
|
||||
|
||||
/* spec defines authentication flavor as an unsigned 32 bit integer */
|
||||
typedef u32 rpc_authflavor_t;
|
||||
|
||||
enum rpc_auth_flavors {
|
||||
RPC_AUTH_NULL = 0,
|
||||
RPC_AUTH_UNIX = 1,
|
||||
RPC_AUTH_SHORT = 2,
|
||||
RPC_AUTH_DES = 3,
|
||||
RPC_AUTH_KRB = 4,
|
||||
RPC_AUTH_GSS = 6,
|
||||
RPC_AUTH_MAXFLAVOR = 8,
|
||||
/* pseudoflavors: */
|
||||
RPC_AUTH_GSS_KRB5 = 390003,
|
||||
RPC_AUTH_GSS_KRB5I = 390004,
|
||||
RPC_AUTH_GSS_KRB5P = 390005,
|
||||
RPC_AUTH_GSS_LKEY = 390006,
|
||||
RPC_AUTH_GSS_LKEYI = 390007,
|
||||
RPC_AUTH_GSS_LKEYP = 390008,
|
||||
RPC_AUTH_GSS_SPKM = 390009,
|
||||
RPC_AUTH_GSS_SPKMI = 390010,
|
||||
RPC_AUTH_GSS_SPKMP = 390011,
|
||||
};
|
||||
|
||||
/* Maximum size (in bytes) of an rpc credential or verifier */
|
||||
#define RPC_MAX_AUTH_SIZE (400)
|
||||
|
||||
enum rpc_msg_type {
|
||||
RPC_CALL = 0,
|
||||
RPC_REPLY = 1
|
||||
};
|
||||
|
||||
enum rpc_reply_stat {
|
||||
RPC_MSG_ACCEPTED = 0,
|
||||
RPC_MSG_DENIED = 1
|
||||
};
|
||||
|
||||
enum rpc_accept_stat {
|
||||
RPC_SUCCESS = 0,
|
||||
RPC_PROG_UNAVAIL = 1,
|
||||
RPC_PROG_MISMATCH = 2,
|
||||
RPC_PROC_UNAVAIL = 3,
|
||||
RPC_GARBAGE_ARGS = 4,
|
||||
RPC_SYSTEM_ERR = 5,
|
||||
/* internal use only */
|
||||
RPC_DROP_REPLY = 60000,
|
||||
};
|
||||
|
||||
enum rpc_reject_stat {
|
||||
RPC_MISMATCH = 0,
|
||||
RPC_AUTH_ERROR = 1
|
||||
};
|
||||
|
||||
enum rpc_auth_stat {
|
||||
RPC_AUTH_OK = 0,
|
||||
RPC_AUTH_BADCRED = 1,
|
||||
RPC_AUTH_REJECTEDCRED = 2,
|
||||
RPC_AUTH_BADVERF = 3,
|
||||
RPC_AUTH_REJECTEDVERF = 4,
|
||||
RPC_AUTH_TOOWEAK = 5,
|
||||
/* RPCSEC_GSS errors */
|
||||
RPCSEC_GSS_CREDPROBLEM = 13,
|
||||
RPCSEC_GSS_CTXPROBLEM = 14
|
||||
};
|
||||
|
||||
#define RPC_MAXNETNAMELEN 256
|
||||
|
||||
/*
|
||||
* From RFC 1831:
|
||||
*
|
||||
* "A record is composed of one or more record fragments. A record
|
||||
* fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
|
||||
* fragment data. The bytes encode an unsigned binary number; as with
|
||||
* XDR integers, the byte order is from highest to lowest. The number
|
||||
* encodes two values -- a boolean which indicates whether the fragment
|
||||
* is the last fragment of the record (bit value 1 implies the fragment
|
||||
* is the last fragment) and a 31-bit unsigned binary value which is the
|
||||
* length in bytes of the fragment's data. The boolean value is the
|
||||
* highest-order bit of the header; the length is the 31 low-order bits.
|
||||
* (Note that this record specification is NOT in XDR standard form!)"
|
||||
*
|
||||
* The Linux RPC client always sends its requests in a single record
|
||||
* fragment, limiting the maximum payload size for stream transports to
|
||||
* 2GB.
|
||||
*/
|
||||
|
||||
typedef __be32 rpc_fraghdr;
|
||||
|
||||
#define RPC_LAST_STREAM_FRAGMENT (1U << 31)
|
||||
#define RPC_FRAGMENT_SIZE_MASK (~RPC_LAST_STREAM_FRAGMENT)
|
||||
#define RPC_MAX_FRAGMENT_SIZE ((1U << 31) - 1)
|
||||
|
||||
/*
|
||||
* RPC call and reply header size as number of 32bit words (verifier
|
||||
* size computed separately, see below)
|
||||
*/
|
||||
#define RPC_CALLHDRSIZE (6)
|
||||
#define RPC_REPHDRSIZE (4)
|
||||
|
||||
|
||||
/*
|
||||
* Maximum RPC header size, including authentication,
|
||||
* as number of 32bit words (see RFCs 1831, 1832).
|
||||
*
|
||||
* xid 1 xdr unit = 4 bytes
|
||||
* mtype 1
|
||||
* rpc_version 1
|
||||
* program 1
|
||||
* prog_version 1
|
||||
* procedure 1
|
||||
* cred {
|
||||
* flavor 1
|
||||
* length 1
|
||||
* body<RPC_MAX_AUTH_SIZE> 100 xdr units = 400 bytes
|
||||
* }
|
||||
* verf {
|
||||
* flavor 1
|
||||
* length 1
|
||||
* body<RPC_MAX_AUTH_SIZE> 100 xdr units = 400 bytes
|
||||
* }
|
||||
* TOTAL 210 xdr units = 840 bytes
|
||||
*/
|
||||
#define RPC_MAX_HEADER_WITH_AUTH \
|
||||
(RPC_CALLHDRSIZE + 2*(2+RPC_MAX_AUTH_SIZE/4))
|
||||
|
||||
#define RPC_MAX_REPHEADER_WITH_AUTH \
|
||||
(RPC_REPHDRSIZE + (2 + RPC_MAX_AUTH_SIZE/4))
|
||||
|
||||
/*
|
||||
* RFC1833/RFC3530 rpcbind (v3+) well-known netid's.
|
||||
*/
|
||||
#define RPCBIND_NETID_UDP "udp"
|
||||
#define RPCBIND_NETID_TCP "tcp"
|
||||
#define RPCBIND_NETID_UDP6 "udp6"
|
||||
#define RPCBIND_NETID_TCP6 "tcp6"
|
||||
#define RPCBIND_NETID_LOCAL "local"
|
||||
|
||||
/*
|
||||
* Note that RFC 1833 does not put any size restrictions on the
|
||||
* netid string, but all currently defined netid's fit in 4 bytes.
|
||||
*/
|
||||
#define RPCBIND_MAXNETIDLEN (4u)
|
||||
|
||||
/*
|
||||
* Universal addresses are introduced in RFC 1833 and further spelled
|
||||
* out in RFC 3530. RPCBIND_MAXUADDRLEN defines a maximum byte length
|
||||
* of a universal address for use in allocating buffers and character
|
||||
* arrays.
|
||||
*
|
||||
* Quoting RFC 3530, section 2.2:
|
||||
*
|
||||
* For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the
|
||||
* US-ASCII string:
|
||||
*
|
||||
* h1.h2.h3.h4.p1.p2
|
||||
*
|
||||
* The prefix, "h1.h2.h3.h4", is the standard textual form for
|
||||
* representing an IPv4 address, which is always four octets long.
|
||||
* Assuming big-endian ordering, h1, h2, h3, and h4, are respectively,
|
||||
* the first through fourth octets each converted to ASCII-decimal.
|
||||
* Assuming big-endian ordering, p1 and p2 are, respectively, the first
|
||||
* and second octets each converted to ASCII-decimal. For example, if a
|
||||
* host, in big-endian order, has an address of 0x0A010307 and there is
|
||||
* a service listening on, in big endian order, port 0x020F (decimal
|
||||
* 527), then the complete universal address is "10.1.3.7.2.15".
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the
|
||||
* US-ASCII string:
|
||||
*
|
||||
* x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
|
||||
*
|
||||
* The suffix "p1.p2" is the service port, and is computed the same way
|
||||
* as with universal addresses for TCP and UDP over IPv4. The prefix,
|
||||
* "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for
|
||||
* representing an IPv6 address as defined in Section 2.2 of [RFC2373].
|
||||
* Additionally, the two alternative forms specified in Section 2.2 of
|
||||
* [RFC2373] are also acceptable.
|
||||
*/
|
||||
|
||||
#include <linux/inet.h>
|
||||
|
||||
/* Maximum size of the port number part of a universal address */
|
||||
#define RPCBIND_MAXUADDRPLEN sizeof(".255.255")
|
||||
|
||||
/* Maximum size of an IPv4 universal address */
|
||||
#define RPCBIND_MAXUADDR4LEN \
|
||||
(INET_ADDRSTRLEN + RPCBIND_MAXUADDRPLEN)
|
||||
|
||||
/* Maximum size of an IPv6 universal address */
|
||||
#define RPCBIND_MAXUADDR6LEN \
|
||||
(INET6_ADDRSTRLEN + RPCBIND_MAXUADDRPLEN)
|
||||
|
||||
/* Assume INET6_ADDRSTRLEN will always be larger than INET_ADDRSTRLEN... */
|
||||
#define RPCBIND_MAXUADDRLEN RPCBIND_MAXUADDR6LEN
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SUNRPC_MSGPROT_H_ */
|
137
include/linux/sunrpc/rpc_pipe_fs.h
Normal file
137
include/linux/sunrpc/rpc_pipe_fs.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef _LINUX_SUNRPC_RPC_PIPE_FS_H
|
||||
#define _LINUX_SUNRPC_RPC_PIPE_FS_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct rpc_pipe_dir_head {
|
||||
struct list_head pdh_entries;
|
||||
struct dentry *pdh_dentry;
|
||||
};
|
||||
|
||||
struct rpc_pipe_dir_object_ops;
|
||||
struct rpc_pipe_dir_object {
|
||||
struct list_head pdo_head;
|
||||
const struct rpc_pipe_dir_object_ops *pdo_ops;
|
||||
|
||||
void *pdo_data;
|
||||
};
|
||||
|
||||
struct rpc_pipe_dir_object_ops {
|
||||
int (*create)(struct dentry *dir,
|
||||
struct rpc_pipe_dir_object *pdo);
|
||||
void (*destroy)(struct dentry *dir,
|
||||
struct rpc_pipe_dir_object *pdo);
|
||||
};
|
||||
|
||||
struct rpc_pipe_msg {
|
||||
struct list_head list;
|
||||
void *data;
|
||||
size_t len;
|
||||
size_t copied;
|
||||
int errno;
|
||||
};
|
||||
|
||||
struct rpc_pipe_ops {
|
||||
ssize_t (*upcall)(struct file *, struct rpc_pipe_msg *, char __user *, size_t);
|
||||
ssize_t (*downcall)(struct file *, const char __user *, size_t);
|
||||
void (*release_pipe)(struct inode *);
|
||||
int (*open_pipe)(struct inode *);
|
||||
void (*destroy_msg)(struct rpc_pipe_msg *);
|
||||
};
|
||||
|
||||
struct rpc_pipe {
|
||||
struct list_head pipe;
|
||||
struct list_head in_upcall;
|
||||
struct list_head in_downcall;
|
||||
int pipelen;
|
||||
int nreaders;
|
||||
int nwriters;
|
||||
#define RPC_PIPE_WAIT_FOR_OPEN 1
|
||||
int flags;
|
||||
struct delayed_work queue_timeout;
|
||||
const struct rpc_pipe_ops *ops;
|
||||
spinlock_t lock;
|
||||
struct dentry *dentry;
|
||||
};
|
||||
|
||||
struct rpc_inode {
|
||||
struct inode vfs_inode;
|
||||
void *private;
|
||||
struct rpc_pipe *pipe;
|
||||
wait_queue_head_t waitq;
|
||||
};
|
||||
|
||||
static inline struct rpc_inode *
|
||||
RPC_I(struct inode *inode)
|
||||
{
|
||||
return container_of(inode, struct rpc_inode, vfs_inode);
|
||||
}
|
||||
|
||||
enum {
|
||||
SUNRPC_PIPEFS_NFS_PRIO,
|
||||
SUNRPC_PIPEFS_RPC_PRIO,
|
||||
};
|
||||
|
||||
extern int rpc_pipefs_notifier_register(struct notifier_block *);
|
||||
extern void rpc_pipefs_notifier_unregister(struct notifier_block *);
|
||||
|
||||
enum {
|
||||
RPC_PIPEFS_MOUNT,
|
||||
RPC_PIPEFS_UMOUNT,
|
||||
};
|
||||
|
||||
extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
|
||||
const unsigned char *dir_name);
|
||||
extern int rpc_pipefs_init_net(struct net *net);
|
||||
extern void rpc_pipefs_exit_net(struct net *net);
|
||||
extern struct super_block *rpc_get_sb_net(const struct net *net);
|
||||
extern void rpc_put_sb_net(const struct net *net);
|
||||
|
||||
extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
|
||||
char __user *, size_t);
|
||||
extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
|
||||
|
||||
struct rpc_clnt;
|
||||
extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *);
|
||||
extern int rpc_remove_client_dir(struct rpc_clnt *);
|
||||
|
||||
extern void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh);
|
||||
extern void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
|
||||
const struct rpc_pipe_dir_object_ops *pdo_ops,
|
||||
void *pdo_data);
|
||||
extern int rpc_add_pipe_dir_object(struct net *net,
|
||||
struct rpc_pipe_dir_head *pdh,
|
||||
struct rpc_pipe_dir_object *pdo);
|
||||
extern void rpc_remove_pipe_dir_object(struct net *net,
|
||||
struct rpc_pipe_dir_head *pdh,
|
||||
struct rpc_pipe_dir_object *pdo);
|
||||
extern struct rpc_pipe_dir_object *rpc_find_or_alloc_pipe_dir_object(
|
||||
struct net *net,
|
||||
struct rpc_pipe_dir_head *pdh,
|
||||
int (*match)(struct rpc_pipe_dir_object *, void *),
|
||||
struct rpc_pipe_dir_object *(*alloc)(void *),
|
||||
void *data);
|
||||
|
||||
struct cache_detail;
|
||||
extern struct dentry *rpc_create_cache_dir(struct dentry *,
|
||||
const char *,
|
||||
umode_t umode,
|
||||
struct cache_detail *);
|
||||
extern void rpc_remove_cache_dir(struct dentry *);
|
||||
|
||||
extern int rpc_rmdir(struct dentry *dentry);
|
||||
|
||||
struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags);
|
||||
void rpc_destroy_pipe_data(struct rpc_pipe *pipe);
|
||||
extern struct dentry *rpc_mkpipe_dentry(struct dentry *, const char *, void *,
|
||||
struct rpc_pipe *);
|
||||
extern int rpc_unlink(struct dentry *);
|
||||
extern int register_rpc_pipefs(void);
|
||||
extern void unregister_rpc_pipefs(void);
|
||||
|
||||
extern bool gssd_running(struct net *net);
|
||||
|
||||
#endif
|
||||
#endif
|
118
include/linux/sunrpc/rpc_rdma.h
Normal file
118
include/linux/sunrpc/rpc_rdma.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_RPC_RDMA_H
|
||||
#define _LINUX_SUNRPC_RPC_RDMA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct rpcrdma_segment {
|
||||
__be32 rs_handle; /* Registered memory handle */
|
||||
__be32 rs_length; /* Length of the chunk in bytes */
|
||||
__be64 rs_offset; /* Chunk virtual address or offset */
|
||||
};
|
||||
|
||||
/*
|
||||
* read chunk(s), encoded as a linked list.
|
||||
*/
|
||||
struct rpcrdma_read_chunk {
|
||||
__be32 rc_discrim; /* 1 indicates presence */
|
||||
__be32 rc_position; /* Position in XDR stream */
|
||||
struct rpcrdma_segment rc_target;
|
||||
};
|
||||
|
||||
/*
|
||||
* write chunk, and reply chunk.
|
||||
*/
|
||||
struct rpcrdma_write_chunk {
|
||||
struct rpcrdma_segment wc_target;
|
||||
};
|
||||
|
||||
/*
|
||||
* write chunk(s), encoded as a counted array.
|
||||
*/
|
||||
struct rpcrdma_write_array {
|
||||
__be32 wc_discrim; /* 1 indicates presence */
|
||||
__be32 wc_nchunks; /* Array count */
|
||||
struct rpcrdma_write_chunk wc_array[0];
|
||||
};
|
||||
|
||||
struct rpcrdma_msg {
|
||||
__be32 rm_xid; /* Mirrors the RPC header xid */
|
||||
__be32 rm_vers; /* Version of this protocol */
|
||||
__be32 rm_credit; /* Buffers requested/granted */
|
||||
__be32 rm_type; /* Type of message (enum rpcrdma_proc) */
|
||||
union {
|
||||
|
||||
struct { /* no chunks */
|
||||
__be32 rm_empty[3]; /* 3 empty chunk lists */
|
||||
} rm_nochunks;
|
||||
|
||||
struct { /* no chunks and padded */
|
||||
__be32 rm_align; /* Padding alignment */
|
||||
__be32 rm_thresh; /* Padding threshold */
|
||||
__be32 rm_pempty[3]; /* 3 empty chunk lists */
|
||||
} rm_padded;
|
||||
|
||||
__be32 rm_chunks[0]; /* read, write and reply chunks */
|
||||
|
||||
} rm_body;
|
||||
};
|
||||
|
||||
#define RPCRDMA_HDRLEN_MIN 28
|
||||
|
||||
enum rpcrdma_errcode {
|
||||
ERR_VERS = 1,
|
||||
ERR_CHUNK = 2
|
||||
};
|
||||
|
||||
struct rpcrdma_err_vers {
|
||||
uint32_t rdma_vers_low; /* Version range supported by peer */
|
||||
uint32_t rdma_vers_high;
|
||||
};
|
||||
|
||||
enum rpcrdma_proc {
|
||||
RDMA_MSG = 0, /* An RPC call or reply msg */
|
||||
RDMA_NOMSG = 1, /* An RPC call or reply msg - separate body */
|
||||
RDMA_MSGP = 2, /* An RPC call or reply msg with padding */
|
||||
RDMA_DONE = 3, /* Client signals reply completion */
|
||||
RDMA_ERROR = 4 /* An RPC RDMA encoding error */
|
||||
};
|
||||
|
||||
#endif /* _LINUX_SUNRPC_RPC_RDMA_H */
|
272
include/linux/sunrpc/sched.h
Normal file
272
include/linux/sunrpc/sched.h
Normal file
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/sched.h
|
||||
*
|
||||
* Scheduling primitives for kernel Sun RPC.
|
||||
*
|
||||
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_SCHED_H_
|
||||
#define _LINUX_SUNRPC_SCHED_H_
|
||||
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/sunrpc/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
|
||||
/*
|
||||
* This is the actual RPC procedure call info.
|
||||
*/
|
||||
struct rpc_procinfo;
|
||||
struct rpc_message {
|
||||
struct rpc_procinfo * rpc_proc; /* Procedure information */
|
||||
void * rpc_argp; /* Arguments */
|
||||
void * rpc_resp; /* Result */
|
||||
struct rpc_cred * rpc_cred; /* Credentials */
|
||||
};
|
||||
|
||||
struct rpc_call_ops;
|
||||
struct rpc_wait_queue;
|
||||
struct rpc_wait {
|
||||
struct list_head list; /* wait queue links */
|
||||
struct list_head links; /* Links to related tasks */
|
||||
struct list_head timer_list; /* Timer list */
|
||||
unsigned long expires;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the RPC task struct
|
||||
*/
|
||||
struct rpc_task {
|
||||
atomic_t tk_count; /* Reference count */
|
||||
struct list_head tk_task; /* global list of tasks */
|
||||
struct rpc_clnt * tk_client; /* RPC client */
|
||||
struct rpc_rqst * tk_rqstp; /* RPC request */
|
||||
|
||||
/*
|
||||
* RPC call state
|
||||
*/
|
||||
struct rpc_message tk_msg; /* RPC call info */
|
||||
|
||||
/*
|
||||
* callback to be executed after waking up
|
||||
* action next procedure for async tasks
|
||||
* tk_ops caller callbacks
|
||||
*/
|
||||
void (*tk_callback)(struct rpc_task *);
|
||||
void (*tk_action)(struct rpc_task *);
|
||||
const struct rpc_call_ops *tk_ops;
|
||||
void * tk_calldata;
|
||||
|
||||
unsigned long tk_timeout; /* timeout for rpc_sleep() */
|
||||
unsigned long tk_runstate; /* Task run status */
|
||||
struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could
|
||||
* be any workqueue
|
||||
*/
|
||||
struct rpc_wait_queue *tk_waitqueue; /* RPC wait queue we're on */
|
||||
union {
|
||||
struct work_struct tk_work; /* Async task work queue */
|
||||
struct rpc_wait tk_wait; /* RPC wait */
|
||||
} u;
|
||||
|
||||
ktime_t tk_start; /* RPC task init timestamp */
|
||||
|
||||
pid_t tk_owner; /* Process id for batching tasks */
|
||||
int tk_status; /* result of last operation */
|
||||
unsigned short tk_flags; /* misc flags */
|
||||
unsigned short tk_timeouts; /* maj timeouts */
|
||||
|
||||
#if defined(RPC_DEBUG) || defined(RPC_TRACEPOINTS)
|
||||
unsigned short tk_pid; /* debugging aid */
|
||||
#endif
|
||||
unsigned char tk_priority : 2,/* Task priority */
|
||||
tk_garb_retry : 2,
|
||||
tk_cred_retry : 2,
|
||||
tk_rebind_retry : 2;
|
||||
};
|
||||
|
||||
typedef void (*rpc_action)(struct rpc_task *);
|
||||
|
||||
struct rpc_call_ops {
|
||||
void (*rpc_call_prepare)(struct rpc_task *, void *);
|
||||
void (*rpc_call_done)(struct rpc_task *, void *);
|
||||
void (*rpc_count_stats)(struct rpc_task *, void *);
|
||||
void (*rpc_release)(void *);
|
||||
};
|
||||
|
||||
struct rpc_task_setup {
|
||||
struct rpc_task *task;
|
||||
struct rpc_clnt *rpc_client;
|
||||
const struct rpc_message *rpc_message;
|
||||
const struct rpc_call_ops *callback_ops;
|
||||
void *callback_data;
|
||||
struct workqueue_struct *workqueue;
|
||||
unsigned short flags;
|
||||
signed char priority;
|
||||
};
|
||||
|
||||
/*
|
||||
* RPC task flags
|
||||
*/
|
||||
#define RPC_TASK_ASYNC 0x0001 /* is an async task */
|
||||
#define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */
|
||||
#define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */
|
||||
#define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */
|
||||
#define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */
|
||||
#define RPC_TASK_KILLED 0x0100 /* task was killed */
|
||||
#define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */
|
||||
#define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */
|
||||
#define RPC_TASK_SENT 0x0800 /* message was sent */
|
||||
#define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */
|
||||
#define RPC_TASK_NOCONNECT 0x2000 /* return ENOTCONN if not connected */
|
||||
#define RPC_TASK_NO_RETRANS_TIMEOUT 0x4000 /* wait forever for a reply */
|
||||
|
||||
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
|
||||
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
|
||||
#define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
|
||||
#define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED)
|
||||
#define RPC_IS_SOFT(t) ((t)->tk_flags & (RPC_TASK_SOFT|RPC_TASK_TIMEOUT))
|
||||
#define RPC_IS_SOFTCONN(t) ((t)->tk_flags & RPC_TASK_SOFTCONN)
|
||||
#define RPC_WAS_SENT(t) ((t)->tk_flags & RPC_TASK_SENT)
|
||||
|
||||
#define RPC_TASK_RUNNING 0
|
||||
#define RPC_TASK_QUEUED 1
|
||||
#define RPC_TASK_ACTIVE 2
|
||||
|
||||
#define RPC_IS_RUNNING(t) test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
|
||||
#define rpc_set_running(t) set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
|
||||
#define rpc_test_and_set_running(t) \
|
||||
test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
|
||||
#define rpc_clear_running(t) \
|
||||
do { \
|
||||
smp_mb__before_atomic(); \
|
||||
clear_bit(RPC_TASK_RUNNING, &(t)->tk_runstate); \
|
||||
smp_mb__after_atomic(); \
|
||||
} while (0)
|
||||
|
||||
#define RPC_IS_QUEUED(t) test_bit(RPC_TASK_QUEUED, &(t)->tk_runstate)
|
||||
#define rpc_set_queued(t) set_bit(RPC_TASK_QUEUED, &(t)->tk_runstate)
|
||||
#define rpc_clear_queued(t) \
|
||||
do { \
|
||||
smp_mb__before_atomic(); \
|
||||
clear_bit(RPC_TASK_QUEUED, &(t)->tk_runstate); \
|
||||
smp_mb__after_atomic(); \
|
||||
} while (0)
|
||||
|
||||
#define RPC_IS_ACTIVATED(t) test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
|
||||
|
||||
/*
|
||||
* Task priorities.
|
||||
* Note: if you change these, you must also change
|
||||
* the task initialization definitions below.
|
||||
*/
|
||||
#define RPC_PRIORITY_LOW (-1)
|
||||
#define RPC_PRIORITY_NORMAL (0)
|
||||
#define RPC_PRIORITY_HIGH (1)
|
||||
#define RPC_PRIORITY_PRIVILEGED (2)
|
||||
#define RPC_NR_PRIORITY (1 + RPC_PRIORITY_PRIVILEGED - RPC_PRIORITY_LOW)
|
||||
|
||||
struct rpc_timer {
|
||||
struct timer_list timer;
|
||||
struct list_head list;
|
||||
unsigned long expires;
|
||||
};
|
||||
|
||||
/*
|
||||
* RPC synchronization objects
|
||||
*/
|
||||
struct rpc_wait_queue {
|
||||
spinlock_t lock;
|
||||
struct list_head tasks[RPC_NR_PRIORITY]; /* task queue for each priority level */
|
||||
pid_t owner; /* process id of last task serviced */
|
||||
unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */
|
||||
unsigned char priority; /* current priority */
|
||||
unsigned char nr; /* # tasks remaining for cookie */
|
||||
unsigned short qlen; /* total # tasks waiting in queue */
|
||||
struct rpc_timer timer_list;
|
||||
#if defined(RPC_DEBUG) || defined(RPC_TRACEPOINTS)
|
||||
const char * name;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the # requests to send consecutively
|
||||
* from a single cookie. The aim is to improve
|
||||
* performance of NFS operations such as read/write.
|
||||
*/
|
||||
#define RPC_BATCH_COUNT 16
|
||||
#define RPC_IS_PRIORITY(q) ((q)->maxpriority > 0)
|
||||
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
struct rpc_task *rpc_new_task(const struct rpc_task_setup *);
|
||||
struct rpc_task *rpc_run_task(const struct rpc_task_setup *);
|
||||
struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
|
||||
const struct rpc_call_ops *ops);
|
||||
void rpc_put_task(struct rpc_task *);
|
||||
void rpc_put_task_async(struct rpc_task *);
|
||||
void rpc_exit_task(struct rpc_task *);
|
||||
void rpc_exit(struct rpc_task *, int);
|
||||
void rpc_release_calldata(const struct rpc_call_ops *, void *);
|
||||
void rpc_killall_tasks(struct rpc_clnt *);
|
||||
void rpc_execute(struct rpc_task *);
|
||||
void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
|
||||
void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
|
||||
void rpc_destroy_wait_queue(struct rpc_wait_queue *);
|
||||
void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
|
||||
rpc_action action);
|
||||
void rpc_sleep_on_priority(struct rpc_wait_queue *,
|
||||
struct rpc_task *,
|
||||
rpc_action action,
|
||||
int priority);
|
||||
void rpc_wake_up_queued_task(struct rpc_wait_queue *,
|
||||
struct rpc_task *);
|
||||
void rpc_wake_up(struct rpc_wait_queue *);
|
||||
struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
|
||||
struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *,
|
||||
bool (*)(struct rpc_task *, void *),
|
||||
void *);
|
||||
void rpc_wake_up_status(struct rpc_wait_queue *, int);
|
||||
void rpc_delay(struct rpc_task *, unsigned long);
|
||||
void * rpc_malloc(struct rpc_task *, size_t);
|
||||
void rpc_free(void *);
|
||||
int rpciod_up(void);
|
||||
void rpciod_down(void);
|
||||
int __rpc_wait_for_completion_task(struct rpc_task *task, wait_bit_action_f *);
|
||||
#ifdef RPC_DEBUG
|
||||
struct net;
|
||||
void rpc_show_tasks(struct net *);
|
||||
#endif
|
||||
int rpc_init_mempool(void);
|
||||
void rpc_destroy_mempool(void);
|
||||
extern struct workqueue_struct *rpciod_workqueue;
|
||||
void rpc_prepare_task(struct rpc_task *task);
|
||||
|
||||
static inline int rpc_wait_for_completion_task(struct rpc_task *task)
|
||||
{
|
||||
return __rpc_wait_for_completion_task(task, NULL);
|
||||
}
|
||||
|
||||
#if defined(RPC_DEBUG) || defined (RPC_TRACEPOINTS)
|
||||
static inline const char * rpc_qname(const struct rpc_wait_queue *q)
|
||||
{
|
||||
return ((q && q->name) ? q->name : "unknown");
|
||||
}
|
||||
|
||||
static inline void rpc_assign_waitqueue_name(struct rpc_wait_queue *q,
|
||||
const char *name)
|
||||
{
|
||||
q->name = name;
|
||||
}
|
||||
#else
|
||||
static inline void rpc_assign_waitqueue_name(struct rpc_wait_queue *q,
|
||||
const char *name)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_SUNRPC_SCHED_H_ */
|
84
include/linux/sunrpc/stats.h
Normal file
84
include/linux/sunrpc/stats.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/stats.h
|
||||
*
|
||||
* Client statistics collection for SUN RPC
|
||||
*
|
||||
* Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_STATS_H
|
||||
#define _LINUX_SUNRPC_STATS_H
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
struct rpc_stat {
|
||||
const struct rpc_program *program;
|
||||
|
||||
unsigned int netcnt,
|
||||
netudpcnt,
|
||||
nettcpcnt,
|
||||
nettcpconn,
|
||||
netreconn;
|
||||
unsigned int rpccnt,
|
||||
rpcretrans,
|
||||
rpcauthrefresh,
|
||||
rpcgarbage;
|
||||
};
|
||||
|
||||
struct svc_stat {
|
||||
struct svc_program * program;
|
||||
|
||||
unsigned int netcnt,
|
||||
netudpcnt,
|
||||
nettcpcnt,
|
||||
nettcpconn;
|
||||
unsigned int rpccnt,
|
||||
rpcbadfmt,
|
||||
rpcbadauth,
|
||||
rpcbadclnt;
|
||||
};
|
||||
|
||||
struct net;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
int rpc_proc_init(struct net *);
|
||||
void rpc_proc_exit(struct net *);
|
||||
#else
|
||||
static inline int rpc_proc_init(struct net *net)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rpc_proc_exit(struct net *net)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODULE
|
||||
void rpc_modcount(struct inode *, int);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry * rpc_proc_register(struct net *,struct rpc_stat *);
|
||||
void rpc_proc_unregister(struct net *,const char *);
|
||||
void rpc_proc_zero(const struct rpc_program *);
|
||||
struct proc_dir_entry * svc_proc_register(struct net *, struct svc_stat *,
|
||||
const struct file_operations *);
|
||||
void svc_proc_unregister(struct net *, const char *);
|
||||
|
||||
void svc_seq_show(struct seq_file *,
|
||||
const struct svc_stat *);
|
||||
#else
|
||||
|
||||
static inline struct proc_dir_entry *rpc_proc_register(struct net *net, struct rpc_stat *s) { return NULL; }
|
||||
static inline void rpc_proc_unregister(struct net *net, const char *p) {}
|
||||
static inline void rpc_proc_zero(const struct rpc_program *p) {}
|
||||
|
||||
static inline struct proc_dir_entry *svc_proc_register(struct net *net, struct svc_stat *s,
|
||||
const struct file_operations *f) { return NULL; }
|
||||
static inline void svc_proc_unregister(struct net *net, const char *p) {}
|
||||
|
||||
static inline void svc_seq_show(struct seq_file *seq,
|
||||
const struct svc_stat *st) {}
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_SUNRPC_STATS_H */
|
464
include/linux/sunrpc/svc.h
Normal file
464
include/linux/sunrpc/svc.h
Normal file
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/svc.h
|
||||
*
|
||||
* RPC server declarations.
|
||||
*
|
||||
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SUNRPC_SVC_H
|
||||
#define SUNRPC_SVC_H
|
||||
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/sunrpc/types.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/auth.h>
|
||||
#include <linux/sunrpc/svcauth.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
/*
|
||||
* This is the RPC server thread function prototype
|
||||
*/
|
||||
typedef int (*svc_thread_fn)(void *);
|
||||
|
||||
/* statistics for svc_pool structures */
|
||||
struct svc_pool_stats {
|
||||
unsigned long packets;
|
||||
unsigned long sockets_queued;
|
||||
unsigned long threads_woken;
|
||||
unsigned long threads_timedout;
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* RPC service thread pool.
|
||||
*
|
||||
* Pool of threads and temporary sockets. Generally there is only
|
||||
* a single one of these per RPC service, but on NUMA machines those
|
||||
* services that can benefit from it (i.e. nfs but not lockd) will
|
||||
* have one pool per NUMA node. This optimisation reduces cross-
|
||||
* node traffic on multi-node NUMA NFS servers.
|
||||
*/
|
||||
struct svc_pool {
|
||||
unsigned int sp_id; /* pool id; also node id on NUMA */
|
||||
spinlock_t sp_lock; /* protects all fields */
|
||||
struct list_head sp_threads; /* idle server threads */
|
||||
struct list_head sp_sockets; /* pending sockets */
|
||||
unsigned int sp_nrthreads; /* # of threads in pool */
|
||||
struct list_head sp_all_threads; /* all server threads */
|
||||
struct svc_pool_stats sp_stats; /* statistics on pool operation */
|
||||
int sp_task_pending;/* has pending task */
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
/*
|
||||
* RPC service.
|
||||
*
|
||||
* An RPC service is a ``daemon,'' possibly multithreaded, which
|
||||
* receives and processes incoming RPC messages.
|
||||
* It has one or more transport sockets associated with it, and maintains
|
||||
* a list of idle threads waiting for input.
|
||||
*
|
||||
* We currently do not support more than one RPC program per daemon.
|
||||
*/
|
||||
struct svc_serv {
|
||||
struct svc_program * sv_program; /* RPC program */
|
||||
struct svc_stat * sv_stats; /* RPC statistics */
|
||||
spinlock_t sv_lock;
|
||||
unsigned int sv_nrthreads; /* # of server threads */
|
||||
unsigned int sv_maxconn; /* max connections allowed or
|
||||
* '0' causing max to be based
|
||||
* on number of threads. */
|
||||
|
||||
unsigned int sv_max_payload; /* datagram payload size */
|
||||
unsigned int sv_max_mesg; /* max_payload + 1 page for overheads */
|
||||
unsigned int sv_xdrsize; /* XDR buffer size */
|
||||
struct list_head sv_permsocks; /* all permanent sockets */
|
||||
struct list_head sv_tempsocks; /* all temporary sockets */
|
||||
int sv_tmpcnt; /* count of temporary sockets */
|
||||
struct timer_list sv_temptimer; /* timer for aging temporary sockets */
|
||||
|
||||
char * sv_name; /* service name */
|
||||
|
||||
unsigned int sv_nrpools; /* number of thread pools */
|
||||
struct svc_pool * sv_pools; /* array of thread pools */
|
||||
|
||||
void (*sv_shutdown)(struct svc_serv *serv,
|
||||
struct net *net);
|
||||
/* Callback to use when last thread
|
||||
* exits.
|
||||
*/
|
||||
|
||||
struct module * sv_module; /* optional module to count when
|
||||
* adding threads */
|
||||
svc_thread_fn sv_function; /* main function for threads */
|
||||
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
|
||||
struct list_head sv_cb_list; /* queue for callback requests
|
||||
* that arrive over the same
|
||||
* connection */
|
||||
spinlock_t sv_cb_lock; /* protects the svc_cb_list */
|
||||
wait_queue_head_t sv_cb_waitq; /* sleep here if there are no
|
||||
* entries in the svc_cb_list */
|
||||
struct svc_xprt *sv_bc_xprt; /* callback on fore channel */
|
||||
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
|
||||
};
|
||||
|
||||
/*
|
||||
* We use sv_nrthreads as a reference count. svc_destroy() drops
|
||||
* this refcount, so we need to bump it up around operations that
|
||||
* change the number of threads. Horrible, but there it is.
|
||||
* Should be called with the BKL held.
|
||||
*/
|
||||
static inline void svc_get(struct svc_serv *serv)
|
||||
{
|
||||
serv->sv_nrthreads++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum payload size supported by a kernel RPC server.
|
||||
* This is use to determine the max number of pages nfsd is
|
||||
* willing to return in a single READ operation.
|
||||
*
|
||||
* These happen to all be powers of 2, which is not strictly
|
||||
* necessary but helps enforce the real limitation, which is
|
||||
* that they should be multiples of PAGE_CACHE_SIZE.
|
||||
*
|
||||
* For UDP transports, a block plus NFS,RPC, and UDP headers
|
||||
* has to fit into the IP datagram limit of 64K. The largest
|
||||
* feasible number for all known page sizes is probably 48K,
|
||||
* but we choose 32K here. This is the same as the historical
|
||||
* Linux limit; someone who cares more about NFS/UDP performance
|
||||
* can test a larger number.
|
||||
*
|
||||
* For TCP transports we have more freedom. A size of 1MB is
|
||||
* chosen to match the client limit. Other OSes are known to
|
||||
* have larger limits, but those numbers are probably beyond
|
||||
* the point of diminishing returns.
|
||||
*/
|
||||
#define RPCSVC_MAXPAYLOAD (1*1024*1024u)
|
||||
#define RPCSVC_MAXPAYLOAD_TCP RPCSVC_MAXPAYLOAD
|
||||
#define RPCSVC_MAXPAYLOAD_UDP (32*1024u)
|
||||
|
||||
extern u32 svc_max_payload(const struct svc_rqst *rqstp);
|
||||
|
||||
/*
|
||||
* RPC Requsts and replies are stored in one or more pages.
|
||||
* We maintain an array of pages for each server thread.
|
||||
* Requests are copied into these pages as they arrive. Remaining
|
||||
* pages are available to write the reply into.
|
||||
*
|
||||
* Pages are sent using ->sendpage so each server thread needs to
|
||||
* allocate more to replace those used in sending. To help keep track
|
||||
* of these pages we have a receive list where all pages initialy live,
|
||||
* and a send list where pages are moved to when there are to be part
|
||||
* of a reply.
|
||||
*
|
||||
* We use xdr_buf for holding responses as it fits well with NFS
|
||||
* read responses (that have a header, and some data pages, and possibly
|
||||
* a tail) and means we can share some client side routines.
|
||||
*
|
||||
* The xdr_buf.head kvec always points to the first page in the rq_*pages
|
||||
* list. The xdr_buf.pages pointer points to the second page on that
|
||||
* list. xdr_buf.tail points to the end of the first page.
|
||||
* This assumes that the non-page part of an rpc reply will fit
|
||||
* in a page - NFSd ensures this. lockd also has no trouble.
|
||||
*
|
||||
* Each request/reply pair can have at most one "payload", plus two pages,
|
||||
* one for the request, and one for the reply.
|
||||
* We using ->sendfile to return read data, we might need one extra page
|
||||
* if the request is not page-aligned. So add another '1'.
|
||||
*/
|
||||
#define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE \
|
||||
+ 2 + 1)
|
||||
|
||||
static inline u32 svc_getnl(struct kvec *iov)
|
||||
{
|
||||
__be32 val, *vp;
|
||||
vp = iov->iov_base;
|
||||
val = *vp++;
|
||||
iov->iov_base = (void*)vp;
|
||||
iov->iov_len -= sizeof(__be32);
|
||||
return ntohl(val);
|
||||
}
|
||||
|
||||
static inline void svc_putnl(struct kvec *iov, u32 val)
|
||||
{
|
||||
__be32 *vp = iov->iov_base + iov->iov_len;
|
||||
*vp = htonl(val);
|
||||
iov->iov_len += sizeof(__be32);
|
||||
}
|
||||
|
||||
static inline __be32 svc_getu32(struct kvec *iov)
|
||||
{
|
||||
__be32 val, *vp;
|
||||
vp = iov->iov_base;
|
||||
val = *vp++;
|
||||
iov->iov_base = (void*)vp;
|
||||
iov->iov_len -= sizeof(__be32);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void svc_ungetu32(struct kvec *iov)
|
||||
{
|
||||
__be32 *vp = (__be32 *)iov->iov_base;
|
||||
iov->iov_base = (void *)(vp - 1);
|
||||
iov->iov_len += sizeof(*vp);
|
||||
}
|
||||
|
||||
static inline void svc_putu32(struct kvec *iov, __be32 val)
|
||||
{
|
||||
__be32 *vp = iov->iov_base + iov->iov_len;
|
||||
*vp = val;
|
||||
iov->iov_len += sizeof(__be32);
|
||||
}
|
||||
|
||||
/*
|
||||
* The context of a single thread, including the request currently being
|
||||
* processed.
|
||||
*/
|
||||
struct svc_rqst {
|
||||
struct list_head rq_list; /* idle list */
|
||||
struct list_head rq_all; /* all threads list */
|
||||
struct svc_xprt * rq_xprt; /* transport ptr */
|
||||
|
||||
struct sockaddr_storage rq_addr; /* peer address */
|
||||
size_t rq_addrlen;
|
||||
struct sockaddr_storage rq_daddr; /* dest addr of request
|
||||
* - reply from here */
|
||||
size_t rq_daddrlen;
|
||||
|
||||
struct svc_serv * rq_server; /* RPC service definition */
|
||||
struct svc_pool * rq_pool; /* thread pool */
|
||||
struct svc_procedure * rq_procinfo; /* procedure info */
|
||||
struct auth_ops * rq_authop; /* authentication flavour */
|
||||
struct svc_cred rq_cred; /* auth info */
|
||||
void * rq_xprt_ctxt; /* transport specific context ptr */
|
||||
struct svc_deferred_req*rq_deferred; /* deferred request we are replaying */
|
||||
bool rq_usedeferral; /* use deferral */
|
||||
|
||||
size_t rq_xprt_hlen; /* xprt header len */
|
||||
struct xdr_buf rq_arg;
|
||||
struct xdr_buf rq_res;
|
||||
struct page * rq_pages[RPCSVC_MAXPAGES];
|
||||
struct page * *rq_respages; /* points into rq_pages */
|
||||
struct page * *rq_next_page; /* next reply page to use */
|
||||
struct page * *rq_page_end; /* one past the last page */
|
||||
|
||||
struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */
|
||||
|
||||
__be32 rq_xid; /* transmission id */
|
||||
u32 rq_prog; /* program number */
|
||||
u32 rq_vers; /* program version */
|
||||
u32 rq_proc; /* procedure number */
|
||||
u32 rq_prot; /* IP protocol */
|
||||
unsigned short
|
||||
rq_secure : 1; /* secure port */
|
||||
unsigned short rq_local : 1; /* local request */
|
||||
|
||||
void * rq_argp; /* decoded arguments */
|
||||
void * rq_resp; /* xdr'd results */
|
||||
void * rq_auth_data; /* flavor-specific data */
|
||||
int rq_auth_slack; /* extra space xdr code
|
||||
* should leave in head
|
||||
* for krb5i, krb5p.
|
||||
*/
|
||||
int rq_reserved; /* space on socket outq
|
||||
* reserved for this request
|
||||
*/
|
||||
|
||||
struct cache_req rq_chandle; /* handle passed to caches for
|
||||
* request delaying
|
||||
*/
|
||||
bool rq_dropme;
|
||||
/* Catering to nfsd */
|
||||
struct auth_domain * rq_client; /* RPC peer info */
|
||||
struct auth_domain * rq_gssclient; /* "gss/"-style peer info */
|
||||
int rq_cachetype;
|
||||
struct svc_cacherep * rq_cacherep; /* cache info */
|
||||
bool rq_splice_ok; /* turned off in gss privacy
|
||||
* to prevent encrypting page
|
||||
* cache pages */
|
||||
struct task_struct *rq_task; /* service thread */
|
||||
};
|
||||
|
||||
#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net)
|
||||
|
||||
/*
|
||||
* Rigorous type checking on sockaddr type conversions
|
||||
*/
|
||||
static inline struct sockaddr_in *svc_addr_in(const struct svc_rqst *rqst)
|
||||
{
|
||||
return (struct sockaddr_in *) &rqst->rq_addr;
|
||||
}
|
||||
|
||||
static inline struct sockaddr_in6 *svc_addr_in6(const struct svc_rqst *rqst)
|
||||
{
|
||||
return (struct sockaddr_in6 *) &rqst->rq_addr;
|
||||
}
|
||||
|
||||
static inline struct sockaddr *svc_addr(const struct svc_rqst *rqst)
|
||||
{
|
||||
return (struct sockaddr *) &rqst->rq_addr;
|
||||
}
|
||||
|
||||
static inline struct sockaddr_in *svc_daddr_in(const struct svc_rqst *rqst)
|
||||
{
|
||||
return (struct sockaddr_in *) &rqst->rq_daddr;
|
||||
}
|
||||
|
||||
static inline struct sockaddr_in6 *svc_daddr_in6(const struct svc_rqst *rqst)
|
||||
{
|
||||
return (struct sockaddr_in6 *) &rqst->rq_daddr;
|
||||
}
|
||||
|
||||
static inline struct sockaddr *svc_daddr(const struct svc_rqst *rqst)
|
||||
{
|
||||
return (struct sockaddr *) &rqst->rq_daddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check buffer bounds after decoding arguments
|
||||
*/
|
||||
static inline int
|
||||
xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
char *cp = (char *)p;
|
||||
struct kvec *vec = &rqstp->rq_arg.head[0];
|
||||
return cp >= (char*)vec->iov_base
|
||||
&& cp <= (char*)vec->iov_base + vec->iov_len;
|
||||
}
|
||||
|
||||
static inline int
|
||||
xdr_ressize_check(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct kvec *vec = &rqstp->rq_res.head[0];
|
||||
char *cp = (char*)p;
|
||||
|
||||
vec->iov_len = cp - (char*)vec->iov_base;
|
||||
|
||||
return vec->iov_len <= PAGE_SIZE;
|
||||
}
|
||||
|
||||
static inline void svc_free_res_pages(struct svc_rqst *rqstp)
|
||||
{
|
||||
while (rqstp->rq_next_page != rqstp->rq_respages) {
|
||||
struct page **pp = --rqstp->rq_next_page;
|
||||
if (*pp) {
|
||||
put_page(*pp);
|
||||
*pp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct svc_deferred_req {
|
||||
u32 prot; /* protocol (UDP or TCP) */
|
||||
struct svc_xprt *xprt;
|
||||
struct sockaddr_storage addr; /* where reply must go */
|
||||
size_t addrlen;
|
||||
struct sockaddr_storage daddr; /* where reply must come from */
|
||||
size_t daddrlen;
|
||||
struct cache_deferred_req handle;
|
||||
size_t xprt_hlen;
|
||||
int argslen;
|
||||
__be32 args[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* List of RPC programs on the same transport endpoint
|
||||
*/
|
||||
struct svc_program {
|
||||
struct svc_program * pg_next; /* other programs (same xprt) */
|
||||
u32 pg_prog; /* program number */
|
||||
unsigned int pg_lovers; /* lowest version */
|
||||
unsigned int pg_hivers; /* highest version */
|
||||
unsigned int pg_nvers; /* number of versions */
|
||||
struct svc_version ** pg_vers; /* version array */
|
||||
char * pg_name; /* service name */
|
||||
char * pg_class; /* class name: services sharing authentication */
|
||||
struct svc_stat * pg_stats; /* rpc statistics */
|
||||
int (*pg_authenticate)(struct svc_rqst *);
|
||||
};
|
||||
|
||||
/*
|
||||
* RPC program version
|
||||
*/
|
||||
struct svc_version {
|
||||
u32 vs_vers; /* version number */
|
||||
u32 vs_nproc; /* number of procedures */
|
||||
struct svc_procedure * vs_proc; /* per-procedure info */
|
||||
u32 vs_xdrsize; /* xdrsize needed for this version */
|
||||
|
||||
unsigned int vs_hidden : 1, /* Don't register with portmapper.
|
||||
* Only used for nfsacl so far. */
|
||||
vs_rpcb_optnl:1;/* Don't care the result of register.
|
||||
* Only used for nfsv4. */
|
||||
|
||||
/* Override dispatch function (e.g. when caching replies).
|
||||
* A return value of 0 means drop the request.
|
||||
* vs_dispatch == NULL means use default dispatcher.
|
||||
*/
|
||||
int (*vs_dispatch)(struct svc_rqst *, __be32 *);
|
||||
};
|
||||
|
||||
/*
|
||||
* RPC procedure info
|
||||
*/
|
||||
typedef __be32 (*svc_procfunc)(struct svc_rqst *, void *argp, void *resp);
|
||||
struct svc_procedure {
|
||||
svc_procfunc pc_func; /* process the request */
|
||||
kxdrproc_t pc_decode; /* XDR decode args */
|
||||
kxdrproc_t pc_encode; /* XDR encode result */
|
||||
kxdrproc_t pc_release; /* XDR free result */
|
||||
unsigned int pc_argsize; /* argument struct size */
|
||||
unsigned int pc_ressize; /* result struct size */
|
||||
unsigned int pc_count; /* call count */
|
||||
unsigned int pc_cachetype; /* cache info (NFS) */
|
||||
unsigned int pc_xdrressize; /* maximum size of XDR reply */
|
||||
};
|
||||
|
||||
/*
|
||||
* Function prototypes.
|
||||
*/
|
||||
int svc_rpcb_setup(struct svc_serv *serv, struct net *net);
|
||||
void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net);
|
||||
int svc_bind(struct svc_serv *serv, struct net *net);
|
||||
struct svc_serv *svc_create(struct svc_program *, unsigned int,
|
||||
void (*shutdown)(struct svc_serv *, struct net *net));
|
||||
struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
|
||||
struct svc_pool *pool, int node);
|
||||
void svc_exit_thread(struct svc_rqst *);
|
||||
struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
|
||||
void (*shutdown)(struct svc_serv *, struct net *net),
|
||||
svc_thread_fn, struct module *);
|
||||
int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
|
||||
int svc_pool_stats_open(struct svc_serv *serv, struct file *file);
|
||||
void svc_destroy(struct svc_serv *);
|
||||
void svc_shutdown_net(struct svc_serv *, struct net *);
|
||||
int svc_process(struct svc_rqst *);
|
||||
int bc_svc_process(struct svc_serv *, struct rpc_rqst *,
|
||||
struct svc_rqst *);
|
||||
int svc_register(const struct svc_serv *, struct net *, const int,
|
||||
const unsigned short, const unsigned short);
|
||||
|
||||
void svc_wake_up(struct svc_serv *);
|
||||
void svc_reserve(struct svc_rqst *rqstp, int space);
|
||||
struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu);
|
||||
char * svc_print_addr(struct svc_rqst *, char *, size_t);
|
||||
|
||||
#define RPC_MAX_ADDRBUFLEN (63U)
|
||||
|
||||
/*
|
||||
* When we want to reduce the size of the reserved space in the response
|
||||
* buffer, we need to take into account the size of any checksum data that
|
||||
* may be at the end of the packet. This is difficult to determine exactly
|
||||
* for all cases without actually generating the checksum, so we just use a
|
||||
* static value.
|
||||
*/
|
||||
static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space)
|
||||
{
|
||||
svc_reserve(rqstp, space + rqstp->rq_auth_slack);
|
||||
}
|
||||
|
||||
#endif /* SUNRPC_SVC_H */
|
308
include/linux/sunrpc/svc_rdma.h
Normal file
308
include/linux/sunrpc/svc_rdma.h
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2006 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.
|
||||
*
|
||||
* Author: Tom Tucker <tom@opengridcomputing.com>
|
||||
*/
|
||||
|
||||
#ifndef SVC_RDMA_H
|
||||
#define SVC_RDMA_H
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/svcsock.h>
|
||||
#include <linux/sunrpc/rpc_rdma.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <rdma/rdma_cm.h>
|
||||
#define SVCRDMA_DEBUG
|
||||
|
||||
/* RPC/RDMA parameters and stats */
|
||||
extern unsigned int svcrdma_ord;
|
||||
extern unsigned int svcrdma_max_requests;
|
||||
extern unsigned int svcrdma_max_req_size;
|
||||
|
||||
extern atomic_t rdma_stat_recv;
|
||||
extern atomic_t rdma_stat_read;
|
||||
extern atomic_t rdma_stat_write;
|
||||
extern atomic_t rdma_stat_sq_starve;
|
||||
extern atomic_t rdma_stat_rq_starve;
|
||||
extern atomic_t rdma_stat_rq_poll;
|
||||
extern atomic_t rdma_stat_rq_prod;
|
||||
extern atomic_t rdma_stat_sq_poll;
|
||||
extern atomic_t rdma_stat_sq_prod;
|
||||
|
||||
#define RPCRDMA_VERSION 1
|
||||
|
||||
/*
|
||||
* Contexts are built when an RDMA request is created and are a
|
||||
* record of the resources that can be recovered when the request
|
||||
* completes.
|
||||
*/
|
||||
struct svc_rdma_op_ctxt {
|
||||
struct svc_rdma_op_ctxt *read_hdr;
|
||||
struct svc_rdma_fastreg_mr *frmr;
|
||||
int hdr_count;
|
||||
struct xdr_buf arg;
|
||||
struct list_head dto_q;
|
||||
enum ib_wr_opcode wr_op;
|
||||
enum ib_wc_status wc_status;
|
||||
u32 byte_len;
|
||||
struct svcxprt_rdma *xprt;
|
||||
unsigned long flags;
|
||||
enum dma_data_direction direction;
|
||||
int count;
|
||||
struct ib_sge sge[RPCSVC_MAXPAGES];
|
||||
struct page *pages[RPCSVC_MAXPAGES];
|
||||
};
|
||||
|
||||
/*
|
||||
* NFS_ requests are mapped on the client side by the chunk lists in
|
||||
* the RPCRDMA header. During the fetching of the RPC from the client
|
||||
* and the writing of the reply to the client, the memory in the
|
||||
* client and the memory in the server must be mapped as contiguous
|
||||
* vaddr/len for access by the hardware. These data strucures keep
|
||||
* these mappings.
|
||||
*
|
||||
* For an RDMA_WRITE, the 'sge' maps the RPC REPLY. For RDMA_READ, the
|
||||
* 'sge' in the svc_rdma_req_map maps the server side RPC reply and the
|
||||
* 'ch' field maps the read-list of the RPCRDMA header to the 'sge'
|
||||
* mapping of the reply.
|
||||
*/
|
||||
struct svc_rdma_chunk_sge {
|
||||
int start; /* sge no for this chunk */
|
||||
int count; /* sge count for this chunk */
|
||||
};
|
||||
struct svc_rdma_fastreg_mr {
|
||||
struct ib_mr *mr;
|
||||
void *kva;
|
||||
struct ib_fast_reg_page_list *page_list;
|
||||
int page_list_len;
|
||||
unsigned long access_flags;
|
||||
unsigned long map_len;
|
||||
enum dma_data_direction direction;
|
||||
struct list_head frmr_list;
|
||||
};
|
||||
struct svc_rdma_req_map {
|
||||
unsigned long count;
|
||||
union {
|
||||
struct kvec sge[RPCSVC_MAXPAGES];
|
||||
struct svc_rdma_chunk_sge ch[RPCSVC_MAXPAGES];
|
||||
unsigned long lkey[RPCSVC_MAXPAGES];
|
||||
};
|
||||
};
|
||||
#define RDMACTXT_F_LAST_CTXT 2
|
||||
|
||||
#define SVCRDMA_DEVCAP_FAST_REG 1 /* fast mr registration */
|
||||
#define SVCRDMA_DEVCAP_READ_W_INV 2 /* read w/ invalidate */
|
||||
|
||||
struct svcxprt_rdma {
|
||||
struct svc_xprt sc_xprt; /* SVC transport structure */
|
||||
struct rdma_cm_id *sc_cm_id; /* RDMA connection id */
|
||||
struct list_head sc_accept_q; /* Conn. waiting accept */
|
||||
int sc_ord; /* RDMA read limit */
|
||||
int sc_max_sge;
|
||||
|
||||
int sc_sq_depth; /* Depth of SQ */
|
||||
atomic_t sc_sq_count; /* Number of SQ WR on queue */
|
||||
|
||||
int sc_max_requests; /* Depth of RQ */
|
||||
int sc_max_req_size; /* Size of each RQ WR buf */
|
||||
|
||||
struct ib_pd *sc_pd;
|
||||
|
||||
atomic_t sc_dma_used;
|
||||
atomic_t sc_ctxt_used;
|
||||
struct list_head sc_rq_dto_q;
|
||||
spinlock_t sc_rq_dto_lock;
|
||||
struct ib_qp *sc_qp;
|
||||
struct ib_cq *sc_rq_cq;
|
||||
struct ib_cq *sc_sq_cq;
|
||||
struct ib_mr *sc_phys_mr; /* MR for server memory */
|
||||
u32 sc_dev_caps; /* distilled device caps */
|
||||
u32 sc_dma_lkey; /* local dma key */
|
||||
unsigned int sc_frmr_pg_list_len;
|
||||
struct list_head sc_frmr_q;
|
||||
spinlock_t sc_frmr_q_lock;
|
||||
|
||||
spinlock_t sc_lock; /* transport lock */
|
||||
|
||||
wait_queue_head_t sc_send_wait; /* SQ exhaustion waitlist */
|
||||
unsigned long sc_flags;
|
||||
struct list_head sc_dto_q; /* DTO tasklet I/O pending Q */
|
||||
struct list_head sc_read_complete_q;
|
||||
struct work_struct sc_work;
|
||||
};
|
||||
/* sc_flags */
|
||||
#define RDMAXPRT_RQ_PENDING 1
|
||||
#define RDMAXPRT_SQ_PENDING 2
|
||||
#define RDMAXPRT_CONN_PENDING 3
|
||||
|
||||
#define RPCRDMA_LISTEN_BACKLOG 10
|
||||
/* The default ORD value is based on two outstanding full-size writes with a
|
||||
* page size of 4k, or 32k * 2 ops / 4k = 16 outstanding RDMA_READ. */
|
||||
#define RPCRDMA_ORD (64/4)
|
||||
#define RPCRDMA_SQ_DEPTH_MULT 8
|
||||
#define RPCRDMA_MAX_REQUESTS 32
|
||||
#define RPCRDMA_MAX_REQ_SIZE 4096
|
||||
|
||||
/* svc_rdma_marshal.c */
|
||||
extern void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *,
|
||||
int *, int *);
|
||||
extern int svc_rdma_xdr_decode_req(struct rpcrdma_msg **, struct svc_rqst *);
|
||||
extern int svc_rdma_xdr_decode_deferred_req(struct svc_rqst *);
|
||||
extern int svc_rdma_xdr_encode_error(struct svcxprt_rdma *,
|
||||
struct rpcrdma_msg *,
|
||||
enum rpcrdma_errcode, u32 *);
|
||||
extern void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *, int);
|
||||
extern void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *, int);
|
||||
extern void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *, int,
|
||||
__be32, __be64, u32);
|
||||
extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *,
|
||||
struct rpcrdma_msg *,
|
||||
struct rpcrdma_msg *,
|
||||
enum rpcrdma_proc);
|
||||
extern int svc_rdma_xdr_get_reply_hdr_len(struct rpcrdma_msg *);
|
||||
|
||||
/* svc_rdma_recvfrom.c */
|
||||
extern int svc_rdma_recvfrom(struct svc_rqst *);
|
||||
|
||||
/* svc_rdma_sendto.c */
|
||||
extern int svc_rdma_sendto(struct svc_rqst *);
|
||||
|
||||
/* svc_rdma_transport.c */
|
||||
extern int svc_rdma_send(struct svcxprt_rdma *, struct ib_send_wr *);
|
||||
extern void svc_rdma_send_error(struct svcxprt_rdma *, struct rpcrdma_msg *,
|
||||
enum rpcrdma_errcode);
|
||||
struct page *svc_rdma_get_page(void);
|
||||
extern int svc_rdma_post_recv(struct svcxprt_rdma *);
|
||||
extern int svc_rdma_create_listen(struct svc_serv *, int, struct sockaddr *);
|
||||
extern struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *);
|
||||
extern void svc_rdma_put_context(struct svc_rdma_op_ctxt *, int);
|
||||
extern void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt);
|
||||
extern struct svc_rdma_req_map *svc_rdma_get_req_map(void);
|
||||
extern void svc_rdma_put_req_map(struct svc_rdma_req_map *);
|
||||
extern int svc_rdma_fastreg(struct svcxprt_rdma *, struct svc_rdma_fastreg_mr *);
|
||||
extern struct svc_rdma_fastreg_mr *svc_rdma_get_frmr(struct svcxprt_rdma *);
|
||||
extern void svc_rdma_put_frmr(struct svcxprt_rdma *,
|
||||
struct svc_rdma_fastreg_mr *);
|
||||
extern void svc_sq_reap(struct svcxprt_rdma *);
|
||||
extern void svc_rq_reap(struct svcxprt_rdma *);
|
||||
extern struct svc_xprt_class svc_rdma_class;
|
||||
extern void svc_rdma_prep_reply_hdr(struct svc_rqst *);
|
||||
|
||||
/* svc_rdma.c */
|
||||
extern int svc_rdma_init(void);
|
||||
extern void svc_rdma_cleanup(void);
|
||||
|
||||
/*
|
||||
* Returns the address of the first read chunk or <nul> if no read chunk is
|
||||
* present
|
||||
*/
|
||||
static inline struct rpcrdma_read_chunk *
|
||||
svc_rdma_get_read_chunk(struct rpcrdma_msg *rmsgp)
|
||||
{
|
||||
struct rpcrdma_read_chunk *ch =
|
||||
(struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
|
||||
|
||||
if (ch->rc_discrim == 0)
|
||||
return NULL;
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address of the first read write array element or <nul> if no
|
||||
* write array list is present
|
||||
*/
|
||||
static inline struct rpcrdma_write_array *
|
||||
svc_rdma_get_write_array(struct rpcrdma_msg *rmsgp)
|
||||
{
|
||||
if (rmsgp->rm_body.rm_chunks[0] != 0
|
||||
|| rmsgp->rm_body.rm_chunks[1] == 0)
|
||||
return NULL;
|
||||
|
||||
return (struct rpcrdma_write_array *)&rmsgp->rm_body.rm_chunks[1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address of the first reply array element or <nul> if no
|
||||
* reply array is present
|
||||
*/
|
||||
static inline struct rpcrdma_write_array *
|
||||
svc_rdma_get_reply_array(struct rpcrdma_msg *rmsgp)
|
||||
{
|
||||
struct rpcrdma_read_chunk *rch;
|
||||
struct rpcrdma_write_array *wr_ary;
|
||||
struct rpcrdma_write_array *rp_ary;
|
||||
|
||||
/* XXX: Need to fix when reply list may occur with read-list and/or
|
||||
* write list */
|
||||
if (rmsgp->rm_body.rm_chunks[0] != 0 ||
|
||||
rmsgp->rm_body.rm_chunks[1] != 0)
|
||||
return NULL;
|
||||
|
||||
rch = svc_rdma_get_read_chunk(rmsgp);
|
||||
if (rch) {
|
||||
while (rch->rc_discrim)
|
||||
rch++;
|
||||
|
||||
/* The reply list follows an empty write array located
|
||||
* at 'rc_position' here. The reply array is at rc_target.
|
||||
*/
|
||||
rp_ary = (struct rpcrdma_write_array *)&rch->rc_target;
|
||||
|
||||
goto found_it;
|
||||
}
|
||||
|
||||
wr_ary = svc_rdma_get_write_array(rmsgp);
|
||||
if (wr_ary) {
|
||||
rp_ary = (struct rpcrdma_write_array *)
|
||||
&wr_ary->
|
||||
wc_array[ntohl(wr_ary->wc_nchunks)].wc_target.rs_length;
|
||||
|
||||
goto found_it;
|
||||
}
|
||||
|
||||
/* No read list, no write list */
|
||||
rp_ary = (struct rpcrdma_write_array *)
|
||||
&rmsgp->rm_body.rm_chunks[2];
|
||||
|
||||
found_it:
|
||||
if (rp_ary->wc_discrim == 0)
|
||||
return NULL;
|
||||
|
||||
return rp_ary;
|
||||
}
|
||||
#endif
|
211
include/linux/sunrpc/svc_xprt.h
Normal file
211
include/linux/sunrpc/svc_xprt.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/svc_xprt.h
|
||||
*
|
||||
* RPC server transport I/O
|
||||
*/
|
||||
|
||||
#ifndef SUNRPC_SVC_XPRT_H
|
||||
#define SUNRPC_SVC_XPRT_H
|
||||
|
||||
#include <linux/sunrpc/svc.h>
|
||||
|
||||
struct module;
|
||||
|
||||
struct svc_xprt_ops {
|
||||
struct svc_xprt *(*xpo_create)(struct svc_serv *,
|
||||
struct net *net,
|
||||
struct sockaddr *, int,
|
||||
int);
|
||||
struct svc_xprt *(*xpo_accept)(struct svc_xprt *);
|
||||
int (*xpo_has_wspace)(struct svc_xprt *);
|
||||
int (*xpo_recvfrom)(struct svc_rqst *);
|
||||
void (*xpo_prep_reply_hdr)(struct svc_rqst *);
|
||||
int (*xpo_sendto)(struct svc_rqst *);
|
||||
void (*xpo_release_rqst)(struct svc_rqst *);
|
||||
void (*xpo_detach)(struct svc_xprt *);
|
||||
void (*xpo_free)(struct svc_xprt *);
|
||||
int (*xpo_secure_port)(struct svc_rqst *);
|
||||
void (*xpo_adjust_wspace)(struct svc_xprt *);
|
||||
};
|
||||
|
||||
struct svc_xprt_class {
|
||||
const char *xcl_name;
|
||||
struct module *xcl_owner;
|
||||
struct svc_xprt_ops *xcl_ops;
|
||||
struct list_head xcl_list;
|
||||
u32 xcl_max_payload;
|
||||
int xcl_ident;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is embedded in an object that wants a callback before deleting
|
||||
* an xprt; intended for use by NFSv4.1, which needs to know when a
|
||||
* client's tcp connection (and hence possibly a backchannel) goes away.
|
||||
*/
|
||||
struct svc_xpt_user {
|
||||
struct list_head list;
|
||||
void (*callback)(struct svc_xpt_user *);
|
||||
};
|
||||
|
||||
struct svc_xprt {
|
||||
struct svc_xprt_class *xpt_class;
|
||||
struct svc_xprt_ops *xpt_ops;
|
||||
struct kref xpt_ref;
|
||||
struct list_head xpt_list;
|
||||
struct list_head xpt_ready;
|
||||
unsigned long xpt_flags;
|
||||
#define XPT_BUSY 0 /* enqueued/receiving */
|
||||
#define XPT_CONN 1 /* conn pending */
|
||||
#define XPT_CLOSE 2 /* dead or dying */
|
||||
#define XPT_DATA 3 /* data pending */
|
||||
#define XPT_TEMP 4 /* connected transport */
|
||||
#define XPT_DEAD 6 /* transport closed */
|
||||
#define XPT_CHNGBUF 7 /* need to change snd/rcv buf sizes */
|
||||
#define XPT_DEFERRED 8 /* deferred request pending */
|
||||
#define XPT_OLD 9 /* used for xprt aging mark+sweep */
|
||||
#define XPT_DETACHED 10 /* detached from tempsocks list */
|
||||
#define XPT_LISTENER 11 /* listening endpoint */
|
||||
#define XPT_CACHE_AUTH 12 /* cache auth info */
|
||||
#define XPT_LOCAL 13 /* connection from loopback interface */
|
||||
|
||||
struct svc_serv *xpt_server; /* service for transport */
|
||||
atomic_t xpt_reserved; /* space on outq that is rsvd */
|
||||
struct mutex xpt_mutex; /* to serialize sending data */
|
||||
spinlock_t xpt_lock; /* protects sk_deferred
|
||||
* and xpt_auth_cache */
|
||||
void *xpt_auth_cache;/* auth cache */
|
||||
struct list_head xpt_deferred; /* deferred requests that need
|
||||
* to be revisted */
|
||||
struct sockaddr_storage xpt_local; /* local address */
|
||||
size_t xpt_locallen; /* length of address */
|
||||
struct sockaddr_storage xpt_remote; /* remote peer's address */
|
||||
size_t xpt_remotelen; /* length of address */
|
||||
struct rpc_wait_queue xpt_bc_pending; /* backchannel wait queue */
|
||||
struct list_head xpt_users; /* callbacks on free */
|
||||
|
||||
struct net *xpt_net;
|
||||
struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */
|
||||
};
|
||||
|
||||
static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
|
||||
{
|
||||
spin_lock(&xpt->xpt_lock);
|
||||
list_del_init(&u->list);
|
||||
spin_unlock(&xpt->xpt_lock);
|
||||
}
|
||||
|
||||
static inline int register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
|
||||
{
|
||||
spin_lock(&xpt->xpt_lock);
|
||||
if (test_bit(XPT_CLOSE, &xpt->xpt_flags)) {
|
||||
/*
|
||||
* The connection is about to be deleted soon (or,
|
||||
* worse, may already be deleted--in which case we've
|
||||
* already notified the xpt_users).
|
||||
*/
|
||||
spin_unlock(&xpt->xpt_lock);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
list_add(&u->list, &xpt->xpt_users);
|
||||
spin_unlock(&xpt->xpt_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int svc_reg_xprt_class(struct svc_xprt_class *);
|
||||
void svc_unreg_xprt_class(struct svc_xprt_class *);
|
||||
void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
|
||||
struct svc_serv *);
|
||||
int svc_create_xprt(struct svc_serv *, const char *, struct net *,
|
||||
const int, const unsigned short, int);
|
||||
void svc_xprt_enqueue(struct svc_xprt *xprt);
|
||||
void svc_xprt_put(struct svc_xprt *xprt);
|
||||
void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt);
|
||||
void svc_close_xprt(struct svc_xprt *xprt);
|
||||
int svc_port_is_privileged(struct sockaddr *sin);
|
||||
int svc_print_xprts(char *buf, int maxlen);
|
||||
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);
|
||||
int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
|
||||
void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt);
|
||||
|
||||
static inline void svc_xprt_get(struct svc_xprt *xprt)
|
||||
{
|
||||
kref_get(&xprt->xpt_ref);
|
||||
}
|
||||
static inline void svc_xprt_set_local(struct svc_xprt *xprt,
|
||||
const struct sockaddr *sa,
|
||||
const size_t salen)
|
||||
{
|
||||
memcpy(&xprt->xpt_local, sa, salen);
|
||||
xprt->xpt_locallen = salen;
|
||||
}
|
||||
static inline void svc_xprt_set_remote(struct svc_xprt *xprt,
|
||||
const struct sockaddr *sa,
|
||||
const size_t salen)
|
||||
{
|
||||
memcpy(&xprt->xpt_remote, sa, salen);
|
||||
xprt->xpt_remotelen = salen;
|
||||
}
|
||||
static inline unsigned short svc_addr_port(const struct sockaddr *sa)
|
||||
{
|
||||
const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
|
||||
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
return ntohs(sin->sin_port);
|
||||
case AF_INET6:
|
||||
return ntohs(sin6->sin6_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t svc_addr_len(const struct sockaddr *sa)
|
||||
{
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt)
|
||||
{
|
||||
return svc_addr_port((const struct sockaddr *)&xprt->xpt_local);
|
||||
}
|
||||
|
||||
static inline unsigned short svc_xprt_remote_port(const struct svc_xprt *xprt)
|
||||
{
|
||||
return svc_addr_port((const struct sockaddr *)&xprt->xpt_remote);
|
||||
}
|
||||
|
||||
static inline char *__svc_print_addr(const struct sockaddr *addr,
|
||||
char *buf, const size_t len)
|
||||
{
|
||||
const struct sockaddr_in *sin = (const struct sockaddr_in *)addr;
|
||||
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)addr;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
snprintf(buf, len, "%pI4, port=%u", &sin->sin_addr,
|
||||
ntohs(sin->sin_port));
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
snprintf(buf, len, "%pI6, port=%u",
|
||||
&sin6->sin6_addr,
|
||||
ntohs(sin6->sin6_port));
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, len, "unknown address type: %d", addr->sa_family);
|
||||
break;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
#endif /* SUNRPC_SVC_XPRT_H */
|
200
include/linux/sunrpc/svcauth.h
Normal file
200
include/linux/sunrpc/svcauth.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/svcauth.h
|
||||
*
|
||||
* RPC server-side authentication stuff.
|
||||
*
|
||||
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_SVCAUTH_H_
|
||||
#define _LINUX_SUNRPC_SVCAUTH_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
#include <linux/sunrpc/cache.h>
|
||||
#include <linux/sunrpc/gss_api.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/cred.h>
|
||||
|
||||
struct svc_cred {
|
||||
kuid_t cr_uid;
|
||||
kgid_t cr_gid;
|
||||
struct group_info *cr_group_info;
|
||||
u32 cr_flavor; /* pseudoflavor */
|
||||
char *cr_principal; /* for gss */
|
||||
struct gss_api_mech *cr_gss_mech;
|
||||
};
|
||||
|
||||
static inline void init_svc_cred(struct svc_cred *cred)
|
||||
{
|
||||
cred->cr_group_info = NULL;
|
||||
cred->cr_principal = NULL;
|
||||
cred->cr_gss_mech = NULL;
|
||||
}
|
||||
|
||||
static inline void free_svc_cred(struct svc_cred *cred)
|
||||
{
|
||||
if (cred->cr_group_info)
|
||||
put_group_info(cred->cr_group_info);
|
||||
kfree(cred->cr_principal);
|
||||
gss_mech_put(cred->cr_gss_mech);
|
||||
init_svc_cred(cred);
|
||||
}
|
||||
|
||||
struct svc_rqst; /* forward decl */
|
||||
struct in6_addr;
|
||||
|
||||
/* Authentication is done in the context of a domain.
|
||||
*
|
||||
* Currently, the nfs server uses the auth_domain to stand
|
||||
* for the "client" listed in /etc/exports.
|
||||
*
|
||||
* More generally, a domain might represent a group of clients using
|
||||
* a common mechanism for authentication and having a common mapping
|
||||
* between local identity (uid) and network identity. All clients
|
||||
* in a domain have similar general access rights. Each domain can
|
||||
* contain multiple principals which will have different specific right
|
||||
* based on normal Discretionary Access Control.
|
||||
*
|
||||
* A domain is created by an authentication flavour module based on name
|
||||
* only. Userspace then fills in detail on demand.
|
||||
*
|
||||
* In the case of auth_unix and auth_null, the auth_domain is also
|
||||
* associated with entries in another cache representing the mapping
|
||||
* of ip addresses to the given client.
|
||||
*/
|
||||
struct auth_domain {
|
||||
struct kref ref;
|
||||
struct hlist_node hash;
|
||||
char *name;
|
||||
struct auth_ops *flavour;
|
||||
};
|
||||
|
||||
/*
|
||||
* Each authentication flavour registers an auth_ops
|
||||
* structure.
|
||||
* name is simply the name.
|
||||
* flavour gives the auth flavour. It determines where the flavour is registered
|
||||
* accept() is given a request and should verify it.
|
||||
* It should inspect the authenticator and verifier, and possibly the data.
|
||||
* If there is a problem with the authentication *authp should be set.
|
||||
* The return value of accept() can indicate:
|
||||
* OK - authorised. client and credential are set in rqstp.
|
||||
* reqbuf points to arguments
|
||||
* resbuf points to good place for results. verfier
|
||||
* is (probably) already in place. Certainly space is
|
||||
* reserved for it.
|
||||
* DROP - simply drop the request. It may have been deferred
|
||||
* GARBAGE - rpc garbage_args error
|
||||
* SYSERR - rpc system_err error
|
||||
* DENIED - authp holds reason for denial.
|
||||
* COMPLETE - the reply is encoded already and ready to be sent; no
|
||||
* further processing is necessary. (This is used for processing
|
||||
* null procedure calls which are used to set up encryption
|
||||
* contexts.)
|
||||
*
|
||||
* accept is passed the proc number so that it can accept NULL rpc requests
|
||||
* even if it cannot authenticate the client (as is sometimes appropriate).
|
||||
*
|
||||
* release() is given a request after the procedure has been run.
|
||||
* It should sign/encrypt the results if needed
|
||||
* It should return:
|
||||
* OK - the resbuf is ready to be sent
|
||||
* DROP - the reply should be quitely dropped
|
||||
* DENIED - authp holds a reason for MSG_DENIED
|
||||
* SYSERR - rpc system_err
|
||||
*
|
||||
* domain_release()
|
||||
* This call releases a domain.
|
||||
* set_client()
|
||||
* Givens a pending request (struct svc_rqst), finds and assigns
|
||||
* an appropriate 'auth_domain' as the client.
|
||||
*/
|
||||
struct auth_ops {
|
||||
char * name;
|
||||
struct module *owner;
|
||||
int flavour;
|
||||
int (*accept)(struct svc_rqst *rq, __be32 *authp);
|
||||
int (*release)(struct svc_rqst *rq);
|
||||
void (*domain_release)(struct auth_domain *);
|
||||
int (*set_client)(struct svc_rqst *rq);
|
||||
};
|
||||
|
||||
#define SVC_GARBAGE 1
|
||||
#define SVC_SYSERR 2
|
||||
#define SVC_VALID 3
|
||||
#define SVC_NEGATIVE 4
|
||||
#define SVC_OK 5
|
||||
#define SVC_DROP 6
|
||||
#define SVC_CLOSE 7 /* Like SVC_DROP, but request is definitely
|
||||
* lost so if there is a tcp connection, it
|
||||
* should be closed
|
||||
*/
|
||||
#define SVC_DENIED 8
|
||||
#define SVC_PENDING 9
|
||||
#define SVC_COMPLETE 10
|
||||
|
||||
struct svc_xprt;
|
||||
|
||||
extern int svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
|
||||
extern int svc_authorise(struct svc_rqst *rqstp);
|
||||
extern int svc_set_client(struct svc_rqst *rqstp);
|
||||
extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
|
||||
extern void svc_auth_unregister(rpc_authflavor_t flavor);
|
||||
|
||||
extern struct auth_domain *unix_domain_find(char *name);
|
||||
extern void auth_domain_put(struct auth_domain *item);
|
||||
extern int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom);
|
||||
extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
|
||||
extern struct auth_domain *auth_domain_find(char *name);
|
||||
extern struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr);
|
||||
extern int auth_unix_forget_old(struct auth_domain *dom);
|
||||
extern void svcauth_unix_purge(struct net *net);
|
||||
extern void svcauth_unix_info_release(struct svc_xprt *xpt);
|
||||
extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
|
||||
|
||||
extern int unix_gid_cache_create(struct net *net);
|
||||
extern void unix_gid_cache_destroy(struct net *net);
|
||||
|
||||
static inline unsigned long hash_str(char *name, int bits)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
unsigned long l = 0;
|
||||
int len = 0;
|
||||
unsigned char c;
|
||||
do {
|
||||
if (unlikely(!(c = *name++))) {
|
||||
c = (char)len; len = -1;
|
||||
}
|
||||
l = (l << 8) | c;
|
||||
len++;
|
||||
if ((len & (BITS_PER_LONG/8-1))==0)
|
||||
hash = hash_long(hash^l, BITS_PER_LONG);
|
||||
} while (len);
|
||||
return hash >> (BITS_PER_LONG - bits);
|
||||
}
|
||||
|
||||
static inline unsigned long hash_mem(char *buf, int length, int bits)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
unsigned long l = 0;
|
||||
int len = 0;
|
||||
unsigned char c;
|
||||
do {
|
||||
if (len == length) {
|
||||
c = (char)len; len = -1;
|
||||
} else
|
||||
c = *buf++;
|
||||
l = (l << 8) | c;
|
||||
len++;
|
||||
if ((len & (BITS_PER_LONG/8-1))==0)
|
||||
hash = hash_long(hash^l, BITS_PER_LONG);
|
||||
} while (len);
|
||||
return hash >> (BITS_PER_LONG - bits);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_SUNRPC_SVCAUTH_H_ */
|
27
include/linux/sunrpc/svcauth_gss.h
Normal file
27
include/linux/sunrpc/svcauth_gss.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/svcauth_gss.h
|
||||
*
|
||||
* Bruce Fields <bfields@umich.edu>
|
||||
* Copyright (c) 2002 The Regents of the University of Michigan
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_SVCAUTH_GSS_H
|
||||
#define _LINUX_SUNRPC_SVCAUTH_GSS_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sunrpc/types.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/svcauth.h>
|
||||
#include <linux/sunrpc/svcsock.h>
|
||||
#include <linux/sunrpc/auth_gss.h>
|
||||
|
||||
int gss_svc_init(void);
|
||||
void gss_svc_shutdown(void);
|
||||
int gss_svc_init_net(struct net *net);
|
||||
void gss_svc_shutdown_net(struct net *net);
|
||||
int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
|
||||
u32 svcauth_gss_flavor(struct auth_domain *dom);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
|
74
include/linux/sunrpc/svcsock.h
Normal file
74
include/linux/sunrpc/svcsock.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/svcsock.h
|
||||
*
|
||||
* RPC server socket I/O.
|
||||
*
|
||||
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef SUNRPC_SVCSOCK_H
|
||||
#define SUNRPC_SVCSOCK_H
|
||||
|
||||
#include <linux/sunrpc/svc.h>
|
||||
#include <linux/sunrpc/svc_xprt.h>
|
||||
|
||||
/*
|
||||
* RPC server socket.
|
||||
*/
|
||||
struct svc_sock {
|
||||
struct svc_xprt sk_xprt;
|
||||
struct socket * sk_sock; /* berkeley socket layer */
|
||||
struct sock * sk_sk; /* INET layer */
|
||||
|
||||
/* We keep the old state_change and data_ready CB's here */
|
||||
void (*sk_ostate)(struct sock *);
|
||||
void (*sk_odata)(struct sock *);
|
||||
void (*sk_owspace)(struct sock *);
|
||||
|
||||
/* private TCP part */
|
||||
/* On-the-wire fragment header: */
|
||||
__be32 sk_reclen;
|
||||
/* As we receive a record, this includes the length received so
|
||||
* far (including the fragment header): */
|
||||
u32 sk_tcplen;
|
||||
/* Total length of the data (not including fragment headers)
|
||||
* received so far in the fragments making up this rpc: */
|
||||
u32 sk_datalen;
|
||||
|
||||
struct page * sk_pages[RPCSVC_MAXPAGES]; /* received data */
|
||||
};
|
||||
|
||||
static inline u32 svc_sock_reclen(struct svc_sock *svsk)
|
||||
{
|
||||
return ntohl(svsk->sk_reclen) & RPC_FRAGMENT_SIZE_MASK;
|
||||
}
|
||||
|
||||
static inline u32 svc_sock_final_rec(struct svc_sock *svsk)
|
||||
{
|
||||
return ntohl(svsk->sk_reclen) & RPC_LAST_STREAM_FRAGMENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function prototypes.
|
||||
*/
|
||||
void svc_close_net(struct svc_serv *, struct net *);
|
||||
int svc_recv(struct svc_rqst *, long);
|
||||
int svc_send(struct svc_rqst *);
|
||||
void svc_drop(struct svc_rqst *);
|
||||
void svc_sock_update_bufs(struct svc_serv *serv);
|
||||
bool svc_alien_sock(struct net *net, int fd);
|
||||
int svc_addsock(struct svc_serv *serv, const int fd,
|
||||
char *name_return, const size_t len);
|
||||
void svc_init_xprt_sock(void);
|
||||
void svc_cleanup_xprt_sock(void);
|
||||
struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
|
||||
void svc_sock_destroy(struct svc_xprt *);
|
||||
|
||||
/*
|
||||
* svc_makesock socket characteristics
|
||||
*/
|
||||
#define SVC_SOCK_DEFAULTS (0U)
|
||||
#define SVC_SOCK_ANONYMOUS (1U << 0) /* don't register with pmap */
|
||||
#define SVC_SOCK_TEMPORARY (1U << 1) /* flag socket as temporary */
|
||||
|
||||
#endif /* SUNRPC_SVCSOCK_H */
|
49
include/linux/sunrpc/timer.h
Normal file
49
include/linux/sunrpc/timer.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/timer.h
|
||||
*
|
||||
* Declarations for the RPC transport timer.
|
||||
*
|
||||
* Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_TIMER_H
|
||||
#define _LINUX_SUNRPC_TIMER_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
|
||||
struct rpc_rtt {
|
||||
unsigned long timeo; /* default timeout value */
|
||||
unsigned long srtt[5]; /* smoothed round trip time << 3 */
|
||||
unsigned long sdrtt[5]; /* smoothed medium deviation of RTT */
|
||||
int ntimeouts[5]; /* Number of timeouts for the last request */
|
||||
};
|
||||
|
||||
|
||||
extern void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo);
|
||||
extern void rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m);
|
||||
extern unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned timer);
|
||||
|
||||
static inline void rpc_set_timeo(struct rpc_rtt *rt, int timer, int ntimeo)
|
||||
{
|
||||
int *t;
|
||||
if (!timer)
|
||||
return;
|
||||
t = &rt->ntimeouts[timer-1];
|
||||
if (ntimeo < *t) {
|
||||
if (*t > 0)
|
||||
(*t)--;
|
||||
} else {
|
||||
if (ntimeo > 8)
|
||||
ntimeo = 8;
|
||||
*t = ntimeo;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int rpc_ntimeo(struct rpc_rtt *rt, int timer)
|
||||
{
|
||||
if (!timer)
|
||||
return 0;
|
||||
return rt->ntimeouts[timer-1];
|
||||
}
|
||||
|
||||
#endif /* _LINUX_SUNRPC_TIMER_H */
|
22
include/linux/sunrpc/types.h
Normal file
22
include/linux/sunrpc/types.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/types.h
|
||||
*
|
||||
* Generic types and misc stuff for RPC.
|
||||
*
|
||||
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_TYPES_H_
|
||||
#define _LINUX_SUNRPC_TYPES_H_
|
||||
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sunrpc/debug.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
/*
|
||||
* Shorthands
|
||||
*/
|
||||
#define signalled() (signal_pending(current))
|
||||
|
||||
#endif /* _LINUX_SUNRPC_TYPES_H_ */
|
235
include/linux/sunrpc/xdr.h
Normal file
235
include/linux/sunrpc/xdr.h
Normal file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* XDR standard data types and function declarations
|
||||
*
|
||||
* Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
|
||||
*
|
||||
* Based on:
|
||||
* RFC 4506 "XDR: External Data Representation Standard", May 2006
|
||||
*/
|
||||
|
||||
#ifndef _SUNRPC_XDR_H_
|
||||
#define _SUNRPC_XDR_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/uio.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
/*
|
||||
* Buffer adjustment
|
||||
*/
|
||||
#define XDR_QUADLEN(l) (((l) + 3) >> 2)
|
||||
|
||||
/*
|
||||
* Generic opaque `network object.' At the kernel level, this type
|
||||
* is used only by lockd.
|
||||
*/
|
||||
#define XDR_MAX_NETOBJ 1024
|
||||
struct xdr_netobj {
|
||||
unsigned int len;
|
||||
u8 * data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the legacy generic XDR function. rqstp is either a rpc_rqst
|
||||
* (client side) or svc_rqst pointer (server side).
|
||||
* Encode functions always assume there's enough room in the buffer.
|
||||
*/
|
||||
typedef int (*kxdrproc_t)(void *rqstp, __be32 *data, void *obj);
|
||||
|
||||
/*
|
||||
* Basic structure for transmission/reception of a client XDR message.
|
||||
* Features a header (for a linear buffer containing RPC headers
|
||||
* and the data payload for short messages), and then an array of
|
||||
* pages.
|
||||
* The tail iovec allows you to append data after the page array. Its
|
||||
* main interest is for appending padding to the pages in order to
|
||||
* satisfy the int_32-alignment requirements in RFC1832.
|
||||
*
|
||||
* For the future, we might want to string several of these together
|
||||
* in a list if anybody wants to make use of NFSv4 COMPOUND
|
||||
* operations and/or has a need for scatter/gather involving pages.
|
||||
*/
|
||||
struct xdr_buf {
|
||||
struct kvec head[1], /* RPC header + non-page data */
|
||||
tail[1]; /* Appended after page data */
|
||||
|
||||
struct page ** pages; /* Array of pages */
|
||||
unsigned int page_base, /* Start of page data */
|
||||
page_len, /* Length of page data */
|
||||
flags; /* Flags for data disposition */
|
||||
#define XDRBUF_READ 0x01 /* target of file read */
|
||||
#define XDRBUF_WRITE 0x02 /* source of file write */
|
||||
|
||||
unsigned int buflen, /* Total length of storage buffer */
|
||||
len; /* Length of XDR encoded message */
|
||||
};
|
||||
|
||||
/*
|
||||
* pre-xdr'ed macros.
|
||||
*/
|
||||
|
||||
#define xdr_zero cpu_to_be32(0)
|
||||
#define xdr_one cpu_to_be32(1)
|
||||
#define xdr_two cpu_to_be32(2)
|
||||
|
||||
#define rpc_success cpu_to_be32(RPC_SUCCESS)
|
||||
#define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL)
|
||||
#define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH)
|
||||
#define rpc_proc_unavail cpu_to_be32(RPC_PROC_UNAVAIL)
|
||||
#define rpc_garbage_args cpu_to_be32(RPC_GARBAGE_ARGS)
|
||||
#define rpc_system_err cpu_to_be32(RPC_SYSTEM_ERR)
|
||||
#define rpc_drop_reply cpu_to_be32(RPC_DROP_REPLY)
|
||||
|
||||
#define rpc_auth_ok cpu_to_be32(RPC_AUTH_OK)
|
||||
#define rpc_autherr_badcred cpu_to_be32(RPC_AUTH_BADCRED)
|
||||
#define rpc_autherr_rejectedcred cpu_to_be32(RPC_AUTH_REJECTEDCRED)
|
||||
#define rpc_autherr_badverf cpu_to_be32(RPC_AUTH_BADVERF)
|
||||
#define rpc_autherr_rejectedverf cpu_to_be32(RPC_AUTH_REJECTEDVERF)
|
||||
#define rpc_autherr_tooweak cpu_to_be32(RPC_AUTH_TOOWEAK)
|
||||
#define rpcsec_gsserr_credproblem cpu_to_be32(RPCSEC_GSS_CREDPROBLEM)
|
||||
#define rpcsec_gsserr_ctxproblem cpu_to_be32(RPCSEC_GSS_CTXPROBLEM)
|
||||
#define rpc_autherr_oldseqnum cpu_to_be32(101)
|
||||
|
||||
/*
|
||||
* Miscellaneous XDR helper functions
|
||||
*/
|
||||
__be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len);
|
||||
__be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len);
|
||||
__be32 *xdr_encode_string(__be32 *p, const char *s);
|
||||
__be32 *xdr_decode_string_inplace(__be32 *p, char **sp, unsigned int *lenp,
|
||||
unsigned int maxlen);
|
||||
__be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *);
|
||||
__be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
|
||||
|
||||
void xdr_inline_pages(struct xdr_buf *, unsigned int,
|
||||
struct page **, unsigned int, unsigned int);
|
||||
void xdr_terminate_string(struct xdr_buf *, const u32);
|
||||
|
||||
static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
|
||||
{
|
||||
return xdr_encode_opaque(p, s, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode 64bit quantities (NFSv3 support)
|
||||
*/
|
||||
static inline __be32 *
|
||||
xdr_encode_hyper(__be32 *p, __u64 val)
|
||||
{
|
||||
put_unaligned_be64(val, p);
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
static inline __be32 *
|
||||
xdr_decode_hyper(__be32 *p, __u64 *valp)
|
||||
{
|
||||
*valp = get_unaligned_be64(p);
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
static inline __be32 *
|
||||
xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len)
|
||||
{
|
||||
memcpy(ptr, p, len);
|
||||
return p + XDR_QUADLEN(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
|
||||
*/
|
||||
static inline int
|
||||
xdr_adjust_iovec(struct kvec *iov, __be32 *p)
|
||||
{
|
||||
return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR buffer helper functions
|
||||
*/
|
||||
extern void xdr_shift_buf(struct xdr_buf *, size_t);
|
||||
extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *);
|
||||
extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int);
|
||||
extern void xdr_buf_trim(struct xdr_buf *, unsigned int);
|
||||
extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, unsigned int);
|
||||
extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
|
||||
extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
|
||||
|
||||
/*
|
||||
* Helper structure for copying from an sk_buff.
|
||||
*/
|
||||
struct xdr_skb_reader {
|
||||
struct sk_buff *skb;
|
||||
unsigned int offset;
|
||||
size_t count;
|
||||
__wsum csum;
|
||||
};
|
||||
|
||||
typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, size_t len);
|
||||
|
||||
size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len);
|
||||
extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
|
||||
extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
|
||||
struct xdr_skb_reader *, xdr_skb_read_actor);
|
||||
|
||||
extern int xdr_encode_word(struct xdr_buf *, unsigned int, u32);
|
||||
extern int xdr_decode_word(struct xdr_buf *, unsigned int, u32 *);
|
||||
|
||||
struct xdr_array2_desc;
|
||||
typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
|
||||
struct xdr_array2_desc {
|
||||
unsigned int elem_size;
|
||||
unsigned int array_len;
|
||||
unsigned int array_maxlen;
|
||||
xdr_xcode_elem_t xcode;
|
||||
};
|
||||
|
||||
extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
|
||||
struct xdr_array2_desc *desc);
|
||||
extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
|
||||
struct xdr_array2_desc *desc);
|
||||
extern void _copy_from_pages(char *p, struct page **pages, size_t pgbase,
|
||||
size_t len);
|
||||
|
||||
/*
|
||||
* Provide some simple tools for XDR buffer overflow-checking etc.
|
||||
*/
|
||||
struct xdr_stream {
|
||||
__be32 *p; /* start of available buffer */
|
||||
struct xdr_buf *buf; /* XDR buffer to read/write */
|
||||
|
||||
__be32 *end; /* end of available buffer space */
|
||||
struct kvec *iov; /* pointer to the current kvec */
|
||||
struct kvec scratch; /* Scratch buffer */
|
||||
struct page **page_ptr; /* pointer to the current page */
|
||||
unsigned int nwords; /* Remaining decode buffer length */
|
||||
};
|
||||
|
||||
/*
|
||||
* These are the xdr_stream style generic XDR encode and decode functions.
|
||||
*/
|
||||
typedef void (*kxdreproc_t)(void *rqstp, struct xdr_stream *xdr, void *obj);
|
||||
typedef int (*kxdrdproc_t)(void *rqstp, struct xdr_stream *xdr, void *obj);
|
||||
|
||||
extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
|
||||
extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
|
||||
extern void xdr_commit_encode(struct xdr_stream *xdr);
|
||||
extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
|
||||
extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
|
||||
extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
|
||||
unsigned int base, unsigned int len);
|
||||
extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
|
||||
extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
|
||||
extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
|
||||
struct page **pages, unsigned int len);
|
||||
extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen);
|
||||
extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
|
||||
extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
|
||||
extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
|
||||
extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _SUNRPC_XDR_H_ */
|
433
include/linux/sunrpc/xprt.h
Normal file
433
include/linux/sunrpc/xprt.h
Normal file
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/xprt.h
|
||||
*
|
||||
* Declarations for the RPC transport interface.
|
||||
*
|
||||
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_XPRT_H
|
||||
#define _LINUX_SUNRPC_XPRT_H
|
||||
|
||||
#include <linux/uio.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/sunrpc/sched.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define RPC_MIN_SLOT_TABLE (2U)
|
||||
#define RPC_DEF_SLOT_TABLE (16U)
|
||||
#define RPC_MAX_SLOT_TABLE_LIMIT (65536U)
|
||||
#define RPC_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE_LIMIT
|
||||
|
||||
#define RPC_CWNDSHIFT (8U)
|
||||
#define RPC_CWNDSCALE (1U << RPC_CWNDSHIFT)
|
||||
#define RPC_INITCWND RPC_CWNDSCALE
|
||||
#define RPC_MAXCWND(xprt) ((xprt)->max_reqs << RPC_CWNDSHIFT)
|
||||
#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
|
||||
|
||||
/*
|
||||
* This describes a timeout strategy
|
||||
*/
|
||||
struct rpc_timeout {
|
||||
unsigned long to_initval, /* initial timeout */
|
||||
to_maxval, /* max timeout */
|
||||
to_increment; /* if !exponential */
|
||||
unsigned int to_retries; /* max # of retries */
|
||||
unsigned char to_exponential;
|
||||
};
|
||||
|
||||
enum rpc_display_format_t {
|
||||
RPC_DISPLAY_ADDR = 0,
|
||||
RPC_DISPLAY_PORT,
|
||||
RPC_DISPLAY_PROTO,
|
||||
RPC_DISPLAY_HEX_ADDR,
|
||||
RPC_DISPLAY_HEX_PORT,
|
||||
RPC_DISPLAY_NETID,
|
||||
RPC_DISPLAY_MAX,
|
||||
};
|
||||
|
||||
struct rpc_task;
|
||||
struct rpc_xprt;
|
||||
struct seq_file;
|
||||
|
||||
/*
|
||||
* This describes a complete RPC request
|
||||
*/
|
||||
struct rpc_rqst {
|
||||
/*
|
||||
* This is the user-visible part
|
||||
*/
|
||||
struct rpc_xprt * rq_xprt; /* RPC client */
|
||||
struct xdr_buf rq_snd_buf; /* send buffer */
|
||||
struct xdr_buf rq_rcv_buf; /* recv buffer */
|
||||
|
||||
/*
|
||||
* This is the private part
|
||||
*/
|
||||
struct rpc_task * rq_task; /* RPC task data */
|
||||
struct rpc_cred * rq_cred; /* Bound cred */
|
||||
__be32 rq_xid; /* request XID */
|
||||
int rq_cong; /* has incremented xprt->cong */
|
||||
u32 rq_seqno; /* gss seq no. used on req. */
|
||||
int rq_enc_pages_num;
|
||||
struct page **rq_enc_pages; /* scratch pages for use by
|
||||
gss privacy code */
|
||||
void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
|
||||
struct list_head rq_list;
|
||||
|
||||
__u32 * rq_buffer; /* XDR encode buffer */
|
||||
size_t rq_callsize,
|
||||
rq_rcvsize;
|
||||
size_t rq_xmit_bytes_sent; /* total bytes sent */
|
||||
size_t rq_reply_bytes_recvd; /* total reply bytes */
|
||||
/* received */
|
||||
|
||||
struct xdr_buf rq_private_buf; /* The receive buffer
|
||||
* used in the softirq.
|
||||
*/
|
||||
unsigned long rq_majortimeo; /* major timeout alarm */
|
||||
unsigned long rq_timeout; /* Current timeout value */
|
||||
ktime_t rq_rtt; /* round-trip time */
|
||||
unsigned int rq_retries; /* # of retries */
|
||||
unsigned int rq_connect_cookie;
|
||||
/* A cookie used to track the
|
||||
state of the transport
|
||||
connection */
|
||||
|
||||
/*
|
||||
* Partial send handling
|
||||
*/
|
||||
u32 rq_bytes_sent; /* Bytes we have sent */
|
||||
|
||||
ktime_t rq_xtime; /* transmit time stamp */
|
||||
int rq_ntrans;
|
||||
|
||||
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
|
||||
struct list_head rq_bc_list; /* Callback service list */
|
||||
unsigned long rq_bc_pa_state; /* Backchannel prealloc state */
|
||||
struct list_head rq_bc_pa_list; /* Backchannel prealloc list */
|
||||
#endif /* CONFIG_SUNRPC_BACKCHANEL */
|
||||
};
|
||||
#define rq_svec rq_snd_buf.head
|
||||
#define rq_slen rq_snd_buf.len
|
||||
|
||||
struct rpc_xprt_ops {
|
||||
void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
|
||||
int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void (*rpcbind)(struct rpc_task *task);
|
||||
void (*set_port)(struct rpc_xprt *xprt, unsigned short port);
|
||||
void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void * (*buf_alloc)(struct rpc_task *task, size_t size);
|
||||
void (*buf_free)(void *buffer);
|
||||
int (*send_request)(struct rpc_task *task);
|
||||
void (*set_retrans_timeout)(struct rpc_task *task);
|
||||
void (*timer)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void (*release_request)(struct rpc_task *task);
|
||||
void (*close)(struct rpc_xprt *xprt);
|
||||
void (*destroy)(struct rpc_xprt *xprt);
|
||||
void (*print_stats)(struct rpc_xprt *xprt, struct seq_file *seq);
|
||||
};
|
||||
|
||||
/*
|
||||
* RPC transport identifiers
|
||||
*
|
||||
* To preserve compatibility with the historical use of raw IP protocol
|
||||
* id's for transport selection, UDP and TCP identifiers are specified
|
||||
* with the previous values. No such restriction exists for new transports,
|
||||
* except that they may not collide with these values (17 and 6,
|
||||
* respectively).
|
||||
*/
|
||||
#define XPRT_TRANSPORT_BC (1 << 31)
|
||||
enum xprt_transports {
|
||||
XPRT_TRANSPORT_UDP = IPPROTO_UDP,
|
||||
XPRT_TRANSPORT_TCP = IPPROTO_TCP,
|
||||
XPRT_TRANSPORT_BC_TCP = IPPROTO_TCP | XPRT_TRANSPORT_BC,
|
||||
XPRT_TRANSPORT_RDMA = 256,
|
||||
XPRT_TRANSPORT_LOCAL = 257,
|
||||
};
|
||||
|
||||
struct rpc_xprt {
|
||||
atomic_t count; /* Reference count */
|
||||
struct rpc_xprt_ops * ops; /* transport methods */
|
||||
|
||||
const struct rpc_timeout *timeout; /* timeout parms */
|
||||
struct sockaddr_storage addr; /* server address */
|
||||
size_t addrlen; /* size of server address */
|
||||
int prot; /* IP protocol */
|
||||
|
||||
unsigned long cong; /* current congestion */
|
||||
unsigned long cwnd; /* congestion window */
|
||||
|
||||
size_t max_payload; /* largest RPC payload size,
|
||||
in bytes */
|
||||
unsigned int tsh_size; /* size of transport specific
|
||||
header */
|
||||
|
||||
struct rpc_wait_queue binding; /* requests waiting on rpcbind */
|
||||
struct rpc_wait_queue sending; /* requests waiting to send */
|
||||
struct rpc_wait_queue pending; /* requests in flight */
|
||||
struct rpc_wait_queue backlog; /* waiting for slot */
|
||||
struct list_head free; /* free slots */
|
||||
unsigned int max_reqs; /* max number of slots */
|
||||
unsigned int min_reqs; /* min number of slots */
|
||||
atomic_t num_reqs; /* total slots */
|
||||
unsigned long state; /* transport state */
|
||||
unsigned char resvport : 1; /* use a reserved port */
|
||||
unsigned int swapper; /* we're swapping over this
|
||||
transport */
|
||||
unsigned int bind_index; /* bind function index */
|
||||
|
||||
/*
|
||||
* Connection of transports
|
||||
*/
|
||||
unsigned long bind_timeout,
|
||||
reestablish_timeout;
|
||||
unsigned int connect_cookie; /* A cookie that gets bumped
|
||||
every time the transport
|
||||
is reconnected */
|
||||
|
||||
/*
|
||||
* Disconnection of idle transports
|
||||
*/
|
||||
struct work_struct task_cleanup;
|
||||
struct timer_list timer;
|
||||
unsigned long last_used,
|
||||
idle_timeout;
|
||||
|
||||
/*
|
||||
* Send stuff
|
||||
*/
|
||||
spinlock_t transport_lock; /* lock transport info */
|
||||
spinlock_t reserve_lock; /* lock slot table */
|
||||
u32 xid; /* Next XID value to use */
|
||||
struct rpc_task * snd_task; /* Task blocked in send */
|
||||
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
|
||||
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
|
||||
struct svc_serv *bc_serv; /* The RPC service which will */
|
||||
/* process the callback */
|
||||
unsigned int bc_alloc_count; /* Total number of preallocs */
|
||||
spinlock_t bc_pa_lock; /* Protects the preallocated
|
||||
* items */
|
||||
struct list_head bc_pa_list; /* List of preallocated
|
||||
* backchannel rpc_rqst's */
|
||||
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
|
||||
struct list_head recv;
|
||||
|
||||
struct {
|
||||
unsigned long bind_count, /* total number of binds */
|
||||
connect_count, /* total number of connects */
|
||||
connect_start, /* connect start timestamp */
|
||||
connect_time, /* jiffies waiting for connect */
|
||||
sends, /* how many complete requests */
|
||||
recvs, /* how many complete requests */
|
||||
bad_xids, /* lookup_rqst didn't find XID */
|
||||
max_slots; /* max rpc_slots used */
|
||||
|
||||
unsigned long long req_u, /* average requests on the wire */
|
||||
bklog_u, /* backlog queue utilization */
|
||||
sending_u, /* send q utilization */
|
||||
pending_u; /* pend q utilization */
|
||||
} stat;
|
||||
|
||||
struct net *xprt_net;
|
||||
const char *servername;
|
||||
const char *address_strings[RPC_DISPLAY_MAX];
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
|
||||
/*
|
||||
* Backchannel flags
|
||||
*/
|
||||
#define RPC_BC_PA_IN_USE 0x0001 /* Preallocated backchannel */
|
||||
/* buffer in use */
|
||||
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
|
||||
|
||||
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
|
||||
static inline int bc_prealloc(struct rpc_rqst *req)
|
||||
{
|
||||
return test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
|
||||
}
|
||||
#else
|
||||
static inline int bc_prealloc(struct rpc_rqst *req)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
|
||||
|
||||
#define XPRT_CREATE_INFINITE_SLOTS (1U)
|
||||
#define XPRT_CREATE_NO_IDLE_TIMEOUT (1U << 1)
|
||||
|
||||
struct xprt_create {
|
||||
int ident; /* XPRT_TRANSPORT identifier */
|
||||
struct net * net;
|
||||
struct sockaddr * srcaddr; /* optional local address */
|
||||
struct sockaddr * dstaddr; /* remote peer address */
|
||||
size_t addrlen;
|
||||
const char *servername;
|
||||
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct xprt_class {
|
||||
struct list_head list;
|
||||
int ident; /* XPRT_TRANSPORT identifier */
|
||||
struct rpc_xprt * (*setup)(struct xprt_create *);
|
||||
struct module *owner;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
/*
|
||||
* Generic internal transport functions
|
||||
*/
|
||||
struct rpc_xprt *xprt_create_transport(struct xprt_create *args);
|
||||
void xprt_connect(struct rpc_task *task);
|
||||
void xprt_reserve(struct rpc_task *task);
|
||||
void xprt_retry_reserve(struct rpc_task *task);
|
||||
int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
bool xprt_prepare_transmit(struct rpc_task *task);
|
||||
void xprt_transmit(struct rpc_task *task);
|
||||
void xprt_end_transmit(struct rpc_task *task);
|
||||
int xprt_adjust_timeout(struct rpc_rqst *req);
|
||||
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void xprt_release(struct rpc_task *task);
|
||||
void xprt_put(struct rpc_xprt *xprt);
|
||||
struct rpc_xprt * xprt_alloc(struct net *net, size_t size,
|
||||
unsigned int num_prealloc,
|
||||
unsigned int max_req);
|
||||
void xprt_free(struct rpc_xprt *);
|
||||
|
||||
/**
|
||||
* xprt_get - return a reference to an RPC transport.
|
||||
* @xprt: pointer to the transport
|
||||
*
|
||||
*/
|
||||
static inline struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
|
||||
{
|
||||
if (atomic_inc_not_zero(&xprt->count))
|
||||
return xprt;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
|
||||
{
|
||||
return p + xprt->tsh_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transport switch helper functions
|
||||
*/
|
||||
int xprt_register_transport(struct xprt_class *type);
|
||||
int xprt_unregister_transport(struct xprt_class *type);
|
||||
int xprt_load_transport(const char *);
|
||||
void xprt_set_retrans_timeout_def(struct rpc_task *task);
|
||||
void xprt_set_retrans_timeout_rtt(struct rpc_task *task);
|
||||
void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
|
||||
void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action);
|
||||
void xprt_write_space(struct rpc_xprt *xprt);
|
||||
void xprt_adjust_cwnd(struct rpc_xprt *xprt, struct rpc_task *task, int result);
|
||||
struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid);
|
||||
void xprt_complete_rqst(struct rpc_task *task, int copied);
|
||||
void xprt_release_rqst_cong(struct rpc_task *task);
|
||||
void xprt_disconnect_done(struct rpc_xprt *xprt);
|
||||
void xprt_force_disconnect(struct rpc_xprt *xprt);
|
||||
void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
|
||||
int xs_swapper(struct rpc_xprt *xprt, int enable);
|
||||
|
||||
/*
|
||||
* Reserved bit positions in xprt->state
|
||||
*/
|
||||
#define XPRT_LOCKED (0)
|
||||
#define XPRT_CONNECTED (1)
|
||||
#define XPRT_CONNECTING (2)
|
||||
#define XPRT_CLOSE_WAIT (3)
|
||||
#define XPRT_BOUND (4)
|
||||
#define XPRT_BINDING (5)
|
||||
#define XPRT_CLOSING (6)
|
||||
#define XPRT_CONNECTION_ABORT (7)
|
||||
#define XPRT_CONNECTION_CLOSE (8)
|
||||
#define XPRT_CONGESTED (9)
|
||||
#define XPRT_CONNECTION_REUSE (10)
|
||||
|
||||
static inline void xprt_set_connected(struct rpc_xprt *xprt)
|
||||
{
|
||||
set_bit(XPRT_CONNECTED, &xprt->state);
|
||||
}
|
||||
|
||||
static inline void xprt_clear_connected(struct rpc_xprt *xprt)
|
||||
{
|
||||
clear_bit(XPRT_CONNECTED, &xprt->state);
|
||||
}
|
||||
|
||||
static inline int xprt_connected(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_bit(XPRT_CONNECTED, &xprt->state);
|
||||
}
|
||||
|
||||
static inline int xprt_test_and_set_connected(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_and_set_bit(XPRT_CONNECTED, &xprt->state);
|
||||
}
|
||||
|
||||
static inline int xprt_test_and_clear_connected(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_and_clear_bit(XPRT_CONNECTED, &xprt->state);
|
||||
}
|
||||
|
||||
static inline void xprt_clear_connecting(struct rpc_xprt *xprt)
|
||||
{
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(XPRT_CONNECTING, &xprt->state);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
static inline int xprt_connecting(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_bit(XPRT_CONNECTING, &xprt->state);
|
||||
}
|
||||
|
||||
static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_and_set_bit(XPRT_CONNECTING, &xprt->state);
|
||||
}
|
||||
|
||||
static inline void xprt_set_bound(struct rpc_xprt *xprt)
|
||||
{
|
||||
test_and_set_bit(XPRT_BOUND, &xprt->state);
|
||||
}
|
||||
|
||||
static inline int xprt_bound(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_bit(XPRT_BOUND, &xprt->state);
|
||||
}
|
||||
|
||||
static inline void xprt_clear_bound(struct rpc_xprt *xprt)
|
||||
{
|
||||
clear_bit(XPRT_BOUND, &xprt->state);
|
||||
}
|
||||
|
||||
static inline void xprt_clear_binding(struct rpc_xprt *xprt)
|
||||
{
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(XPRT_BINDING, &xprt->state);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
static inline int xprt_test_and_set_binding(struct rpc_xprt *xprt)
|
||||
{
|
||||
return test_and_set_bit(XPRT_BINDING, &xprt->state);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__*/
|
||||
|
||||
#endif /* _LINUX_SUNRPC_XPRT_H */
|
76
include/linux/sunrpc/xprtrdma.h
Normal file
76
include/linux/sunrpc/xprtrdma.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_XPRTRDMA_H
|
||||
#define _LINUX_SUNRPC_XPRTRDMA_H
|
||||
|
||||
/*
|
||||
* rpcbind (v3+) RDMA netid.
|
||||
*/
|
||||
#define RPCBIND_NETID_RDMA "rdma"
|
||||
|
||||
/*
|
||||
* Constants. Max RPC/NFS header is big enough to account for
|
||||
* additional marshaling buffers passed down by Linux client.
|
||||
*
|
||||
* RDMA header is currently fixed max size, and is big enough for a
|
||||
* fully-chunked NFS message (read chunks are the largest). Note only
|
||||
* a single chunk type per message is supported currently.
|
||||
*/
|
||||
#define RPCRDMA_MIN_SLOT_TABLE (2U)
|
||||
#define RPCRDMA_DEF_SLOT_TABLE (32U)
|
||||
#define RPCRDMA_MAX_SLOT_TABLE (256U)
|
||||
|
||||
#define RPCRDMA_DEF_INLINE (1024) /* default inline max */
|
||||
|
||||
#define RPCRDMA_INLINE_PAD_THRESH (512)/* payload threshold to pad (bytes) */
|
||||
|
||||
/* memory registration strategies */
|
||||
enum rpcrdma_memreg {
|
||||
RPCRDMA_BOUNCEBUFFERS = 0,
|
||||
RPCRDMA_REGISTER,
|
||||
RPCRDMA_MEMWINDOWS,
|
||||
RPCRDMA_MEMWINDOWS_ASYNC,
|
||||
RPCRDMA_MTHCAFMR,
|
||||
RPCRDMA_FRMR,
|
||||
RPCRDMA_ALLPHYSICAL,
|
||||
RPCRDMA_LAST
|
||||
};
|
||||
|
||||
#endif /* _LINUX_SUNRPC_XPRTRDMA_H */
|
22
include/linux/sunrpc/xprtsock.h
Normal file
22
include/linux/sunrpc/xprtsock.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* linux/include/linux/sunrpc/xprtsock.h
|
||||
*
|
||||
* Declarations for the RPC transport socket provider.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SUNRPC_XPRTSOCK_H
|
||||
#define _LINUX_SUNRPC_XPRTSOCK_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
int init_socket_xprt(void);
|
||||
void cleanup_socket_xprt(void);
|
||||
|
||||
#define RPC_MIN_RESVPORT (1U)
|
||||
#define RPC_MAX_RESVPORT (65535U)
|
||||
#define RPC_DEF_MIN_RESVPORT (665U)
|
||||
#define RPC_DEF_MAX_RESVPORT (1023U)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_SUNRPC_XPRTSOCK_H */
|
Loading…
Add table
Add a link
Reference in a new issue