* [PATCH v3 0/4] XDR cleanups for NFSv4
@ 2017-02-18 19:12 Trond Myklebust
2017-02-18 19:12 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Trond Myklebust
0 siblings, 1 reply; 11+ messages in thread
From: Trond Myklebust @ 2017-02-18 19:12 UTC (permalink / raw)
To: Anna Schumaker; +Cc: linux-nfs
Various cleanups and bugfixes for the NFSv4 client XDR code
v2: Add documentation to the generic helpers
v3: Fix a bug in xdr_stream_encode_opaque (Whoops!)
Trond Myklebust (4):
SUNRPC: Add generic helpers for xdr_stream encode/decode
NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_*
generics
NFSv4: Fix the underestimation of delegation XDR space reservation
NFSv4: Remove bogus "struct nfs_client" argument from decode_ace()
fs/nfs/callback_xdr.c | 8 +-
fs/nfs/flexfilelayout/flexfilelayout.c | 5 +-
fs/nfs/nfs4xdr.c | 58 ++++-------
include/linux/sunrpc/xdr.h | 173 +++++++++++++++++++++++++++++++++
4 files changed, 195 insertions(+), 49 deletions(-)
--
2.9.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-18 19:12 [PATCH v3 0/4] XDR cleanups for NFSv4 Trond Myklebust @ 2017-02-18 19:12 ` Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 2/4] NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics Trond Myklebust 2017-02-18 22:21 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Chuck Lever 0 siblings, 2 replies; 11+ messages in thread From: Trond Myklebust @ 2017-02-18 19:12 UTC (permalink / raw) To: Anna Schumaker; +Cc: linux-nfs Add some generic helpers for encoding/decoding opaque structures and basic u32/u64. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- include/linux/sunrpc/xdr.h | 173 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 56c48c884a24..37bf1be20b62 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -242,6 +242,179 @@ 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); +/** + * xdr_align_size - Calculate padded size of an object + * @n: Size of an object being XDR encoded (in bytes) + * + * Return value: + * Size (in bytes) of the object including xdr padding + */ +static inline size_t +xdr_align_size(size_t n) +{ + const size_t mask = sizeof(__u32) - 1; + + return (n + mask) & ~mask; +} + +/** + * xdr_stream_encode_u32 - Encode a 32-bit integer + * @xdr: pointer to xdr_stream + * @n: integer to encode + * + * Return values: + * On success, returns length in bytes of XDR buffer consumed + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n) +{ + const size_t len = sizeof(n); + __be32 *p = xdr_reserve_space(xdr, len); + + if (unlikely(!p)) + return -ENOBUFS; + *p = cpu_to_be32(n); + return len; +} + +/** + * xdr_stream_encode_u64 - Encode a 64-bit integer + * @xdr: pointer to xdr_stream + * @n: 64-bit integer to encode + * + * Return values: + * On success, returns length in bytes of XDR buffer consumed + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n) +{ + const size_t len = sizeof(n); + __be32 *p = xdr_reserve_space(xdr, len); + + if (unlikely(!p)) + return -ENOBUFS; + xdr_encode_hyper(p, n); + return len; +} + +/** + * xdr_stream_encode_opaque_fixed - Encode fixed length opaque xdr data + * @xdr: pointer to xdr_stream + * @ptr: pointer to opaque data object + * @len: size of object pointed to by @ptr + * + * Return values: + * On success, returns length in bytes of XDR buffer consumed + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void *ptr, size_t len) +{ + __be32 *p = xdr_reserve_space(xdr, len); + + if (unlikely(!p)) + return -ENOBUFS; + xdr_encode_opaque_fixed(p, ptr, len); + return xdr_align_size(len); +} + +/** + * xdr_stream_encode_opaque - Encode variable length opaque xdr data + * @xdr: pointer to xdr_stream + * @ptr: pointer to opaque data object + * @len: size of object pointed to by @ptr + * + * Return values: + * On success, returns length in bytes of XDR buffer consumed + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, size_t len) +{ + size_t count = sizeof(__u32) + xdr_align_size(len); + __be32 *p = xdr_reserve_space(xdr, count); + + if (unlikely(!p)) + return -ENOBUFS; + xdr_encode_opaque(p, ptr, len); + return count; +} + +/** + * xdr_stream_decode_u32 - Decode a 32-bit integer + * @xdr: pointer to xdr_stream + * @ptr: location to store integer + * + * Return values: + * %0 on success + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr) +{ + const size_t count = sizeof(*ptr); + __be32 *p = xdr_inline_decode(xdr, count); + + if (unlikely(!p)) + return -ENOBUFS; + *ptr = be32_to_cpup(p); + return 0; +} + +/** + * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data + * @xdr: pointer to xdr_stream + * @ptr: location to store data + * @len: size of buffer pointed to by @ptr + * + * Return values: + * On success, returns size of object stored in @ptr + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len) +{ + __be32 *p = xdr_inline_decode(xdr, len); + + if (unlikely(!p)) + return -ENOBUFS; + xdr_decode_opaque_fixed(p, ptr, len); + return len; +} + +/** + * xdr_stream_decode_opaque_inline - Decode variable length opaque xdr data + * @xdr: pointer to xdr_stream + * @ptr: location to store pointer to opaque data + * + * Note: the pointer stored in @ptr cannot be assumed valid after the XDR + * buffer has been destroyed, or even after calling xdr_inline_decode() + * on @xdr. It is therefore expected that the object it points to should + * be processed immediately. + * + * Return values: + * On success, returns size of object stored in *@ptr + * %-ENOBUFS on XDR buffer overflow + */ +static inline ssize_t +xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr) +{ + __be32 *p; + __u32 len; + + if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0)) + return -ENOBUFS; + if (len != 0) { + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + return -ENOBUFS; + *ptr = p; + } else + *ptr = NULL; + return len; +} #endif /* __KERNEL__ */ #endif /* _SUNRPC_XDR_H_ */ -- 2.9.3 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 2/4] NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics 2017-02-18 19:12 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Trond Myklebust @ 2017-02-18 19:12 ` Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 3/4] NFSv4: Fix the underestimation of delegation XDR space reservation Trond Myklebust 2017-02-18 22:21 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Chuck Lever 1 sibling, 1 reply; 11+ messages in thread From: Trond Myklebust @ 2017-02-18 19:12 UTC (permalink / raw) To: Anna Schumaker; +Cc: linux-nfs Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfs/callback_xdr.c | 8 ++---- fs/nfs/flexfilelayout/flexfilelayout.c | 5 +--- fs/nfs/nfs4xdr.c | 52 ++++++++++------------------------ 3 files changed, 18 insertions(+), 47 deletions(-) diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index eb094c6011d8..e732a65db546 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -582,12 +582,8 @@ static __be32 decode_notify_lock_args(struct svc_rqst *rqstp, struct xdr_stream static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) { - __be32 *p; - - p = xdr_reserve_space(xdr, 4 + len); - if (unlikely(p == NULL)) - return htonl(NFS4ERR_RESOURCE); - xdr_encode_opaque(p, str, len); + if (unlikely(xdr_stream_encode_opaque(xdr, str, len) < 0)) + return cpu_to_be32(NFS4ERR_RESOURCE); return 0; } diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 42e3e9daa328..471efdc2589d 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -1966,10 +1966,7 @@ static int ff_layout_encode_ioerr(struct xdr_stream *xdr, static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) { - __be32 *p; - - p = xdr_reserve_space(xdr, len); - xdr_encode_opaque_fixed(p, buf, len); + WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); } static void diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index e9255cb453e6..62ff0ff19880 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -924,34 +924,22 @@ static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) { - __be32 *p; - - p = xdr_reserve_space(xdr, len); - xdr_encode_opaque_fixed(p, buf, len); + WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); } static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) { - __be32 *p; - - p = reserve_space(xdr, 4 + len); - xdr_encode_opaque(p, str, len); + WARN_ON_ONCE(xdr_stream_encode_opaque(xdr, str, len) < 0); } static void encode_uint32(struct xdr_stream *xdr, u32 n) { - __be32 *p; - - p = reserve_space(xdr, 4); - *p = cpu_to_be32(n); + WARN_ON_ONCE(xdr_stream_encode_u32(xdr, n) < 0); } static void encode_uint64(struct xdr_stream *xdr, u64 n) { - __be32 *p; - - p = reserve_space(xdr, 8); - xdr_encode_hyper(p, n); + WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0); } static void encode_nfs4_seqid(struct xdr_stream *xdr, @@ -3062,20 +3050,13 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) { - __be32 *p; - - p = xdr_inline_decode(xdr, 4); - if (unlikely(!p)) - goto out_overflow; - *len = be32_to_cpup(p); - p = xdr_inline_decode(xdr, *len); - if (unlikely(!p)) - goto out_overflow; - *string = (char *)p; + ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string); + if (unlikely(ret < 0)) { + print_overflow_msg(__func__, xdr); + return -EIO; + } + *len = ret; return 0; -out_overflow: - print_overflow_msg(__func__, xdr); - return -EIO; } static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) @@ -4294,15 +4275,12 @@ static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access) static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) { - __be32 *p; - - p = xdr_inline_decode(xdr, len); - if (likely(p)) { - memcpy(buf, p, len); - return 0; + ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len); + if (unlikely(ret < 0)) { + print_overflow_msg(__func__, xdr); + return -EIO; } - print_overflow_msg(__func__, xdr); - return -EIO; + return 0; } static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) -- 2.9.3 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 3/4] NFSv4: Fix the underestimation of delegation XDR space reservation 2017-02-18 19:12 ` [PATCH v3 2/4] NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics Trond Myklebust @ 2017-02-18 19:12 ` Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 4/4] NFSv4: Remove bogus "struct nfs_client" argument from decode_ace() Trond Myklebust 0 siblings, 1 reply; 11+ messages in thread From: Trond Myklebust @ 2017-02-18 19:12 UTC (permalink / raw) To: Anna Schumaker; +Cc: linux-nfs Account for the "space_limit" field in struct open_write_delegation4. Fixes: 2cebf82883f4 ("NFSv4: Fix the underestimate of NFSv4 open request size") Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfs/nfs4xdr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 62ff0ff19880..7510a0cd93fa 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -169,8 +169,10 @@ static int nfs4_stat_to_errno(int); open_owner_id_maxsz + \ encode_opentype_maxsz + \ encode_claim_null_maxsz) +#define decode_space_limit_maxsz (3) #define decode_ace_maxsz (3 + nfs4_owner_maxsz) #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ + decode_space_limit_maxsz + \ decode_ace_maxsz) #define decode_change_info_maxsz (5) #define decode_open_maxsz (op_decode_hdr_maxsz + \ -- 2.9.3 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 4/4] NFSv4: Remove bogus "struct nfs_client" argument from decode_ace() 2017-02-18 19:12 ` [PATCH v3 3/4] NFSv4: Fix the underestimation of delegation XDR space reservation Trond Myklebust @ 2017-02-18 19:12 ` Trond Myklebust 0 siblings, 0 replies; 11+ messages in thread From: Trond Myklebust @ 2017-02-18 19:12 UTC (permalink / raw) To: Anna Schumaker; +Cc: linux-nfs We shouldn't need to force callers to carry an unused argument. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfs/nfs4xdr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 7510a0cd93fa..dbb765fb4180 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -3125,7 +3125,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) } /* Dummy routine */ -static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) +static int decode_ace(struct xdr_stream *xdr, void *ace) { __be32 *p; unsigned int strlen; @@ -5073,7 +5073,7 @@ static int decode_rw_delegation(struct xdr_stream *xdr, if (decode_space_limit(xdr, &res->pagemod_limit) < 0) return -EIO; } - return decode_ace(xdr, NULL, res->server->nfs_client); + return decode_ace(xdr, NULL); out_overflow: print_overflow_msg(__func__, xdr); return -EIO; -- 2.9.3 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-18 19:12 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 2/4] NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics Trond Myklebust @ 2017-02-18 22:21 ` Chuck Lever 2017-02-19 5:36 ` Trond Myklebust 1 sibling, 1 reply; 11+ messages in thread From: Chuck Lever @ 2017-02-18 22:21 UTC (permalink / raw) To: Trond Myklebust; +Cc: Anna Schumaker, Linux NFS Mailing List > On Feb 18, 2017, at 2:12 PM, Trond Myklebust <trond.myklebust@primarydata.com> wrote: > > Add some generic helpers for encoding/decoding opaque structures and > basic u32/u64. I have some random-thoughts-slash-wacky-ideas. I'm going to paint the garden shed a little since these helpers appear to be broadly applicable. Generally speaking I like the idea of building "stream" versions of the traditional basic type encoders and decoders. > Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> > --- > include/linux/sunrpc/xdr.h | 173 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 173 insertions(+) > > diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h > index 56c48c884a24..37bf1be20b62 100644 > --- a/include/linux/sunrpc/xdr.h > +++ b/include/linux/sunrpc/xdr.h > @@ -242,6 +242,179 @@ 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); > > +/** > + * xdr_align_size - Calculate padded size of an object > + * @n: Size of an object being XDR encoded (in bytes) > + * > + * Return value: > + * Size (in bytes) of the object including xdr padding > + */ > +static inline size_t > +xdr_align_size(size_t n) > +{ > + const size_t mask = sizeof(__u32) - 1; I know this doesn't make a functional difference, but I'm wondering if this should be sizeof(__be32), since it is actually the size of a wire object? Seems like that is a common question wherever sizeof is used below. Is this a constant variable rather than an enum because you want it to retain the type of size_t (matching the type of the xdr_inline_{en,de}code() functions) ? Since we see sizeof(yada) repeated elsewhere, did you consider defining size constants in a scope where they can be shared amongst all of the XDR functions? For example, xdr_reserve_space itself could immediately make use of a "sizeof(__be32) - 1" constant. Is your intention to replace XDR_QUADLEN with this function eventually? > + > + return (n + mask) & ~mask; > +} > + > +/** > + * xdr_stream_encode_u32 - Encode a 32-bit integer > + * @xdr: pointer to xdr_stream > + * @n: integer to encode > + * > + * Return values: > + * On success, returns length in bytes of XDR buffer consumed > + * %-ENOBUFS on XDR buffer overflow I've never been crazy about these amplified return types, though I know it's typical kernel coding style. Here, though, I wonder if they are really necessary. The returned length seems to be interesting only for decoding variable-length objects (farther below). Maybe those are the only functions that need to provide a positive return value? Perhaps the WARN_ON_ONCE calls added in later patches should be in these helpers instead of in their callers. Then the encoder helpers can return void. > + */ > +static inline ssize_t > +xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n) > +{ > + const size_t len = sizeof(n); > + __be32 *p = xdr_reserve_space(xdr, len); > + > + if (unlikely(!p)) > + return -ENOBUFS; > + *p = cpu_to_be32(n); > + return len; > +} > + > +/** > + * xdr_stream_encode_u64 - Encode a 64-bit integer > + * @xdr: pointer to xdr_stream > + * @n: 64-bit integer to encode > + * > + * Return values: > + * On success, returns length in bytes of XDR buffer consumed > + * %-ENOBUFS on XDR buffer overflow > + */ > +static inline ssize_t > +xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n) > +{ > + const size_t len = sizeof(n); > + __be32 *p = xdr_reserve_space(xdr, len); > + > + if (unlikely(!p)) > + return -ENOBUFS; > + xdr_encode_hyper(p, n); > + return len; > +} > + > +/** > + * xdr_stream_encode_opaque_fixed - Encode fixed length opaque xdr data > + * @xdr: pointer to xdr_stream > + * @ptr: pointer to opaque data object > + * @len: size of object pointed to by @ptr > + * > + * Return values: > + * On success, returns length in bytes of XDR buffer consumed > + * %-ENOBUFS on XDR buffer overflow > + */ > +static inline ssize_t > +xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void *ptr, size_t len) > +{ > + __be32 *p = xdr_reserve_space(xdr, len); > + > + if (unlikely(!p)) > + return -ENOBUFS; > + xdr_encode_opaque_fixed(p, ptr, len); > + return xdr_align_size(len); Seems like the caller can use xdr_align_size() just as easily as overloading the return value here, for example. But I can't think of any fixed-size opaque XDR object that is not already properly rounded up, or where the length is not already known to the XDR layer (as a defined macro constant). > +} > + > +/** > + * xdr_stream_encode_opaque - Encode variable length opaque xdr data > + * @xdr: pointer to xdr_stream > + * @ptr: pointer to opaque data object > + * @len: size of object pointed to by @ptr > + * > + * Return values: > + * On success, returns length in bytes of XDR buffer consumed > + * %-ENOBUFS on XDR buffer overflow > + */ > +static inline ssize_t > +xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, size_t len) > +{ > + size_t count = sizeof(__u32) + xdr_align_size(len); > + __be32 *p = xdr_reserve_space(xdr, count); > + > + if (unlikely(!p)) > + return -ENOBUFS; > + xdr_encode_opaque(p, ptr, len); > + return count; These helpers already update the state of the passed in xdr_stream, so a caller typically would not need to care much about the bytes consumed by the encoded opaque. > +} > + > +/** > + * xdr_stream_decode_u32 - Decode a 32-bit integer > + * @xdr: pointer to xdr_stream > + * @ptr: location to store integer > + * > + * Return values: > + * %0 on success > + * %-ENOBUFS on XDR buffer overflow > + */ > +static inline ssize_t > +xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr) > +{ > + const size_t count = sizeof(*ptr); > + __be32 *p = xdr_inline_decode(xdr, count); > + > + if (unlikely(!p)) > + return -ENOBUFS; > + *ptr = be32_to_cpup(p); > + return 0; No length returned here. The caller knows the length of this object, clearly, and only cares about whether decoding has overrun the XDR stream. > +} > + > +/** > + * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data > + * @xdr: pointer to xdr_stream > + * @ptr: location to store data > + * @len: size of buffer pointed to by @ptr > + * > + * Return values: > + * On success, returns size of object stored in @ptr You're returning the passed-in length. Thus the caller already knows the size of the object stored at @ptr. > + * %-ENOBUFS on XDR buffer overflow > + */ > +static inline ssize_t > +xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len) > +{ > + __be32 *p = xdr_inline_decode(xdr, len); > + > + if (unlikely(!p)) > + return -ENOBUFS; > + xdr_decode_opaque_fixed(p, ptr, len); > + return len; > +} > + > +/** > + * xdr_stream_decode_opaque_inline - Decode variable length opaque xdr data > + * @xdr: pointer to xdr_stream > + * @ptr: location to store pointer to opaque data > + * > + * Note: the pointer stored in @ptr cannot be assumed valid after the XDR > + * buffer has been destroyed, or even after calling xdr_inline_decode() > + * on @xdr. It is therefore expected that the object it points to should > + * be processed immediately. > + * > + * Return values: > + * On success, returns size of object stored in *@ptr This seems to be the only function where the caller might not already know the length of the object, but might actually care. Since the object length can be considered part of the object itself, maybe that length should be returned via an output parameter rather than as the function's return value. > + * %-ENOBUFS on XDR buffer overflow EINVAL is probably better: the caller didn't provide the correct inputs. That's a nit, though. However, as a matter of defensive coding, this errno could leak up the stack if developers are not careful. A boolean return value could be entirely adequate for these decoders? > + */ > +static inline ssize_t > +xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr) > +{ > + __be32 *p; > + __u32 len; > + > + if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0)) > + return -ENOBUFS; > + if (len != 0) { > + p = xdr_inline_decode(xdr, len); > + if (unlikely(!p)) > + return -ENOBUFS; > + *ptr = p; > + } else > + *ptr = NULL; > + return len; > +} > #endif /* __KERNEL__ */ > > #endif /* _SUNRPC_XDR_H_ */ > -- > 2.9.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Chuck Lever ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-18 22:21 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Chuck Lever @ 2017-02-19 5:36 ` Trond Myklebust 2017-02-19 19:07 ` Chuck Lever 0 siblings, 1 reply; 11+ messages in thread From: Trond Myklebust @ 2017-02-19 5:36 UTC (permalink / raw) To: chuck.lever@oracle.com Cc: anna.schumaker@netapp.com, linux-nfs@vger.kernel.org T24gU2F0LCAyMDE3LTAyLTE4IGF0IDE3OjIxIC0wNTAwLCBDaHVjayBMZXZlciB3cm90ZToNCj4g PiBPbiBGZWIgMTgsIDIwMTcsIGF0IDI6MTIgUE0sIFRyb25kIE15a2xlYnVzdCA8dHJvbmQubXlr bGVidXN0QHByaW1hDQo+ID4gcnlkYXRhLmNvbT4gd3JvdGU6DQo+ID4gDQo+ID4gQWRkIHNvbWUg Z2VuZXJpYyBoZWxwZXJzIGZvciBlbmNvZGluZy9kZWNvZGluZyBvcGFxdWUgc3RydWN0dXJlcw0K PiA+IGFuZA0KPiA+IGJhc2ljIHUzMi91NjQuDQo+IA0KPiBJIGhhdmUgc29tZSByYW5kb20tdGhv dWdodHMtc2xhc2gtd2Fja3ktaWRlYXMuDQo+IA0KPiBJJ20gZ29pbmcgdG8gcGFpbnQgdGhlIGdh cmRlbiBzaGVkIGEgbGl0dGxlIHNpbmNlDQo+IHRoZXNlIGhlbHBlcnMgYXBwZWFyIHRvIGJlIGJy b2FkbHkgYXBwbGljYWJsZS4NCj4gR2VuZXJhbGx5IHNwZWFraW5nIEkgbGlrZSB0aGUgaWRlYSBv ZiBidWlsZGluZw0KPiAic3RyZWFtIiB2ZXJzaW9ucyBvZiB0aGUgdHJhZGl0aW9uYWwgYmFzaWMg dHlwZQ0KPiBlbmNvZGVycyBhbmQgZGVjb2RlcnMuDQo+IA0KPiANCj4gPiBTaWduZWQtb2ZmLWJ5 OiBUcm9uZCBNeWtsZWJ1c3QgPHRyb25kLm15a2xlYnVzdEBwcmltYXJ5ZGF0YS5jb20+DQo+ID4g LS0tDQo+ID4gaW5jbHVkZS9saW51eC9zdW5ycGMveGRyLmggfCAxNzMNCj4gPiArKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gPiAxIGZpbGUgY2hhbmdlZCwg MTczIGluc2VydGlvbnMoKykNCj4gPiANCj4gPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9z dW5ycGMveGRyLmgNCj4gPiBiL2luY2x1ZGUvbGludXgvc3VucnBjL3hkci5oDQo+ID4gaW5kZXgg NTZjNDhjODg0YTI0Li4zN2JmMWJlMjBiNjIgMTAwNjQ0DQo+ID4gLS0tIGEvaW5jbHVkZS9saW51 eC9zdW5ycGMveGRyLmgNCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3N1bnJwYy94ZHIuaA0KPiA+ IEBAIC0yNDIsNiArMjQyLDE3OSBAQCBleHRlcm4gdW5zaWduZWQgaW50IHhkcl9yZWFkX3BhZ2Vz KHN0cnVjdA0KPiA+IHhkcl9zdHJlYW0gKnhkciwgdW5zaWduZWQgaW50IGxlbik7DQo+ID4gZXh0 ZXJuIHZvaWQgeGRyX2VudGVyX3BhZ2Uoc3RydWN0IHhkcl9zdHJlYW0gKnhkciwgdW5zaWduZWQg aW50DQo+ID4gbGVuKTsNCj4gPiBleHRlcm4gaW50IHhkcl9wcm9jZXNzX2J1ZihzdHJ1Y3QgeGRy X2J1ZiAqYnVmLCB1bnNpZ25lZCBpbnQNCj4gPiBvZmZzZXQsIHVuc2lnbmVkIGludCBsZW4sIGlu dCAoKmFjdG9yKShzdHJ1Y3Qgc2NhdHRlcmxpc3QgKiwgdm9pZA0KPiA+ICopLCB2b2lkICpkYXRh KTsNCj4gPiANCj4gPiArLyoqDQo+ID4gKyAqIHhkcl9hbGlnbl9zaXplIC0gQ2FsY3VsYXRlIHBh ZGRlZCBzaXplIG9mIGFuIG9iamVjdA0KPiA+ICsgKiBAbjogU2l6ZSBvZiBhbiBvYmplY3QgYmVp bmcgWERSIGVuY29kZWQgKGluIGJ5dGVzKQ0KPiA+ICsgKg0KPiA+ICsgKiBSZXR1cm4gdmFsdWU6 DQo+ID4gKyAqwqDCoMKgU2l6ZSAoaW4gYnl0ZXMpIG9mIHRoZSBvYmplY3QgaW5jbHVkaW5nIHhk ciBwYWRkaW5nDQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMgaW5saW5lIHNpemVfdA0KPiA+ICt4ZHJf YWxpZ25fc2l6ZShzaXplX3QgbikNCj4gPiArew0KPiA+ICsJY29uc3Qgc2l6ZV90IG1hc2sgPSBz aXplb2YoX191MzIpIC0gMTsNCj4gDQo+IEkga25vdyB0aGlzIGRvZXNuJ3QgbWFrZSBhIGZ1bmN0 aW9uYWwgZGlmZmVyZW5jZSwgYnV0DQo+IEknbSB3b25kZXJpbmcgaWYgdGhpcyBzaG91bGQgYmUg c2l6ZW9mKF9fYmUzMiksIHNpbmNlDQo+IGl0IGlzIGFjdHVhbGx5IHRoZSBzaXplIG9mIGEgd2ly ZSBvYmplY3Q/IFNlZW1zIGxpa2UNCj4gdGhhdCBpcyBhIGNvbW1vbiBxdWVzdGlvbiB3aGVyZXZl ciBzaXplb2YgaXMgdXNlZA0KPiBiZWxvdy4NCg0KVGhlIF9fYmUzMiBpcyByZXF1aXJlZCB0byBi ZSB0aGUgc2FtZSBzaXplIGFzIHUzMi4gVGhlIG9ubHkgYWxsb3dlZA0KZGlmZmVyZW5jZSBiZXR3 ZWVuIHRoZSB0d28gaXMgYmUgdGhlIGVuZGlhbm5lc3MuDQoNCj4gSXMgdGhpcyBhIGNvbnN0YW50 IHZhcmlhYmxlIHJhdGhlciB0aGFuIGFuIGVudW0gYmVjYXVzZQ0KPiB5b3Ugd2FudCBpdCB0byBy ZXRhaW4gdGhlIHR5cGUgb2Ygc2l6ZV90IChtYXRjaGluZyB0aGUNCj4gdHlwZSBvZiB0aGUgeGRy X2lubGluZV97ZW4sZGV9Y29kZSgpIGZ1bmN0aW9ucykgPw0KDQpJdCdzIHJlYWxseSBqdXN0IGZv ciBlZmZpY2llbmN5LCBpbiBvcmRlciB0byBwcm9kIGdjYyBpbnRvIG9wdGltaXNpbmcNCml0IGFz IGl0IHdvdWxkIGFueSBvdGhlciBjb25zdGFudC4NCg0KPiBTaW5jZSB3ZSBzZWUgc2l6ZW9mKHlh ZGEpIHJlcGVhdGVkIGVsc2V3aGVyZSwgZGlkIHlvdQ0KPiBjb25zaWRlciBkZWZpbmluZyBzaXpl IGNvbnN0YW50cyBpbiBhIHNjb3BlIHdoZXJlIHRoZXkNCj4gY2FuIGJlIHNoYXJlZCBhbW9uZ3N0 IGFsbCBvZiB0aGUgWERSIGZ1bmN0aW9ucz8NCj4gDQo+IEZvciBleGFtcGxlLCB4ZHJfcmVzZXJ2 ZV9zcGFjZSBpdHNlbGYgY291bGQgaW1tZWRpYXRlbHkNCj4gbWFrZSB1c2Ugb2YgYSAic2l6ZW9m KF9fYmUzMikgLSAxIiBjb25zdGFudC4NCg0KVGhhdCBjb3VsZCBiZSBkb25lLiBJIGhhdmVuJ3Qg cmVhbGx5IGNvbnNpZGVyZWQgaXQuDQoNCj4gSXMgeW91ciBpbnRlbnRpb24gdG8gcmVwbGFjZSBY RFJfUVVBRExFTiB3aXRoIHRoaXMNCj4gZnVuY3Rpb24gZXZlbnR1YWxseT8NCg0KRXZlbnR1YWxs eSwgSSdkIGxpa2UgdXMgdG8gZ2V0IHJpZCBvZiBtb3N0IG9mIHRoZSBvcGVuIGNvZGVkIGluc3Rh bmNlcw0Kb2YgJ3BvaW50ZXIgdG8gX19iZTMyJyBpbiB0aGUgTkZTIGNvZGUsIGFuZCBoaWRlIGFs bCBrbm93bGVkZ2Ugb2YgdGhhdA0KaW4gc3RydWN0IHhkcl9zdHJlYW0gYW5kIHRoZXNlIFNVTlJQ QyBsYXllcmVkIGhlbHBlcnMuDQoNCj4gPiArDQo+ID4gKwlyZXR1cm4gKG4gKyBtYXNrKSAmIH5t YXNrOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICsvKioNCj4gPiArICogeGRyX3N0cmVhbV9lbmNvZGVf dTMyIC0gRW5jb2RlIGEgMzItYml0IGludGVnZXINCj4gPiArICogQHhkcjogcG9pbnRlciB0byB4 ZHJfc3RyZWFtDQo+ID4gKyAqIEBuOiBpbnRlZ2VyIHRvIGVuY29kZQ0KPiA+ICsgKg0KPiA+ICsg KiBSZXR1cm4gdmFsdWVzOg0KPiA+ICsgKsKgwqDCoE9uIHN1Y2Nlc3MsIHJldHVybnMgbGVuZ3Ro IGluIGJ5dGVzIG9mIFhEUiBidWZmZXIgY29uc3VtZWQNCj4gPiArICrCoMKgwqAlLUVOT0JVRlMg b24gWERSIGJ1ZmZlciBvdmVyZmxvdw0KPiANCj4gSSd2ZSBuZXZlciBiZWVuIGNyYXp5IGFib3V0 IHRoZXNlIGFtcGxpZmllZCByZXR1cm4NCj4gdHlwZXMsIHRob3VnaCBJIGtub3cgaXQncyB0eXBp Y2FsIGtlcm5lbCBjb2Rpbmcgc3R5bGUuDQo+IEhlcmUsIHRob3VnaCwgSSB3b25kZXIgaWYgdGhl eSBhcmUgcmVhbGx5IG5lY2Vzc2FyeS4NCj4gDQo+IFRoZSByZXR1cm5lZCBsZW5ndGggc2VlbXMg dG8gYmUgaW50ZXJlc3Rpbmcgb25seSBmb3INCj4gZGVjb2RpbmcgdmFyaWFibGUtbGVuZ3RoIG9i amVjdHMgKGZhcnRoZXIgYmVsb3cpLiBNYXliZQ0KPiB0aG9zZSBhcmUgdGhlIG9ubHkgZnVuY3Rp b25zIHRoYXQgbmVlZCB0byBwcm92aWRlIGENCj4gcG9zaXRpdmUgcmV0dXJuIHZhbHVlPw0KDQpO RlN2NCBpbnRyb2R1Y2VzIHRoZSAoSU1PIG5hc3R5KSBoYWJpdCBvZiBuZXN0aW5nIFhEUi1lbmNv ZGVkIG9iamVjdHMNCmluc2lkZSBhIHZhcmlhYmxlIGxlbmd0aCBvcGFxdWUgb2JqZWN0IChzYXkg aGVsbG8gdG8gdHlwZSAiYXR0cmxpc3Q0IikuDQpJbiB0aGF0IGNhc2UsIHdlIG5lZWQgdG8ga2Vl cCBhIHJ1bm5pbmcgdGFsbHkgb2YgdGhlIGxlbmd0aCBvZiB0aGUNCm9iamVjdHMgd2UgaGF2ZSBY RFIgZW5jb2RlZCBzbyB0aGF0IHdlIGNhbiByZXRyb2FjdGl2ZWx5IHNldCB0aGUgbGVuZ3RoDQpv ZiB0aGUgb3BhcXVlIG9iamVjdC4gQ3VycmVudGx5IHdlIHVzZSB0aGUgeGRyX3N0cmVhbV9wb3Mo KSB0bw0KZGV0ZXJtaW5lIHRoYXQgbGVuZ3RoLCBidXQgaXQgbWlnaHQgYmUgbmljZSB0byByZXBs YWNlIHRoYXQgd2l0aA0Kc29tZXRoaW5nIGEgbGl0dGxlIG1vcmUgZGlyZWN0Lg0KDQpOb3RlIGFs c28gdGhhdCB0aGUgbGVuZ3RocyByZXR1cm5lZCBoZXJlIGFyZSBub3QgdGhlIG9iamVjdCBzaXpl cw0KdGhlbXNlbHZlcywgYnV0IHRoZSBhbW91bnQgb2YgYnVmZmVyIHNwYWNlIGNvbnN1bWVkIChp LmUuIHRoZSBhbGlnbmVkDQpzaXplKS4NCg0KPiBQZXJoYXBzIHRoZSBXQVJOX09OX09OQ0UgY2Fs bHMgYWRkZWQgaW4gbGF0ZXIgcGF0Y2hlcw0KPiBzaG91bGQgYmUgaW4gdGhlc2UgaGVscGVycyBp bnN0ZWFkIG9mIGluIHRoZWlyIGNhbGxlcnMuDQo+IFRoZW4gdGhlIGVuY29kZXIgaGVscGVycyBj YW4gcmV0dXJuIHZvaWQuDQoNCkF0IHNvbWUgcG9pbnQsIEknZCBsaWtlIHRvIHJlaW5zdGF0ZSB0 aGUgcHJhY3RpY2Ugb2YgcmV0dXJuaW5nIGFuIGVycm9yDQp3aGVuIGVuY29kaW5nIGZhaWxzLiBJ dCBtYXkgYmUgYmV0dGVyIHRvIGFib3J0IHNlbmRpbmcgYSB0cnVuY2F0ZWQgUlBDDQpjYWxsIHJh dGhlciB0aGFuIGhhdmluZyBpdCBleGVjdXRlIHBhcnRpYWxseTsgc3BlY2lhbGx5IG5vdyB0aGF0 IHdlJ3JlDQpmaW5hbGx5IHN0YXJ0aW5nIHRvIHVzZSBDT01QT1VORCB0byBjcmVhdGUgbW9yZSBj b21wbGV4IG9wZXJhdGlvbnMuDQoNCj4gDQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMgaW5saW5lIHNz aXplX3QNCj4gPiAreGRyX3N0cmVhbV9lbmNvZGVfdTMyKHN0cnVjdCB4ZHJfc3RyZWFtICp4ZHIs IF9fdTMyIG4pDQo+ID4gK3sNCj4gPiArCWNvbnN0IHNpemVfdCBsZW4gPSBzaXplb2Yobik7DQo+ ID4gKwlfX2JlMzIgKnAgPSB4ZHJfcmVzZXJ2ZV9zcGFjZSh4ZHIsIGxlbik7DQo+ID4gKw0KPiA+ ICsJaWYgKHVubGlrZWx5KCFwKSkNCj4gPiArCQlyZXR1cm4gLUVOT0JVRlM7DQo+ID4gKwkqcCA9 IGNwdV90b19iZTMyKG4pOw0KPiA+ICsJcmV0dXJuIGxlbjsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr LyoqDQo+ID4gKyAqIHhkcl9zdHJlYW1fZW5jb2RlX3U2NCAtIEVuY29kZSBhIDY0LWJpdCBpbnRl Z2VyDQo+ID4gKyAqIEB4ZHI6IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ICsgKiBAbjogNjQt Yml0IGludGVnZXIgdG8gZW5jb2RlDQo+ID4gKyAqDQo+ID4gKyAqIFJldHVybiB2YWx1ZXM6DQo+ ID4gKyAqwqDCoMKgT24gc3VjY2VzcywgcmV0dXJucyBsZW5ndGggaW4gYnl0ZXMgb2YgWERSIGJ1 ZmZlciBjb25zdW1lZA0KPiA+ICsgKsKgwqDCoCUtRU5PQlVGUyBvbiBYRFIgYnVmZmVyIG92ZXJm bG93DQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMgaW5saW5lIHNzaXplX3QNCj4gPiAreGRyX3N0cmVh bV9lbmNvZGVfdTY0KHN0cnVjdCB4ZHJfc3RyZWFtICp4ZHIsIF9fdTY0IG4pDQo+ID4gK3sNCj4g PiArCWNvbnN0IHNpemVfdCBsZW4gPSBzaXplb2Yobik7DQo+ID4gKwlfX2JlMzIgKnAgPSB4ZHJf cmVzZXJ2ZV9zcGFjZSh4ZHIsIGxlbik7DQo+ID4gKw0KPiA+ICsJaWYgKHVubGlrZWx5KCFwKSkN Cj4gPiArCQlyZXR1cm4gLUVOT0JVRlM7DQo+ID4gKwl4ZHJfZW5jb2RlX2h5cGVyKHAsIG4pOw0K PiA+ICsJcmV0dXJuIGxlbjsNCj4gPiArfQ0KPiA+ICsNCj4gPiArLyoqDQo+ID4gKyAqIHhkcl9z dHJlYW1fZW5jb2RlX29wYXF1ZV9maXhlZCAtIEVuY29kZSBmaXhlZCBsZW5ndGggb3BhcXVlIHhk cg0KPiA+IGRhdGENCj4gPiArICogQHhkcjogcG9pbnRlciB0byB4ZHJfc3RyZWFtDQo+ID4gKyAq IEBwdHI6IHBvaW50ZXIgdG8gb3BhcXVlIGRhdGEgb2JqZWN0DQo+ID4gKyAqIEBsZW46IHNpemUg b2Ygb2JqZWN0IHBvaW50ZWQgdG8gYnkgQHB0cg0KPiA+ICsgKg0KPiA+ICsgKiBSZXR1cm4gdmFs dWVzOg0KPiA+ICsgKsKgwqDCoE9uIHN1Y2Nlc3MsIHJldHVybnMgbGVuZ3RoIGluIGJ5dGVzIG9m IFhEUiBidWZmZXIgY29uc3VtZWQNCj4gPiArICrCoMKgwqAlLUVOT0JVRlMgb24gWERSIGJ1ZmZl ciBvdmVyZmxvdw0KPiA+ICsgKi8NCj4gPiArc3RhdGljIGlubGluZSBzc2l6ZV90DQo+ID4gK3hk cl9zdHJlYW1fZW5jb2RlX29wYXF1ZV9maXhlZChzdHJ1Y3QgeGRyX3N0cmVhbSAqeGRyLCBjb25z dCB2b2lkDQo+ID4gKnB0ciwgc2l6ZV90IGxlbikNCj4gPiArew0KPiA+ICsJX19iZTMyICpwID0g eGRyX3Jlc2VydmVfc3BhY2UoeGRyLCBsZW4pOw0KPiA+ICsNCj4gPiArCWlmICh1bmxpa2VseSgh cCkpDQo+ID4gKwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ICsJeGRyX2VuY29kZV9vcGFxdWVfZml4 ZWQocCwgcHRyLCBsZW4pOw0KPiA+ICsJcmV0dXJuIHhkcl9hbGlnbl9zaXplKGxlbik7DQo+IA0K PiBTZWVtcyBsaWtlIHRoZSBjYWxsZXIgY2FuIHVzZSB4ZHJfYWxpZ25fc2l6ZSgpIGp1c3QgYXMN Cj4gZWFzaWx5IGFzIG92ZXJsb2FkaW5nIHRoZSByZXR1cm4gdmFsdWUgaGVyZSwgZm9yIGV4YW1w bGUuDQo+IA0KPiBCdXQgSSBjYW4ndCB0aGluayBvZiBhbnkgZml4ZWQtc2l6ZSBvcGFxdWUgWERS IG9iamVjdA0KPiB0aGF0IGlzIG5vdCBhbHJlYWR5IHByb3Blcmx5IHJvdW5kZWQgdXAsIG9yIHdo ZXJlIHRoZQ0KPiBsZW5ndGggaXMgbm90IGFscmVhZHkga25vd24gdG8gdGhlIFhEUiBsYXllciAo YXMgYQ0KPiBkZWZpbmVkIG1hY3JvIGNvbnN0YW50KS4NCj4gDQo+IA0KPiA+ICt9DQo+ID4gKw0K PiA+ICsvKioNCj4gPiArICogeGRyX3N0cmVhbV9lbmNvZGVfb3BhcXVlIC0gRW5jb2RlIHZhcmlh YmxlIGxlbmd0aCBvcGFxdWUgeGRyDQo+ID4gZGF0YQ0KPiA+ICsgKiBAeGRyOiBwb2ludGVyIHRv IHhkcl9zdHJlYW0NCj4gPiArICogQHB0cjogcG9pbnRlciB0byBvcGFxdWUgZGF0YSBvYmplY3QN Cj4gPiArICogQGxlbjogc2l6ZSBvZiBvYmplY3QgcG9pbnRlZCB0byBieSBAcHRyDQo+ID4gKyAq DQo+ID4gKyAqIFJldHVybiB2YWx1ZXM6DQo+ID4gKyAqwqDCoMKgT24gc3VjY2VzcywgcmV0dXJu cyBsZW5ndGggaW4gYnl0ZXMgb2YgWERSIGJ1ZmZlciBjb25zdW1lZA0KPiA+ICsgKsKgwqDCoCUt RU5PQlVGUyBvbiBYRFIgYnVmZmVyIG92ZXJmbG93DQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMgaW5s aW5lIHNzaXplX3QNCj4gPiAreGRyX3N0cmVhbV9lbmNvZGVfb3BhcXVlKHN0cnVjdCB4ZHJfc3Ry ZWFtICp4ZHIsIGNvbnN0IHZvaWQgKnB0ciwNCj4gPiBzaXplX3QgbGVuKQ0KPiA+ICt7DQo+ID4g KwlzaXplX3QgY291bnQgPSBzaXplb2YoX191MzIpICsgeGRyX2FsaWduX3NpemUobGVuKTsNCj4g PiArCV9fYmUzMiAqcCA9IHhkcl9yZXNlcnZlX3NwYWNlKHhkciwgY291bnQpOw0KPiA+ICsNCj4g PiArCWlmICh1bmxpa2VseSghcCkpDQo+ID4gKwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ICsJeGRy X2VuY29kZV9vcGFxdWUocCwgcHRyLCBsZW4pOw0KPiA+ICsJcmV0dXJuIGNvdW50Ow0KPiANCj4g VGhlc2UgaGVscGVycyBhbHJlYWR5IHVwZGF0ZSB0aGUgc3RhdGUgb2YgdGhlIHBhc3NlZA0KPiBp biB4ZHJfc3RyZWFtLCBzbyBhIGNhbGxlciB0eXBpY2FsbHkgd291bGQgbm90IG5lZWQNCj4gdG8g Y2FyZSBtdWNoIGFib3V0IHRoZSBieXRlcyBjb25zdW1lZCBieSB0aGUgZW5jb2RlZA0KPiBvcGFx dWUuDQo+IA0KPiANCj4gPiArfQ0KPiA+ICsNCj4gPiArLyoqDQo+ID4gKyAqIHhkcl9zdHJlYW1f ZGVjb2RlX3UzMiAtIERlY29kZSBhIDMyLWJpdCBpbnRlZ2VyDQo+ID4gKyAqIEB4ZHI6IHBvaW50 ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ICsgKiBAcHRyOiBsb2NhdGlvbiB0byBzdG9yZSBpbnRlZ2Vy DQo+ID4gKyAqDQo+ID4gKyAqIFJldHVybiB2YWx1ZXM6DQo+ID4gKyAqwqDCoMKgJTAgb24gc3Vj Y2Vzcw0KPiA+ICsgKsKgwqDCoCUtRU5PQlVGUyBvbiBYRFIgYnVmZmVyIG92ZXJmbG93DQo+ID4g KyAqLw0KPiA+ICtzdGF0aWMgaW5saW5lIHNzaXplX3QNCj4gPiAreGRyX3N0cmVhbV9kZWNvZGVf dTMyKHN0cnVjdCB4ZHJfc3RyZWFtICp4ZHIsIF9fdTMyICpwdHIpDQo+ID4gK3sNCj4gPiArCWNv bnN0IHNpemVfdCBjb3VudCA9IHNpemVvZigqcHRyKTsNCj4gPiArCV9fYmUzMiAqcCA9IHhkcl9p bmxpbmVfZGVjb2RlKHhkciwgY291bnQpOw0KPiA+ICsNCj4gPiArCWlmICh1bmxpa2VseSghcCkp DQo+ID4gKwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ICsJKnB0ciA9IGJlMzJfdG9fY3B1cChwKTsN Cj4gPiArCXJldHVybiAwOw0KPiANCj4gTm8gbGVuZ3RoIHJldHVybmVkIGhlcmUuIFRoZSBjYWxs ZXIga25vd3MgdGhlIGxlbmd0aA0KPiBvZiB0aGlzIG9iamVjdCwgY2xlYXJseSwgYW5kIG9ubHkg Y2FyZXMgYWJvdXQgd2hldGhlcg0KPiBkZWNvZGluZyBoYXMgb3ZlcnJ1biB0aGUgWERSIHN0cmVh bS4NCg0KWWVzLiBFYXJsaWVyIHZlcnNpb25zIHJldHVybmVkID4gMCwgYnV0IEkgZmlndXJlZCB0 aGF0IGNvdW50aW5nIHRoZQ0KYnVmZmVyIHNwYWNlIGlzIG5vdCBhcyBpbXBvcnRhbnQgd2hlbiBk ZWNvZGluZy4gSSBjYW4ndCB0aGluayBvZiB0b28NCm1hbnkgdXNlIGNhc2VzLg0KDQo+ID4gK30N Cj4gPiArDQo+ID4gKy8qKg0KPiA+ICsgKiB4ZHJfc3RyZWFtX2RlY29kZV9vcGFxdWVfZml4ZWQg LSBEZWNvZGUgZml4ZWQgbGVuZ3RoIG9wYXF1ZSB4ZHINCj4gPiBkYXRhDQo+ID4gKyAqIEB4ZHI6 IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ICsgKiBAcHRyOiBsb2NhdGlvbiB0byBzdG9yZSBk YXRhDQo+ID4gKyAqIEBsZW46IHNpemUgb2YgYnVmZmVyIHBvaW50ZWQgdG8gYnkgQHB0cg0KPiA+ ICsgKg0KPiA+ICsgKiBSZXR1cm4gdmFsdWVzOg0KPiA+ICsgKsKgwqDCoE9uIHN1Y2Nlc3MsIHJl dHVybnMgc2l6ZSBvZiBvYmplY3Qgc3RvcmVkIGluIEBwdHINCj4gDQo+IFlvdSdyZSByZXR1cm5p bmcgdGhlIHBhc3NlZC1pbiBsZW5ndGguIFRodXMgdGhlIGNhbGxlcg0KPiBhbHJlYWR5IGtub3dz IHRoZSBzaXplIG9mIHRoZSBvYmplY3Qgc3RvcmVkIGF0IEBwdHIuDQoNCkNvbnNpc3RlbmN5LCBh bmQgaXQgYWxsb3dzIGl0IHRvIGJlIGVhc2lseSB1c2VkIGFzIGEgaGVscGVyIGluc2lkZQ0Kb3Ro ZXIgZnVuY3Rpb25zIHRoYXQgZG8gbmVlZCB0byByZXR1cm4gdGhlIG9iamVjdCBsZW5ndGguDQoN Ck5vdGUgdGhhdCB0aGUgZnVuY3Rpb24gaXMgaW5saW5lZCwgc28gdGhlIGNvbXBpbGVyIHNob3Vs ZCBub3JtYWxseQ0Kb3B0aW1pc2UgYXdheSByZXR1cm4gdmFsdWVzIHRoYXQgYXJlIHVudXNlZCBi eSB0aGUgY2FsbGVyLg0KDQo+ID4gKyAqwqDCoMKgJS1FTk9CVUZTIG9uIFhEUiBidWZmZXIgb3Zl cmZsb3cNCj4gPiArICovDQo+ID4gK3N0YXRpYyBpbmxpbmUgc3NpemVfdA0KPiA+ICt4ZHJfc3Ry ZWFtX2RlY29kZV9vcGFxdWVfZml4ZWQoc3RydWN0IHhkcl9zdHJlYW0gKnhkciwgdm9pZCAqcHRy LA0KPiA+IHNpemVfdCBsZW4pDQo+ID4gK3sNCj4gPiArCV9fYmUzMiAqcCA9IHhkcl9pbmxpbmVf ZGVjb2RlKHhkciwgbGVuKTsNCj4gPiArDQo+ID4gKwlpZiAodW5saWtlbHkoIXApKQ0KPiA+ICsJ CXJldHVybiAtRU5PQlVGUzsNCj4gPiArCXhkcl9kZWNvZGVfb3BhcXVlX2ZpeGVkKHAsIHB0ciwg bGVuKTsNCj4gPiArCXJldHVybiBsZW47DQo+ID4gK30NCj4gPiArDQo+ID4gKy8qKg0KPiA+ICsg KiB4ZHJfc3RyZWFtX2RlY29kZV9vcGFxdWVfaW5saW5lIC0gRGVjb2RlIHZhcmlhYmxlIGxlbmd0 aCBvcGFxdWUNCj4gPiB4ZHIgZGF0YQ0KPiA+ICsgKiBAeGRyOiBwb2ludGVyIHRvIHhkcl9zdHJl YW0NCj4gPiArICogQHB0cjogbG9jYXRpb24gdG8gc3RvcmUgcG9pbnRlciB0byBvcGFxdWUgZGF0 YQ0KPiA+ICsgKg0KPiA+ICsgKiBOb3RlOiB0aGUgcG9pbnRlciBzdG9yZWQgaW4gQHB0ciBjYW5u b3QgYmUgYXNzdW1lZCB2YWxpZCBhZnRlcg0KPiA+IHRoZSBYRFINCj4gPiArICogYnVmZmVyIGhh cyBiZWVuIGRlc3Ryb3llZCwgb3IgZXZlbiBhZnRlciBjYWxsaW5nDQo+ID4geGRyX2lubGluZV9k ZWNvZGUoKQ0KPiA+ICsgKiBvbiBAeGRyLiBJdCBpcyB0aGVyZWZvcmUgZXhwZWN0ZWQgdGhhdCB0 aGUgb2JqZWN0IGl0IHBvaW50cyB0bw0KPiA+IHNob3VsZA0KPiA+ICsgKiBiZSBwcm9jZXNzZWQg aW1tZWRpYXRlbHkuDQo+ID4gKyAqDQo+ID4gKyAqIFJldHVybiB2YWx1ZXM6DQo+ID4gKyAqwqDC oMKgT24gc3VjY2VzcywgcmV0dXJucyBzaXplIG9mIG9iamVjdCBzdG9yZWQgaW4gKkBwdHINCj4g DQo+IFRoaXMgc2VlbXMgdG8gYmUgdGhlIG9ubHkgZnVuY3Rpb24gd2hlcmUgdGhlIGNhbGxlcg0K PiBtaWdodCBub3QgYWxyZWFkeSBrbm93IHRoZSBsZW5ndGggb2YgdGhlIG9iamVjdCwgYnV0DQo+ IG1pZ2h0IGFjdHVhbGx5IGNhcmUuIFNpbmNlIHRoZSBvYmplY3QgbGVuZ3RoIGNhbiBiZQ0KPiBj b25zaWRlcmVkIHBhcnQgb2YgdGhlIG9iamVjdCBpdHNlbGYsIG1heWJlIHRoYXQNCj4gbGVuZ3Ro IHNob3VsZCBiZSByZXR1cm5lZCB2aWEgYW4gb3V0cHV0IHBhcmFtZXRlcg0KPiByYXRoZXIgdGhh biBhcyB0aGUgZnVuY3Rpb24ncyByZXR1cm4gdmFsdWUuDQoNCkkgY29uc2lkZXJlZCBpdCwgYnV0 IHRoYXQgbWVhbnMgeW91IGhhdmUgdG8gY2hvb3NlIGFuIGV4YWN0IHN0b3JhZ2UNCnR5cGUgYW5k IGdjYyB3aWxsIGNvbXBsYWluIGlmIHRoZSB0eXBlIGNoZWNrIGZhaWxzLg0KSW4gbW9zdCBjYXNl cywgd2UgZG9uJ3QgcmVhbGx5IGNhcmUgaWYgdGhlIHUzMiB2YWx1ZSBnZXRzIHN0b3JlZCBpbiBh bg0KdW5zaWduZWQgaW50LCBpbnQsIHVuc2lnbmVkIGxvbmcsIGxvbmcsIHNpemVfdCwgc3NpemVf dCBiZWNhdXNlIHdlIGhhdmUNCmEgZ29vZCBpZGVhIG9mIHdoYXQgdG8gZXhwZWN0IGZvciB0aGUg b2JqZWN0IHNpemUuDQoNCj4gPiArICrCoMKgwqAlLUVOT0JVRlMgb24gWERSIGJ1ZmZlciBvdmVy Zmxvdw0KPiANCj4gRUlOVkFMIGlzIHByb2JhYmx5IGJldHRlcjogdGhlIGNhbGxlciBkaWRuJ3Qg cHJvdmlkZQ0KPiB0aGUgY29ycmVjdCBpbnB1dHMuIFRoYXQncyBhIG5pdCwgdGhvdWdoLg0KDQpJ dCdzIG5vdCBhIGNhbGxlciBwcm9ibGVtLiBUaGUgRU5PQlVGUyBlcnJvciBvbiBkZWNvZGUgaW5k aWNhdGVzIHRoYXQNCnRoZSBSUEMgbWVzc2FnZSB3ZSdyZSB0cnlpbmcgdG8gZGVjb2RlIHdhcyBw cm9iYWJseSB0cnVuY2F0ZWQgb3INCmNvcnJ1cHRlZC4NCg0KPiBIb3dldmVyLCBhcyBhIG1hdHRl ciBvZiBkZWZlbnNpdmUgY29kaW5nLCB0aGlzIGVycm5vDQo+IGNvdWxkIGxlYWsgdXAgdGhlIHN0 YWNrIGlmIGRldmVsb3BlcnMgYXJlIG5vdCBjYXJlZnVsLg0KPiANCj4gQSBib29sZWFuIHJldHVy biB2YWx1ZSBjb3VsZCBiZSBlbnRpcmVseSBhZGVxdWF0ZSBmb3INCj4gdGhlc2UgZGVjb2RlcnM/ DQo+IA0KPiANCj4gPiArICovDQo+ID4gK3N0YXRpYyBpbmxpbmUgc3NpemVfdA0KPiA+ICt4ZHJf c3RyZWFtX2RlY29kZV9vcGFxdWVfaW5saW5lKHN0cnVjdCB4ZHJfc3RyZWFtICp4ZHIsIHZvaWQN Cj4gPiAqKnB0cikNCj4gPiArew0KPiA+ICsJX19iZTMyICpwOw0KPiA+ICsJX191MzIgbGVuOw0K PiA+ICsNCj4gPiArCWlmICh1bmxpa2VseSh4ZHJfc3RyZWFtX2RlY29kZV91MzIoeGRyLCAmbGVu KSA8IDApKQ0KPiA+ICsJCXJldHVybiAtRU5PQlVGUzsNCj4gPiArCWlmIChsZW4gIT0gMCkgew0K PiA+ICsJCXAgPSB4ZHJfaW5saW5lX2RlY29kZSh4ZHIsIGxlbik7DQo+ID4gKwkJaWYgKHVubGlr ZWx5KCFwKSkNCj4gPiArCQkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ICsJCSpwdHIgPSBwOw0KPiA+ ICsJfSBlbHNlDQo+ID4gKwkJKnB0ciA9IE5VTEw7DQo+ID4gKwlyZXR1cm4gbGVuOw0KPiA+ICt9 DQo+ID4gI2VuZGlmIC8qIF9fS0VSTkVMX18gKi8NCj4gPiANCj4gPiAjZW5kaWYgLyogX1NVTlJQ Q19YRFJfSF8gKi8NCj4gPiAtLcKgDQo+ID4gMi45LjMNCj4gPiANCj4gPiAtLQ0KPiA+IFRvIHVu c3Vic2NyaWJlIGZyb20gdGhpcyBsaXN0OiBzZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51 eC0NCj4gPiBuZnMiIGluDQo+ID4gdGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2 Z2VyLmtlcm5lbC5vcmcNCj4gPiBNb3JlIG1ham9yZG9tbyBpbmZvIGF0wqDCoGh0dHA6Ly92Z2Vy Lmtlcm5lbC5vcmcvbWFqb3Jkb21vLWluZm8uaHRtbA0KPiANCj4gLS0NCj4gQ2h1Y2sgTGV2ZXIN Cj4gDQo+IA0KPiANCi0tIA0KVHJvbmQgTXlrbGVidXN0DQpMaW51eCBORlMgY2xpZW50IG1haW50 YWluZXIsIFByaW1hcnlEYXRhDQp0cm9uZC5teWtsZWJ1c3RAcHJpbWFyeWRhdGEuY29tDQo= ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-19 5:36 ` Trond Myklebust @ 2017-02-19 19:07 ` Chuck Lever 2017-02-19 19:28 ` Trond Myklebust 0 siblings, 1 reply; 11+ messages in thread From: Chuck Lever @ 2017-02-19 19:07 UTC (permalink / raw) To: Trond Myklebust; +Cc: Anna Schumaker, Linux NFS Mailing List > On Feb 19, 2017, at 12:36 AM, Trond Myklebust <trondmy@primarydata.com> wrote: > > On Sat, 2017-02-18 at 17:21 -0500, Chuck Lever wrote: >>> On Feb 18, 2017, at 2:12 PM, Trond Myklebust <trond.myklebust@prima >>> rydata.com> wrote: >>> >>> Add some generic helpers for encoding/decoding opaque structures >>> and >>> basic u32/u64. >> >> I have some random-thoughts-slash-wacky-ideas. >> >> I'm going to paint the garden shed a little since >> these helpers appear to be broadly applicable. >> Generally speaking I like the idea of building >> "stream" versions of the traditional basic type >> encoders and decoders. >> >> >>> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> >>> --- >>> include/linux/sunrpc/xdr.h | 173 >>> +++++++++++++++++++++++++++++++++++++++++++++ >>> 1 file changed, 173 insertions(+) >>> >>> diff --git a/include/linux/sunrpc/xdr.h >>> b/include/linux/sunrpc/xdr.h >>> index 56c48c884a24..37bf1be20b62 100644 >>> --- a/include/linux/sunrpc/xdr.h >>> +++ b/include/linux/sunrpc/xdr.h >>> @@ -242,6 +242,179 @@ 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); >>> >>> +/** >>> + * xdr_align_size - Calculate padded size of an object >>> + * @n: Size of an object being XDR encoded (in bytes) >>> + * >>> + * Return value: >>> + * Size (in bytes) of the object including xdr padding >>> + */ >>> +static inline size_t >>> +xdr_align_size(size_t n) >>> +{ >>> + const size_t mask = sizeof(__u32) - 1; >> >> I know this doesn't make a functional difference, but >> I'm wondering if this should be sizeof(__be32), since >> it is actually the size of a wire object? Seems like >> that is a common question wherever sizeof is used >> below. > > The __be32 is required to be the same size as u32. The only allowed > difference between the two is be the endianness. Right, sizeof(__u32) == sizeof(__be32). __be has always been about endian annotation; no real functional difference with __u. The issue for me is precision of documentation (or, in some sense, code readability). In all of these cases, it's not the size of the local variable that is important, it's the size of the (XDR encoded) wire object. That's sizeof(__be32). Those just happen to be the same here. It's pretty easy to mistake the size of a local object as being always the same as the size of the encoded data type. I've done that myself often enough that it makes sense to be consistent and careful, even in the simple cases. I'm not going to make a big deal, but I'd like to point out that subtle difference. IMO it would make more sense to human readers if these were __be and not __u. >> Is this a constant variable rather than an enum because >> you want it to retain the type of size_t (matching the >> type of the xdr_inline_{en,de}code() functions) ? > > It's really just for efficiency, in order to prod gcc into optimising > it as it would any other constant. > >> Since we see sizeof(yada) repeated elsewhere, did you >> consider defining size constants in a scope where they >> can be shared amongst all of the XDR functions? >> >> For example, xdr_reserve_space itself could immediately >> make use of a "sizeof(__be32) - 1" constant. > > That could be done. I haven't really considered it. > >> Is your intention to replace XDR_QUADLEN with this >> function eventually? > > Eventually, I'd like us to get rid of most of the open coded instances > of 'pointer to __be32' in the NFS code, and hide all knowledge of that > in struct xdr_stream and these SUNRPC layered helpers. Sounds good to me. >>> + >>> + return (n + mask) & ~mask; >>> +} >>> + >>> +/** >>> + * xdr_stream_encode_u32 - Encode a 32-bit integer >>> + * @xdr: pointer to xdr_stream >>> + * @n: integer to encode >>> + * >>> + * Return values: >>> + * On success, returns length in bytes of XDR buffer consumed >>> + * %-ENOBUFS on XDR buffer overflow >> >> I've never been crazy about these amplified return >> types, though I know it's typical kernel coding style. >> Here, though, I wonder if they are really necessary. >> >> The returned length seems to be interesting only for >> decoding variable-length objects (farther below). Maybe >> those are the only functions that need to provide a >> positive return value? > > NFSv4 introduces the (IMO nasty) habit of nesting XDR-encoded objects > inside a variable length opaque object (say hello to type "attrlist4"). And pNFS layouts. Fair enough. > In that case, we need to keep a running tally of the length of the > objects we have XDR encoded so that we can retroactively set the length > of the opaque object. Currently we use the xdr_stream_pos() to > determine that length, but it might be nice to replace that with > something a little more direct. The new helpers appear to be abstracting away from a direct approach. IMHO staying with something that looks like a function call (like xdr_stream_pos) seems like it is clean and consistent with these new helpers. > Note also that the lengths returned here are not the object sizes > themselves, but the amount of buffer space consumed (i.e. the aligned > size). Makes sense. Still, seems like the callers already know these "space consumed" values in every case. Maybe that won't be true when these helpers are glued together to handle more abstract data types. >> Perhaps the WARN_ON_ONCE calls added in later patches >> should be in these helpers instead of in their callers. >> Then the encoder helpers can return void. > > At some point, I'd like to reinstate the practice of returning an error > when encoding fails. It may be better to abort sending a truncated RPC > call rather than having it execute partially; specially now that we're > finally starting to use COMPOUND to create more complex operations. I agree, IMO that would be a better approach. >>> + */ >>> +static inline ssize_t >>> +xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n) >>> +{ >>> + const size_t len = sizeof(n); >>> + __be32 *p = xdr_reserve_space(xdr, len); >>> + >>> + if (unlikely(!p)) >>> + return -ENOBUFS; >>> + *p = cpu_to_be32(n); >>> + return len; >>> +} >>> + >>> +/** >>> + * xdr_stream_encode_u64 - Encode a 64-bit integer >>> + * @xdr: pointer to xdr_stream >>> + * @n: 64-bit integer to encode >>> + * >>> + * Return values: >>> + * On success, returns length in bytes of XDR buffer consumed >>> + * %-ENOBUFS on XDR buffer overflow >>> + */ >>> +static inline ssize_t >>> +xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n) >>> +{ >>> + const size_t len = sizeof(n); >>> + __be32 *p = xdr_reserve_space(xdr, len); >>> + >>> + if (unlikely(!p)) >>> + return -ENOBUFS; >>> + xdr_encode_hyper(p, n); >>> + return len; >>> +} >>> + >>> +/** >>> + * xdr_stream_encode_opaque_fixed - Encode fixed length opaque xdr >>> data >>> + * @xdr: pointer to xdr_stream >>> + * @ptr: pointer to opaque data object >>> + * @len: size of object pointed to by @ptr >>> + * >>> + * Return values: >>> + * On success, returns length in bytes of XDR buffer consumed >>> + * %-ENOBUFS on XDR buffer overflow >>> + */ >>> +static inline ssize_t >>> +xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void >>> *ptr, size_t len) >>> +{ >>> + __be32 *p = xdr_reserve_space(xdr, len); >>> + >>> + if (unlikely(!p)) >>> + return -ENOBUFS; >>> + xdr_encode_opaque_fixed(p, ptr, len); >>> + return xdr_align_size(len); >> >> Seems like the caller can use xdr_align_size() just as >> easily as overloading the return value here, for example. >> >> But I can't think of any fixed-size opaque XDR object >> that is not already properly rounded up, or where the >> length is not already known to the XDR layer (as a >> defined macro constant). >> >> >>> +} >>> + >>> +/** >>> + * xdr_stream_encode_opaque - Encode variable length opaque xdr >>> data >>> + * @xdr: pointer to xdr_stream >>> + * @ptr: pointer to opaque data object >>> + * @len: size of object pointed to by @ptr >>> + * >>> + * Return values: >>> + * On success, returns length in bytes of XDR buffer consumed >>> + * %-ENOBUFS on XDR buffer overflow >>> + */ >>> +static inline ssize_t >>> +xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, >>> size_t len) >>> +{ >>> + size_t count = sizeof(__u32) + xdr_align_size(len); >>> + __be32 *p = xdr_reserve_space(xdr, count); >>> + >>> + if (unlikely(!p)) >>> + return -ENOBUFS; >>> + xdr_encode_opaque(p, ptr, len); >>> + return count; >> >> These helpers already update the state of the passed >> in xdr_stream, so a caller typically would not need >> to care much about the bytes consumed by the encoded >> opaque. >> >> >>> +} >>> + >>> +/** >>> + * xdr_stream_decode_u32 - Decode a 32-bit integer >>> + * @xdr: pointer to xdr_stream >>> + * @ptr: location to store integer >>> + * >>> + * Return values: >>> + * %0 on success >>> + * %-ENOBUFS on XDR buffer overflow >>> + */ >>> +static inline ssize_t >>> +xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr) >>> +{ >>> + const size_t count = sizeof(*ptr); >>> + __be32 *p = xdr_inline_decode(xdr, count); >>> + >>> + if (unlikely(!p)) >>> + return -ENOBUFS; >>> + *ptr = be32_to_cpup(p); >>> + return 0; >> >> No length returned here. The caller knows the length >> of this object, clearly, and only cares about whether >> decoding has overrun the XDR stream. > > Yes. Earlier versions returned > 0, but I figured that counting the > buffer space is not as important when decoding. I can't think of too > many use cases. > >>> +} >>> + >>> +/** >>> + * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr >>> data >>> + * @xdr: pointer to xdr_stream >>> + * @ptr: location to store data >>> + * @len: size of buffer pointed to by @ptr >>> + * >>> + * Return values: >>> + * On success, returns size of object stored in @ptr >> >> You're returning the passed-in length. Thus the caller >> already knows the size of the object stored at @ptr. > > Consistency, and it allows it to be easily used as a helper inside > other functions that do need to return the object length. Going for ease of composing these functions. OK. > Note that the function is inlined, so the compiler should normally > optimise away return values that are unused by the caller. True. However future code readers might wonder why this value is being computed if the value or the computation itself is unneeded in most cases. Seems like a separate helper that derives this value where and when it is needed might be cleaner; but that is entirely subjective. >>> + * %-ENOBUFS on XDR buffer overflow >>> + */ >>> +static inline ssize_t >>> +xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, >>> size_t len) >>> +{ >>> + __be32 *p = xdr_inline_decode(xdr, len); >>> + >>> + if (unlikely(!p)) >>> + return -ENOBUFS; >>> + xdr_decode_opaque_fixed(p, ptr, len); >>> + return len; >>> +} >>> + >>> +/** >>> + * xdr_stream_decode_opaque_inline - Decode variable length opaque >>> xdr data >>> + * @xdr: pointer to xdr_stream >>> + * @ptr: location to store pointer to opaque data >>> + * >>> + * Note: the pointer stored in @ptr cannot be assumed valid after >>> the XDR >>> + * buffer has been destroyed, or even after calling >>> xdr_inline_decode() >>> + * on @xdr. It is therefore expected that the object it points to >>> should >>> + * be processed immediately. >>> + * >>> + * Return values: >>> + * On success, returns size of object stored in *@ptr >> >> This seems to be the only function where the caller >> might not already know the length of the object, but >> might actually care. Since the object length can be >> considered part of the object itself, maybe that >> length should be returned via an output parameter >> rather than as the function's return value. > > I considered it, but that means you have to choose an exact storage > type and gcc will complain if the type check fails. > In most cases, we don't really care if the u32 value gets stored in an > unsigned int, int, unsigned long, long, size_t, ssize_t because we have > a good idea of what to expect for the object size. > >>> + * %-ENOBUFS on XDR buffer overflow >> >> EINVAL is probably better: the caller didn't provide >> the correct inputs. That's a nit, though. > > It's not a caller problem. The ENOBUFS error on decode indicates that > the RPC message we're trying to decode was probably truncated or > corrupted. Ah. Agree now, not a caller bug. I still wonder if the meaning of ENOBUFS is a good enough match to this use case. EINVAL is a permanent error, but I don't think ENOBUFS is. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-19 19:07 ` Chuck Lever @ 2017-02-19 19:28 ` Trond Myklebust 2017-02-19 20:06 ` Chuck Lever 0 siblings, 1 reply; 11+ messages in thread From: Trond Myklebust @ 2017-02-19 19:28 UTC (permalink / raw) To: chuck.lever@oracle.com Cc: anna.schumaker@netapp.com, linux-nfs@vger.kernel.org VGhhbmtzIGZvciB0aGUgZGlzY3Vzc2lvbiwgQlRXLiBJIGFwcHJlY2lhdGUgdGhlIGZlZWRiYWNr Lg0KDQpPbiBTdW4sIDIwMTctMDItMTkgYXQgMTQ6MDcgLTA1MDAsIENodWNrIExldmVyIHdyb3Rl Og0KPiA+IE9uIEZlYiAxOSwgMjAxNywgYXQgMTI6MzYgQU0sIFRyb25kIE15a2xlYnVzdCA8dHJv bmRteUBwcmltYXJ5ZGF0YS4NCj4gPiBjb20+IHdyb3RlOg0KPiA+IA0KPiA+IE9uIFNhdCwgMjAx Ny0wMi0xOCBhdCAxNzoyMSAtMDUwMCwgQ2h1Y2sgTGV2ZXIgd3JvdGU6DQo+ID4gPiA+IE9uIEZl YiAxOCwgMjAxNywgYXQgMjoxMiBQTSwgVHJvbmQgTXlrbGVidXN0IDx0cm9uZC5teWtsZWJ1c3RA cA0KPiA+ID4gPiByaW1hDQo+ID4gPiA+IHJ5ZGF0YS5jb20+IHdyb3RlOg0KPiA+ID4gPiANCj4g PiA+ID4gQWRkIHNvbWUgZ2VuZXJpYyBoZWxwZXJzIGZvciBlbmNvZGluZy9kZWNvZGluZyBvcGFx dWUNCj4gPiA+ID4gc3RydWN0dXJlcw0KPiA+ID4gPiBhbmQNCj4gPiA+ID4gYmFzaWMgdTMyL3U2 NC4NCj4gPiA+IA0KPiA+ID4gSSBoYXZlIHNvbWUgcmFuZG9tLXRob3VnaHRzLXNsYXNoLXdhY2t5 LWlkZWFzLg0KPiA+ID4gDQo+ID4gPiBJJ20gZ29pbmcgdG8gcGFpbnQgdGhlIGdhcmRlbiBzaGVk IGEgbGl0dGxlIHNpbmNlDQo+ID4gPiB0aGVzZSBoZWxwZXJzIGFwcGVhciB0byBiZSBicm9hZGx5 IGFwcGxpY2FibGUuDQo+ID4gPiBHZW5lcmFsbHkgc3BlYWtpbmcgSSBsaWtlIHRoZSBpZGVhIG9m IGJ1aWxkaW5nDQo+ID4gPiAic3RyZWFtIiB2ZXJzaW9ucyBvZiB0aGUgdHJhZGl0aW9uYWwgYmFz aWMgdHlwZQ0KPiA+ID4gZW5jb2RlcnMgYW5kIGRlY29kZXJzLg0KPiA+ID4gDQo+ID4gPiANCj4g PiA+ID4gU2lnbmVkLW9mZi1ieTogVHJvbmQgTXlrbGVidXN0IDx0cm9uZC5teWtsZWJ1c3RAcHJp bWFyeWRhdGEuY29tDQo+ID4gPiA+ID4NCj4gPiA+ID4gLS0tDQo+ID4gPiA+IGluY2x1ZGUvbGlu dXgvc3VucnBjL3hkci5oIHwgMTczDQo+ID4gPiA+ICsrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKw0KPiA+ID4gPiAxIGZpbGUgY2hhbmdlZCwgMTczIGluc2VydGlv bnMoKykNCj4gPiA+ID4gDQo+ID4gPiA+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L3N1bnJw Yy94ZHIuaA0KPiA+ID4gPiBiL2luY2x1ZGUvbGludXgvc3VucnBjL3hkci5oDQo+ID4gPiA+IGlu ZGV4IDU2YzQ4Yzg4NGEyNC4uMzdiZjFiZTIwYjYyIDEwMDY0NA0KPiA+ID4gPiAtLS0gYS9pbmNs dWRlL2xpbnV4L3N1bnJwYy94ZHIuaA0KPiA+ID4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3N1bnJw Yy94ZHIuaA0KPiA+ID4gPiBAQCAtMjQyLDYgKzI0MiwxNzkgQEAgZXh0ZXJuIHVuc2lnbmVkIGlu dCB4ZHJfcmVhZF9wYWdlcyhzdHJ1Y3QNCj4gPiA+ID4geGRyX3N0cmVhbSAqeGRyLCB1bnNpZ25l ZCBpbnQgbGVuKTsNCj4gPiA+ID4gZXh0ZXJuIHZvaWQgeGRyX2VudGVyX3BhZ2Uoc3RydWN0IHhk cl9zdHJlYW0gKnhkciwgdW5zaWduZWQgaW50DQo+ID4gPiA+IGxlbik7DQo+ID4gPiA+IGV4dGVy biBpbnQgeGRyX3Byb2Nlc3NfYnVmKHN0cnVjdCB4ZHJfYnVmICpidWYsIHVuc2lnbmVkIGludA0K PiA+ID4gPiBvZmZzZXQsIHVuc2lnbmVkIGludCBsZW4sIGludCAoKmFjdG9yKShzdHJ1Y3Qgc2Nh dHRlcmxpc3QgKiwNCj4gPiA+ID4gdm9pZA0KPiA+ID4gPiAqKSwgdm9pZCAqZGF0YSk7DQo+ID4g PiA+IA0KPiA+ID4gPiArLyoqDQo+ID4gPiA+ICsgKiB4ZHJfYWxpZ25fc2l6ZSAtIENhbGN1bGF0 ZSBwYWRkZWQgc2l6ZSBvZiBhbiBvYmplY3QNCj4gPiA+ID4gKyAqIEBuOiBTaXplIG9mIGFuIG9i amVjdCBiZWluZyBYRFIgZW5jb2RlZCAoaW4gYnl0ZXMpDQo+ID4gPiA+ICsgKg0KPiA+ID4gPiAr ICogUmV0dXJuIHZhbHVlOg0KPiA+ID4gPiArICrCoMKgwqBTaXplIChpbiBieXRlcykgb2YgdGhl IG9iamVjdCBpbmNsdWRpbmcgeGRyIHBhZGRpbmcNCj4gPiA+ID4gKyAqLw0KPiA+ID4gPiArc3Rh dGljIGlubGluZSBzaXplX3QNCj4gPiA+ID4gK3hkcl9hbGlnbl9zaXplKHNpemVfdCBuKQ0KPiA+ ID4gPiArew0KPiA+ID4gPiArCWNvbnN0IHNpemVfdCBtYXNrID0gc2l6ZW9mKF9fdTMyKSAtIDE7 DQo+ID4gPiANCj4gPiA+IEkga25vdyB0aGlzIGRvZXNuJ3QgbWFrZSBhIGZ1bmN0aW9uYWwgZGlm ZmVyZW5jZSwgYnV0DQo+ID4gPiBJJ20gd29uZGVyaW5nIGlmIHRoaXMgc2hvdWxkIGJlIHNpemVv ZihfX2JlMzIpLCBzaW5jZQ0KPiA+ID4gaXQgaXMgYWN0dWFsbHkgdGhlIHNpemUgb2YgYSB3aXJl IG9iamVjdD8gU2VlbXMgbGlrZQ0KPiA+ID4gdGhhdCBpcyBhIGNvbW1vbiBxdWVzdGlvbiB3aGVy ZXZlciBzaXplb2YgaXMgdXNlZA0KPiA+ID4gYmVsb3cuDQo+ID4gDQo+ID4gVGhlIF9fYmUzMiBp cyByZXF1aXJlZCB0byBiZSB0aGUgc2FtZSBzaXplIGFzIHUzMi4gVGhlIG9ubHkgYWxsb3dlZA0K PiA+IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIGlzIGJlIHRoZSBlbmRpYW5uZXNzLg0KPiAN Cj4gUmlnaHQsIHNpemVvZihfX3UzMikgPT0gc2l6ZW9mKF9fYmUzMikuwqDCoF9fYmUgaGFzIGFs d2F5cw0KPiBiZWVuIGFib3V0IGVuZGlhbiBhbm5vdGF0aW9uOyBubyByZWFsIGZ1bmN0aW9uYWwg ZGlmZmVyZW5jZQ0KPiB3aXRoIF9fdS4NCj4gDQo+IFRoZSBpc3N1ZSBmb3IgbWUgaXMgcHJlY2lz aW9uIG9mIGRvY3VtZW50YXRpb24gKG9yLCBpbiBzb21lDQo+IHNlbnNlLCBjb2RlIHJlYWRhYmls aXR5KS4gSW4gYWxsIG9mIHRoZXNlIGNhc2VzLCBpdCdzIG5vdA0KPiB0aGUgc2l6ZSBvZiB0aGUg bG9jYWwgdmFyaWFibGUgdGhhdCBpcyBpbXBvcnRhbnQsIGl0J3MgdGhlDQo+IHNpemUgb2YgdGhl IChYRFIgZW5jb2RlZCkgd2lyZSBvYmplY3QuIFRoYXQncyBzaXplb2YoX19iZTMyKS4NCj4gDQo+ IFRob3NlIGp1c3QgaGFwcGVuIHRvIGJlIHRoZSBzYW1lIGhlcmUuIEl0J3MgcHJldHR5IGVhc3kg dG8NCj4gbWlzdGFrZSB0aGUgc2l6ZSBvZiBhIGxvY2FsIG9iamVjdCBhcyBiZWluZyBhbHdheXMg dGhlIHNhbWUNCj4gYXMgdGhlIHNpemUgb2YgdGhlIGVuY29kZWQgZGF0YSB0eXBlLiBJJ3ZlIGRv bmUgdGhhdCBteXNlbGYNCj4gb2Z0ZW4gZW5vdWdoIHRoYXQgaXQgbWFrZXMgc2Vuc2UgdG8gYmUg Y29uc2lzdGVudCBhbmQNCj4gY2FyZWZ1bCwgZXZlbiBpbiB0aGUgc2ltcGxlIGNhc2VzLg0KPiAN Cj4gSSdtIG5vdCBnb2luZyB0byBtYWtlIGEgYmlnIGRlYWwsIGJ1dCBJJ2QgbGlrZSB0byBwb2lu dCBvdXQNCj4gdGhhdCBzdWJ0bGUgZGlmZmVyZW5jZS4gSU1PIGl0IHdvdWxkIG1ha2UgbW9yZSBz ZW5zZSB0bw0KPiBodW1hbiByZWFkZXJzIGlmIHRoZXNlIHdlcmUgX19iZSBhbmQgbm90IF9fdS4N Cg0KRmFpciBlbm91Z2guIEkgY2FuIHVwZGF0ZSB0aGF0Lg0KDQo+IA0KPiA+ID4gSXMgdGhpcyBh IGNvbnN0YW50IHZhcmlhYmxlIHJhdGhlciB0aGFuIGFuIGVudW0gYmVjYXVzZQ0KPiA+ID4geW91 IHdhbnQgaXQgdG8gcmV0YWluIHRoZSB0eXBlIG9mIHNpemVfdCAobWF0Y2hpbmcgdGhlDQo+ID4g PiB0eXBlIG9mIHRoZSB4ZHJfaW5saW5lX3tlbixkZX1jb2RlKCkgZnVuY3Rpb25zKSA/DQo+ID4g DQo+ID4gSXQncyByZWFsbHkganVzdCBmb3IgZWZmaWNpZW5jeSwgaW4gb3JkZXIgdG8gcHJvZCBn Y2MgaW50bw0KPiA+IG9wdGltaXNpbmcNCj4gPiBpdCBhcyBpdCB3b3VsZCBhbnkgb3RoZXIgY29u c3RhbnQuDQo+ID4gDQo+ID4gPiBTaW5jZSB3ZSBzZWUgc2l6ZW9mKHlhZGEpIHJlcGVhdGVkIGVs c2V3aGVyZSwgZGlkIHlvdQ0KPiA+ID4gY29uc2lkZXIgZGVmaW5pbmcgc2l6ZSBjb25zdGFudHMg aW4gYSBzY29wZSB3aGVyZSB0aGV5DQo+ID4gPiBjYW4gYmUgc2hhcmVkIGFtb25nc3QgYWxsIG9m IHRoZSBYRFIgZnVuY3Rpb25zPw0KPiA+ID4gDQo+ID4gPiBGb3IgZXhhbXBsZSwgeGRyX3Jlc2Vy dmVfc3BhY2UgaXRzZWxmIGNvdWxkIGltbWVkaWF0ZWx5DQo+ID4gPiBtYWtlIHVzZSBvZiBhICJz aXplb2YoX19iZTMyKSAtIDEiIGNvbnN0YW50Lg0KPiA+IA0KPiA+IFRoYXQgY291bGQgYmUgZG9u ZS4gSSBoYXZlbid0IHJlYWxseSBjb25zaWRlcmVkIGl0Lg0KPiA+IA0KPiA+ID4gSXMgeW91ciBp bnRlbnRpb24gdG8gcmVwbGFjZSBYRFJfUVVBRExFTiB3aXRoIHRoaXMNCj4gPiA+IGZ1bmN0aW9u IGV2ZW50dWFsbHk/DQo+ID4gDQo+ID4gRXZlbnR1YWxseSwgSSdkIGxpa2UgdXMgdG8gZ2V0IHJp ZCBvZiBtb3N0IG9mIHRoZSBvcGVuIGNvZGVkDQo+ID4gaW5zdGFuY2VzDQo+ID4gb2YgJ3BvaW50 ZXIgdG8gX19iZTMyJyBpbiB0aGUgTkZTIGNvZGUsIGFuZCBoaWRlIGFsbCBrbm93bGVkZ2Ugb2YN Cj4gPiB0aGF0DQo+ID4gaW4gc3RydWN0IHhkcl9zdHJlYW0gYW5kIHRoZXNlIFNVTlJQQyBsYXll cmVkIGhlbHBlcnMuDQo+IA0KPiBTb3VuZHMgZ29vZCB0byBtZS4NCj4gDQo+IA0KPiA+ID4gPiAr DQo+ID4gPiA+ICsJcmV0dXJuIChuICsgbWFzaykgJiB+bWFzazsNCj4gPiA+ID4gK30NCj4gPiA+ ID4gKw0KPiA+ID4gPiArLyoqDQo+ID4gPiA+ICsgKiB4ZHJfc3RyZWFtX2VuY29kZV91MzIgLSBF bmNvZGUgYSAzMi1iaXQgaW50ZWdlcg0KPiA+ID4gPiArICogQHhkcjogcG9pbnRlciB0byB4ZHJf c3RyZWFtDQo+ID4gPiA+ICsgKiBAbjogaW50ZWdlciB0byBlbmNvZGUNCj4gPiA+ID4gKyAqDQo+ ID4gPiA+ICsgKiBSZXR1cm4gdmFsdWVzOg0KPiA+ID4gPiArICrCoMKgwqBPbiBzdWNjZXNzLCBy ZXR1cm5zIGxlbmd0aCBpbiBieXRlcyBvZiBYRFIgYnVmZmVyDQo+ID4gPiA+IGNvbnN1bWVkDQo+ ID4gPiA+ICsgKsKgwqDCoCUtRU5PQlVGUyBvbiBYRFIgYnVmZmVyIG92ZXJmbG93DQo+ID4gPiAN Cj4gPiA+IEkndmUgbmV2ZXIgYmVlbiBjcmF6eSBhYm91dCB0aGVzZSBhbXBsaWZpZWQgcmV0dXJu DQo+ID4gPiB0eXBlcywgdGhvdWdoIEkga25vdyBpdCdzIHR5cGljYWwga2VybmVsIGNvZGluZyBz dHlsZS4NCj4gPiA+IEhlcmUsIHRob3VnaCwgSSB3b25kZXIgaWYgdGhleSBhcmUgcmVhbGx5IG5l Y2Vzc2FyeS4NCj4gPiA+IA0KPiA+ID4gVGhlIHJldHVybmVkIGxlbmd0aCBzZWVtcyB0byBiZSBp bnRlcmVzdGluZyBvbmx5IGZvcg0KPiA+ID4gZGVjb2RpbmcgdmFyaWFibGUtbGVuZ3RoIG9iamVj dHMgKGZhcnRoZXIgYmVsb3cpLiBNYXliZQ0KPiA+ID4gdGhvc2UgYXJlIHRoZSBvbmx5IGZ1bmN0 aW9ucyB0aGF0IG5lZWQgdG8gcHJvdmlkZSBhDQo+ID4gPiBwb3NpdGl2ZSByZXR1cm4gdmFsdWU/ DQo+ID4gDQo+ID4gTkZTdjQgaW50cm9kdWNlcyB0aGUgKElNTyBuYXN0eSkgaGFiaXQgb2YgbmVz dGluZyBYRFItZW5jb2RlZA0KPiA+IG9iamVjdHMNCj4gPiBpbnNpZGUgYSB2YXJpYWJsZSBsZW5n dGggb3BhcXVlIG9iamVjdCAoc2F5IGhlbGxvIHRvIHR5cGUNCj4gPiAiYXR0cmxpc3Q0IikuDQo+ IA0KPiBBbmQgcE5GUyBsYXlvdXRzLiBGYWlyIGVub3VnaC4NCj4gDQo+IA0KPiA+IEluIHRoYXQg Y2FzZSwgd2UgbmVlZCB0byBrZWVwIGEgcnVubmluZyB0YWxseSBvZiB0aGUgbGVuZ3RoIG9mIHRo ZQ0KPiA+IG9iamVjdHMgd2UgaGF2ZSBYRFIgZW5jb2RlZCBzbyB0aGF0IHdlIGNhbiByZXRyb2Fj dGl2ZWx5IHNldCB0aGUNCj4gPiBsZW5ndGgNCj4gPiBvZiB0aGUgb3BhcXVlIG9iamVjdC4gQ3Vy cmVudGx5IHdlIHVzZSB0aGUgeGRyX3N0cmVhbV9wb3MoKSB0bw0KPiA+IGRldGVybWluZSB0aGF0 IGxlbmd0aCwgYnV0IGl0IG1pZ2h0IGJlIG5pY2UgdG8gcmVwbGFjZSB0aGF0IHdpdGgNCj4gPiBz b21ldGhpbmcgYSBsaXR0bGUgbW9yZSBkaXJlY3QuDQo+IA0KPiBUaGUgbmV3IGhlbHBlcnMgYXBw ZWFyIHRvIGJlIGFic3RyYWN0aW5nIGF3YXkgZnJvbSBhDQo+IGRpcmVjdCBhcHByb2FjaC4gSU1I TyBzdGF5aW5nIHdpdGggc29tZXRoaW5nIHRoYXQgbG9va3MNCj4gbGlrZSBhIGZ1bmN0aW9uIGNh bGwgKGxpa2UgeGRyX3N0cmVhbV9wb3MpIHNlZW1zIGxpa2UNCj4gaXQgaXMgY2xlYW4gYW5kIGNv bnNpc3RlbnQgd2l0aCB0aGVzZSBuZXcgaGVscGVycy4NCj4gDQo+IA0KPiA+IE5vdGUgYWxzbyB0 aGF0IHRoZSBsZW5ndGhzIHJldHVybmVkIGhlcmUgYXJlIG5vdCB0aGUgb2JqZWN0IHNpemVzDQo+ ID4gdGhlbXNlbHZlcywgYnV0IHRoZSBhbW91bnQgb2YgYnVmZmVyIHNwYWNlIGNvbnN1bWVkIChp LmUuIHRoZQ0KPiA+IGFsaWduZWQNCj4gPiBzaXplKS4NCj4gDQo+IE1ha2VzIHNlbnNlLiBTdGls bCwgc2VlbXMgbGlrZSB0aGUgY2FsbGVycyBhbHJlYWR5IGtub3cNCj4gdGhlc2UgInNwYWNlIGNv bnN1bWVkIiB2YWx1ZXMgaW4gZXZlcnkgY2FzZS4gTWF5YmUgdGhhdA0KPiB3b24ndCBiZSB0cnVl IHdoZW4gdGhlc2UgaGVscGVycyBhcmUgZ2x1ZWQgdG9nZXRoZXIgdG8NCj4gaGFuZGxlIG1vcmUg YWJzdHJhY3QgZGF0YSB0eXBlcy4NCj4gDQo+ID4gPiBQZXJoYXBzIHRoZSBXQVJOX09OX09OQ0Ug Y2FsbHMgYWRkZWQgaW4gbGF0ZXIgcGF0Y2hlcw0KPiA+ID4gc2hvdWxkIGJlIGluIHRoZXNlIGhl bHBlcnMgaW5zdGVhZCBvZiBpbiB0aGVpciBjYWxsZXJzLg0KPiA+ID4gVGhlbiB0aGUgZW5jb2Rl ciBoZWxwZXJzIGNhbiByZXR1cm4gdm9pZC4NCj4gPiANCj4gPiBBdCBzb21lIHBvaW50LCBJJ2Qg bGlrZSB0byByZWluc3RhdGUgdGhlIHByYWN0aWNlIG9mIHJldHVybmluZyBhbg0KPiA+IGVycm9y DQo+ID4gd2hlbiBlbmNvZGluZyBmYWlscy4gSXQgbWF5IGJlIGJldHRlciB0byBhYm9ydCBzZW5k aW5nIGEgdHJ1bmNhdGVkDQo+ID4gUlBDDQo+ID4gY2FsbCByYXRoZXIgdGhhbiBoYXZpbmcgaXQg ZXhlY3V0ZSBwYXJ0aWFsbHk7IHNwZWNpYWxseSBub3cgdGhhdA0KPiA+IHdlJ3JlDQo+ID4gZmlu YWxseSBzdGFydGluZyB0byB1c2UgQ09NUE9VTkQgdG8gY3JlYXRlIG1vcmUgY29tcGxleCBvcGVy YXRpb25zLg0KPiANCj4gSSBhZ3JlZSwgSU1PIHRoYXQgd291bGQgYmUgYSBiZXR0ZXIgYXBwcm9h Y2guDQo+IA0KPiANCj4gPiA+ID4gKyAqLw0KPiA+ID4gPiArc3RhdGljIGlubGluZSBzc2l6ZV90 DQo+ID4gPiA+ICt4ZHJfc3RyZWFtX2VuY29kZV91MzIoc3RydWN0IHhkcl9zdHJlYW0gKnhkciwg X191MzIgbikNCj4gPiA+ID4gK3sNCj4gPiA+ID4gKwljb25zdCBzaXplX3QgbGVuID0gc2l6ZW9m KG4pOw0KPiA+ID4gPiArCV9fYmUzMiAqcCA9IHhkcl9yZXNlcnZlX3NwYWNlKHhkciwgbGVuKTsN Cj4gPiA+ID4gKw0KPiA+ID4gPiArCWlmICh1bmxpa2VseSghcCkpDQo+ID4gPiA+ICsJCXJldHVy biAtRU5PQlVGUzsNCj4gPiA+ID4gKwkqcCA9IGNwdV90b19iZTMyKG4pOw0KPiA+ID4gPiArCXJl dHVybiBsZW47DQo+ID4gPiA+ICt9DQo+ID4gPiA+ICsNCj4gPiA+ID4gKy8qKg0KPiA+ID4gPiAr ICogeGRyX3N0cmVhbV9lbmNvZGVfdTY0IC0gRW5jb2RlIGEgNjQtYml0IGludGVnZXINCj4gPiA+ ID4gKyAqIEB4ZHI6IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ID4gPiArICogQG46IDY0LWJp dCBpbnRlZ2VyIHRvIGVuY29kZQ0KPiA+ID4gPiArICoNCj4gPiA+ID4gKyAqIFJldHVybiB2YWx1 ZXM6DQo+ID4gPiA+ICsgKsKgwqDCoE9uIHN1Y2Nlc3MsIHJldHVybnMgbGVuZ3RoIGluIGJ5dGVz IG9mIFhEUiBidWZmZXINCj4gPiA+ID4gY29uc3VtZWQNCj4gPiA+ID4gKyAqwqDCoMKgJS1FTk9C VUZTIG9uIFhEUiBidWZmZXIgb3ZlcmZsb3cNCj4gPiA+ID4gKyAqLw0KPiA+ID4gPiArc3RhdGlj IGlubGluZSBzc2l6ZV90DQo+ID4gPiA+ICt4ZHJfc3RyZWFtX2VuY29kZV91NjQoc3RydWN0IHhk cl9zdHJlYW0gKnhkciwgX191NjQgbikNCj4gPiA+ID4gK3sNCj4gPiA+ID4gKwljb25zdCBzaXpl X3QgbGVuID0gc2l6ZW9mKG4pOw0KPiA+ID4gPiArCV9fYmUzMiAqcCA9IHhkcl9yZXNlcnZlX3Nw YWNlKHhkciwgbGVuKTsNCj4gPiA+ID4gKw0KPiA+ID4gPiArCWlmICh1bmxpa2VseSghcCkpDQo+ ID4gPiA+ICsJCXJldHVybiAtRU5PQlVGUzsNCj4gPiA+ID4gKwl4ZHJfZW5jb2RlX2h5cGVyKHAs IG4pOw0KPiA+ID4gPiArCXJldHVybiBsZW47DQo+ID4gPiA+ICt9DQo+ID4gPiA+ICsNCj4gPiA+ ID4gKy8qKg0KPiA+ID4gPiArICogeGRyX3N0cmVhbV9lbmNvZGVfb3BhcXVlX2ZpeGVkIC0gRW5j b2RlIGZpeGVkIGxlbmd0aCBvcGFxdWUNCj4gPiA+ID4geGRyDQo+ID4gPiA+IGRhdGENCj4gPiA+ ID4gKyAqIEB4ZHI6IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ID4gPiArICogQHB0cjogcG9p bnRlciB0byBvcGFxdWUgZGF0YSBvYmplY3QNCj4gPiA+ID4gKyAqIEBsZW46IHNpemUgb2Ygb2Jq ZWN0IHBvaW50ZWQgdG8gYnkgQHB0cg0KPiA+ID4gPiArICoNCj4gPiA+ID4gKyAqIFJldHVybiB2 YWx1ZXM6DQo+ID4gPiA+ICsgKsKgwqDCoE9uIHN1Y2Nlc3MsIHJldHVybnMgbGVuZ3RoIGluIGJ5 dGVzIG9mIFhEUiBidWZmZXINCj4gPiA+ID4gY29uc3VtZWQNCj4gPiA+ID4gKyAqwqDCoMKgJS1F Tk9CVUZTIG9uIFhEUiBidWZmZXIgb3ZlcmZsb3cNCj4gPiA+ID4gKyAqLw0KPiA+ID4gPiArc3Rh dGljIGlubGluZSBzc2l6ZV90DQo+ID4gPiA+ICt4ZHJfc3RyZWFtX2VuY29kZV9vcGFxdWVfZml4 ZWQoc3RydWN0IHhkcl9zdHJlYW0gKnhkciwgY29uc3QNCj4gPiA+ID4gdm9pZA0KPiA+ID4gPiAq cHRyLCBzaXplX3QgbGVuKQ0KPiA+ID4gPiArew0KPiA+ID4gPiArCV9fYmUzMiAqcCA9IHhkcl9y ZXNlcnZlX3NwYWNlKHhkciwgbGVuKTsNCj4gPiA+ID4gKw0KPiA+ID4gPiArCWlmICh1bmxpa2Vs eSghcCkpDQo+ID4gPiA+ICsJCXJldHVybiAtRU5PQlVGUzsNCj4gPiA+ID4gKwl4ZHJfZW5jb2Rl X29wYXF1ZV9maXhlZChwLCBwdHIsIGxlbik7DQo+ID4gPiA+ICsJcmV0dXJuIHhkcl9hbGlnbl9z aXplKGxlbik7DQo+ID4gPiANCj4gPiA+IFNlZW1zIGxpa2UgdGhlIGNhbGxlciBjYW4gdXNlIHhk cl9hbGlnbl9zaXplKCkganVzdCBhcw0KPiA+ID4gZWFzaWx5IGFzIG92ZXJsb2FkaW5nIHRoZSBy ZXR1cm4gdmFsdWUgaGVyZSwgZm9yIGV4YW1wbGUuDQo+ID4gPiANCj4gPiA+IEJ1dCBJIGNhbid0 IHRoaW5rIG9mIGFueSBmaXhlZC1zaXplIG9wYXF1ZSBYRFIgb2JqZWN0DQo+ID4gPiB0aGF0IGlz IG5vdCBhbHJlYWR5IHByb3Blcmx5IHJvdW5kZWQgdXAsIG9yIHdoZXJlIHRoZQ0KPiA+ID4gbGVu Z3RoIGlzIG5vdCBhbHJlYWR5IGtub3duIHRvIHRoZSBYRFIgbGF5ZXIgKGFzIGENCj4gPiA+IGRl ZmluZWQgbWFjcm8gY29uc3RhbnQpLg0KPiA+ID4gDQo+ID4gPiANCj4gPiA+ID4gK30NCj4gPiA+ ID4gKw0KPiA+ID4gPiArLyoqDQo+ID4gPiA+ICsgKiB4ZHJfc3RyZWFtX2VuY29kZV9vcGFxdWUg LSBFbmNvZGUgdmFyaWFibGUgbGVuZ3RoIG9wYXF1ZQ0KPiA+ID4gPiB4ZHINCj4gPiA+ID4gZGF0 YQ0KPiA+ID4gPiArICogQHhkcjogcG9pbnRlciB0byB4ZHJfc3RyZWFtDQo+ID4gPiA+ICsgKiBA cHRyOiBwb2ludGVyIHRvIG9wYXF1ZSBkYXRhIG9iamVjdA0KPiA+ID4gPiArICogQGxlbjogc2l6 ZSBvZiBvYmplY3QgcG9pbnRlZCB0byBieSBAcHRyDQo+ID4gPiA+ICsgKg0KPiA+ID4gPiArICog UmV0dXJuIHZhbHVlczoNCj4gPiA+ID4gKyAqwqDCoMKgT24gc3VjY2VzcywgcmV0dXJucyBsZW5n dGggaW4gYnl0ZXMgb2YgWERSIGJ1ZmZlcg0KPiA+ID4gPiBjb25zdW1lZA0KPiA+ID4gPiArICrC oMKgwqAlLUVOT0JVRlMgb24gWERSIGJ1ZmZlciBvdmVyZmxvdw0KPiA+ID4gPiArICovDQo+ID4g PiA+ICtzdGF0aWMgaW5saW5lIHNzaXplX3QNCj4gPiA+ID4gK3hkcl9zdHJlYW1fZW5jb2RlX29w YXF1ZShzdHJ1Y3QgeGRyX3N0cmVhbSAqeGRyLCBjb25zdCB2b2lkDQo+ID4gPiA+ICpwdHIsDQo+ ID4gPiA+IHNpemVfdCBsZW4pDQo+ID4gPiA+ICt7DQo+ID4gPiA+ICsJc2l6ZV90IGNvdW50ID0g c2l6ZW9mKF9fdTMyKSArIHhkcl9hbGlnbl9zaXplKGxlbik7DQo+ID4gPiA+ICsJX19iZTMyICpw ID0geGRyX3Jlc2VydmVfc3BhY2UoeGRyLCBjb3VudCk7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwlp ZiAodW5saWtlbHkoIXApKQ0KPiA+ID4gPiArCQlyZXR1cm4gLUVOT0JVRlM7DQo+ID4gPiA+ICsJ eGRyX2VuY29kZV9vcGFxdWUocCwgcHRyLCBsZW4pOw0KPiA+ID4gPiArCXJldHVybiBjb3VudDsN Cj4gPiA+IA0KPiA+ID4gVGhlc2UgaGVscGVycyBhbHJlYWR5IHVwZGF0ZSB0aGUgc3RhdGUgb2Yg dGhlIHBhc3NlZA0KPiA+ID4gaW4geGRyX3N0cmVhbSwgc28gYSBjYWxsZXIgdHlwaWNhbGx5IHdv dWxkIG5vdCBuZWVkDQo+ID4gPiB0byBjYXJlIG11Y2ggYWJvdXQgdGhlIGJ5dGVzIGNvbnN1bWVk IGJ5IHRoZSBlbmNvZGVkDQo+ID4gPiBvcGFxdWUuDQo+ID4gPiANCj4gPiA+IA0KPiA+ID4gPiAr fQ0KPiA+ID4gPiArDQo+ID4gPiA+ICsvKioNCj4gPiA+ID4gKyAqIHhkcl9zdHJlYW1fZGVjb2Rl X3UzMiAtIERlY29kZSBhIDMyLWJpdCBpbnRlZ2VyDQo+ID4gPiA+ICsgKiBAeGRyOiBwb2ludGVy IHRvIHhkcl9zdHJlYW0NCj4gPiA+ID4gKyAqIEBwdHI6IGxvY2F0aW9uIHRvIHN0b3JlIGludGVn ZXINCj4gPiA+ID4gKyAqDQo+ID4gPiA+ICsgKiBSZXR1cm4gdmFsdWVzOg0KPiA+ID4gPiArICrC oMKgwqAlMCBvbiBzdWNjZXNzDQo+ID4gPiA+ICsgKsKgwqDCoCUtRU5PQlVGUyBvbiBYRFIgYnVm ZmVyIG92ZXJmbG93DQo+ID4gPiA+ICsgKi8NCj4gPiA+ID4gK3N0YXRpYyBpbmxpbmUgc3NpemVf dA0KPiA+ID4gPiAreGRyX3N0cmVhbV9kZWNvZGVfdTMyKHN0cnVjdCB4ZHJfc3RyZWFtICp4ZHIs IF9fdTMyICpwdHIpDQo+ID4gPiA+ICt7DQo+ID4gPiA+ICsJY29uc3Qgc2l6ZV90IGNvdW50ID0g c2l6ZW9mKCpwdHIpOw0KPiA+ID4gPiArCV9fYmUzMiAqcCA9IHhkcl9pbmxpbmVfZGVjb2RlKHhk ciwgY291bnQpOw0KPiA+ID4gPiArDQo+ID4gPiA+ICsJaWYgKHVubGlrZWx5KCFwKSkNCj4gPiA+ ID4gKwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ID4gPiArCSpwdHIgPSBiZTMyX3RvX2NwdXAocCk7 DQo+ID4gPiA+ICsJcmV0dXJuIDA7DQo+ID4gPiANCj4gPiA+IE5vIGxlbmd0aCByZXR1cm5lZCBo ZXJlLiBUaGUgY2FsbGVyIGtub3dzIHRoZSBsZW5ndGgNCj4gPiA+IG9mIHRoaXMgb2JqZWN0LCBj bGVhcmx5LCBhbmQgb25seSBjYXJlcyBhYm91dCB3aGV0aGVyDQo+ID4gPiBkZWNvZGluZyBoYXMg b3ZlcnJ1biB0aGUgWERSIHN0cmVhbS4NCj4gPiANCj4gPiBZZXMuIEVhcmxpZXIgdmVyc2lvbnMg cmV0dXJuZWQgPiAwLCBidXQgSSBmaWd1cmVkIHRoYXQgY291bnRpbmcgdGhlDQo+ID4gYnVmZmVy IHNwYWNlIGlzIG5vdCBhcyBpbXBvcnRhbnQgd2hlbiBkZWNvZGluZy4gSSBjYW4ndCB0aGluayBv Zg0KPiA+IHRvbw0KPiA+IG1hbnkgdXNlIGNhc2VzLg0KPiA+IA0KPiA+ID4gPiArfQ0KPiA+ID4g PiArDQo+ID4gPiA+ICsvKioNCj4gPiA+ID4gKyAqIHhkcl9zdHJlYW1fZGVjb2RlX29wYXF1ZV9m aXhlZCAtIERlY29kZSBmaXhlZCBsZW5ndGggb3BhcXVlDQo+ID4gPiA+IHhkcg0KPiA+ID4gPiBk YXRhDQo+ID4gPiA+ICsgKiBAeGRyOiBwb2ludGVyIHRvIHhkcl9zdHJlYW0NCj4gPiA+ID4gKyAq IEBwdHI6IGxvY2F0aW9uIHRvIHN0b3JlIGRhdGENCj4gPiA+ID4gKyAqIEBsZW46IHNpemUgb2Yg YnVmZmVyIHBvaW50ZWQgdG8gYnkgQHB0cg0KPiA+ID4gPiArICoNCj4gPiA+ID4gKyAqIFJldHVy biB2YWx1ZXM6DQo+ID4gPiA+ICsgKsKgwqDCoE9uIHN1Y2Nlc3MsIHJldHVybnMgc2l6ZSBvZiBv YmplY3Qgc3RvcmVkIGluIEBwdHINCj4gPiA+IA0KPiA+ID4gWW91J3JlIHJldHVybmluZyB0aGUg cGFzc2VkLWluIGxlbmd0aC4gVGh1cyB0aGUgY2FsbGVyDQo+ID4gPiBhbHJlYWR5IGtub3dzIHRo ZSBzaXplIG9mIHRoZSBvYmplY3Qgc3RvcmVkIGF0IEBwdHIuDQo+ID4gDQo+ID4gQ29uc2lzdGVu Y3ksIGFuZCBpdCBhbGxvd3MgaXQgdG8gYmUgZWFzaWx5IHVzZWQgYXMgYSBoZWxwZXIgaW5zaWRl DQo+ID4gb3RoZXIgZnVuY3Rpb25zIHRoYXQgZG8gbmVlZCB0byByZXR1cm4gdGhlIG9iamVjdCBs ZW5ndGguDQo+IA0KPiBHb2luZyBmb3IgZWFzZSBvZiBjb21wb3NpbmcgdGhlc2UgZnVuY3Rpb25z LiBPSy4NCj4gDQo+IA0KPiA+IE5vdGUgdGhhdCB0aGUgZnVuY3Rpb24gaXMgaW5saW5lZCwgc28g dGhlIGNvbXBpbGVyIHNob3VsZCBub3JtYWxseQ0KPiA+IG9wdGltaXNlIGF3YXkgcmV0dXJuIHZh bHVlcyB0aGF0IGFyZSB1bnVzZWQgYnkgdGhlIGNhbGxlci4NCj4gDQo+IFRydWUuIEhvd2V2ZXIg ZnV0dXJlIGNvZGUgcmVhZGVycyBtaWdodCB3b25kZXIgd2h5IHRoaXMNCj4gdmFsdWUgaXMgYmVp bmcgY29tcHV0ZWQgaWYgdGhlIHZhbHVlIG9yIHRoZSBjb21wdXRhdGlvbg0KPiBpdHNlbGYgaXMg dW5uZWVkZWQgaW4gbW9zdCBjYXNlcy4NCj4gDQo+IFNlZW1zIGxpa2UgYSBzZXBhcmF0ZSBoZWxw ZXIgdGhhdCBkZXJpdmVzIHRoaXMgdmFsdWUNCj4gd2hlcmUgYW5kIHdoZW4gaXQgaXMgbmVlZGVk IG1pZ2h0IGJlIGNsZWFuZXI7IGJ1dCB0aGF0DQo+IGlzIGVudGlyZWx5IHN1YmplY3RpdmUuDQo+ IA0KPiANCj4gPiA+ID4gKyAqwqDCoMKgJS1FTk9CVUZTIG9uIFhEUiBidWZmZXIgb3ZlcmZsb3cN Cj4gPiA+ID4gKyAqLw0KPiA+ID4gPiArc3RhdGljIGlubGluZSBzc2l6ZV90DQo+ID4gPiA+ICt4 ZHJfc3RyZWFtX2RlY29kZV9vcGFxdWVfZml4ZWQoc3RydWN0IHhkcl9zdHJlYW0gKnhkciwgdm9p ZA0KPiA+ID4gPiAqcHRyLA0KPiA+ID4gPiBzaXplX3QgbGVuKQ0KPiA+ID4gPiArew0KPiA+ID4g PiArCV9fYmUzMiAqcCA9IHhkcl9pbmxpbmVfZGVjb2RlKHhkciwgbGVuKTsNCj4gPiA+ID4gKw0K PiA+ID4gPiArCWlmICh1bmxpa2VseSghcCkpDQo+ID4gPiA+ICsJCXJldHVybiAtRU5PQlVGUzsN Cj4gPiA+ID4gKwl4ZHJfZGVjb2RlX29wYXF1ZV9maXhlZChwLCBwdHIsIGxlbik7DQo+ID4gPiA+ ICsJcmV0dXJuIGxlbjsNCj4gPiA+ID4gK30NCj4gPiA+ID4gKw0KPiA+ID4gPiArLyoqDQo+ID4g PiA+ICsgKiB4ZHJfc3RyZWFtX2RlY29kZV9vcGFxdWVfaW5saW5lIC0gRGVjb2RlIHZhcmlhYmxl IGxlbmd0aA0KPiA+ID4gPiBvcGFxdWUNCj4gPiA+ID4geGRyIGRhdGENCj4gPiA+ID4gKyAqIEB4 ZHI6IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ID4gPiArICogQHB0cjogbG9jYXRpb24gdG8g c3RvcmUgcG9pbnRlciB0byBvcGFxdWUgZGF0YQ0KPiA+ID4gPiArICoNCj4gPiA+ID4gKyAqIE5v dGU6IHRoZSBwb2ludGVyIHN0b3JlZCBpbiBAcHRyIGNhbm5vdCBiZSBhc3N1bWVkIHZhbGlkDQo+ ID4gPiA+IGFmdGVyDQo+ID4gPiA+IHRoZSBYRFINCj4gPiA+ID4gKyAqIGJ1ZmZlciBoYXMgYmVl biBkZXN0cm95ZWQsIG9yIGV2ZW4gYWZ0ZXIgY2FsbGluZw0KPiA+ID4gPiB4ZHJfaW5saW5lX2Rl Y29kZSgpDQo+ID4gPiA+ICsgKiBvbiBAeGRyLiBJdCBpcyB0aGVyZWZvcmUgZXhwZWN0ZWQgdGhh dCB0aGUgb2JqZWN0IGl0IHBvaW50cw0KPiA+ID4gPiB0bw0KPiA+ID4gPiBzaG91bGQNCj4gPiA+ ID4gKyAqIGJlIHByb2Nlc3NlZCBpbW1lZGlhdGVseS4NCj4gPiA+ID4gKyAqDQo+ID4gPiA+ICsg KiBSZXR1cm4gdmFsdWVzOg0KPiA+ID4gPiArICrCoMKgwqBPbiBzdWNjZXNzLCByZXR1cm5zIHNp emUgb2Ygb2JqZWN0IHN0b3JlZCBpbiAqQHB0cg0KPiA+ID4gDQo+ID4gPiBUaGlzIHNlZW1zIHRv IGJlIHRoZSBvbmx5IGZ1bmN0aW9uIHdoZXJlIHRoZSBjYWxsZXINCj4gPiA+IG1pZ2h0IG5vdCBh bHJlYWR5IGtub3cgdGhlIGxlbmd0aCBvZiB0aGUgb2JqZWN0LCBidXQNCj4gPiA+IG1pZ2h0IGFj dHVhbGx5IGNhcmUuIFNpbmNlIHRoZSBvYmplY3QgbGVuZ3RoIGNhbiBiZQ0KPiA+ID4gY29uc2lk ZXJlZCBwYXJ0IG9mIHRoZSBvYmplY3QgaXRzZWxmLCBtYXliZSB0aGF0DQo+ID4gPiBsZW5ndGgg c2hvdWxkIGJlIHJldHVybmVkIHZpYSBhbiBvdXRwdXQgcGFyYW1ldGVyDQo+ID4gPiByYXRoZXIg dGhhbiBhcyB0aGUgZnVuY3Rpb24ncyByZXR1cm4gdmFsdWUuDQo+ID4gDQo+ID4gSSBjb25zaWRl cmVkIGl0LCBidXQgdGhhdCBtZWFucyB5b3UgaGF2ZSB0byBjaG9vc2UgYW4gZXhhY3Qgc3RvcmFn ZQ0KPiA+IHR5cGUgYW5kIGdjYyB3aWxsIGNvbXBsYWluIGlmIHRoZSB0eXBlIGNoZWNrIGZhaWxz Lg0KPiA+IEluIG1vc3QgY2FzZXMsIHdlIGRvbid0IHJlYWxseSBjYXJlIGlmIHRoZSB1MzIgdmFs dWUgZ2V0cyBzdG9yZWQgaW4NCj4gPiBhbg0KPiA+IHVuc2lnbmVkIGludCwgaW50LCB1bnNpZ25l ZCBsb25nLCBsb25nLCBzaXplX3QsIHNzaXplX3QgYmVjYXVzZSB3ZQ0KPiA+IGhhdmUNCj4gPiBh IGdvb2QgaWRlYSBvZiB3aGF0IHRvIGV4cGVjdCBmb3IgdGhlIG9iamVjdCBzaXplLg0KPiA+IA0K PiA+ID4gPiArICrCoMKgwqAlLUVOT0JVRlMgb24gWERSIGJ1ZmZlciBvdmVyZmxvdw0KPiA+ID4g DQo+ID4gPiBFSU5WQUwgaXMgcHJvYmFibHkgYmV0dGVyOiB0aGUgY2FsbGVyIGRpZG4ndCBwcm92 aWRlDQo+ID4gPiB0aGUgY29ycmVjdCBpbnB1dHMuIFRoYXQncyBhIG5pdCwgdGhvdWdoLg0KPiA+ IA0KPiA+IEl0J3Mgbm90IGEgY2FsbGVyIHByb2JsZW0uIFRoZSBFTk9CVUZTIGVycm9yIG9uIGRl Y29kZSBpbmRpY2F0ZXMNCj4gPiB0aGF0DQo+ID4gdGhlIFJQQyBtZXNzYWdlIHdlJ3JlIHRyeWlu ZyB0byBkZWNvZGUgd2FzIHByb2JhYmx5IHRydW5jYXRlZCBvcg0KPiA+IGNvcnJ1cHRlZC4NCj4g DQo+IEFoLiBBZ3JlZSBub3csIG5vdCBhIGNhbGxlciBidWcuDQo+IA0KPiBJIHN0aWxsIHdvbmRl ciBpZiB0aGUgbWVhbmluZyBvZiBFTk9CVUZTIGlzIGEgZ29vZCBlbm91Z2ggbWF0Y2gNCj4gdG8g dGhpcyB1c2UgY2FzZS4gRUlOVkFMIGlzIGEgcGVybWFuZW50IGVycm9yLCBidXQgSSBkb24ndCB0 aGluaw0KPiBFTk9CVUZTIGlzLg0KPiANCj4gRnJvbSBodHRwczovL3d3dy5nbnUub3JnL3NvZnR3 YXJlL2xpYmMvbWFudWFsL2h0bWxfbm9kZS9FcnJvci1Db2Rlcy5oDQo+IHRtbDoNCj4gDQo+ID4g TWFjcm86IGludCBFTk9CVUZTDQo+ID4gVGhlIGtlcm5lbOKAmXMgYnVmZmVycyBmb3IgSS9PIG9w ZXJhdGlvbnMgYXJlIGFsbCBpbiB1c2UuIEluIEdOVSwNCj4gPiB0aGlzDQo+ID4gZXJyb3IgaXMg YWx3YXlzIHN5bm9ueW1vdXMgd2l0aCBFTk9NRU07IHlvdSBtYXkgZ2V0IG9uZSBvciB0aGUNCj4g PiBvdGhlcg0KPiA+IGZyb20gbmV0d29yayBvcGVyYXRpb25zLg0KPiANCj4gVGhlIG90aGVyIHBs YWNlcyBJJ3ZlIGxvb2tlZCBhbHNvIHN1Z2dlc3QgdGhpcyBlcnJvciBjb2RlIG1lYW5zDQo+IGEg dGVtcG9yYXJ5IG91dCBvZiBidWZmZXJzIGNvbmRpdGlvbiwgYW5kIHRoZSBjYWxsZXIgc2hvdWxk IHRyeQ0KPiBhZ2FpbiBsYXRlci4gVGhlIGVycm9yIGlzIHVzZWQgdG8gbWVhbiB0aGVyZSBhcmUg bm8gbW9yZSBidWZmZXJzDQo+IChwbHVyYWwpIHRvIHVzZSBmb3IgYSBzZW5kIG9wZXJhdGlvbi4g QXMgaXQgc2F5cywgYWtpbiB0byBFTk9NRU0uDQo+IFRoYXQncyB0aGUgd2F5IEkndmUgdXNlZCB0 aGlzIGVycm5vIGluIHRoZSBwYXN0Lg0KPiANCj4gSGVyZSB0aGUgZXJyb3IgaXMgdXNlZCB0byBt ZWFuICJidWZmZXIgKHNpbmd1bGFyKSB3b3VsZCBvdmVyZmxvdyINCj4gZHVyaW5nIGEgcmVjZWl2 ZTsgcGVybWFuZW50IGVycm9yLCBubyByZXRyeSBwb3NzaWJsZS4gUG9zc2libGUNCj4gYWx0ZXJu YXRpdmVzIHRoYXQgbWlnaHQgYmUgY2xvc2VyIGluIHB1cnBvc2U6IEVNU0dTSVpFLCBFQkFETVNH LA0KPiBFUkVNT1RFSU8sIG9yIEUyQklHLg0KDQpIb3cgYWJvdXQgRU5PREFUQSwgdGhlbj8NCg0K PiBJIGFzc3VtZSB5b3Ugd2FudCB0byByZXR1cm4gZXJybm9zIGZyb20gdGhlc2UgaGVscGVycyBi ZWNhdXNlDQo+IGV2ZW50dWFsbHkgc29tZSBvZiB0aGVtIG1pZ2h0IGVuY291bnRlciBvdGhlciB0 eXBlcyBvZiBlcnJvcnM/DQo+IElmIG5vdCwgdGhlbiBzdGlja2luZyB3aXRoIC0xIG9uIGVycm9y LCAwIG9yIHBvc2l0aXZlIHZhbHVlIG9uDQo+IHN1Y2Nlc3MgbWlnaHQgYmUgZW50aXJlbHkgYWRl cXVhdGUuDQoNClNlZSB0aGUgInY0IiBwYXRjaHNldCB3aGljaCBnb2VzIGEgbGl0dGxlIGZ1cnRo ZXIgaW4gcmVwbGFjaW5nIHRoZQ0Kb2JqZWN0IHNpemUgY2hlY2tzLiBGb3Igb25lIHRoaW5nLCB0 aGF0IGFsbG93cyB1cyB0byBiZSBtb3JlIGZvcmNlZnVsDQphYm91dCBlbnN1cmluZyB0aGF0IHdl IF9hbHdheXNfIGNoZWNrIHRoZSBzaXplIG9mIHRoZSBvYmplY3QgYWdhaW5zdA0KZXhwZWN0YXRp b25zLg0KDQo+IA0KPiA+ID4gSG93ZXZlciwgYXMgYSBtYXR0ZXIgb2YgZGVmZW5zaXZlIGNvZGlu ZywgdGhpcyBlcnJubw0KPiA+ID4gY291bGQgbGVhayB1cCB0aGUgc3RhY2sgaWYgZGV2ZWxvcGVy cyBhcmUgbm90IGNhcmVmdWwuDQo+ID4gPiANCj4gPiA+IEEgYm9vbGVhbiByZXR1cm4gdmFsdWUg Y291bGQgYmUgZW50aXJlbHkgYWRlcXVhdGUgZm9yDQo+ID4gPiB0aGVzZSBkZWNvZGVycz8NCj4g PiA+IA0KPiA+ID4gDQo+ID4gPiA+ICsgKi8NCj4gPiA+ID4gK3N0YXRpYyBpbmxpbmUgc3NpemVf dA0KPiA+ID4gPiAreGRyX3N0cmVhbV9kZWNvZGVfb3BhcXVlX2lubGluZShzdHJ1Y3QgeGRyX3N0 cmVhbSAqeGRyLCB2b2lkDQo+ID4gPiA+ICoqcHRyKQ0KPiA+ID4gPiArew0KPiA+ID4gPiArCV9f YmUzMiAqcDsNCj4gPiA+ID4gKwlfX3UzMiBsZW47DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwlpZiAo dW5saWtlbHkoeGRyX3N0cmVhbV9kZWNvZGVfdTMyKHhkciwgJmxlbikgPCAwKSkNCj4gPiA+ID4g KwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ID4gPiArCWlmIChsZW4gIT0gMCkgew0KPiA+ID4gPiAr CQlwID0geGRyX2lubGluZV9kZWNvZGUoeGRyLCBsZW4pOw0KPiA+ID4gPiArCQlpZiAodW5saWtl bHkoIXApKQ0KPiA+ID4gPiArCQkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ID4gPiArCQkqcHRyID0g cDsNCj4gPiA+ID4gKwl9IGVsc2UNCj4gPiA+ID4gKwkJKnB0ciA9IE5VTEw7DQo+ID4gPiA+ICsJ cmV0dXJuIGxlbjsNCj4gPiA+ID4gK30NCj4gPiA+ID4gI2VuZGlmIC8qIF9fS0VSTkVMX18gKi8N Cj4gPiA+ID4gDQo+ID4gPiA+ICNlbmRpZiAvKiBfU1VOUlBDX1hEUl9IXyAqLw0KPiA+ID4gPiAt LcKgDQo+ID4gPiA+IDIuOS4zDQo+ID4gPiA+IA0KPiA+ID4gPiAtLQ0KPiA+ID4gPiBUbyB1bnN1 YnNjcmliZSBmcm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGluZSAidW5zdWJzY3JpYmUNCj4gPiA+ ID4gbGludXgtDQo+ID4gPiA+IG5mcyIgaW4NCj4gPiA+ID4gdGhlIGJvZHkgb2YgYSBtZXNzYWdl IHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcNCj4gPiA+ID4gTW9yZSBtYWpvcmRvbW8gaW5m byBhdMKgwqBodHRwOi8vdmdlci5rZXJuZWwub3JnL21ham9yZG9tby1pbmZvLmgNCj4gPiA+ID4g dG1sDQo+ID4gPiANCj4gPiA+IC0tDQo+ID4gPiBDaHVjayBMZXZlcg0KPiA+ID4gDQo+ID4gPiAN Cj4gPiA+IA0KPiA+IA0KPiA+IC0twqANCj4gPiBUcm9uZCBNeWtsZWJ1c3QNCj4gPiBMaW51eCBO RlMgY2xpZW50IG1haW50YWluZXIsIFByaW1hcnlEYXRhDQo+ID4gdHJvbmQubXlrbGVidXN0QHBy aW1hcnlkYXRhLmNvbQ0KPiA+IE7vv73vv73vv71y77+9ee+/ve+/ve+/vWLvv71Y77+9x6d277+9 Xu+/vSneunsubu+/vSvvv71777+9Iu+/ve+/vV5u77+9cu+/ve+/vXrvv70a77+977+9aO+/ve+/ ve+/vSbvv70e77+9R++/ve+/vWjvv70DKO+/vemaju+/vd2iaiLvv70a77+9DQo+ID4gG23vv73v v73vv73vv71677+93pbvv73vv71m77+9aO+/vX7vv71tDQo+IA0KPiAtLQ0KPiBDaHVjayBMZXZl cg0KPiANCj4gDQo+IA0KLS0gDQpUcm9uZCBNeWtsZWJ1c3QNCkxpbnV4IE5GUyBjbGllbnQgbWFp bnRhaW5lciwgUHJpbWFyeURhdGENCnRyb25kLm15a2xlYnVzdEBwcmltYXJ5ZGF0YS5jb20NCg== ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-19 19:28 ` Trond Myklebust @ 2017-02-19 20:06 ` Chuck Lever 2017-02-19 20:33 ` Trond Myklebust 0 siblings, 1 reply; 11+ messages in thread From: Chuck Lever @ 2017-02-19 20:06 UTC (permalink / raw) To: Trond Myklebust; +Cc: Anna Schumaker, Linux NFS Mailing List > On Feb 19, 2017, at 2:28 PM, Trond Myklebust <trondmy@primarydata.com> wrote: > > Thanks for the discussion, BTW. I appreciate the feedback. No problem! Feel free to add Reviewed-by: Chuck Lever <chuck.lever@oracle.com> > On Sun, 2017-02-19 at 14:07 -0500, Chuck Lever wrote: >>> On Feb 19, 2017, at 12:36 AM, Trond Myklebust <trondmy@primarydata. >>> com> wrote: >>> >>> On Sat, 2017-02-18 at 17:21 -0500, Chuck Lever wrote: >>>>> On Feb 18, 2017, at 2:12 PM, Trond Myklebust <trond.myklebust@p >>>>> rima >>>>> rydata.com> wrote: >>>>> >>>>> Add some generic helpers for encoding/decoding opaque >>>>> structures >>>>> and >>>>> basic u32/u64. >>>> >>>> I have some random-thoughts-slash-wacky-ideas. >>>> >>>> I'm going to paint the garden shed a little since >>>> these helpers appear to be broadly applicable. >>>> Generally speaking I like the idea of building >>>> "stream" versions of the traditional basic type >>>> encoders and decoders. >>>> >>>> >>>>> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com >>>>>> >>>>> --- >>>>> include/linux/sunrpc/xdr.h | 173 >>>>> +++++++++++++++++++++++++++++++++++++++++++++ >>>>> 1 file changed, 173 insertions(+) >>>>> >>>>> diff --git a/include/linux/sunrpc/xdr.h >>>>> b/include/linux/sunrpc/xdr.h >>>>> index 56c48c884a24..37bf1be20b62 100644 >>>>> --- a/include/linux/sunrpc/xdr.h >>>>> +++ b/include/linux/sunrpc/xdr.h >>>>> @@ -242,6 +242,179 @@ 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); >>>>> >>>>> +/** >>>>> + * xdr_align_size - Calculate padded size of an object >>>>> + * @n: Size of an object being XDR encoded (in bytes) >>>>> + * >>>>> + * Return value: >>>>> + * Size (in bytes) of the object including xdr padding >>>>> + */ >>>>> +static inline size_t >>>>> +xdr_align_size(size_t n) >>>>> +{ >>>>> + const size_t mask = sizeof(__u32) - 1; >>>> >>>> I know this doesn't make a functional difference, but >>>> I'm wondering if this should be sizeof(__be32), since >>>> it is actually the size of a wire object? Seems like >>>> that is a common question wherever sizeof is used >>>> below. >>> >>> The __be32 is required to be the same size as u32. The only allowed >>> difference between the two is be the endianness. >> >> Right, sizeof(__u32) == sizeof(__be32). __be has always >> been about endian annotation; no real functional difference >> with __u. >> >> The issue for me is precision of documentation (or, in some >> sense, code readability). In all of these cases, it's not >> the size of the local variable that is important, it's the >> size of the (XDR encoded) wire object. That's sizeof(__be32). >> >> Those just happen to be the same here. It's pretty easy to >> mistake the size of a local object as being always the same >> as the size of the encoded data type. I've done that myself >> often enough that it makes sense to be consistent and >> careful, even in the simple cases. >> >> I'm not going to make a big deal, but I'd like to point out >> that subtle difference. IMO it would make more sense to >> human readers if these were __be and not __u. > > Fair enough. I can update that. > >> >>>> Is this a constant variable rather than an enum because >>>> you want it to retain the type of size_t (matching the >>>> type of the xdr_inline_{en,de}code() functions) ? >>> >>> It's really just for efficiency, in order to prod gcc into >>> optimising >>> it as it would any other constant. >>> >>>> Since we see sizeof(yada) repeated elsewhere, did you >>>> consider defining size constants in a scope where they >>>> can be shared amongst all of the XDR functions? >>>> >>>> For example, xdr_reserve_space itself could immediately >>>> make use of a "sizeof(__be32) - 1" constant. >>> >>> That could be done. I haven't really considered it. >>> >>>> Is your intention to replace XDR_QUADLEN with this >>>> function eventually? >>> >>> Eventually, I'd like us to get rid of most of the open coded >>> instances >>> of 'pointer to __be32' in the NFS code, and hide all knowledge of >>> that >>> in struct xdr_stream and these SUNRPC layered helpers. >> >> Sounds good to me. >> >> >>>>> + >>>>> + return (n + mask) & ~mask; >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_encode_u32 - Encode a 32-bit integer >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @n: integer to encode >>>>> + * >>>>> + * Return values: >>>>> + * On success, returns length in bytes of XDR buffer >>>>> consumed >>>>> + * %-ENOBUFS on XDR buffer overflow >>>> >>>> I've never been crazy about these amplified return >>>> types, though I know it's typical kernel coding style. >>>> Here, though, I wonder if they are really necessary. >>>> >>>> The returned length seems to be interesting only for >>>> decoding variable-length objects (farther below). Maybe >>>> those are the only functions that need to provide a >>>> positive return value? >>> >>> NFSv4 introduces the (IMO nasty) habit of nesting XDR-encoded >>> objects >>> inside a variable length opaque object (say hello to type >>> "attrlist4"). >> >> And pNFS layouts. Fair enough. >> >> >>> In that case, we need to keep a running tally of the length of the >>> objects we have XDR encoded so that we can retroactively set the >>> length >>> of the opaque object. Currently we use the xdr_stream_pos() to >>> determine that length, but it might be nice to replace that with >>> something a little more direct. >> >> The new helpers appear to be abstracting away from a >> direct approach. IMHO staying with something that looks >> like a function call (like xdr_stream_pos) seems like >> it is clean and consistent with these new helpers. >> >> >>> Note also that the lengths returned here are not the object sizes >>> themselves, but the amount of buffer space consumed (i.e. the >>> aligned >>> size). >> >> Makes sense. Still, seems like the callers already know >> these "space consumed" values in every case. Maybe that >> won't be true when these helpers are glued together to >> handle more abstract data types. >> >>>> Perhaps the WARN_ON_ONCE calls added in later patches >>>> should be in these helpers instead of in their callers. >>>> Then the encoder helpers can return void. >>> >>> At some point, I'd like to reinstate the practice of returning an >>> error >>> when encoding fails. It may be better to abort sending a truncated >>> RPC >>> call rather than having it execute partially; specially now that >>> we're >>> finally starting to use COMPOUND to create more complex operations. >> >> I agree, IMO that would be a better approach. >> >> >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n) >>>>> +{ >>>>> + const size_t len = sizeof(n); >>>>> + __be32 *p = xdr_reserve_space(xdr, len); >>>>> + >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + *p = cpu_to_be32(n); >>>>> + return len; >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_encode_u64 - Encode a 64-bit integer >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @n: 64-bit integer to encode >>>>> + * >>>>> + * Return values: >>>>> + * On success, returns length in bytes of XDR buffer >>>>> consumed >>>>> + * %-ENOBUFS on XDR buffer overflow >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n) >>>>> +{ >>>>> + const size_t len = sizeof(n); >>>>> + __be32 *p = xdr_reserve_space(xdr, len); >>>>> + >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + xdr_encode_hyper(p, n); >>>>> + return len; >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_encode_opaque_fixed - Encode fixed length opaque >>>>> xdr >>>>> data >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @ptr: pointer to opaque data object >>>>> + * @len: size of object pointed to by @ptr >>>>> + * >>>>> + * Return values: >>>>> + * On success, returns length in bytes of XDR buffer >>>>> consumed >>>>> + * %-ENOBUFS on XDR buffer overflow >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const >>>>> void >>>>> *ptr, size_t len) >>>>> +{ >>>>> + __be32 *p = xdr_reserve_space(xdr, len); >>>>> + >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + xdr_encode_opaque_fixed(p, ptr, len); >>>>> + return xdr_align_size(len); >>>> >>>> Seems like the caller can use xdr_align_size() just as >>>> easily as overloading the return value here, for example. >>>> >>>> But I can't think of any fixed-size opaque XDR object >>>> that is not already properly rounded up, or where the >>>> length is not already known to the XDR layer (as a >>>> defined macro constant). >>>> >>>> >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_encode_opaque - Encode variable length opaque >>>>> xdr >>>>> data >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @ptr: pointer to opaque data object >>>>> + * @len: size of object pointed to by @ptr >>>>> + * >>>>> + * Return values: >>>>> + * On success, returns length in bytes of XDR buffer >>>>> consumed >>>>> + * %-ENOBUFS on XDR buffer overflow >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_encode_opaque(struct xdr_stream *xdr, const void >>>>> *ptr, >>>>> size_t len) >>>>> +{ >>>>> + size_t count = sizeof(__u32) + xdr_align_size(len); >>>>> + __be32 *p = xdr_reserve_space(xdr, count); >>>>> + >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + xdr_encode_opaque(p, ptr, len); >>>>> + return count; >>>> >>>> These helpers already update the state of the passed >>>> in xdr_stream, so a caller typically would not need >>>> to care much about the bytes consumed by the encoded >>>> opaque. >>>> >>>> >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_decode_u32 - Decode a 32-bit integer >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @ptr: location to store integer >>>>> + * >>>>> + * Return values: >>>>> + * %0 on success >>>>> + * %-ENOBUFS on XDR buffer overflow >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr) >>>>> +{ >>>>> + const size_t count = sizeof(*ptr); >>>>> + __be32 *p = xdr_inline_decode(xdr, count); >>>>> + >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + *ptr = be32_to_cpup(p); >>>>> + return 0; >>>> >>>> No length returned here. The caller knows the length >>>> of this object, clearly, and only cares about whether >>>> decoding has overrun the XDR stream. >>> >>> Yes. Earlier versions returned > 0, but I figured that counting the >>> buffer space is not as important when decoding. I can't think of >>> too >>> many use cases. >>> >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_decode_opaque_fixed - Decode fixed length opaque >>>>> xdr >>>>> data >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @ptr: location to store data >>>>> + * @len: size of buffer pointed to by @ptr >>>>> + * >>>>> + * Return values: >>>>> + * On success, returns size of object stored in @ptr >>>> >>>> You're returning the passed-in length. Thus the caller >>>> already knows the size of the object stored at @ptr. >>> >>> Consistency, and it allows it to be easily used as a helper inside >>> other functions that do need to return the object length. >> >> Going for ease of composing these functions. OK. >> >> >>> Note that the function is inlined, so the compiler should normally >>> optimise away return values that are unused by the caller. >> >> True. However future code readers might wonder why this >> value is being computed if the value or the computation >> itself is unneeded in most cases. >> >> Seems like a separate helper that derives this value >> where and when it is needed might be cleaner; but that >> is entirely subjective. >> >> >>>>> + * %-ENOBUFS on XDR buffer overflow >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void >>>>> *ptr, >>>>> size_t len) >>>>> +{ >>>>> + __be32 *p = xdr_inline_decode(xdr, len); >>>>> + >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + xdr_decode_opaque_fixed(p, ptr, len); >>>>> + return len; >>>>> +} >>>>> + >>>>> +/** >>>>> + * xdr_stream_decode_opaque_inline - Decode variable length >>>>> opaque >>>>> xdr data >>>>> + * @xdr: pointer to xdr_stream >>>>> + * @ptr: location to store pointer to opaque data >>>>> + * >>>>> + * Note: the pointer stored in @ptr cannot be assumed valid >>>>> after >>>>> the XDR >>>>> + * buffer has been destroyed, or even after calling >>>>> xdr_inline_decode() >>>>> + * on @xdr. It is therefore expected that the object it points >>>>> to >>>>> should >>>>> + * be processed immediately. >>>>> + * >>>>> + * Return values: >>>>> + * On success, returns size of object stored in *@ptr >>>> >>>> This seems to be the only function where the caller >>>> might not already know the length of the object, but >>>> might actually care. Since the object length can be >>>> considered part of the object itself, maybe that >>>> length should be returned via an output parameter >>>> rather than as the function's return value. >>> >>> I considered it, but that means you have to choose an exact storage >>> type and gcc will complain if the type check fails. >>> In most cases, we don't really care if the u32 value gets stored in >>> an >>> unsigned int, int, unsigned long, long, size_t, ssize_t because we >>> have >>> a good idea of what to expect for the object size. >>> >>>>> + * %-ENOBUFS on XDR buffer overflow >>>> >>>> EINVAL is probably better: the caller didn't provide >>>> the correct inputs. That's a nit, though. >>> >>> It's not a caller problem. The ENOBUFS error on decode indicates >>> that >>> the RPC message we're trying to decode was probably truncated or >>> corrupted. >> >> Ah. Agree now, not a caller bug. >> >> I still wonder if the meaning of ENOBUFS is a good enough match >> to this use case. EINVAL is a permanent error, but I don't think >> ENOBUFS is. >> >> From https://www.gnu.org/software/libc/manual/html_node/Error-Codes.h >> tml: >> >>> Macro: int ENOBUFS >>> The kernel’s buffers for I/O operations are all in use. In GNU, >>> this >>> error is always synonymous with ENOMEM; you may get one or the >>> other >>> from network operations. >> >> The other places I've looked also suggest this error code means >> a temporary out of buffers condition, and the caller should try >> again later. The error is used to mean there are no more buffers >> (plural) to use for a send operation. As it says, akin to ENOMEM. >> That's the way I've used this errno in the past. >> >> Here the error is used to mean "buffer (singular) would overflow" >> during a receive; permanent error, no retry possible. Possible >> alternatives that might be closer in purpose: EMSGSIZE, EBADMSG, >> EREMOTEIO, or E2BIG. > > How about ENODATA, then? ENODATA is indeed a permanent error. To me, EBADMSG still feels closer to a decode failure. Other systems have EBADRPC, but Linux doesn't appear to. On the encode side, EINVAL or the venerable EIO makes sense. Both seem to be used for a lot of other purposes in the RPC stack, though. It would be great to have one distinct error code meaning "failed to encode Call" and one meaning "failed to decode Reply". For instance, TI-RPC has 21 enum clnt_stat { 22 RPC_SUCCESS = 0, /* call succeeded */ 23 /* 24 * local errors 25 */ 26 RPC_CANTENCODEARGS = 1, /* can't encode arguments */ 27 RPC_CANTDECODERES = 2, /* can't decode results */ 28 RPC_CANTSEND = 3, /* failure in sending call */ 29 RPC_CANTRECV = 4, Maybe that's over-engineering for us, but there could be some instances where it might help the upper layer to know that the RPC Call was never sent (like, SEQUENCE ? ). >> I assume you want to return errnos from these helpers because >> eventually some of them might encounter other types of errors? >> If not, then sticking with -1 on error, 0 or positive value on >> success might be entirely adequate. > > See the "v4" patchset which goes a little further in replacing the > object size checks. For one thing, that allows us to be more forceful > about ensuring that we _always_ check the size of the object against > expectations. Glanced at that. Yes, that's more clear, and length checking in addition to buffer overrun checking is good. Why would the upper layer want to distinguish those two cases. Are there some cases where the UL can take some recourse, or is a decoding failure always permanent? >>>> However, as a matter of defensive coding, this errno >>>> could leak up the stack if developers are not careful. >>>> >>>> A boolean return value could be entirely adequate for >>>> these decoders? >>>> >>>> >>>>> + */ >>>>> +static inline ssize_t >>>>> +xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void >>>>> **ptr) >>>>> +{ >>>>> + __be32 *p; >>>>> + __u32 len; >>>>> + >>>>> + if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0)) >>>>> + return -ENOBUFS; >>>>> + if (len != 0) { >>>>> + p = xdr_inline_decode(xdr, len); >>>>> + if (unlikely(!p)) >>>>> + return -ENOBUFS; >>>>> + *ptr = p; >>>>> + } else >>>>> + *ptr = NULL; >>>>> + return len; >>>>> +} >>>>> #endif /* __KERNEL__ */ >>>>> >>>>> #endif /* _SUNRPC_XDR_H_ */ >>>>> -- >>>>> 2.9.3 >>>>> >>>>> -- >>>>> To unsubscribe from this list: send the line "unsubscribe >>>>> linux- >>>>> nfs" in >>>>> the body of a message to majordomo@vger.kernel.org >>>>> More majordomo info at http://vger.kernel.org/majordomo-info.h >>>>> tml >>>> >>>> -- >>>> Chuck Lever >>>> >>>> >>>> >>> >>> -- >>> Trond Myklebust >>> Linux NFS client maintainer, PrimaryData >>> trond.myklebust@primarydata.com >>> N���r�y���b�X�ǧv�^�){.n�+�{�"��^n�r��z�\x1a��h���&�\x1e�G��h�\x03(�階�ݢj"�\x1a� >>> ^[m����z�ޖ��f�h�~�m >> >> -- >> Chuck Lever >> >> >> > -- > Trond Myklebust > Linux NFS client maintainer, PrimaryData > trond.myklebust@primarydata.com -- Chuck Lever ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode 2017-02-19 20:06 ` Chuck Lever @ 2017-02-19 20:33 ` Trond Myklebust 0 siblings, 0 replies; 11+ messages in thread From: Trond Myklebust @ 2017-02-19 20:33 UTC (permalink / raw) To: chuck.lever@oracle.com Cc: anna.schumaker@netapp.com, linux-nfs@vger.kernel.org T24gU3VuLCAyMDE3LTAyLTE5IGF0IDE1OjA2IC0wNTAwLCBDaHVjayBMZXZlciB3cm90ZToNCj4g PiBPbiBGZWIgMTksIDIwMTcsIGF0IDI6MjggUE0sIFRyb25kIE15a2xlYnVzdCA8dHJvbmRteUBw cmltYXJ5ZGF0YS5jDQo+ID4gb20+IHdyb3RlOg0KPiA+IA0KPiA+IFRoYW5rcyBmb3IgdGhlIGRp c2N1c3Npb24sIEJUVy4gSSBhcHByZWNpYXRlIHRoZSBmZWVkYmFjay4NCj4gDQo+IE5vIHByb2Js ZW0hIEZlZWwgZnJlZSB0byBhZGQNCj4gDQo+IFJldmlld2VkLWJ5OiBDaHVjayBMZXZlciA8Y2h1 Y2subGV2ZXJAb3JhY2xlLmNvbT4NCg0KV2lsbCBkby4NCg0KPiANCj4gDQo+ID4gT24gU3VuLCAy MDE3LTAyLTE5IGF0IDE0OjA3IC0wNTAwLCBDaHVjayBMZXZlciB3cm90ZToNCj4gPiA+ID4gT24g RmViIDE5LCAyMDE3LCBhdCAxMjozNiBBTSwgVHJvbmQgTXlrbGVidXN0IDx0cm9uZG15QHByaW1h cnlkDQo+ID4gPiA+IGF0YS4NCj4gPiA+ID4gY29tPiB3cm90ZToNCj4gPiA+ID4gDQo+ID4gPiA+ IE9uIFNhdCwgMjAxNy0wMi0xOCBhdCAxNzoyMSAtMDUwMCwgQ2h1Y2sgTGV2ZXIgd3JvdGU6DQo+ ID4gPiA+ID4gPiBPbiBGZWIgMTgsIDIwMTcsIGF0IDI6MTIgUE0sIFRyb25kIE15a2xlYnVzdCA8 dHJvbmQubXlrbGVidQ0KPiA+ID4gPiA+ID4gc3RAcA0KPiA+ID4gPiA+ID4gcmltYQ0KPiA+ID4g PiA+ID4gcnlkYXRhLmNvbT4gd3JvdGU6DQo+ID4gPiA+ID4gPiANCj4gPiA+ID4gPiA+IEFkZCBz b21lIGdlbmVyaWMgaGVscGVycyBmb3IgZW5jb2RpbmcvZGVjb2Rpbmcgb3BhcXVlDQo+ID4gPiA+ ID4gPiBzdHJ1Y3R1cmVzDQo+ID4gPiA+ID4gPiBhbmQNCj4gPiA+ID4gPiA+IGJhc2ljIHUzMi91 NjQuDQo+ID4gPiA+ID4gDQo+ID4gPiA+ID4gSSBoYXZlIHNvbWUgcmFuZG9tLXRob3VnaHRzLXNs YXNoLXdhY2t5LWlkZWFzLg0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+IEknbSBnb2luZyB0byBwYWlu dCB0aGUgZ2FyZGVuIHNoZWQgYSBsaXR0bGUgc2luY2UNCj4gPiA+ID4gPiB0aGVzZSBoZWxwZXJz IGFwcGVhciB0byBiZSBicm9hZGx5IGFwcGxpY2FibGUuDQo+ID4gPiA+ID4gR2VuZXJhbGx5IHNw ZWFraW5nIEkgbGlrZSB0aGUgaWRlYSBvZiBidWlsZGluZw0KPiA+ID4gPiA+ICJzdHJlYW0iIHZl cnNpb25zIG9mIHRoZSB0cmFkaXRpb25hbCBiYXNpYyB0eXBlDQo+ID4gPiA+ID4gZW5jb2RlcnMg YW5kIGRlY29kZXJzLg0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+ID4gU2lnbmVk LW9mZi1ieTogVHJvbmQgTXlrbGVidXN0IDx0cm9uZC5teWtsZWJ1c3RAcHJpbWFyeWRhdGENCj4g PiA+ID4gPiA+IC5jb20NCj4gPiA+ID4gPiA+ID4gDQo+ID4gPiA+ID4gPiANCj4gPiA+ID4gPiA+ IC0tLQ0KPiA+ID4gPiA+ID4gaW5jbHVkZS9saW51eC9zdW5ycGMveGRyLmggfCAxNzMNCj4gPiA+ ID4gPiA+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiA+ ID4gPiA+ID4gMSBmaWxlIGNoYW5nZWQsIDE3MyBpbnNlcnRpb25zKCspDQo+ID4gPiA+ID4gPiAN Cj4gPiA+ID4gPiA+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L3N1bnJwYy94ZHIuaA0KPiA+ ID4gPiA+ID4gYi9pbmNsdWRlL2xpbnV4L3N1bnJwYy94ZHIuaA0KPiA+ID4gPiA+ID4gaW5kZXgg NTZjNDhjODg0YTI0Li4zN2JmMWJlMjBiNjIgMTAwNjQ0DQo+ID4gPiA+ID4gPiAtLS0gYS9pbmNs dWRlL2xpbnV4L3N1bnJwYy94ZHIuaA0KPiA+ID4gPiA+ID4gKysrIGIvaW5jbHVkZS9saW51eC9z dW5ycGMveGRyLmgNCj4gPiA+ID4gPiA+IEBAIC0yNDIsNiArMjQyLDE3OSBAQCBleHRlcm4gdW5z aWduZWQgaW50DQo+ID4gPiA+ID4gPiB4ZHJfcmVhZF9wYWdlcyhzdHJ1Y3QNCj4gPiA+ID4gPiA+ IHhkcl9zdHJlYW0gKnhkciwgdW5zaWduZWQgaW50IGxlbik7DQo+ID4gPiA+ID4gPiBleHRlcm4g dm9pZCB4ZHJfZW50ZXJfcGFnZShzdHJ1Y3QgeGRyX3N0cmVhbSAqeGRyLCB1bnNpZ25lZA0KPiA+ ID4gPiA+ID4gaW50DQo+ID4gPiA+ID4gPiBsZW4pOw0KPiA+ID4gPiA+ID4gZXh0ZXJuIGludCB4 ZHJfcHJvY2Vzc19idWYoc3RydWN0IHhkcl9idWYgKmJ1ZiwgdW5zaWduZWQNCj4gPiA+ID4gPiA+ IGludA0KPiA+ID4gPiA+ID4gb2Zmc2V0LCB1bnNpZ25lZCBpbnQgbGVuLCBpbnQgKCphY3Rvciko c3RydWN0IHNjYXR0ZXJsaXN0DQo+ID4gPiA+ID4gPiAqLA0KPiA+ID4gPiA+ID4gdm9pZA0KPiA+ ID4gPiA+ID4gKiksIHZvaWQgKmRhdGEpOw0KPiA+ID4gPiA+ID4gDQo+ID4gPiA+ID4gPiArLyoq DQo+ID4gPiA+ID4gPiArICogeGRyX2FsaWduX3NpemUgLSBDYWxjdWxhdGUgcGFkZGVkIHNpemUg b2YgYW4gb2JqZWN0DQo+ID4gPiA+ID4gPiArICogQG46IFNpemUgb2YgYW4gb2JqZWN0IGJlaW5n IFhEUiBlbmNvZGVkIChpbiBieXRlcykNCj4gPiA+ID4gPiA+ICsgKg0KPiA+ID4gPiA+ID4gKyAq IFJldHVybiB2YWx1ZToNCj4gPiA+ID4gPiA+ICsgKsKgwqDCoFNpemUgKGluIGJ5dGVzKSBvZiB0 aGUgb2JqZWN0IGluY2x1ZGluZyB4ZHIgcGFkZGluZw0KPiA+ID4gPiA+ID4gKyAqLw0KPiA+ID4g PiA+ID4gK3N0YXRpYyBpbmxpbmUgc2l6ZV90DQo+ID4gPiA+ID4gPiAreGRyX2FsaWduX3NpemUo c2l6ZV90IG4pDQo+ID4gPiA+ID4gPiArew0KPiA+ID4gPiA+ID4gKwljb25zdCBzaXplX3QgbWFz ayA9IHNpemVvZihfX3UzMikgLSAxOw0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+IEkga25vdyB0aGlz IGRvZXNuJ3QgbWFrZSBhIGZ1bmN0aW9uYWwgZGlmZmVyZW5jZSwgYnV0DQo+ID4gPiA+ID4gSSdt IHdvbmRlcmluZyBpZiB0aGlzIHNob3VsZCBiZSBzaXplb2YoX19iZTMyKSwgc2luY2UNCj4gPiA+ ID4gPiBpdCBpcyBhY3R1YWxseSB0aGUgc2l6ZSBvZiBhIHdpcmUgb2JqZWN0PyBTZWVtcyBsaWtl DQo+ID4gPiA+ID4gdGhhdCBpcyBhIGNvbW1vbiBxdWVzdGlvbiB3aGVyZXZlciBzaXplb2YgaXMg dXNlZA0KPiA+ID4gPiA+IGJlbG93Lg0KPiA+ID4gPiANCj4gPiA+ID4gVGhlIF9fYmUzMiBpcyBy ZXF1aXJlZCB0byBiZSB0aGUgc2FtZSBzaXplIGFzIHUzMi4gVGhlIG9ubHkNCj4gPiA+ID4gYWxs b3dlZA0KPiA+ID4gPiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBpcyBiZSB0aGUgZW5kaWFu bmVzcy4NCj4gPiA+IA0KPiA+ID4gUmlnaHQsIHNpemVvZihfX3UzMikgPT0gc2l6ZW9mKF9fYmUz MikuwqDCoF9fYmUgaGFzIGFsd2F5cw0KPiA+ID4gYmVlbiBhYm91dCBlbmRpYW4gYW5ub3RhdGlv bjsgbm8gcmVhbCBmdW5jdGlvbmFsIGRpZmZlcmVuY2UNCj4gPiA+IHdpdGggX191Lg0KPiA+ID4g DQo+ID4gPiBUaGUgaXNzdWUgZm9yIG1lIGlzIHByZWNpc2lvbiBvZiBkb2N1bWVudGF0aW9uIChv ciwgaW4gc29tZQ0KPiA+ID4gc2Vuc2UsIGNvZGUgcmVhZGFiaWxpdHkpLiBJbiBhbGwgb2YgdGhl c2UgY2FzZXMsIGl0J3Mgbm90DQo+ID4gPiB0aGUgc2l6ZSBvZiB0aGUgbG9jYWwgdmFyaWFibGUg dGhhdCBpcyBpbXBvcnRhbnQsIGl0J3MgdGhlDQo+ID4gPiBzaXplIG9mIHRoZSAoWERSIGVuY29k ZWQpIHdpcmUgb2JqZWN0LiBUaGF0J3Mgc2l6ZW9mKF9fYmUzMikuDQo+ID4gPiANCj4gPiA+IFRo b3NlIGp1c3QgaGFwcGVuIHRvIGJlIHRoZSBzYW1lIGhlcmUuIEl0J3MgcHJldHR5IGVhc3kgdG8N Cj4gPiA+IG1pc3Rha2UgdGhlIHNpemUgb2YgYSBsb2NhbCBvYmplY3QgYXMgYmVpbmcgYWx3YXlz IHRoZSBzYW1lDQo+ID4gPiBhcyB0aGUgc2l6ZSBvZiB0aGUgZW5jb2RlZCBkYXRhIHR5cGUuIEkn dmUgZG9uZSB0aGF0IG15c2VsZg0KPiA+ID4gb2Z0ZW4gZW5vdWdoIHRoYXQgaXQgbWFrZXMgc2Vu c2UgdG8gYmUgY29uc2lzdGVudCBhbmQNCj4gPiA+IGNhcmVmdWwsIGV2ZW4gaW4gdGhlIHNpbXBs ZSBjYXNlcy4NCj4gPiA+IA0KPiA+ID4gSSdtIG5vdCBnb2luZyB0byBtYWtlIGEgYmlnIGRlYWws IGJ1dCBJJ2QgbGlrZSB0byBwb2ludCBvdXQNCj4gPiA+IHRoYXQgc3VidGxlIGRpZmZlcmVuY2Uu IElNTyBpdCB3b3VsZCBtYWtlIG1vcmUgc2Vuc2UgdG8NCj4gPiA+IGh1bWFuIHJlYWRlcnMgaWYg dGhlc2Ugd2VyZSBfX2JlIGFuZCBub3QgX191Lg0KPiA+IA0KPiA+IEZhaXIgZW5vdWdoLiBJIGNh biB1cGRhdGUgdGhhdC4NCj4gPiANCj4gPiA+IA0KPiA+ID4gPiA+IElzIHRoaXMgYSBjb25zdGFu dCB2YXJpYWJsZSByYXRoZXIgdGhhbiBhbiBlbnVtIGJlY2F1c2UNCj4gPiA+ID4gPiB5b3Ugd2Fu dCBpdCB0byByZXRhaW4gdGhlIHR5cGUgb2Ygc2l6ZV90IChtYXRjaGluZyB0aGUNCj4gPiA+ID4g PiB0eXBlIG9mIHRoZSB4ZHJfaW5saW5lX3tlbixkZX1jb2RlKCkgZnVuY3Rpb25zKSA/DQo+ID4g PiA+IA0KPiA+ID4gPiBJdCdzIHJlYWxseSBqdXN0IGZvciBlZmZpY2llbmN5LCBpbiBvcmRlciB0 byBwcm9kIGdjYyBpbnRvDQo+ID4gPiA+IG9wdGltaXNpbmcNCj4gPiA+ID4gaXQgYXMgaXQgd291 bGQgYW55IG90aGVyIGNvbnN0YW50Lg0KPiA+ID4gPiANCj4gPiA+ID4gPiBTaW5jZSB3ZSBzZWUg c2l6ZW9mKHlhZGEpIHJlcGVhdGVkIGVsc2V3aGVyZSwgZGlkIHlvdQ0KPiA+ID4gPiA+IGNvbnNp ZGVyIGRlZmluaW5nIHNpemUgY29uc3RhbnRzIGluIGEgc2NvcGUgd2hlcmUgdGhleQ0KPiA+ID4g PiA+IGNhbiBiZSBzaGFyZWQgYW1vbmdzdCBhbGwgb2YgdGhlIFhEUiBmdW5jdGlvbnM/DQo+ID4g PiA+ID4gDQo+ID4gPiA+ID4gRm9yIGV4YW1wbGUsIHhkcl9yZXNlcnZlX3NwYWNlIGl0c2VsZiBj b3VsZCBpbW1lZGlhdGVseQ0KPiA+ID4gPiA+IG1ha2UgdXNlIG9mIGEgInNpemVvZihfX2JlMzIp IC0gMSIgY29uc3RhbnQuDQo+ID4gPiA+IA0KPiA+ID4gPiBUaGF0IGNvdWxkIGJlIGRvbmUuIEkg aGF2ZW4ndCByZWFsbHkgY29uc2lkZXJlZCBpdC4NCj4gPiA+ID4gDQo+ID4gPiA+ID4gSXMgeW91 ciBpbnRlbnRpb24gdG8gcmVwbGFjZSBYRFJfUVVBRExFTiB3aXRoIHRoaXMNCj4gPiA+ID4gPiBm dW5jdGlvbiBldmVudHVhbGx5Pw0KPiA+ID4gPiANCj4gPiA+ID4gRXZlbnR1YWxseSwgSSdkIGxp a2UgdXMgdG8gZ2V0IHJpZCBvZiBtb3N0IG9mIHRoZSBvcGVuIGNvZGVkDQo+ID4gPiA+IGluc3Rh bmNlcw0KPiA+ID4gPiBvZiAncG9pbnRlciB0byBfX2JlMzInIGluIHRoZSBORlMgY29kZSwgYW5k IGhpZGUgYWxsIGtub3dsZWRnZQ0KPiA+ID4gPiBvZg0KPiA+ID4gPiB0aGF0DQo+ID4gPiA+IGlu IHN0cnVjdCB4ZHJfc3RyZWFtIGFuZCB0aGVzZSBTVU5SUEMgbGF5ZXJlZCBoZWxwZXJzLg0KPiA+ ID4gDQo+ID4gPiBTb3VuZHMgZ29vZCB0byBtZS4NCj4gPiA+IA0KPiA+ID4gDQo+ID4gPiA+ID4g PiArDQo+ID4gPiA+ID4gPiArCXJldHVybiAobiArIG1hc2spICYgfm1hc2s7DQo+ID4gPiA+ID4g PiArfQ0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gKy8qKg0KPiA+ID4gPiA+ID4gKyAqIHhk cl9zdHJlYW1fZW5jb2RlX3UzMiAtIEVuY29kZSBhIDMyLWJpdCBpbnRlZ2VyDQo+ID4gPiA+ID4g PiArICogQHhkcjogcG9pbnRlciB0byB4ZHJfc3RyZWFtDQo+ID4gPiA+ID4gPiArICogQG46IGlu dGVnZXIgdG8gZW5jb2RlDQo+ID4gPiA+ID4gPiArICoNCj4gPiA+ID4gPiA+ICsgKiBSZXR1cm4g dmFsdWVzOg0KPiA+ID4gPiA+ID4gKyAqwqDCoMKgT24gc3VjY2VzcywgcmV0dXJucyBsZW5ndGgg aW4gYnl0ZXMgb2YgWERSIGJ1ZmZlcg0KPiA+ID4gPiA+ID4gY29uc3VtZWQNCj4gPiA+ID4gPiA+ ICsgKsKgwqDCoCUtRU5PQlVGUyBvbiBYRFIgYnVmZmVyIG92ZXJmbG93DQo+ID4gPiA+ID4gDQo+ ID4gPiA+ID4gSSd2ZSBuZXZlciBiZWVuIGNyYXp5IGFib3V0IHRoZXNlIGFtcGxpZmllZCByZXR1 cm4NCj4gPiA+ID4gPiB0eXBlcywgdGhvdWdoIEkga25vdyBpdCdzIHR5cGljYWwga2VybmVsIGNv ZGluZyBzdHlsZS4NCj4gPiA+ID4gPiBIZXJlLCB0aG91Z2gsIEkgd29uZGVyIGlmIHRoZXkgYXJl IHJlYWxseSBuZWNlc3NhcnkuDQo+ID4gPiA+ID4gDQo+ID4gPiA+ID4gVGhlIHJldHVybmVkIGxl bmd0aCBzZWVtcyB0byBiZSBpbnRlcmVzdGluZyBvbmx5IGZvcg0KPiA+ID4gPiA+IGRlY29kaW5n IHZhcmlhYmxlLWxlbmd0aCBvYmplY3RzIChmYXJ0aGVyIGJlbG93KS4gTWF5YmUNCj4gPiA+ID4g PiB0aG9zZSBhcmUgdGhlIG9ubHkgZnVuY3Rpb25zIHRoYXQgbmVlZCB0byBwcm92aWRlIGENCj4g PiA+ID4gPiBwb3NpdGl2ZSByZXR1cm4gdmFsdWU/DQo+ID4gPiA+IA0KPiA+ID4gPiBORlN2NCBp bnRyb2R1Y2VzIHRoZSAoSU1PIG5hc3R5KSBoYWJpdCBvZiBuZXN0aW5nIFhEUi1lbmNvZGVkDQo+ ID4gPiA+IG9iamVjdHMNCj4gPiA+ID4gaW5zaWRlIGEgdmFyaWFibGUgbGVuZ3RoIG9wYXF1ZSBv YmplY3QgKHNheSBoZWxsbyB0byB0eXBlDQo+ID4gPiA+ICJhdHRybGlzdDQiKS4NCj4gPiA+IA0K PiA+ID4gQW5kIHBORlMgbGF5b3V0cy4gRmFpciBlbm91Z2guDQo+ID4gPiANCj4gPiA+IA0KPiA+ ID4gPiBJbiB0aGF0IGNhc2UsIHdlIG5lZWQgdG8ga2VlcCBhIHJ1bm5pbmcgdGFsbHkgb2YgdGhl IGxlbmd0aCBvZg0KPiA+ID4gPiB0aGUNCj4gPiA+ID4gb2JqZWN0cyB3ZSBoYXZlIFhEUiBlbmNv ZGVkIHNvIHRoYXQgd2UgY2FuIHJldHJvYWN0aXZlbHkgc2V0DQo+ID4gPiA+IHRoZQ0KPiA+ID4g PiBsZW5ndGgNCj4gPiA+ID4gb2YgdGhlIG9wYXF1ZSBvYmplY3QuIEN1cnJlbnRseSB3ZSB1c2Ug dGhlIHhkcl9zdHJlYW1fcG9zKCkgdG8NCj4gPiA+ID4gZGV0ZXJtaW5lIHRoYXQgbGVuZ3RoLCBi dXQgaXQgbWlnaHQgYmUgbmljZSB0byByZXBsYWNlIHRoYXQNCj4gPiA+ID4gd2l0aA0KPiA+ID4g PiBzb21ldGhpbmcgYSBsaXR0bGUgbW9yZSBkaXJlY3QuDQo+ID4gPiANCj4gPiA+IFRoZSBuZXcg aGVscGVycyBhcHBlYXIgdG8gYmUgYWJzdHJhY3RpbmcgYXdheSBmcm9tIGENCj4gPiA+IGRpcmVj dCBhcHByb2FjaC4gSU1ITyBzdGF5aW5nIHdpdGggc29tZXRoaW5nIHRoYXQgbG9va3MNCj4gPiA+ IGxpa2UgYSBmdW5jdGlvbiBjYWxsIChsaWtlIHhkcl9zdHJlYW1fcG9zKSBzZWVtcyBsaWtlDQo+ ID4gPiBpdCBpcyBjbGVhbiBhbmQgY29uc2lzdGVudCB3aXRoIHRoZXNlIG5ldyBoZWxwZXJzLg0K PiA+ID4gDQo+ID4gPiANCj4gPiA+ID4gTm90ZSBhbHNvIHRoYXQgdGhlIGxlbmd0aHMgcmV0dXJu ZWQgaGVyZSBhcmUgbm90IHRoZSBvYmplY3QNCj4gPiA+ID4gc2l6ZXMNCj4gPiA+ID4gdGhlbXNl bHZlcywgYnV0IHRoZSBhbW91bnQgb2YgYnVmZmVyIHNwYWNlIGNvbnN1bWVkIChpLmUuIHRoZQ0K PiA+ID4gPiBhbGlnbmVkDQo+ID4gPiA+IHNpemUpLg0KPiA+ID4gDQo+ID4gPiBNYWtlcyBzZW5z ZS4gU3RpbGwsIHNlZW1zIGxpa2UgdGhlIGNhbGxlcnMgYWxyZWFkeSBrbm93DQo+ID4gPiB0aGVz ZSAic3BhY2UgY29uc3VtZWQiIHZhbHVlcyBpbiBldmVyeSBjYXNlLiBNYXliZSB0aGF0DQo+ID4g PiB3b24ndCBiZSB0cnVlIHdoZW4gdGhlc2UgaGVscGVycyBhcmUgZ2x1ZWQgdG9nZXRoZXIgdG8N Cj4gPiA+IGhhbmRsZSBtb3JlIGFic3RyYWN0IGRhdGEgdHlwZXMuDQo+ID4gPiANCj4gPiA+ID4g PiBQZXJoYXBzIHRoZSBXQVJOX09OX09OQ0UgY2FsbHMgYWRkZWQgaW4gbGF0ZXIgcGF0Y2hlcw0K PiA+ID4gPiA+IHNob3VsZCBiZSBpbiB0aGVzZSBoZWxwZXJzIGluc3RlYWQgb2YgaW4gdGhlaXIg Y2FsbGVycy4NCj4gPiA+ID4gPiBUaGVuIHRoZSBlbmNvZGVyIGhlbHBlcnMgY2FuIHJldHVybiB2 b2lkLg0KPiA+ID4gPiANCj4gPiA+ID4gQXQgc29tZSBwb2ludCwgSSdkIGxpa2UgdG8gcmVpbnN0 YXRlIHRoZSBwcmFjdGljZSBvZiByZXR1cm5pbmcNCj4gPiA+ID4gYW4NCj4gPiA+ID4gZXJyb3IN Cj4gPiA+ID4gd2hlbiBlbmNvZGluZyBmYWlscy4gSXQgbWF5IGJlIGJldHRlciB0byBhYm9ydCBz ZW5kaW5nIGENCj4gPiA+ID4gdHJ1bmNhdGVkDQo+ID4gPiA+IFJQQw0KPiA+ID4gPiBjYWxsIHJh dGhlciB0aGFuIGhhdmluZyBpdCBleGVjdXRlIHBhcnRpYWxseTsgc3BlY2lhbGx5IG5vdw0KPiA+ ID4gPiB0aGF0DQo+ID4gPiA+IHdlJ3JlDQo+ID4gPiA+IGZpbmFsbHkgc3RhcnRpbmcgdG8gdXNl IENPTVBPVU5EIHRvIGNyZWF0ZSBtb3JlIGNvbXBsZXgNCj4gPiA+ID4gb3BlcmF0aW9ucy4NCj4g PiA+IA0KPiA+ID4gSSBhZ3JlZSwgSU1PIHRoYXQgd291bGQgYmUgYSBiZXR0ZXIgYXBwcm9hY2gu DQo+ID4gPiANCj4gPiA+IA0KPiA+ID4gPiA+ID4gKyAqLw0KPiA+ID4gPiA+ID4gK3N0YXRpYyBp bmxpbmUgc3NpemVfdA0KPiA+ID4gPiA+ID4gK3hkcl9zdHJlYW1fZW5jb2RlX3UzMihzdHJ1Y3Qg eGRyX3N0cmVhbSAqeGRyLCBfX3UzMiBuKQ0KPiA+ID4gPiA+ID4gK3sNCj4gPiA+ID4gPiA+ICsJ Y29uc3Qgc2l6ZV90IGxlbiA9IHNpemVvZihuKTsNCj4gPiA+ID4gPiA+ICsJX19iZTMyICpwID0g eGRyX3Jlc2VydmVfc3BhY2UoeGRyLCBsZW4pOw0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4g KwlpZiAodW5saWtlbHkoIXApKQ0KPiA+ID4gPiA+ID4gKwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ ID4gPiA+ID4gKwkqcCA9IGNwdV90b19iZTMyKG4pOw0KPiA+ID4gPiA+ID4gKwlyZXR1cm4gbGVu Ow0KPiA+ID4gPiA+ID4gK30NCj4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ICsvKioNCj4gPiA+ ID4gPiA+ICsgKiB4ZHJfc3RyZWFtX2VuY29kZV91NjQgLSBFbmNvZGUgYSA2NC1iaXQgaW50ZWdl cg0KPiA+ID4gPiA+ID4gKyAqIEB4ZHI6IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ID4gPiA+ ID4gKyAqIEBuOiA2NC1iaXQgaW50ZWdlciB0byBlbmNvZGUNCj4gPiA+ID4gPiA+ICsgKg0KPiA+ ID4gPiA+ID4gKyAqIFJldHVybiB2YWx1ZXM6DQo+ID4gPiA+ID4gPiArICrCoMKgwqBPbiBzdWNj ZXNzLCByZXR1cm5zIGxlbmd0aCBpbiBieXRlcyBvZiBYRFIgYnVmZmVyDQo+ID4gPiA+ID4gPiBj b25zdW1lZA0KPiA+ID4gPiA+ID4gKyAqwqDCoMKgJS1FTk9CVUZTIG9uIFhEUiBidWZmZXIgb3Zl cmZsb3cNCj4gPiA+ID4gPiA+ICsgKi8NCj4gPiA+ID4gPiA+ICtzdGF0aWMgaW5saW5lIHNzaXpl X3QNCj4gPiA+ID4gPiA+ICt4ZHJfc3RyZWFtX2VuY29kZV91NjQoc3RydWN0IHhkcl9zdHJlYW0g KnhkciwgX191NjQgbikNCj4gPiA+ID4gPiA+ICt7DQo+ID4gPiA+ID4gPiArCWNvbnN0IHNpemVf dCBsZW4gPSBzaXplb2Yobik7DQo+ID4gPiA+ID4gPiArCV9fYmUzMiAqcCA9IHhkcl9yZXNlcnZl X3NwYWNlKHhkciwgbGVuKTsNCj4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ICsJaWYgKHVubGlr ZWx5KCFwKSkNCj4gPiA+ID4gPiA+ICsJCXJldHVybiAtRU5PQlVGUzsNCj4gPiA+ID4gPiA+ICsJ eGRyX2VuY29kZV9oeXBlcihwLCBuKTsNCj4gPiA+ID4gPiA+ICsJcmV0dXJuIGxlbjsNCj4gPiA+ ID4gPiA+ICt9DQo+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiArLyoqDQo+ID4gPiA+ID4gPiAr ICogeGRyX3N0cmVhbV9lbmNvZGVfb3BhcXVlX2ZpeGVkIC0gRW5jb2RlIGZpeGVkIGxlbmd0aA0K PiA+ID4gPiA+ID4gb3BhcXVlDQo+ID4gPiA+ID4gPiB4ZHINCj4gPiA+ID4gPiA+IGRhdGENCj4g PiA+ID4gPiA+ICsgKiBAeGRyOiBwb2ludGVyIHRvIHhkcl9zdHJlYW0NCj4gPiA+ID4gPiA+ICsg KiBAcHRyOiBwb2ludGVyIHRvIG9wYXF1ZSBkYXRhIG9iamVjdA0KPiA+ID4gPiA+ID4gKyAqIEBs ZW46IHNpemUgb2Ygb2JqZWN0IHBvaW50ZWQgdG8gYnkgQHB0cg0KPiA+ID4gPiA+ID4gKyAqDQo+ ID4gPiA+ID4gPiArICogUmV0dXJuIHZhbHVlczoNCj4gPiA+ID4gPiA+ICsgKsKgwqDCoE9uIHN1 Y2Nlc3MsIHJldHVybnMgbGVuZ3RoIGluIGJ5dGVzIG9mIFhEUiBidWZmZXINCj4gPiA+ID4gPiA+ IGNvbnN1bWVkDQo+ID4gPiA+ID4gPiArICrCoMKgwqAlLUVOT0JVRlMgb24gWERSIGJ1ZmZlciBv dmVyZmxvdw0KPiA+ID4gPiA+ID4gKyAqLw0KPiA+ID4gPiA+ID4gK3N0YXRpYyBpbmxpbmUgc3Np emVfdA0KPiA+ID4gPiA+ID4gK3hkcl9zdHJlYW1fZW5jb2RlX29wYXF1ZV9maXhlZChzdHJ1Y3Qg eGRyX3N0cmVhbSAqeGRyLA0KPiA+ID4gPiA+ID4gY29uc3QNCj4gPiA+ID4gPiA+IHZvaWQNCj4g PiA+ID4gPiA+ICpwdHIsIHNpemVfdCBsZW4pDQo+ID4gPiA+ID4gPiArew0KPiA+ID4gPiA+ID4g KwlfX2JlMzIgKnAgPSB4ZHJfcmVzZXJ2ZV9zcGFjZSh4ZHIsIGxlbik7DQo+ID4gPiA+ID4gPiAr DQo+ID4gPiA+ID4gPiArCWlmICh1bmxpa2VseSghcCkpDQo+ID4gPiA+ID4gPiArCQlyZXR1cm4g LUVOT0JVRlM7DQo+ID4gPiA+ID4gPiArCXhkcl9lbmNvZGVfb3BhcXVlX2ZpeGVkKHAsIHB0ciwg bGVuKTsNCj4gPiA+ID4gPiA+ICsJcmV0dXJuIHhkcl9hbGlnbl9zaXplKGxlbik7DQo+ID4gPiA+ ID4gDQo+ID4gPiA+ID4gU2VlbXMgbGlrZSB0aGUgY2FsbGVyIGNhbiB1c2UgeGRyX2FsaWduX3Np emUoKSBqdXN0IGFzDQo+ID4gPiA+ID4gZWFzaWx5IGFzIG92ZXJsb2FkaW5nIHRoZSByZXR1cm4g dmFsdWUgaGVyZSwgZm9yIGV4YW1wbGUuDQo+ID4gPiA+ID4gDQo+ID4gPiA+ID4gQnV0IEkgY2Fu J3QgdGhpbmsgb2YgYW55IGZpeGVkLXNpemUgb3BhcXVlIFhEUiBvYmplY3QNCj4gPiA+ID4gPiB0 aGF0IGlzIG5vdCBhbHJlYWR5IHByb3Blcmx5IHJvdW5kZWQgdXAsIG9yIHdoZXJlIHRoZQ0KPiA+ ID4gPiA+IGxlbmd0aCBpcyBub3QgYWxyZWFkeSBrbm93biB0byB0aGUgWERSIGxheWVyIChhcyBh DQo+ID4gPiA+ID4gZGVmaW5lZCBtYWNybyBjb25zdGFudCkuDQo+ID4gPiA+ID4gDQo+ID4gPiA+ ID4gDQo+ID4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gKy8qKg0KPiA+ ID4gPiA+ID4gKyAqIHhkcl9zdHJlYW1fZW5jb2RlX29wYXF1ZSAtIEVuY29kZSB2YXJpYWJsZSBs ZW5ndGgNCj4gPiA+ID4gPiA+IG9wYXF1ZQ0KPiA+ID4gPiA+ID4geGRyDQo+ID4gPiA+ID4gPiBk YXRhDQo+ID4gPiA+ID4gPiArICogQHhkcjogcG9pbnRlciB0byB4ZHJfc3RyZWFtDQo+ID4gPiA+ ID4gPiArICogQHB0cjogcG9pbnRlciB0byBvcGFxdWUgZGF0YSBvYmplY3QNCj4gPiA+ID4gPiA+ ICsgKiBAbGVuOiBzaXplIG9mIG9iamVjdCBwb2ludGVkIHRvIGJ5IEBwdHINCj4gPiA+ID4gPiA+ ICsgKg0KPiA+ID4gPiA+ID4gKyAqIFJldHVybiB2YWx1ZXM6DQo+ID4gPiA+ID4gPiArICrCoMKg wqBPbiBzdWNjZXNzLCByZXR1cm5zIGxlbmd0aCBpbiBieXRlcyBvZiBYRFIgYnVmZmVyDQo+ID4g PiA+ID4gPiBjb25zdW1lZA0KPiA+ID4gPiA+ID4gKyAqwqDCoMKgJS1FTk9CVUZTIG9uIFhEUiBi dWZmZXIgb3ZlcmZsb3cNCj4gPiA+ID4gPiA+ICsgKi8NCj4gPiA+ID4gPiA+ICtzdGF0aWMgaW5s aW5lIHNzaXplX3QNCj4gPiA+ID4gPiA+ICt4ZHJfc3RyZWFtX2VuY29kZV9vcGFxdWUoc3RydWN0 IHhkcl9zdHJlYW0gKnhkciwgY29uc3QNCj4gPiA+ID4gPiA+IHZvaWQNCj4gPiA+ID4gPiA+ICpw dHIsDQo+ID4gPiA+ID4gPiBzaXplX3QgbGVuKQ0KPiA+ID4gPiA+ID4gK3sNCj4gPiA+ID4gPiA+ ICsJc2l6ZV90IGNvdW50ID0gc2l6ZW9mKF9fdTMyKSArDQo+ID4gPiA+ID4gPiB4ZHJfYWxpZ25f c2l6ZShsZW4pOw0KPiA+ID4gPiA+ID4gKwlfX2JlMzIgKnAgPSB4ZHJfcmVzZXJ2ZV9zcGFjZSh4 ZHIsIGNvdW50KTsNCj4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ICsJaWYgKHVubGlrZWx5KCFw KSkNCj4gPiA+ID4gPiA+ICsJCXJldHVybiAtRU5PQlVGUzsNCj4gPiA+ID4gPiA+ICsJeGRyX2Vu Y29kZV9vcGFxdWUocCwgcHRyLCBsZW4pOw0KPiA+ID4gPiA+ID4gKwlyZXR1cm4gY291bnQ7DQo+ ID4gPiA+ID4gDQo+ID4gPiA+ID4gVGhlc2UgaGVscGVycyBhbHJlYWR5IHVwZGF0ZSB0aGUgc3Rh dGUgb2YgdGhlIHBhc3NlZA0KPiA+ID4gPiA+IGluIHhkcl9zdHJlYW0sIHNvIGEgY2FsbGVyIHR5 cGljYWxseSB3b3VsZCBub3QgbmVlZA0KPiA+ID4gPiA+IHRvIGNhcmUgbXVjaCBhYm91dCB0aGUg Ynl0ZXMgY29uc3VtZWQgYnkgdGhlIGVuY29kZWQNCj4gPiA+ID4gPiBvcGFxdWUuDQo+ID4gPiA+ ID4gDQo+ID4gPiA+ID4gDQo+ID4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ ID4gKy8qKg0KPiA+ID4gPiA+ID4gKyAqIHhkcl9zdHJlYW1fZGVjb2RlX3UzMiAtIERlY29kZSBh IDMyLWJpdCBpbnRlZ2VyDQo+ID4gPiA+ID4gPiArICogQHhkcjogcG9pbnRlciB0byB4ZHJfc3Ry ZWFtDQo+ID4gPiA+ID4gPiArICogQHB0cjogbG9jYXRpb24gdG8gc3RvcmUgaW50ZWdlcg0KPiA+ ID4gPiA+ID4gKyAqDQo+ID4gPiA+ID4gPiArICogUmV0dXJuIHZhbHVlczoNCj4gPiA+ID4gPiA+ ICsgKsKgwqDCoCUwIG9uIHN1Y2Nlc3MNCj4gPiA+ID4gPiA+ICsgKsKgwqDCoCUtRU5PQlVGUyBv biBYRFIgYnVmZmVyIG92ZXJmbG93DQo+ID4gPiA+ID4gPiArICovDQo+ID4gPiA+ID4gPiArc3Rh dGljIGlubGluZSBzc2l6ZV90DQo+ID4gPiA+ID4gPiAreGRyX3N0cmVhbV9kZWNvZGVfdTMyKHN0 cnVjdCB4ZHJfc3RyZWFtICp4ZHIsIF9fdTMyICpwdHIpDQo+ID4gPiA+ID4gPiArew0KPiA+ID4g PiA+ID4gKwljb25zdCBzaXplX3QgY291bnQgPSBzaXplb2YoKnB0cik7DQo+ID4gPiA+ID4gPiAr CV9fYmUzMiAqcCA9IHhkcl9pbmxpbmVfZGVjb2RlKHhkciwgY291bnQpOw0KPiA+ID4gPiA+ID4g Kw0KPiA+ID4gPiA+ID4gKwlpZiAodW5saWtlbHkoIXApKQ0KPiA+ID4gPiA+ID4gKwkJcmV0dXJu IC1FTk9CVUZTOw0KPiA+ID4gPiA+ID4gKwkqcHRyID0gYmUzMl90b19jcHVwKHApOw0KPiA+ID4g PiA+ID4gKwlyZXR1cm4gMDsNCj4gPiA+ID4gPiANCj4gPiA+ID4gPiBObyBsZW5ndGggcmV0dXJu ZWQgaGVyZS4gVGhlIGNhbGxlciBrbm93cyB0aGUgbGVuZ3RoDQo+ID4gPiA+ID4gb2YgdGhpcyBv YmplY3QsIGNsZWFybHksIGFuZCBvbmx5IGNhcmVzIGFib3V0IHdoZXRoZXINCj4gPiA+ID4gPiBk ZWNvZGluZyBoYXMgb3ZlcnJ1biB0aGUgWERSIHN0cmVhbS4NCj4gPiA+ID4gDQo+ID4gPiA+IFll cy4gRWFybGllciB2ZXJzaW9ucyByZXR1cm5lZCA+IDAsIGJ1dCBJIGZpZ3VyZWQgdGhhdCBjb3Vu dGluZw0KPiA+ID4gPiB0aGUNCj4gPiA+ID4gYnVmZmVyIHNwYWNlIGlzIG5vdCBhcyBpbXBvcnRh bnQgd2hlbiBkZWNvZGluZy4gSSBjYW4ndCB0aGluaw0KPiA+ID4gPiBvZg0KPiA+ID4gPiB0b28N Cj4gPiA+ID4gbWFueSB1c2UgY2FzZXMuDQo+ID4gPiA+IA0KPiA+ID4gPiA+ID4gK30NCj4gPiA+ ID4gPiA+ICsNCj4gPiA+ID4gPiA+ICsvKioNCj4gPiA+ID4gPiA+ICsgKiB4ZHJfc3RyZWFtX2Rl Y29kZV9vcGFxdWVfZml4ZWQgLSBEZWNvZGUgZml4ZWQgbGVuZ3RoDQo+ID4gPiA+ID4gPiBvcGFx dWUNCj4gPiA+ID4gPiA+IHhkcg0KPiA+ID4gPiA+ID4gZGF0YQ0KPiA+ID4gPiA+ID4gKyAqIEB4 ZHI6IHBvaW50ZXIgdG8geGRyX3N0cmVhbQ0KPiA+ID4gPiA+ID4gKyAqIEBwdHI6IGxvY2F0aW9u IHRvIHN0b3JlIGRhdGENCj4gPiA+ID4gPiA+ICsgKiBAbGVuOiBzaXplIG9mIGJ1ZmZlciBwb2lu dGVkIHRvIGJ5IEBwdHINCj4gPiA+ID4gPiA+ICsgKg0KPiA+ID4gPiA+ID4gKyAqIFJldHVybiB2 YWx1ZXM6DQo+ID4gPiA+ID4gPiArICrCoMKgwqBPbiBzdWNjZXNzLCByZXR1cm5zIHNpemUgb2Yg b2JqZWN0IHN0b3JlZCBpbiBAcHRyDQo+ID4gPiA+ID4gDQo+ID4gPiA+ID4gWW91J3JlIHJldHVy bmluZyB0aGUgcGFzc2VkLWluIGxlbmd0aC4gVGh1cyB0aGUgY2FsbGVyDQo+ID4gPiA+ID4gYWxy ZWFkeSBrbm93cyB0aGUgc2l6ZSBvZiB0aGUgb2JqZWN0IHN0b3JlZCBhdCBAcHRyLg0KPiA+ID4g PiANCj4gPiA+ID4gQ29uc2lzdGVuY3ksIGFuZCBpdCBhbGxvd3MgaXQgdG8gYmUgZWFzaWx5IHVz ZWQgYXMgYSBoZWxwZXINCj4gPiA+ID4gaW5zaWRlDQo+ID4gPiA+IG90aGVyIGZ1bmN0aW9ucyB0 aGF0IGRvIG5lZWQgdG8gcmV0dXJuIHRoZSBvYmplY3QgbGVuZ3RoLg0KPiA+ID4gDQo+ID4gPiBH b2luZyBmb3IgZWFzZSBvZiBjb21wb3NpbmcgdGhlc2UgZnVuY3Rpb25zLiBPSy4NCj4gPiA+IA0K PiA+ID4gDQo+ID4gPiA+IE5vdGUgdGhhdCB0aGUgZnVuY3Rpb24gaXMgaW5saW5lZCwgc28gdGhl IGNvbXBpbGVyIHNob3VsZA0KPiA+ID4gPiBub3JtYWxseQ0KPiA+ID4gPiBvcHRpbWlzZSBhd2F5 IHJldHVybiB2YWx1ZXMgdGhhdCBhcmUgdW51c2VkIGJ5IHRoZSBjYWxsZXIuDQo+ID4gPiANCj4g PiA+IFRydWUuIEhvd2V2ZXIgZnV0dXJlIGNvZGUgcmVhZGVycyBtaWdodCB3b25kZXIgd2h5IHRo aXMNCj4gPiA+IHZhbHVlIGlzIGJlaW5nIGNvbXB1dGVkIGlmIHRoZSB2YWx1ZSBvciB0aGUgY29t cHV0YXRpb24NCj4gPiA+IGl0c2VsZiBpcyB1bm5lZWRlZCBpbiBtb3N0IGNhc2VzLg0KPiA+ID4g DQo+ID4gPiBTZWVtcyBsaWtlIGEgc2VwYXJhdGUgaGVscGVyIHRoYXQgZGVyaXZlcyB0aGlzIHZh bHVlDQo+ID4gPiB3aGVyZSBhbmQgd2hlbiBpdCBpcyBuZWVkZWQgbWlnaHQgYmUgY2xlYW5lcjsg YnV0IHRoYXQNCj4gPiA+IGlzIGVudGlyZWx5IHN1YmplY3RpdmUuDQo+ID4gPiANCj4gPiA+IA0K PiA+ID4gPiA+ID4gKyAqwqDCoMKgJS1FTk9CVUZTIG9uIFhEUiBidWZmZXIgb3ZlcmZsb3cNCj4g PiA+ID4gPiA+ICsgKi8NCj4gPiA+ID4gPiA+ICtzdGF0aWMgaW5saW5lIHNzaXplX3QNCj4gPiA+ ID4gPiA+ICt4ZHJfc3RyZWFtX2RlY29kZV9vcGFxdWVfZml4ZWQoc3RydWN0IHhkcl9zdHJlYW0g KnhkciwNCj4gPiA+ID4gPiA+IHZvaWQNCj4gPiA+ID4gPiA+ICpwdHIsDQo+ID4gPiA+ID4gPiBz aXplX3QgbGVuKQ0KPiA+ID4gPiA+ID4gK3sNCj4gPiA+ID4gPiA+ICsJX19iZTMyICpwID0geGRy X2lubGluZV9kZWNvZGUoeGRyLCBsZW4pOw0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gKwlp ZiAodW5saWtlbHkoIXApKQ0KPiA+ID4gPiA+ID4gKwkJcmV0dXJuIC1FTk9CVUZTOw0KPiA+ID4g PiA+ID4gKwl4ZHJfZGVjb2RlX29wYXF1ZV9maXhlZChwLCBwdHIsIGxlbik7DQo+ID4gPiA+ID4g PiArCXJldHVybiBsZW47DQo+ID4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ ID4gKy8qKg0KPiA+ID4gPiA+ID4gKyAqIHhkcl9zdHJlYW1fZGVjb2RlX29wYXF1ZV9pbmxpbmUg LSBEZWNvZGUgdmFyaWFibGUNCj4gPiA+ID4gPiA+IGxlbmd0aA0KPiA+ID4gPiA+ID4gb3BhcXVl DQo+ID4gPiA+ID4gPiB4ZHIgZGF0YQ0KPiA+ID4gPiA+ID4gKyAqIEB4ZHI6IHBvaW50ZXIgdG8g eGRyX3N0cmVhbQ0KPiA+ID4gPiA+ID4gKyAqIEBwdHI6IGxvY2F0aW9uIHRvIHN0b3JlIHBvaW50 ZXIgdG8gb3BhcXVlIGRhdGENCj4gPiA+ID4gPiA+ICsgKg0KPiA+ID4gPiA+ID4gKyAqIE5vdGU6 IHRoZSBwb2ludGVyIHN0b3JlZCBpbiBAcHRyIGNhbm5vdCBiZSBhc3N1bWVkDQo+ID4gPiA+ID4g PiB2YWxpZA0KPiA+ID4gPiA+ID4gYWZ0ZXINCj4gPiA+ID4gPiA+IHRoZSBYRFINCj4gPiA+ID4g PiA+ICsgKiBidWZmZXIgaGFzIGJlZW4gZGVzdHJveWVkLCBvciBldmVuIGFmdGVyIGNhbGxpbmcN Cj4gPiA+ID4gPiA+IHhkcl9pbmxpbmVfZGVjb2RlKCkNCj4gPiA+ID4gPiA+ICsgKiBvbiBAeGRy LiBJdCBpcyB0aGVyZWZvcmUgZXhwZWN0ZWQgdGhhdCB0aGUgb2JqZWN0IGl0DQo+ID4gPiA+ID4g PiBwb2ludHMNCj4gPiA+ID4gPiA+IHRvDQo+ID4gPiA+ID4gPiBzaG91bGQNCj4gPiA+ID4gPiA+ ICsgKiBiZSBwcm9jZXNzZWQgaW1tZWRpYXRlbHkuDQo+ID4gPiA+ID4gPiArICoNCj4gPiA+ID4g PiA+ICsgKiBSZXR1cm4gdmFsdWVzOg0KPiA+ID4gPiA+ID4gKyAqwqDCoMKgT24gc3VjY2Vzcywg cmV0dXJucyBzaXplIG9mIG9iamVjdCBzdG9yZWQgaW4gKkBwdHINCj4gPiA+ID4gPiANCj4gPiA+ ID4gPiBUaGlzIHNlZW1zIHRvIGJlIHRoZSBvbmx5IGZ1bmN0aW9uIHdoZXJlIHRoZSBjYWxsZXIN Cj4gPiA+ID4gPiBtaWdodCBub3QgYWxyZWFkeSBrbm93IHRoZSBsZW5ndGggb2YgdGhlIG9iamVj dCwgYnV0DQo+ID4gPiA+ID4gbWlnaHQgYWN0dWFsbHkgY2FyZS4gU2luY2UgdGhlIG9iamVjdCBs ZW5ndGggY2FuIGJlDQo+ID4gPiA+ID4gY29uc2lkZXJlZCBwYXJ0IG9mIHRoZSBvYmplY3QgaXRz ZWxmLCBtYXliZSB0aGF0DQo+ID4gPiA+ID4gbGVuZ3RoIHNob3VsZCBiZSByZXR1cm5lZCB2aWEg YW4gb3V0cHV0IHBhcmFtZXRlcg0KPiA+ID4gPiA+IHJhdGhlciB0aGFuIGFzIHRoZSBmdW5jdGlv bidzIHJldHVybiB2YWx1ZS4NCj4gPiA+ID4gDQo+ID4gPiA+IEkgY29uc2lkZXJlZCBpdCwgYnV0 IHRoYXQgbWVhbnMgeW91IGhhdmUgdG8gY2hvb3NlIGFuIGV4YWN0DQo+ID4gPiA+IHN0b3JhZ2UN Cj4gPiA+ID4gdHlwZSBhbmQgZ2NjIHdpbGwgY29tcGxhaW4gaWYgdGhlIHR5cGUgY2hlY2sgZmFp bHMuDQo+ID4gPiA+IEluIG1vc3QgY2FzZXMsIHdlIGRvbid0IHJlYWxseSBjYXJlIGlmIHRoZSB1 MzIgdmFsdWUgZ2V0cw0KPiA+ID4gPiBzdG9yZWQgaW4NCj4gPiA+ID4gYW4NCj4gPiA+ID4gdW5z aWduZWQgaW50LCBpbnQsIHVuc2lnbmVkIGxvbmcsIGxvbmcsIHNpemVfdCwgc3NpemVfdCBiZWNh dXNlDQo+ID4gPiA+IHdlDQo+ID4gPiA+IGhhdmUNCj4gPiA+ID4gYSBnb29kIGlkZWEgb2Ygd2hh dCB0byBleHBlY3QgZm9yIHRoZSBvYmplY3Qgc2l6ZS4NCj4gPiA+ID4gDQo+ID4gPiA+ID4gPiAr ICrCoMKgwqAlLUVOT0JVRlMgb24gWERSIGJ1ZmZlciBvdmVyZmxvdw0KPiA+ID4gPiA+IA0KPiA+ ID4gPiA+IEVJTlZBTCBpcyBwcm9iYWJseSBiZXR0ZXI6IHRoZSBjYWxsZXIgZGlkbid0IHByb3Zp ZGUNCj4gPiA+ID4gPiB0aGUgY29ycmVjdCBpbnB1dHMuIFRoYXQncyBhIG5pdCwgdGhvdWdoLg0K PiA+ID4gPiANCj4gPiA+ID4gSXQncyBub3QgYSBjYWxsZXIgcHJvYmxlbS4gVGhlIEVOT0JVRlMg ZXJyb3Igb24gZGVjb2RlDQo+ID4gPiA+IGluZGljYXRlcw0KPiA+ID4gPiB0aGF0DQo+ID4gPiA+ IHRoZSBSUEMgbWVzc2FnZSB3ZSdyZSB0cnlpbmcgdG8gZGVjb2RlIHdhcyBwcm9iYWJseSB0cnVu Y2F0ZWQNCj4gPiA+ID4gb3INCj4gPiA+ID4gY29ycnVwdGVkLg0KPiA+ID4gDQo+ID4gPiBBaC4g QWdyZWUgbm93LCBub3QgYSBjYWxsZXIgYnVnLg0KPiA+ID4gDQo+ID4gPiBJIHN0aWxsIHdvbmRl ciBpZiB0aGUgbWVhbmluZyBvZiBFTk9CVUZTIGlzIGEgZ29vZCBlbm91Z2ggbWF0Y2gNCj4gPiA+ IHRvIHRoaXMgdXNlIGNhc2UuIEVJTlZBTCBpcyBhIHBlcm1hbmVudCBlcnJvciwgYnV0IEkgZG9u J3QgdGhpbmsNCj4gPiA+IEVOT0JVRlMgaXMuDQo+ID4gPiANCj4gPiA+IEZyb20gaHR0cHM6Ly93 d3cuZ251Lm9yZy9zb2Z0d2FyZS9saWJjL21hbnVhbC9odG1sX25vZGUvRXJyb3ItQ29kDQo+ID4g PiBlcy5oDQo+ID4gPiB0bWw6DQo+ID4gPiANCj4gPiA+ID4gTWFjcm86IGludCBFTk9CVUZTDQo+ ID4gPiA+IFRoZSBrZXJuZWzigJlzIGJ1ZmZlcnMgZm9yIEkvTyBvcGVyYXRpb25zIGFyZSBhbGwg aW4gdXNlLiBJbiBHTlUsDQo+ID4gPiA+IHRoaXMNCj4gPiA+ID4gZXJyb3IgaXMgYWx3YXlzIHN5 bm9ueW1vdXMgd2l0aCBFTk9NRU07IHlvdSBtYXkgZ2V0IG9uZSBvciB0aGUNCj4gPiA+ID4gb3Ro ZXINCj4gPiA+ID4gZnJvbSBuZXR3b3JrIG9wZXJhdGlvbnMuDQo+ID4gPiANCj4gPiA+IFRoZSBv dGhlciBwbGFjZXMgSSd2ZSBsb29rZWQgYWxzbyBzdWdnZXN0IHRoaXMgZXJyb3IgY29kZSBtZWFu cw0KPiA+ID4gYSB0ZW1wb3Jhcnkgb3V0IG9mIGJ1ZmZlcnMgY29uZGl0aW9uLCBhbmQgdGhlIGNh bGxlciBzaG91bGQgdHJ5DQo+ID4gPiBhZ2FpbiBsYXRlci4gVGhlIGVycm9yIGlzIHVzZWQgdG8g bWVhbiB0aGVyZSBhcmUgbm8gbW9yZSBidWZmZXJzDQo+ID4gPiAocGx1cmFsKSB0byB1c2UgZm9y IGEgc2VuZCBvcGVyYXRpb24uIEFzIGl0IHNheXMsIGFraW4gdG8gRU5PTUVNLg0KPiA+ID4gVGhh dCdzIHRoZSB3YXkgSSd2ZSB1c2VkIHRoaXMgZXJybm8gaW4gdGhlIHBhc3QuDQo+ID4gPiANCj4g PiA+IEhlcmUgdGhlIGVycm9yIGlzIHVzZWQgdG8gbWVhbiAiYnVmZmVyIChzaW5ndWxhcikgd291 bGQgb3ZlcmZsb3ciDQo+ID4gPiBkdXJpbmcgYSByZWNlaXZlOyBwZXJtYW5lbnQgZXJyb3IsIG5v IHJldHJ5IHBvc3NpYmxlLiBQb3NzaWJsZQ0KPiA+ID4gYWx0ZXJuYXRpdmVzIHRoYXQgbWlnaHQg YmUgY2xvc2VyIGluIHB1cnBvc2U6IEVNU0dTSVpFLCBFQkFETVNHLA0KPiA+ID4gRVJFTU9URUlP LCBvciBFMkJJRy4NCj4gPiANCj4gPiBIb3cgYWJvdXQgRU5PREFUQSwgdGhlbj8NCj4gDQo+IEVO T0RBVEEgaXMgaW5kZWVkIGEgcGVybWFuZW50IGVycm9yLiBUbyBtZSwgRUJBRE1TRyBzdGlsbA0K PiBmZWVscyBjbG9zZXIgdG8gYSBkZWNvZGUgZmFpbHVyZS4NCg0KRmFpciBlbm91Z2guDQoNCj4g DQo+IE90aGVyIHN5c3RlbXMgaGF2ZSBFQkFEUlBDLCBidXQgTGludXggZG9lc24ndCBhcHBlYXIg dG8uDQo+IA0KPiBPbiB0aGUgZW5jb2RlIHNpZGUsIEVJTlZBTCBvciB0aGUgdmVuZXJhYmxlIEVJ TyBtYWtlcyBzZW5zZS4NCj4gQm90aCBzZWVtIHRvIGJlIHVzZWQgZm9yIGEgbG90IG9mIG90aGVy IHB1cnBvc2VzIGluIHRoZSBSUEMNCj4gc3RhY2ssIHRob3VnaC4NCj4gDQo+IEl0IHdvdWxkIGJl IGdyZWF0IHRvIGhhdmUgb25lIGRpc3RpbmN0IGVycm9yIGNvZGUgbWVhbmluZw0KPiAiZmFpbGVk IHRvIGVuY29kZSBDYWxsIiBhbmQgb25lIG1lYW5pbmcgImZhaWxlZCB0byBkZWNvZGUNCj4gUmVw bHkiLiBGb3IgaW5zdGFuY2UsIFRJLVJQQyBoYXMNCj4gDQo+IMKgMjEgZW51bSBjbG50X3N0YXQg ew0KPiDCoDIywqDCoMKgwqDCoMKgwqDCoMKgUlBDX1NVQ0NFU1MgPSAwLMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgLyogY2FsbCBzdWNjZWVkZWQgKi8NCj4gwqAyM8KgwqDCoMKgwqDC oMKgwqDCoC8qDQo+IMKgMjTCoMKgwqDCoMKgwqDCoMKgwqDCoCogbG9jYWwgZXJyb3JzDQo+IMKg MjXCoMKgwqDCoMKgwqDCoMKgwqDCoCovDQo+IMKgMjbCoMKgwqDCoMKgwqDCoMKgwqBSUENfQ0FO VEVOQ09ERUFSR1MgPSAxLMKgwqDCoMKgwqDCoMKgwqDCoC8qIGNhbid0IGVuY29kZSBhcmd1bWVu dHMNCj4gKi8NCj4gwqAyN8KgwqDCoMKgwqDCoMKgwqDCoFJQQ19DQU5UREVDT0RFUkVTID0gMizC oMKgwqDCoMKgwqDCoMKgwqDCoC8qIGNhbid0IGRlY29kZSByZXN1bHRzDQo+ICovDQo+IMKgMjjC oMKgwqDCoMKgwqDCoMKgwqBSUENfQ0FOVFNFTkQgPSAzLMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoC8qIGZhaWx1cmUgaW4gc2VuZGluZw0KPiBjYWxsICovDQo+IMKgMjnCoMKgwqDCoMKg wqDCoMKgwqBSUENfQ0FOVFJFQ1YgPSA0LA0KPiANCj4gTWF5YmUgdGhhdCdzIG92ZXItZW5naW5l ZXJpbmcgZm9yIHVzLCBidXQgdGhlcmUgY291bGQgYmUNCj4gc29tZSBpbnN0YW5jZXMgd2hlcmUg aXQgbWlnaHQgaGVscCB0aGUgdXBwZXIgbGF5ZXIgdG8ga25vdw0KPiB0aGF0IHRoZSBSUEMgQ2Fs bCB3YXMgbmV2ZXIgc2VudCAobGlrZSwgU0VRVUVOQ0UgPyApLg0KDQpJZiB3ZSdyZSBnb2luZyB0 byBnbyB3aXRoIHRoZSBTVFJFQU1TIHRoZW1lLCB0aGVuIHRoZXJlIGlzIGFsd2F5cw0KRU1TR1NJ WkUgZm9yIHRoaXMgY2FzZS4NCg0KVGhhdCBtaWdodCBhbHNvIGJlIGFwcHJvcHJpYXRlIGluc3Rl YWQgb2YgRTJCSUcgd2hlbiBkZWNvZGluZyBpbnRvIGENCmZpeGVkIHNpemUgYnVmZmVyLg0KDQo+ IA0KPiA+ID4gSSBhc3N1bWUgeW91IHdhbnQgdG8gcmV0dXJuIGVycm5vcyBmcm9tIHRoZXNlIGhl bHBlcnMgYmVjYXVzZQ0KPiA+ID4gZXZlbnR1YWxseSBzb21lIG9mIHRoZW0gbWlnaHQgZW5jb3Vu dGVyIG90aGVyIHR5cGVzIG9mIGVycm9ycz8NCj4gPiA+IElmIG5vdCwgdGhlbiBzdGlja2luZyB3 aXRoIC0xIG9uIGVycm9yLCAwIG9yIHBvc2l0aXZlIHZhbHVlIG9uDQo+ID4gPiBzdWNjZXNzIG1p Z2h0IGJlIGVudGlyZWx5IGFkZXF1YXRlLg0KPiA+IA0KPiA+IFNlZSB0aGUgInY0IiBwYXRjaHNl dCB3aGljaCBnb2VzIGEgbGl0dGxlIGZ1cnRoZXIgaW4gcmVwbGFjaW5nIHRoZQ0KPiA+IG9iamVj dCBzaXplIGNoZWNrcy4gRm9yIG9uZSB0aGluZywgdGhhdCBhbGxvd3MgdXMgdG8gYmUgbW9yZQ0K PiA+IGZvcmNlZnVsDQo+ID4gYWJvdXQgZW5zdXJpbmcgdGhhdCB3ZSBfYWx3YXlzXyBjaGVjayB0 aGUgc2l6ZSBvZiB0aGUgb2JqZWN0DQo+ID4gYWdhaW5zdA0KPiA+IGV4cGVjdGF0aW9ucy4NCj4g DQo+IEdsYW5jZWQgYXQgdGhhdC4gWWVzLCB0aGF0J3MgbW9yZSBjbGVhciwgYW5kIGxlbmd0aCBj aGVja2luZw0KPiBpbiBhZGRpdGlvbiB0byBidWZmZXIgb3ZlcnJ1biBjaGVja2luZyBpcyBnb29k Lg0KPiANCj4gV2h5IHdvdWxkIHRoZSB1cHBlciBsYXllciB3YW50IHRvIGRpc3Rpbmd1aXNoIHRo b3NlIHR3byBjYXNlcy4NCj4gQXJlIHRoZXJlIHNvbWUgY2FzZXMgd2hlcmUgdGhlIFVMIGNhbiB0 YWtlIHNvbWUgcmVjb3Vyc2UsIG9yDQo+IGlzIGEgZGVjb2RpbmcgZmFpbHVyZSBhbHdheXMgcGVy bWFuZW50Pw0KDQpXZSBkZWZpbml0ZWx5IHdhbnQgdG8gcmVwb3J0IGluc3RhbmNlcyBvZiBzZXJ2 ZXJzIHNlbmRpbmcgdXMgb2JqZWN0cw0KdGhhdCBhcmUgdG9vIGJpZy4gVGhhdCdzIGFuIGludGVy b3BlcmFiaWxpdHkgaXNzdWUgdGhhdCBwcm9iYWJseSBuZWVkcw0KdG8gYmUgcmVzb2x2ZWQgdGhy b3VnaCBwcm90b2NvbC1sYXd5ZXJpbmcgb24gdGhlIElFVEYgbWFpbGluZyBsaXN0Lg0KDQpUcnVu Y2F0ZWQgbWVzc2FnZXMgYXJlIGFsbW9zdCBhbHdheXMgYSBjbGllbnQgYnVnLg0KDQo+IA0KPiA+ ID4gPiA+IEhvd2V2ZXIsIGFzIGEgbWF0dGVyIG9mIGRlZmVuc2l2ZSBjb2RpbmcsIHRoaXMgZXJy bm8NCj4gPiA+ID4gPiBjb3VsZCBsZWFrIHVwIHRoZSBzdGFjayBpZiBkZXZlbG9wZXJzIGFyZSBu b3QgY2FyZWZ1bC4NCj4gPiA+ID4gPiANCj4gPiA+ID4gPiBBIGJvb2xlYW4gcmV0dXJuIHZhbHVl IGNvdWxkIGJlIGVudGlyZWx5IGFkZXF1YXRlIGZvcg0KPiA+ID4gPiA+IHRoZXNlIGRlY29kZXJz Pw0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+ID4gKyAqLw0KPiA+ID4gPiA+ID4g K3N0YXRpYyBpbmxpbmUgc3NpemVfdA0KPiA+ID4gPiA+ID4gK3hkcl9zdHJlYW1fZGVjb2RlX29w YXF1ZV9pbmxpbmUoc3RydWN0IHhkcl9zdHJlYW0gKnhkciwNCj4gPiA+ID4gPiA+IHZvaWQNCj4g PiA+ID4gPiA+ICoqcHRyKQ0KPiA+ID4gPiA+ID4gK3sNCj4gPiA+ID4gPiA+ICsJX19iZTMyICpw Ow0KPiA+ID4gPiA+ID4gKwlfX3UzMiBsZW47DQo+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiAr CWlmICh1bmxpa2VseSh4ZHJfc3RyZWFtX2RlY29kZV91MzIoeGRyLCAmbGVuKSA8DQo+ID4gPiA+ ID4gPiAwKSkNCj4gPiA+ID4gPiA+ICsJCXJldHVybiAtRU5PQlVGUzsNCj4gPiA+ID4gPiA+ICsJ aWYgKGxlbiAhPSAwKSB7DQo+ID4gPiA+ID4gPiArCQlwID0geGRyX2lubGluZV9kZWNvZGUoeGRy LCBsZW4pOw0KPiA+ID4gPiA+ID4gKwkJaWYgKHVubGlrZWx5KCFwKSkNCj4gPiA+ID4gPiA+ICsJ CQlyZXR1cm4gLUVOT0JVRlM7DQo+ID4gPiA+ID4gPiArCQkqcHRyID0gcDsNCj4gPiA+ID4gPiA+ ICsJfSBlbHNlDQo+ID4gPiA+ID4gPiArCQkqcHRyID0gTlVMTDsNCj4gPiA+ID4gPiA+ICsJcmV0 dXJuIGxlbjsNCj4gPiA+ID4gPiA+ICt9DQo+ID4gPiA+ID4gPiAjZW5kaWYgLyogX19LRVJORUxf XyAqLw0KPiA+ID4gPiA+ID4gDQo+ID4gPiA+ID4gPiAjZW5kaWYgLyogX1NVTlJQQ19YRFJfSF8g Ki8NCj4gPiA+ID4gPiA+IC0twqANCj4gPiA+ID4gPiA+IDIuOS4zDQo+ID4gPiA+ID4gPiANCj4g PiA+ID4gPiA+IC0tDQo+ID4gPiA+ID4gPiBUbyB1bnN1YnNjcmliZSBmcm9tIHRoaXMgbGlzdDog c2VuZCB0aGUgbGluZSAidW5zdWJzY3JpYmUNCj4gPiA+ID4gPiA+IGxpbnV4LQ0KPiA+ID4gPiA+ ID4gbmZzIiBpbg0KPiA+ID4gPiA+ID4gdGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9t b0B2Z2VyLmtlcm5lbC5vcmcNCj4gPiA+ID4gPiA+IE1vcmUgbWFqb3Jkb21vIGluZm8gYXTCoMKg aHR0cDovL3ZnZXIua2VybmVsLm9yZy9tYWpvcmRvbW8taW4NCj4gPiA+ID4gPiA+IGZvLmgNCj4g PiA+ID4gPiA+IHRtbA0KPiA+ID4gPiA+IA0KPiA+ID4gPiA+IC0tDQo+ID4gPiA+ID4gQ2h1Y2sg TGV2ZXINCj4gPiA+ID4gPiANCj4gPiA+ID4gPiANCj4gPiA+ID4gPiANCj4gPiA+ID4gDQo+ID4g PiA+IC0twqANCj4gPiA+ID4gVHJvbmQgTXlrbGVidXN0DQo+ID4gPiA+IExpbnV4IE5GUyBjbGll bnQgbWFpbnRhaW5lciwgUHJpbWFyeURhdGENCj4gPiA+ID4gdHJvbmQubXlrbGVidXN0QHByaW1h cnlkYXRhLmNvbQ0KPiA+ID4gPiBO77+977+977+9cu+/vXnvv73vv73vv71i77+9WO+/vcendu+/ vV7vv70p3rp7Lm7vv70r77+9e++/vSLvv73vv71ebu+/vXLvv73vv71677+9Gu+/ve+/vWjvv73v v73vv70m77+9Hu+/vUfvv73vv71o77+9Ayjvv73pmo7vv73domoNCj4gPiA+ID4gIu+/vRrvv70N Cj4gPiA+ID4gG23vv73vv73vv73vv71677+93pbvv73vv71m77+9aO+/vX7vv71tDQo+ID4gPiAN Cj4gPiA+IC0tDQo+ID4gPiBDaHVjayBMZXZlcg0KPiA+ID4gDQo+ID4gPiANCj4gPiA+IA0KPiA+ IA0KPiA+IC0twqANCj4gPiBUcm9uZCBNeWtsZWJ1c3QNCj4gPiBMaW51eCBORlMgY2xpZW50IG1h aW50YWluZXIsIFByaW1hcnlEYXRhDQo+ID4gdHJvbmQubXlrbGVidXN0QHByaW1hcnlkYXRhLmNv bQ0KPiANCj4gLS0NCj4gQ2h1Y2sgTGV2ZXINCj4gDQo+IA0KPiANCi0tIA0KVHJvbmQgTXlrbGVi dXN0DQpMaW51eCBORlMgY2xpZW50IG1haW50YWluZXIsIFByaW1hcnlEYXRhDQp0cm9uZC5teWts ZWJ1c3RAcHJpbWFyeWRhdGEuY29tDQo= ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2017-02-19 20:33 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-02-18 19:12 [PATCH v3 0/4] XDR cleanups for NFSv4 Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 2/4] NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 3/4] NFSv4: Fix the underestimation of delegation XDR space reservation Trond Myklebust 2017-02-18 19:12 ` [PATCH v3 4/4] NFSv4: Remove bogus "struct nfs_client" argument from decode_ace() Trond Myklebust 2017-02-18 22:21 ` [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode Chuck Lever 2017-02-19 5:36 ` Trond Myklebust 2017-02-19 19:07 ` Chuck Lever 2017-02-19 19:28 ` Trond Myklebust 2017-02-19 20:06 ` Chuck Lever 2017-02-19 20:33 ` Trond Myklebust
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).