summaryrefslogtreecommitdiff
path: root/include/linux/sunrpc/svc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/sunrpc/svc.h')
-rw-r--r--include/linux/sunrpc/svc.h95
1 files changed, 93 insertions, 2 deletions
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 2db1b9ec5658..cfb5ab17dabd 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -78,6 +78,7 @@ struct svc_serv {
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 */
+ atomic_t sv_rpcb_failures; /* unanswered rpcbind calls */
struct list_head sv_permsocks; /* all permanent sockets */
struct list_head sv_tempsocks; /* all temporary sockets */
int sv_tmpcnt; /* count of temporary "valid" sockets */
@@ -86,6 +87,8 @@ struct svc_serv {
char * sv_name; /* service name */
bool sv_is_pooled; /* is this a pooled service? */
+ /* Caller registers with rpcbind itself. Set before svc_bind(). */
+ bool sv_no_rpcbind;
struct svc_pool * sv_pools; /* array of thread pools */
int (*sv_threadfn)(void *data);
@@ -451,6 +454,7 @@ int sunrpc_set_pool_mode(const char *val);
int sunrpc_get_pool_mode(char *val, size_t size);
void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net);
int svc_bind(struct svc_serv *serv, struct net *net);
+unsigned int svc_rpcb_failure_count(struct svc_serv *serv);
struct svc_serv *svc_create(struct svc_program *, unsigned int,
int (*threadfn)(void *data));
bool svc_rqst_replace_page(struct svc_rqst *rqstp,
@@ -471,8 +475,9 @@ unsigned int svc_serv_maxthreads(const struct svc_serv *serv);
int svc_pool_stats_open(struct svc_info *si, struct file *file);
void svc_process(struct svc_rqst *rqstp);
void svc_process_bc(struct rpc_rqst *req, struct svc_rqst *rqstp);
-int svc_register(const struct svc_serv *, struct net *, const int,
- const unsigned short, const unsigned short);
+int svc_register(struct svc_serv *serv, struct net *net,
+ const int family, const unsigned short proto,
+ const unsigned short port);
void svc_wake_up(struct svc_serv *);
void svc_reserve(struct svc_rqst *rqstp, int space);
@@ -529,6 +534,8 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space)
* svcxdr_init_decode - Prepare an xdr_stream for Call decoding
* @rqstp: controlling server RPC transaction context
*
+ * The stream records @rqstp, so a codec running on it reaches the
+ * transaction with svcxdr_rqst().
*/
static inline void svcxdr_init_decode(struct svc_rqst *rqstp)
{
@@ -541,12 +548,15 @@ static inline void svcxdr_init_decode(struct svc_rqst *rqstp)
xdr_init_decode(xdr, buf, argv->iov_base, NULL);
xdr_set_scratch_folio(xdr, rqstp->rq_scratch_folio);
+ xdr->xdrgen_ctx = rqstp;
}
/**
* svcxdr_init_encode - Prepare an xdr_stream for svc Reply encoding
* @rqstp: controlling server RPC transaction context
*
+ * The stream records @rqstp, so a codec running on it reaches the
+ * transaction with svcxdr_rqst().
*/
static inline void svcxdr_init_encode(struct svc_rqst *rqstp)
{
@@ -564,6 +574,19 @@ static inline void svcxdr_init_encode(struct svc_rqst *rqstp)
xdr->page_ptr = buf->pages - 1;
buf->buflen = PAGE_SIZE * (rqstp->rq_page_end - buf->pages);
xdr->rqst = NULL;
+ xdr->xdrgen_ctx = rqstp;
+}
+
+/**
+ * svcxdr_rqst - Retrieve the transaction bound to an xdr_stream
+ * @xdr: stream to query
+ *
+ * Return: the controlling svc_rqst when @xdr was initialized by
+ * svcxdr_init_decode() or svcxdr_init_encode(), otherwise NULL.
+ */
+static inline struct svc_rqst *svcxdr_rqst(struct xdr_stream *xdr)
+{
+ return xdr->xdrgen_ctx;
}
/**
@@ -588,6 +611,74 @@ static inline void svcxdr_encode_opaque_pages(struct svc_rqst *rqstp,
}
/**
+ * svcxdr_encode_opaque_payload - Encode a page-resident opaque data item
+ * @xdr: xdr_stream to be updated
+ * @len: number of octets of content in the data item
+ *
+ * Context: Process context. @xdr must have been initialized by
+ * svcxdr_init_encode() and still be positioned in the reply
+ * head.
+ *
+ * Return:
+ * %true: Success
+ * %false: The reply head cannot hold the length prefix and XDR
+ * padding, or the transport could not accommodate the result payload
+ */
+static inline bool svcxdr_encode_opaque_payload(struct xdr_stream *xdr, u32 len)
+{
+ struct svc_rqst *rqstp = svcxdr_rqst(xdr);
+ struct xdr_buf *buf = xdr->buf;
+
+ /*
+ * The length prefix and any pad word must land in the reply
+ * head. A prefix that spills into the first Reply page lands
+ * on the payload itself, and xdr_write_pages() BUGs when the
+ * pad word does not fit.
+ */
+ if ((xdr->end - xdr->p) * XDR_UNIT < XDR_UNIT + xdr_pad_size(len))
+ return false;
+ if (xdr_stream_encode_u32(xdr, len) < 0)
+ return false;
+ svcxdr_encode_opaque_pages(rqstp, xdr, buf->pages, buf->page_base, len);
+ if (svc_encode_result_payload(rqstp, buf->head->iov_len, len) < 0)
+ return false;
+ return true;
+}
+
+/**
+ * svcxdr_decode_opaque_payload - Decode a page-resident opaque data item
+ * @xdr: xdr_stream to be decoded
+ * @payload: on success, describes the octets of the data item's content
+ * @maxlen: largest data item length the caller will accept, or zero for
+ * no limit
+ *
+ * A bulk payload such as the content of an NFS WRITE request resides in
+ * the pages of the Receive buffer. Rather than copy it, set @payload to
+ * describe the item's content in place.
+ *
+ * Context: Process context. @xdr must have been initialized by
+ * svcxdr_init_decode().
+ *
+ * Return:
+ * %true: @payload describes the item in place and @xdr has advanced
+ * past it
+ * %false: a bounds error occurred, or the length prefix exceeds
+ * @maxlen; @payload is undefined
+ */
+static inline bool svcxdr_decode_opaque_payload(struct xdr_stream *xdr,
+ struct xdr_buf *payload,
+ u32 maxlen)
+{
+ u32 len;
+
+ if (xdr_stream_decode_u32(xdr, &len) < 0)
+ return false;
+ if (maxlen && len > maxlen)
+ return false;
+ return xdr_stream_subsegment(xdr, payload, len);
+}
+
+/**
* svcxdr_set_auth_slack -
* @rqstp: RPC transaction
* @slack: buffer space to reserve for the transaction's security flavor