2017-02-18 19:12:50

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 0/4] XDR cleanups for NFSv4

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



2017-02-18 19:12:51

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode

Add some generic helpers for encoding/decoding opaque structures and
basic u32/u64.

Signed-off-by: Trond Myklebust <[email protected]>
---
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


2017-02-18 19:12:52

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 2/4] NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics

Signed-off-by: Trond Myklebust <[email protected]>
---
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


2017-02-18 19:12:54

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 3/4] NFSv4: Fix the underestimation of delegation XDR space reservation

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 <[email protected]>
---
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


2017-02-18 19:12:55

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH v3 4/4] NFSv4: Remove bogus "struct nfs_client" argument from decode_ace()

We shouldn't need to force callers to carry an unused argument.

Signed-off-by: Trond Myklebust <[email protected]>
---
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


2017-02-18 22:23:28

by Chuck Lever III

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode


> On Feb 18, 2017, at 2:12 PM, Trond Myklebust <[email protected]> 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 <[email protected]>
> ---
> 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 [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

--
Chuck Lever




2017-02-19 05:36:07

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode

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=


2017-02-19 19:08:00

by Chuck Lever III

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode


> On Feb 19, 2017, at 12:36 AM, Trond Myklebust <[email protected]> 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 <[email protected]>
>>> ---
>>> 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.

2017-02-19 19:28:21

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode

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==


2017-02-19 20:06:26

by Chuck Lever III

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode


> On Feb 19, 2017, at 2:28 PM, Trond Myklebust <[email protected]> wrote:
>
> Thanks for the discussion, BTW. I appreciate the feedback.

No problem! Feel free to add

Reviewed-by: Chuck Lever <[email protected]>


> 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 <[email protected]
>>>>>>
>>>>> ---
>>>>> 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 [email protected]
>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.h
>>>>> tml
>>>>
>>>> --
>>>> Chuck Lever
>>>>
>>>>
>>>>
>>>
>>> --
>>> Trond Myklebust
>>> Linux NFS client maintainer, PrimaryData
>>> [email protected]
>>> N���r�y���b�X�ǧv�^�)޺{.n�+�{�"��^n�r��z���h���&��G��h�(�階�ݢj"��
>>> m����z�ޖ��f�h�~�m
>>
>> --
>> Chuck Lever
>>
>>
>>
> --
> Trond Myklebust
> Linux NFS client maintainer, PrimaryData
> [email protected]

--
Chuck Lever




2017-02-19 20:33:48

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] SUNRPC: Add generic helpers for xdr_stream encode/decode

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=