From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga07.intel.com ([134.134.136.100]:22541 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727188AbeJCPvj (ORCPT ); Wed, 3 Oct 2018 11:51:39 -0400 Subject: Re: [Intel-gfx] [PATCH v3] drm/i915: Handle incomplete Z_FINISH for compressed error states To: Chris Wilson , intel-gfx@lists.freedesktop.org Cc: stable@vger.kernel.org References: <20181001194447.29910-2-chris@chris-wilson.co.uk> <20181003082422.23214-1-chris@chris-wilson.co.uk> From: Tvrtko Ursulin Message-ID: Date: Wed, 3 Oct 2018 10:04:04 +0100 MIME-Version: 1.0 In-Reply-To: <20181003082422.23214-1-chris@chris-wilson.co.uk> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-GB Content-Transfer-Encoding: 7bit Sender: stable-owner@vger.kernel.org List-ID: On 03/10/2018 09:24, Chris Wilson wrote: > The final call to zlib_deflate(Z_FINISH) may require more output > space to be allocated and so needs to re-invoked. Failure to do so in > the current code leads to incomplete zlib streams (albeit intact due to > the use of Z_SYNC_FLUSH) resulting in the occasional short object > capture. > > v2: Check against overrunning our pre-allocated page array > v3: Drop Z_SYNC_FLUSH entirely > > Testcase: igt/i915-error-capture.js > Fixes: 0a97015d45ee ("drm/i915: Compress GPU objects in error state") > Signed-off-by: Chris Wilson > Cc: Joonas Lahtinen > Cc: # v4.10+ > Cc: Tvrtko Ursulin > --- > drivers/gpu/drm/i915/i915_gpu_error.c | 88 +++++++++++++++++++-------- > drivers/gpu/drm/i915/i915_gpu_error.h | 1 + > 2 files changed, 64 insertions(+), 25 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c > index 3d5554f14dfd..705ff122100f 100644 > --- a/drivers/gpu/drm/i915/i915_gpu_error.c > +++ b/drivers/gpu/drm/i915/i915_gpu_error.c > @@ -232,6 +232,20 @@ static bool compress_init(struct compress *c) > return true; > } > > +static void *compress_next_page(struct drm_i915_error_object *dst) > +{ > + unsigned long page; > + > + if (dst->page_count >= dst->num_pages) > + return ERR_PTR(-ENOSPC); > + > + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); > + if (!page) > + return ERR_PTR(-ENOMEM); > + > + return dst->pages[dst->page_count++] = (void *)page; > +} > + > static int compress_page(struct compress *c, > void *src, > struct drm_i915_error_object *dst) > @@ -245,19 +259,14 @@ static int compress_page(struct compress *c, > > do { > if (zstream->avail_out == 0) { > - unsigned long page; > - > - page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); > - if (!page) > - return -ENOMEM; > + zstream->next_out = compress_next_page(dst); > + if (IS_ERR(zstream->next_out)) > + return PTR_ERR(zstream->next_out); > > - dst->pages[dst->page_count++] = (void *)page; > - > - zstream->next_out = (void *)page; > zstream->avail_out = PAGE_SIZE; > } > > - if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK) > + if (zlib_deflate(zstream, Z_NO_FLUSH) != Z_OK) > return -EIO; > } while (zstream->avail_in); > > @@ -268,19 +277,42 @@ static int compress_page(struct compress *c, > return 0; > } > > -static void compress_fini(struct compress *c, > +static int compress_flush(struct compress *c, > struct drm_i915_error_object *dst) > { > struct z_stream_s *zstream = &c->zstream; > > - if (dst) { > - zlib_deflate(zstream, Z_FINISH); > - dst->unused = zstream->avail_out; > - } > + do { > + switch (zlib_deflate(zstream, Z_FINISH)) { > + case Z_OK: /* more space requested */ > + zstream->next_out = compress_next_page(dst); > + if (IS_ERR(zstream->next_out)) > + return PTR_ERR(zstream->next_out); > + > + zstream->avail_out = PAGE_SIZE; > + break; > + > + case Z_STREAM_END: > + goto end; > + > + default: /* any error */ > + return -EIO; > + } > + } while (1); > + > +end: > + memset(zstream->next_out, 0, zstream->avail_out); > + dst->unused = zstream->avail_out; > + return 0; > +} > + > +static void compress_fini(struct compress *c, > + struct drm_i915_error_object *dst) > +{ > + struct z_stream_s *zstream = &c->zstream; > > zlib_deflateEnd(zstream); > kfree(zstream->workspace); > - > if (c->tmp) > free_page((unsigned long)c->tmp); > } > @@ -319,6 +351,12 @@ static int compress_page(struct compress *c, > return 0; > } > > +static int compress_flush(struct compress *c, > + struct drm_i915_error_object *dst) > +{ > + return 0; > +} > + > static void compress_fini(struct compress *c, > struct drm_i915_error_object *dst) > { > @@ -917,6 +955,7 @@ i915_error_object_create(struct drm_i915_private *i915, > unsigned long num_pages; > struct sgt_iter iter; > dma_addr_t dma; > + int ret; > > if (!vma) > return NULL; > @@ -930,6 +969,7 @@ i915_error_object_create(struct drm_i915_private *i915, > > dst->gtt_offset = vma->node.start; > dst->gtt_size = vma->node.size; > + dst->num_pages = num_pages; > dst->page_count = 0; > dst->unused = 0; > > @@ -938,28 +978,26 @@ i915_error_object_create(struct drm_i915_private *i915, > return NULL; > } > > + ret = -EINVAL; > for_each_sgt_dma(dma, iter, vma->pages) > void __iomem *s; > - int ret; > > ggtt->vm.insert_page(&ggtt->vm, dma, slot, I915_CACHE_NONE, 0); > > s = io_mapping_map_atomic_wc(&ggtt->iomap, slot); > ret = compress_page(&compress, (void __force *)s, dst); > io_mapping_unmap_atomic(s); > - > if (ret) > - goto unwind; > + break; > } > - goto out; > > -unwind: > - while (dst->page_count--) > - free_page((unsigned long)dst->pages[dst->page_count]); > - kfree(dst); > - dst = NULL; > + if (ret || compress_flush(&compress, dst)) { > + while (dst->page_count--) > + free_page((unsigned long)dst->pages[dst->page_count]); > + kfree(dst); > + dst = NULL; > + } > > -out: > compress_fini(&compress, dst); > ggtt->vm.clear_range(&ggtt->vm, slot, PAGE_SIZE); > return dst; > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h > index f893a4e8b783..8710fb18ed74 100644 > --- a/drivers/gpu/drm/i915/i915_gpu_error.h > +++ b/drivers/gpu/drm/i915/i915_gpu_error.h > @@ -135,6 +135,7 @@ struct i915_gpu_state { > struct drm_i915_error_object { > u64 gtt_offset; > u64 gtt_size; > + int num_pages; > int page_count; > int unused; > u32 *pages[0]; > Reviewed-by: Tvrtko Ursulin Regards, Tvrtko From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tvrtko Ursulin Subject: Re: [PATCH v3] drm/i915: Handle incomplete Z_FINISH for compressed error states Date: Wed, 3 Oct 2018 10:04:04 +0100 Message-ID: References: <20181001194447.29910-2-chris@chris-wilson.co.uk> <20181003082422.23214-1-chris@chris-wilson.co.uk> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 93E346E251 for ; Wed, 3 Oct 2018 09:04:09 +0000 (UTC) In-Reply-To: <20181003082422.23214-1-chris@chris-wilson.co.uk> Content-Language: en-GB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Chris Wilson , intel-gfx@lists.freedesktop.org Cc: stable@vger.kernel.org List-Id: intel-gfx@lists.freedesktop.org Ck9uIDAzLzEwLzIwMTggMDk6MjQsIENocmlzIFdpbHNvbiB3cm90ZToKPiBUaGUgZmluYWwgY2Fs bCB0byB6bGliX2RlZmxhdGUoWl9GSU5JU0gpIG1heSByZXF1aXJlIG1vcmUgb3V0cHV0Cj4gc3Bh Y2UgdG8gYmUgYWxsb2NhdGVkIGFuZCBzbyBuZWVkcyB0byByZS1pbnZva2VkLiBGYWlsdXJlIHRv IGRvIHNvIGluCj4gdGhlIGN1cnJlbnQgY29kZSBsZWFkcyB0byBpbmNvbXBsZXRlIHpsaWIgc3Ry ZWFtcyAoYWxiZWl0IGludGFjdCBkdWUgdG8KPiB0aGUgdXNlIG9mIFpfU1lOQ19GTFVTSCkgcmVz dWx0aW5nIGluIHRoZSBvY2Nhc2lvbmFsIHNob3J0IG9iamVjdAo+IGNhcHR1cmUuCj4gCj4gdjI6 IENoZWNrIGFnYWluc3Qgb3ZlcnJ1bm5pbmcgb3VyIHByZS1hbGxvY2F0ZWQgcGFnZSBhcnJheQo+ IHYzOiBEcm9wIFpfU1lOQ19GTFVTSCBlbnRpcmVseQo+IAo+IFRlc3RjYXNlOiBpZ3QvaTkxNS1l cnJvci1jYXB0dXJlLmpzCj4gRml4ZXM6IDBhOTcwMTVkNDVlZSAoImRybS9pOTE1OiBDb21wcmVz cyBHUFUgb2JqZWN0cyBpbiBlcnJvciBzdGF0ZSIpCj4gU2lnbmVkLW9mZi1ieTogQ2hyaXMgV2ls c29uIDxjaHJpc0BjaHJpcy13aWxzb24uY28udWs+Cj4gQ2M6IEpvb25hcyBMYWh0aW5lbiA8am9v bmFzLmxhaHRpbmVuQGxpbnV4LmludGVsLmNvbT4KPiBDYzogPHN0YWJsZUB2Z2VyLmtlcm5lbC5v cmc+ICMgdjQuMTArCj4gQ2M6IFR2cnRrbyBVcnN1bGluIDx0dnJ0a28udXJzdWxpbkBpbnRlbC5j b20+Cj4gLS0tCj4gICBkcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X2dwdV9lcnJvci5jIHwgODgg KysrKysrKysrKysrKysrKysrKy0tLS0tLS0tCj4gICBkcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1 X2dwdV9lcnJvci5oIHwgIDEgKwo+ICAgMiBmaWxlcyBjaGFuZ2VkLCA2NCBpbnNlcnRpb25zKCsp LCAyNSBkZWxldGlvbnMoLSkKPiAKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5MTUv aTkxNV9ncHVfZXJyb3IuYyBiL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfZ3B1X2Vycm9yLmMK PiBpbmRleCAzZDU1NTRmMTRkZmQuLjcwNWZmMTIyMTAwZiAxMDA2NDQKPiAtLS0gYS9kcml2ZXJz L2dwdS9kcm0vaTkxNS9pOTE1X2dwdV9lcnJvci5jCj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL2k5 MTUvaTkxNV9ncHVfZXJyb3IuYwo+IEBAIC0yMzIsNiArMjMyLDIwIEBAIHN0YXRpYyBib29sIGNv bXByZXNzX2luaXQoc3RydWN0IGNvbXByZXNzICpjKQo+ICAgCXJldHVybiB0cnVlOwo+ICAgfQo+ ICAgCj4gK3N0YXRpYyB2b2lkICpjb21wcmVzc19uZXh0X3BhZ2Uoc3RydWN0IGRybV9pOTE1X2Vy cm9yX29iamVjdCAqZHN0KQo+ICt7Cj4gKwl1bnNpZ25lZCBsb25nIHBhZ2U7Cj4gKwo+ICsJaWYg KGRzdC0+cGFnZV9jb3VudCA+PSBkc3QtPm51bV9wYWdlcykKPiArCQlyZXR1cm4gRVJSX1BUUigt RU5PU1BDKTsKPiArCj4gKwlwYWdlID0gX19nZXRfZnJlZV9wYWdlKEdGUF9BVE9NSUMgfCBfX0dG UF9OT1dBUk4pOwo+ICsJaWYgKCFwYWdlKQo+ICsJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0pOwo+ ICsKPiArCXJldHVybiBkc3QtPnBhZ2VzW2RzdC0+cGFnZV9jb3VudCsrXSA9ICh2b2lkICopcGFn ZTsKPiArfQo+ICsKPiAgIHN0YXRpYyBpbnQgY29tcHJlc3NfcGFnZShzdHJ1Y3QgY29tcHJlc3Mg KmMsCj4gICAJCQkgdm9pZCAqc3JjLAo+ICAgCQkJIHN0cnVjdCBkcm1faTkxNV9lcnJvcl9vYmpl Y3QgKmRzdCkKPiBAQCAtMjQ1LDE5ICsyNTksMTQgQEAgc3RhdGljIGludCBjb21wcmVzc19wYWdl KHN0cnVjdCBjb21wcmVzcyAqYywKPiAgIAo+ICAgCWRvIHsKPiAgIAkJaWYgKHpzdHJlYW0tPmF2 YWlsX291dCA9PSAwKSB7Cj4gLQkJCXVuc2lnbmVkIGxvbmcgcGFnZTsKPiAtCj4gLQkJCXBhZ2Ug PSBfX2dldF9mcmVlX3BhZ2UoR0ZQX0FUT01JQyB8IF9fR0ZQX05PV0FSTik7Cj4gLQkJCWlmICgh cGFnZSkKPiAtCQkJCXJldHVybiAtRU5PTUVNOwo+ICsJCQl6c3RyZWFtLT5uZXh0X291dCA9IGNv bXByZXNzX25leHRfcGFnZShkc3QpOwo+ICsJCQlpZiAoSVNfRVJSKHpzdHJlYW0tPm5leHRfb3V0 KSkKPiArCQkJCXJldHVybiBQVFJfRVJSKHpzdHJlYW0tPm5leHRfb3V0KTsKPiAgIAo+IC0JCQlk c3QtPnBhZ2VzW2RzdC0+cGFnZV9jb3VudCsrXSA9ICh2b2lkICopcGFnZTsKPiAtCj4gLQkJCXpz dHJlYW0tPm5leHRfb3V0ID0gKHZvaWQgKilwYWdlOwo+ICAgCQkJenN0cmVhbS0+YXZhaWxfb3V0 ID0gUEFHRV9TSVpFOwo+ICAgCQl9Cj4gICAKPiAtCQlpZiAoemxpYl9kZWZsYXRlKHpzdHJlYW0s IFpfU1lOQ19GTFVTSCkgIT0gWl9PSykKPiArCQlpZiAoemxpYl9kZWZsYXRlKHpzdHJlYW0sIFpf Tk9fRkxVU0gpICE9IFpfT0spCj4gICAJCQlyZXR1cm4gLUVJTzsKPiAgIAl9IHdoaWxlICh6c3Ry ZWFtLT5hdmFpbF9pbik7Cj4gICAKPiBAQCAtMjY4LDE5ICsyNzcsNDIgQEAgc3RhdGljIGludCBj b21wcmVzc19wYWdlKHN0cnVjdCBjb21wcmVzcyAqYywKPiAgIAlyZXR1cm4gMDsKPiAgIH0KPiAg IAo+IC1zdGF0aWMgdm9pZCBjb21wcmVzc19maW5pKHN0cnVjdCBjb21wcmVzcyAqYywKPiArc3Rh dGljIGludCBjb21wcmVzc19mbHVzaChzdHJ1Y3QgY29tcHJlc3MgKmMsCj4gICAJCQkgIHN0cnVj dCBkcm1faTkxNV9lcnJvcl9vYmplY3QgKmRzdCkKPiAgIHsKPiAgIAlzdHJ1Y3Qgel9zdHJlYW1f cyAqenN0cmVhbSA9ICZjLT56c3RyZWFtOwo+ICAgCj4gLQlpZiAoZHN0KSB7Cj4gLQkJemxpYl9k ZWZsYXRlKHpzdHJlYW0sIFpfRklOSVNIKTsKPiAtCQlkc3QtPnVudXNlZCA9IHpzdHJlYW0tPmF2 YWlsX291dDsKPiAtCX0KPiArCWRvIHsKPiArCQlzd2l0Y2ggKHpsaWJfZGVmbGF0ZSh6c3RyZWFt LCBaX0ZJTklTSCkpIHsKPiArCQljYXNlIFpfT0s6IC8qIG1vcmUgc3BhY2UgcmVxdWVzdGVkICov Cj4gKwkJCXpzdHJlYW0tPm5leHRfb3V0ID0gY29tcHJlc3NfbmV4dF9wYWdlKGRzdCk7Cj4gKwkJ CWlmIChJU19FUlIoenN0cmVhbS0+bmV4dF9vdXQpKQo+ICsJCQkJcmV0dXJuIFBUUl9FUlIoenN0 cmVhbS0+bmV4dF9vdXQpOwo+ICsKPiArCQkJenN0cmVhbS0+YXZhaWxfb3V0ID0gUEFHRV9TSVpF Owo+ICsJCQlicmVhazsKPiArCj4gKwkJY2FzZSBaX1NUUkVBTV9FTkQ6Cj4gKwkJCWdvdG8gZW5k Owo+ICsKPiArCQlkZWZhdWx0OiAvKiBhbnkgZXJyb3IgKi8KPiArCQkJcmV0dXJuIC1FSU87Cj4g KwkJfQo+ICsJfSB3aGlsZSAoMSk7Cj4gKwo+ICtlbmQ6Cj4gKwltZW1zZXQoenN0cmVhbS0+bmV4 dF9vdXQsIDAsIHpzdHJlYW0tPmF2YWlsX291dCk7Cj4gKwlkc3QtPnVudXNlZCA9IHpzdHJlYW0t PmF2YWlsX291dDsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjb21wcmVz c19maW5pKHN0cnVjdCBjb21wcmVzcyAqYywKPiArCQkJICBzdHJ1Y3QgZHJtX2k5MTVfZXJyb3Jf b2JqZWN0ICpkc3QpCj4gK3sKPiArCXN0cnVjdCB6X3N0cmVhbV9zICp6c3RyZWFtID0gJmMtPnpz dHJlYW07Cj4gICAKPiAgIAl6bGliX2RlZmxhdGVFbmQoenN0cmVhbSk7Cj4gICAJa2ZyZWUoenN0 cmVhbS0+d29ya3NwYWNlKTsKPiAtCj4gICAJaWYgKGMtPnRtcCkKPiAgIAkJZnJlZV9wYWdlKCh1 bnNpZ25lZCBsb25nKWMtPnRtcCk7Cj4gICB9Cj4gQEAgLTMxOSw2ICszNTEsMTIgQEAgc3RhdGlj IGludCBjb21wcmVzc19wYWdlKHN0cnVjdCBjb21wcmVzcyAqYywKPiAgIAlyZXR1cm4gMDsKPiAg IH0KPiAgIAo+ICtzdGF0aWMgaW50IGNvbXByZXNzX2ZsdXNoKHN0cnVjdCBjb21wcmVzcyAqYywK PiArCQkJICBzdHJ1Y3QgZHJtX2k5MTVfZXJyb3Jfb2JqZWN0ICpkc3QpCj4gK3sKPiArCXJldHVy biAwOwo+ICt9Cj4gKwo+ICAgc3RhdGljIHZvaWQgY29tcHJlc3NfZmluaShzdHJ1Y3QgY29tcHJl c3MgKmMsCj4gICAJCQkgIHN0cnVjdCBkcm1faTkxNV9lcnJvcl9vYmplY3QgKmRzdCkKPiAgIHsK PiBAQCAtOTE3LDYgKzk1NSw3IEBAIGk5MTVfZXJyb3Jfb2JqZWN0X2NyZWF0ZShzdHJ1Y3QgZHJt X2k5MTVfcHJpdmF0ZSAqaTkxNSwKPiAgIAl1bnNpZ25lZCBsb25nIG51bV9wYWdlczsKPiAgIAlz dHJ1Y3Qgc2d0X2l0ZXIgaXRlcjsKPiAgIAlkbWFfYWRkcl90IGRtYTsKPiArCWludCByZXQ7Cj4g ICAKPiAgIAlpZiAoIXZtYSkKPiAgIAkJcmV0dXJuIE5VTEw7Cj4gQEAgLTkzMCw2ICs5NjksNyBA QCBpOTE1X2Vycm9yX29iamVjdF9jcmVhdGUoc3RydWN0IGRybV9pOTE1X3ByaXZhdGUgKmk5MTUs Cj4gICAKPiAgIAlkc3QtPmd0dF9vZmZzZXQgPSB2bWEtPm5vZGUuc3RhcnQ7Cj4gICAJZHN0LT5n dHRfc2l6ZSA9IHZtYS0+bm9kZS5zaXplOwo+ICsJZHN0LT5udW1fcGFnZXMgPSBudW1fcGFnZXM7 Cj4gICAJZHN0LT5wYWdlX2NvdW50ID0gMDsKPiAgIAlkc3QtPnVudXNlZCA9IDA7Cj4gICAKPiBA QCAtOTM4LDI4ICs5NzgsMjYgQEAgaTkxNV9lcnJvcl9vYmplY3RfY3JlYXRlKHN0cnVjdCBkcm1f aTkxNV9wcml2YXRlICppOTE1LAo+ICAgCQlyZXR1cm4gTlVMTDsKPiAgIAl9Cj4gICAKPiArCXJl dCA9IC1FSU5WQUw7Cj4gICAJZm9yX2VhY2hfc2d0X2RtYShkbWEsIGl0ZXIsIHZtYS0+cGFnZXMp ICA+ICAgCQl2b2lkIF9faW9tZW0gKnM7Cj4gLQkJaW50IHJldDsKPiAgIAo+ICAgCQlnZ3R0LT52 bS5pbnNlcnRfcGFnZSgmZ2d0dC0+dm0sIGRtYSwgc2xvdCwgSTkxNV9DQUNIRV9OT05FLCAwKTsK PiAgIAo+ICAgCQlzID0gaW9fbWFwcGluZ19tYXBfYXRvbWljX3djKCZnZ3R0LT5pb21hcCwgc2xv dCk7Cj4gICAJCXJldCA9IGNvbXByZXNzX3BhZ2UoJmNvbXByZXNzLCAodm9pZCAgX19mb3JjZSAq KXMsIGRzdCk7Cj4gICAJCWlvX21hcHBpbmdfdW5tYXBfYXRvbWljKHMpOwo+IC0KPiAgIAkJaWYg KHJldCkKPiAtCQkJZ290byB1bndpbmQ7Cj4gKwkJCWJyZWFrOwo+ICAgCX0KPiAtCWdvdG8gb3V0 Owo+ICAgCj4gLXVud2luZDoKPiAtCXdoaWxlIChkc3QtPnBhZ2VfY291bnQtLSkKPiAtCQlmcmVl X3BhZ2UoKHVuc2lnbmVkIGxvbmcpZHN0LT5wYWdlc1tkc3QtPnBhZ2VfY291bnRdKTsKPiAtCWtm cmVlKGRzdCk7Cj4gLQlkc3QgPSBOVUxMOwo+ICsJaWYgKHJldCB8fCBjb21wcmVzc19mbHVzaCgm Y29tcHJlc3MsIGRzdCkpIHsKPiArCQl3aGlsZSAoZHN0LT5wYWdlX2NvdW50LS0pCj4gKwkJCWZy ZWVfcGFnZSgodW5zaWduZWQgbG9uZylkc3QtPnBhZ2VzW2RzdC0+cGFnZV9jb3VudF0pOwo+ICsJ CWtmcmVlKGRzdCk7Cj4gKwkJZHN0ID0gTlVMTDsKPiArCX0KPiAgIAo+IC1vdXQ6Cj4gICAJY29t cHJlc3NfZmluaSgmY29tcHJlc3MsIGRzdCk7Cj4gICAJZ2d0dC0+dm0uY2xlYXJfcmFuZ2UoJmdn dHQtPnZtLCBzbG90LCBQQUdFX1NJWkUpOwo+ICAgCXJldHVybiBkc3Q7Cj4gZGlmZiAtLWdpdCBh L2RyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfZ3B1X2Vycm9yLmggYi9kcml2ZXJzL2dwdS9kcm0v aTkxNS9pOTE1X2dwdV9lcnJvci5oCj4gaW5kZXggZjg5M2E0ZThiNzgzLi44NzEwZmIxOGVkNzQg MTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9ncHVfZXJyb3IuaAo+ICsr KyBiL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfZ3B1X2Vycm9yLmgKPiBAQCAtMTM1LDYgKzEz NSw3IEBAIHN0cnVjdCBpOTE1X2dwdV9zdGF0ZSB7Cj4gICAJCXN0cnVjdCBkcm1faTkxNV9lcnJv cl9vYmplY3Qgewo+ICAgCQkJdTY0IGd0dF9vZmZzZXQ7Cj4gICAJCQl1NjQgZ3R0X3NpemU7Cj4g KwkJCWludCBudW1fcGFnZXM7Cj4gICAJCQlpbnQgcGFnZV9jb3VudDsKPiAgIAkJCWludCB1bnVz ZWQ7Cj4gICAJCQl1MzIgKnBhZ2VzWzBdOwo+IAoKUmV2aWV3ZWQtYnk6IFR2cnRrbyBVcnN1bGlu IDx0dnJ0a28udXJzdWxpbkBpbnRlbC5jb20+CgpSZWdhcmRzLAoKVHZydGtvCl9fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCkludGVsLWdmeCBtYWlsaW5nIGxp c3QKSW50ZWwtZ2Z4QGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNr dG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2ludGVsLWdmeAo=