2018-06-19 21:24:42

by Bill Baker

[permalink] [raw]
Subject: [PATCH v2] NFSv4 client live hangs after live data migration recovery

From: Bill Baker <[email protected]>

After a live data migration event at the NFS server, the client may send
I/O requests to the wrong server, causing a live hang due to repeated
recovery events. On the wire, this will appear as an I/O request failing
with NFS4ERR_BADSESSION, followed by successful CREATE_SESSION, repeatedly.
NFS4ERR_BADSSESSION is returned because the session ID being used was
issued by the other server and is not valid at the old server.

The failure is caused by async worker threads having cached the transport
(xprt) in the rpc_task structure. After the migration recovery completes,
the task is redispatched and the task resends the request to the wrong
server based on the old value still present in tk_xprt.

The solution is to recompute the tk_xprt field of the rpc_task structure
so that the request goes to the correct server.

Signed-off-by: Bill Baker <[email protected]>
Reviewed-by: Chuck Lever <[email protected]>
Tested-by: Helen Chao <[email protected]>
Fixes: fb43d17210ba ("SUNRPC: Use the multipath iterator to assign a ...")
Cc: [email protected] #4.9
---
fs/nfs/nfs4proc.c | 9 ++++++++-
include/linux/sunrpc/clnt.h | 1 +
net/sunrpc/clnt.c | 28 ++++++++++++++++++++--------
3 files changed, 29 insertions(+), 9 deletions(-)

Changes since v1:
- Added "Fixes:" and "Cc: stable" tags

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ed45090..2b1552b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -581,8 +581,15 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
ret = -EIO;
return ret;
out_retry:
- if (ret == 0)
+ if (ret == 0) {
exception->retry = 1;
+ /*
+ * For NFS4ERR_MOVED, the client transport will need to
+ * be recomputed after migration recovery has completed.
+ */
+ if (errorcode == -NFS4ERR_MOVED)
+ rpc_task_release_transport(task);
+ }
return ret;
}

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 9b11b6a..73d5c4a 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -156,6 +156,7 @@ int rpc_switch_client_transport(struct rpc_clnt *,

void rpc_shutdown_client(struct rpc_clnt *);
void rpc_release_client(struct rpc_clnt *);
+void rpc_task_release_transport(struct rpc_task *);
void rpc_task_release_client(struct rpc_task *);

int rpcb_create_local(struct net *);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d839c33..0d85425 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -965,10 +965,20 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
}
EXPORT_SYMBOL_GPL(rpc_bind_new_program);

+void rpc_task_release_transport(struct rpc_task *task)
+{
+ struct rpc_xprt *xprt = task->tk_xprt;
+
+ if (xprt) {
+ task->tk_xprt = NULL;
+ xprt_put(xprt);
+ }
+}
+EXPORT_SYMBOL_GPL(rpc_task_release_transport);
+
void rpc_task_release_client(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
- struct rpc_xprt *xprt = task->tk_xprt;

if (clnt != NULL) {
/* Remove from client task list */
@@ -979,12 +989,14 @@ void rpc_task_release_client(struct rpc_task *task)

rpc_release_client(clnt);
}
+ rpc_task_release_transport(task);
+}

- if (xprt != NULL) {
- task->tk_xprt = NULL;
-
- xprt_put(xprt);
- }
+static
+void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+ if (!task->tk_xprt)
+ task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
}

static
@@ -992,8 +1004,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
{

if (clnt != NULL) {
- if (task->tk_xprt == NULL)
- task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
+ rpc_task_set_transport(task, clnt);
task->tk_client = clnt;
atomic_inc(&clnt->cl_count);
if (clnt->cl_softrtry)
@@ -1512,6 +1523,7 @@ void rpc_force_rebind(struct rpc_clnt *clnt)
clnt->cl_program->version[clnt->cl_vers]->counts[idx]++;
clnt->cl_stats->rpccnt++;
task->tk_action = call_reserve;
+ rpc_task_set_transport(task, clnt);
}

/*
--
1.8.3.1



2018-08-16 18:59:02

by Bill Baker

[permalink] [raw]
Subject: Re: [PATCH v2] NFSv4 client live hangs after live data migration recovery


Hi, Trond, et al,

Have you had a chance to look at this patch? I'd like to get some
feedback (or acceptance into the next merge window). As it stands
now, the live data migration feature is completely broken in the
NFSv4 client in the current upstream kernel.

Thanks,
B

On 06/19/2018 04:24 PM, Bill Baker wrote:
> From: Bill Baker <[email protected]>
>
> After a live data migration event at the NFS server, the client may send
> I/O requests to the wrong server, causing a live hang due to repeated
> recovery events. On the wire, this will appear as an I/O request failing
> with NFS4ERR_BADSESSION, followed by successful CREATE_SESSION, repeatedly.
> NFS4ERR_BADSSESSION is returned because the session ID being used was
> issued by the other server and is not valid at the old server.
>
> The failure is caused by async worker threads having cached the transport
> (xprt) in the rpc_task structure. After the migration recovery completes,
> the task is redispatched and the task resends the request to the wrong
> server based on the old value still present in tk_xprt.
>
> The solution is to recompute the tk_xprt field of the rpc_task structure
> so that the request goes to the correct server.
>
> Signed-off-by: Bill Baker <[email protected]>
> Reviewed-by: Chuck Lever <[email protected]>
> Tested-by: Helen Chao <[email protected]>
> Fixes: fb43d17210ba ("SUNRPC: Use the multipath iterator to assign a ...")
> Cc: [email protected] #4.9
> ---
> fs/nfs/nfs4proc.c | 9 ++++++++-
> include/linux/sunrpc/clnt.h | 1 +
> net/sunrpc/clnt.c | 28 ++++++++++++++++++++--------
> 3 files changed, 29 insertions(+), 9 deletions(-)
>
> Changes since v1:
> - Added "Fixes:" and "Cc: stable" tags
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index ed45090..2b1552b 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -581,8 +581,15 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
> ret = -EIO;
> return ret;
> out_retry:
> - if (ret == 0)
> + if (ret == 0) {
> exception->retry = 1;
> + /*
> + * For NFS4ERR_MOVED, the client transport will need to
> + * be recomputed after migration recovery has completed.
> + */
> + if (errorcode == -NFS4ERR_MOVED)
> + rpc_task_release_transport(task);
> + }
> return ret;
> }
>
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 9b11b6a..73d5c4a 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -156,6 +156,7 @@ int rpc_switch_client_transport(struct rpc_clnt *,
>
> void rpc_shutdown_client(struct rpc_clnt *);
> void rpc_release_client(struct rpc_clnt *);
> +void rpc_task_release_transport(struct rpc_task *);
> void rpc_task_release_client(struct rpc_task *);
>
> int rpcb_create_local(struct net *);
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index d839c33..0d85425 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -965,10 +965,20 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
> }
> EXPORT_SYMBOL_GPL(rpc_bind_new_program);
>
> +void rpc_task_release_transport(struct rpc_task *task)
> +{
> + struct rpc_xprt *xprt = task->tk_xprt;
> +
> + if (xprt) {
> + task->tk_xprt = NULL;
> + xprt_put(xprt);
> + }
> +}
> +EXPORT_SYMBOL_GPL(rpc_task_release_transport);
> +
> void rpc_task_release_client(struct rpc_task *task)
> {
> struct rpc_clnt *clnt = task->tk_client;
> - struct rpc_xprt *xprt = task->tk_xprt;
>
> if (clnt != NULL) {
> /* Remove from client task list */
> @@ -979,12 +989,14 @@ void rpc_task_release_client(struct rpc_task *task)
>
> rpc_release_client(clnt);
> }
> + rpc_task_release_transport(task);
> +}
>
> - if (xprt != NULL) {
> - task->tk_xprt = NULL;
> -
> - xprt_put(xprt);
> - }
> +static
> +void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
> +{
> + if (!task->tk_xprt)
> + task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
> }
>
> static
> @@ -992,8 +1004,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
> {
>
> if (clnt != NULL) {
> - if (task->tk_xprt == NULL)
> - task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
> + rpc_task_set_transport(task, clnt);
> task->tk_client = clnt;
> atomic_inc(&clnt->cl_count);
> if (clnt->cl_softrtry)
> @@ -1512,6 +1523,7 @@ void rpc_force_rebind(struct rpc_clnt *clnt)
> clnt->cl_program->version[clnt->cl_vers]->counts[idx]++;
> clnt->cl_stats->rpccnt++;
> task->tk_action = call_reserve;
> + rpc_task_set_transport(task, clnt);
> }
>
> /*
>

--
Bill Baker - Oracle Linux NFS

2018-08-16 21:57:23

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v2] NFSv4 client live hangs after live data migration recovery

T24gVGh1LCAyMDE4LTA4LTE2IGF0IDEwOjU5IC0wNTAwLCBCaWxsIEJha2VyIHdyb3RlOg0KPiBI
aSwgVHJvbmQsIGV0IGFsLA0KDQpIaSBCaWxsLA0KDQo+IA0KPiBIYXZlIHlvdSBoYWQgYSBjaGFu
Y2UgdG8gbG9vayBhdCB0aGlzIHBhdGNoPyAgSSdkIGxpa2UgdG8gZ2V0IHNvbWUNCj4gZmVlZGJh
Y2sgKG9yIGFjY2VwdGFuY2UgaW50byB0aGUgbmV4dCBtZXJnZSB3aW5kb3cpLiAgQXMgaXQgc3Rh
bmRzDQo+IG5vdywgdGhlIGxpdmUgZGF0YSBtaWdyYXRpb24gZmVhdHVyZSBpcyBjb21wbGV0ZWx5
IGJyb2tlbiBpbiB0aGUNCj4gTkZTdjQgY2xpZW50IGluIHRoZSBjdXJyZW50IHVwc3RyZWFtIGtl
cm5lbC4NCg0KSSBoYXZlIHRoaXMgcGF0Y2ggcXVldWVkIHVwIGluIG15IGxpbnV4LW5leHQgYnJh
bmNoIGZvciA0LjE5DQoNClRoYW5rcyBmb3IgY2hlY2tpbmchDQpBbm5hDQoNCj4gDQo+IFRoYW5r
cywNCj4gQg0KPiANCj4gT24gMDYvMTkvMjAxOCAwNDoyNCBQTSwgQmlsbCBCYWtlciB3cm90ZToN
Cj4gPiBGcm9tOiBCaWxsIEJha2VyIDxCaWxsLkJha2VyQE9yYWNsZS5jb20+DQo+ID4gDQo+ID4g
QWZ0ZXIgYSBsaXZlIGRhdGEgbWlncmF0aW9uIGV2ZW50IGF0IHRoZSBORlMgc2VydmVyLCB0aGUg
Y2xpZW50IG1heQ0KPiA+IHNlbmQNCj4gPiBJL08gcmVxdWVzdHMgdG8gdGhlIHdyb25nIHNlcnZl
ciwgY2F1c2luZyBhIGxpdmUgaGFuZyBkdWUgdG8NCj4gPiByZXBlYXRlZA0KPiA+IHJlY292ZXJ5
IGV2ZW50cy4gIE9uIHRoZSB3aXJlLCB0aGlzIHdpbGwgYXBwZWFyIGFzIGFuIEkvTyByZXF1ZXN0
DQo+ID4gZmFpbGluZw0KPiA+IHdpdGggTkZTNEVSUl9CQURTRVNTSU9OLCBmb2xsb3dlZCBieSBz
dWNjZXNzZnVsIENSRUFURV9TRVNTSU9OLA0KPiA+IHJlcGVhdGVkbHkuDQo+ID4gTkZTNEVSUl9C
QURTU0VTU0lPTiBpcyByZXR1cm5lZCBiZWNhdXNlIHRoZSBzZXNzaW9uIElEIGJlaW5nIHVzZWQN
Cj4gPiB3YXMNCj4gPiBpc3N1ZWQgYnkgdGhlIG90aGVyIHNlcnZlciBhbmQgaXMgbm90IHZhbGlk
IGF0IHRoZSBvbGQgc2VydmVyLg0KPiA+IA0KPiA+IFRoZSBmYWlsdXJlIGlzIGNhdXNlZCBieSBh
c3luYyB3b3JrZXIgdGhyZWFkcyBoYXZpbmcgY2FjaGVkIHRoZQ0KPiA+IHRyYW5zcG9ydA0KPiA+
ICh4cHJ0KSBpbiB0aGUgcnBjX3Rhc2sgc3RydWN0dXJlLiAgQWZ0ZXIgdGhlIG1pZ3JhdGlvbiBy
ZWNvdmVyeQ0KPiA+IGNvbXBsZXRlcywNCj4gPiB0aGUgdGFzayBpcyByZWRpc3BhdGNoZWQgYW5k
IHRoZSB0YXNrIHJlc2VuZHMgdGhlIHJlcXVlc3QgdG8gdGhlDQo+ID4gd3JvbmcNCj4gPiBzZXJ2
ZXIgYmFzZWQgb24gdGhlIG9sZCB2YWx1ZSBzdGlsbCBwcmVzZW50IGluIHRrX3hwcnQuDQo+ID4g
DQo+ID4gVGhlIHNvbHV0aW9uIGlzIHRvIHJlY29tcHV0ZSB0aGUgdGtfeHBydCBmaWVsZCBvZiB0
aGUgcnBjX3Rhc2sNCj4gPiBzdHJ1Y3R1cmUNCj4gPiBzbyB0aGF0IHRoZSByZXF1ZXN0IGdvZXMg
dG8gdGhlIGNvcnJlY3Qgc2VydmVyLg0KPiA+IA0KPiA+IFNpZ25lZC1vZmYtYnk6IEJpbGwgQmFr
ZXIgPGJpbGwuYmFrZXJAb3JhY2xlLmNvbT4NCj4gPiBSZXZpZXdlZC1ieTogQ2h1Y2sgTGV2ZXIg
PGNodWNrLmxldmVyQG9yYWNsZS5jb20+DQo+ID4gVGVzdGVkLWJ5OiBIZWxlbiBDaGFvIDxoZWxl
bi5jaGFvQG9yYWNsZS5jb20+DQo+ID4gRml4ZXM6IGZiNDNkMTcyMTBiYSAoIlNVTlJQQzogVXNl
IHRoZSBtdWx0aXBhdGggaXRlcmF0b3IgdG8gYXNzaWduDQo+ID4gYSAuLi4iKQ0KPiA+IENjOiBz
dGFibGVAdmdlci5rZXJuZWwub3JnICM0LjkNCj4gPiAtLS0NCj4gPiAgIGZzL25mcy9uZnM0cHJv
Yy5jICAgICAgICAgICB8ICA5ICsrKysrKysrLQ0KPiA+ICAgaW5jbHVkZS9saW51eC9zdW5ycGMv
Y2xudC5oIHwgIDEgKw0KPiA+ICAgbmV0L3N1bnJwYy9jbG50LmMgICAgICAgICAgIHwgMjggKysr
KysrKysrKysrKysrKysrKystLS0tLS0tLQ0KPiA+ICAgMyBmaWxlcyBjaGFuZ2VkLCAyOSBpbnNl
cnRpb25zKCspLCA5IGRlbGV0aW9ucygtKQ0KPiA+IA0KPiA+IENoYW5nZXMgc2luY2UgdjE6DQo+
ID4gLSBBZGRlZCAiRml4ZXM6IiBhbmQgIkNjOiBzdGFibGUiIHRhZ3MNCj4gPiANCj4gPiBkaWZm
IC0tZ2l0IGEvZnMvbmZzL25mczRwcm9jLmMgYi9mcy9uZnMvbmZzNHByb2MuYw0KPiA+IGluZGV4
IGVkNDUwOTAuLjJiMTU1MmIgMTAwNjQ0DQo+ID4gLS0tIGEvZnMvbmZzL25mczRwcm9jLmMNCj4g
PiArKysgYi9mcy9uZnMvbmZzNHByb2MuYw0KPiA+IEBAIC01ODEsOCArNTgxLDE1IEBAIGludCBu
ZnM0X2hhbmRsZV9leGNlcHRpb24oc3RydWN0IG5mc19zZXJ2ZXINCj4gPiAqc2VydmVyLCBpbnQg
ZXJyb3Jjb2RlLCBzdHJ1Y3QgbmZzNF8NCj4gPiAgIAkJcmV0ID0gLUVJTzsNCj4gPiAgIAlyZXR1
cm4gcmV0Ow0KPiA+ICAgb3V0X3JldHJ5Og0KPiA+IC0JaWYgKHJldCA9PSAwKQ0KPiA+ICsJaWYg
KHJldCA9PSAwKSB7DQo+ID4gICAJCWV4Y2VwdGlvbi0+cmV0cnkgPSAxOw0KPiA+ICsJCS8qDQo+
ID4gKwkJICogRm9yIE5GUzRFUlJfTU9WRUQsIHRoZSBjbGllbnQgdHJhbnNwb3J0IHdpbGwgbmVl
ZCB0bw0KPiA+ICsJCSAqIGJlIHJlY29tcHV0ZWQgYWZ0ZXIgbWlncmF0aW9uIHJlY292ZXJ5IGhh
cw0KPiA+IGNvbXBsZXRlZC4NCj4gPiArCQkgKi8NCj4gPiArCQlpZiAoZXJyb3Jjb2RlID09IC1O
RlM0RVJSX01PVkVEKQ0KPiA+ICsJCQlycGNfdGFza19yZWxlYXNlX3RyYW5zcG9ydCh0YXNrKTsN
Cj4gPiArCX0NCj4gPiAgIAlyZXR1cm4gcmV0Ow0KPiA+ICAgfQ0KPiA+ICAgDQo+ID4gZGlmZiAt
LWdpdCBhL2luY2x1ZGUvbGludXgvc3VucnBjL2NsbnQuaA0KPiA+IGIvaW5jbHVkZS9saW51eC9z
dW5ycGMvY2xudC5oDQo+ID4gaW5kZXggOWIxMWI2YS4uNzNkNWM0YSAxMDA2NDQNCj4gPiAtLS0g
YS9pbmNsdWRlL2xpbnV4L3N1bnJwYy9jbG50LmgNCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3N1
bnJwYy9jbG50LmgNCj4gPiBAQCAtMTU2LDYgKzE1Niw3IEBAIGludAkJcnBjX3N3aXRjaF9jbGll
bnRfdHJhbnNwb3J0KHN0cg0KPiA+IHVjdCBycGNfY2xudCAqLA0KPiA+ICAgDQo+ID4gICB2b2lk
CQlycGNfc2h1dGRvd25fY2xpZW50KHN0cnVjdCBycGNfY2xudCAqKTsNCj4gPiAgIHZvaWQJCXJw
Y19yZWxlYXNlX2NsaWVudChzdHJ1Y3QgcnBjX2NsbnQgKik7DQo+ID4gK3ZvaWQJCXJwY190YXNr
X3JlbGVhc2VfdHJhbnNwb3J0KHN0cnVjdCBycGNfdGFzayAqKTsNCj4gPiAgIHZvaWQJCXJwY190
YXNrX3JlbGVhc2VfY2xpZW50KHN0cnVjdCBycGNfdGFzayAqKTsNCj4gPiAgIA0KPiA+ICAgaW50
CQlycGNiX2NyZWF0ZV9sb2NhbChzdHJ1Y3QgbmV0ICopOw0KPiA+IGRpZmYgLS1naXQgYS9uZXQv
c3VucnBjL2NsbnQuYyBiL25ldC9zdW5ycGMvY2xudC5jDQo+ID4gaW5kZXggZDgzOWMzMy4uMGQ4
NTQyNSAxMDA2NDQNCj4gPiAtLS0gYS9uZXQvc3VucnBjL2NsbnQuYw0KPiA+ICsrKyBiL25ldC9z
dW5ycGMvY2xudC5jDQo+ID4gQEAgLTk2NSwxMCArOTY1LDIwIEBAIHN0cnVjdCBycGNfY2xudCAq
cnBjX2JpbmRfbmV3X3Byb2dyYW0oc3RydWN0DQo+ID4gcnBjX2NsbnQgKm9sZCwNCj4gPiAgIH0N
Cj4gPiAgIEVYUE9SVF9TWU1CT0xfR1BMKHJwY19iaW5kX25ld19wcm9ncmFtKTsNCj4gPiAgIA0K
PiA+ICt2b2lkIHJwY190YXNrX3JlbGVhc2VfdHJhbnNwb3J0KHN0cnVjdCBycGNfdGFzayAqdGFz
aykNCj4gPiArew0KPiA+ICsJc3RydWN0IHJwY194cHJ0ICp4cHJ0ID0gdGFzay0+dGtfeHBydDsN
Cj4gPiArDQo+ID4gKwlpZiAoeHBydCkgew0KPiA+ICsJCXRhc2stPnRrX3hwcnQgPSBOVUxMOw0K
PiA+ICsJCXhwcnRfcHV0KHhwcnQpOw0KPiA+ICsJfQ0KPiA+ICt9DQo+ID4gK0VYUE9SVF9TWU1C
T0xfR1BMKHJwY190YXNrX3JlbGVhc2VfdHJhbnNwb3J0KTsNCj4gPiArDQo+ID4gICB2b2lkIHJw
Y190YXNrX3JlbGVhc2VfY2xpZW50KHN0cnVjdCBycGNfdGFzayAqdGFzaykNCj4gPiAgIHsNCj4g
PiAgIAlzdHJ1Y3QgcnBjX2NsbnQgKmNsbnQgPSB0YXNrLT50a19jbGllbnQ7DQo+ID4gLQlzdHJ1
Y3QgcnBjX3hwcnQgKnhwcnQgPSB0YXNrLT50a194cHJ0Ow0KPiA+ICAgDQo+ID4gICAJaWYgKGNs
bnQgIT0gTlVMTCkgew0KPiA+ICAgCQkvKiBSZW1vdmUgZnJvbSBjbGllbnQgdGFzayBsaXN0ICov
DQo+ID4gQEAgLTk3OSwxMiArOTg5LDE0IEBAIHZvaWQgcnBjX3Rhc2tfcmVsZWFzZV9jbGllbnQo
c3RydWN0IHJwY190YXNrDQo+ID4gKnRhc2spDQo+ID4gICANCj4gPiAgIAkJcnBjX3JlbGVhc2Vf
Y2xpZW50KGNsbnQpOw0KPiA+ICAgCX0NCj4gPiArCXJwY190YXNrX3JlbGVhc2VfdHJhbnNwb3J0
KHRhc2spOw0KPiA+ICt9DQo+ID4gICANCj4gPiAtCWlmICh4cHJ0ICE9IE5VTEwpIHsNCj4gPiAt
CQl0YXNrLT50a194cHJ0ID0gTlVMTDsNCj4gPiAtDQo+ID4gLQkJeHBydF9wdXQoeHBydCk7DQo+
ID4gLQl9DQo+ID4gK3N0YXRpYw0KPiA+ICt2b2lkIHJwY190YXNrX3NldF90cmFuc3BvcnQoc3Ry
dWN0IHJwY190YXNrICp0YXNrLCBzdHJ1Y3QgcnBjX2NsbnQNCj4gPiAqY2xudCkNCj4gPiArew0K
PiA+ICsJaWYgKCF0YXNrLT50a194cHJ0KQ0KPiA+ICsJCXRhc2stPnRrX3hwcnQgPSB4cHJ0X2l0
ZXJfZ2V0X25leHQoJmNsbnQtPmNsX3hwaSk7DQo+ID4gICB9DQo+ID4gICANCj4gPiAgIHN0YXRp
Yw0KPiA+IEBAIC05OTIsOCArMTAwNCw3IEBAIHZvaWQgcnBjX3Rhc2tfc2V0X2NsaWVudChzdHJ1
Y3QgcnBjX3Rhc2sNCj4gPiAqdGFzaywgc3RydWN0IHJwY19jbG50ICpjbG50KQ0KPiA+ICAgew0K
PiA+ICAgDQo+ID4gICAJaWYgKGNsbnQgIT0gTlVMTCkgew0KPiA+IC0JCWlmICh0YXNrLT50a194
cHJ0ID09IE5VTEwpDQo+ID4gLQkJCXRhc2stPnRrX3hwcnQgPSB4cHJ0X2l0ZXJfZ2V0X25leHQo
JmNsbnQtDQo+ID4gPmNsX3hwaSk7DQo+ID4gKwkJcnBjX3Rhc2tfc2V0X3RyYW5zcG9ydCh0YXNr
LCBjbG50KTsNCj4gPiAgIAkJdGFzay0+dGtfY2xpZW50ID0gY2xudDsNCj4gPiAgIAkJYXRvbWlj
X2luYygmY2xudC0+Y2xfY291bnQpOw0KPiA+ICAgCQlpZiAoY2xudC0+Y2xfc29mdHJ0cnkpDQo+
ID4gQEAgLTE1MTIsNiArMTUyMyw3IEBAIHZvaWQgcnBjX2ZvcmNlX3JlYmluZChzdHJ1Y3QgcnBj
X2NsbnQgKmNsbnQpDQo+ID4gICAJCWNsbnQtPmNsX3Byb2dyYW0tPnZlcnNpb25bY2xudC0+Y2xf
dmVyc10tDQo+ID4gPmNvdW50c1tpZHhdKys7DQo+ID4gICAJY2xudC0+Y2xfc3RhdHMtPnJwY2Nu
dCsrOw0KPiA+ICAgCXRhc2stPnRrX2FjdGlvbiA9IGNhbGxfcmVzZXJ2ZTsNCj4gPiArCXJwY190
YXNrX3NldF90cmFuc3BvcnQodGFzaywgY2xudCk7DQo+ID4gICB9DQo+ID4gICANCj4gPiAgIC8q
DQo+ID4gDQo+IA0KPiANCg==