From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52193) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1biKzF-0006uW-2U for qemu-devel@nongnu.org; Fri, 09 Sep 2016 08:32:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1biKzA-0002Tz-Sv for qemu-devel@nongnu.org; Fri, 09 Sep 2016 08:32:52 -0400 Received: from mail-lf0-x242.google.com ([2a00:1450:4010:c07::242]:36727) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1biKzA-0002Ti-EU for qemu-devel@nongnu.org; Fri, 09 Sep 2016 08:32:48 -0400 Received: by mail-lf0-x242.google.com with SMTP id s29so2636938lfg.3 for ; Fri, 09 Sep 2016 05:32:47 -0700 (PDT) References: <1473244860-6072-1-git-send-email-paulinaszubarczyk@gmail.com> <1473244860-6072-3-git-send-email-paulinaszubarczyk@gmail.com> <57D08E12.4080607@gmail.com> From: Paulina Szubarczyk Message-ID: <57D2ABE9.9070800@gmail.com> Date: Fri, 9 Sep 2016 14:32:41 +0200 MIME-Version: 1.0 In-Reply-To: <57D08E12.4080607@gmail.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v6 2/2] qdisk - hw/block/xen_disk: grant copy implementation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: roger.pau@citrix.com Cc: Stefano Stabellini , xen-devel@lists.xenproject.org, wei.liu2@citrix.com, ian.jackson@eu.citrix.com, david.vrabel@citrix.com, anthony.perard@citrix.com, qemu-devel@nongnu.org On 09/08/2016 12:00 AM, Paulina Szubarczyk wrote: > > On 09/07/2016 10:56 PM, Stefano Stabellini wrote: >> On Wed, 7 Sep 2016, Paulina Szubarczyk wrote: >>> Copy data operated on during request from/to local buffers to/from >>> the grant references. >>> >>> Before grant copy operation local buffers must be allocated what is >>> done by calling ioreq_init_copy_buffers. For the 'read' operation, >>> first, the qemu device invokes the read operation on local buffers >>> and on the completion grant copy is called and buffers are freed. >>> For the 'write' operation grant copy is performed before invoking >>> write by qemu device. >>> >>> A new value 'feature_grant_copy' is added to recognize when the >>> grant copy operation is supported by a guest. >>> >>> Signed-off-by: Paulina Szubarczyk >>> --- >>> Changes since v5: >>> -added checking of every interface in the configure file. Based on >>> the Roger's comment that xengnttab_map_grant_ref was added prior >>> xengnttab_grant_copy, thus do not need to be check again here >>> I dropped this check. >>> >> >> Thank you Paulina, the patch is good. Thanks for your work! Sorry for >> coming in late in the review; I have a couple of minor suggestions >> below. >> > It had not been possible without all the help I have got. I am very > grateful for it. > >> In addition to Anthony's ack, it would be also nice to have Roger's ack >> on this patch. >> Roger, will you need more time to take a look at the patch or may I send a new version with applied Stefano comments? >> >>> configure | 55 ++++++++++++++++ >>> hw/block/xen_disk.c | 157 >>> ++++++++++++++++++++++++++++++++++++++++++-- >>> include/hw/xen/xen_common.h | 14 ++++ >>> 3 files changed, 221 insertions(+), 5 deletions(-) >>> >>> diff --git a/configure b/configure >>> index 4b808f9..3f44d38 100755 >>> --- a/configure >>> +++ b/configure >>> @@ -1956,6 +1956,61 @@ EOF >>> /* >>> * If we have stable libs the we don't want the libxc compat >>> * layers, regardless of what CFLAGS we may have been given. >>> + * >>> + * Also, check if xengnttab_grant_copy_segment_t is defined and >>> + * grant copy operation is implemented. >>> + */ >>> +#undef XC_WANT_COMPAT_EVTCHN_API >>> +#undef XC_WANT_COMPAT_GNTTAB_API >>> +#undef XC_WANT_COMPAT_MAP_FOREIGN_API >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#if !defined(HVM_MAX_VCPUS) >>> +# error HVM_MAX_VCPUS not defined >>> +#endif >>> +int main(void) { >>> + xc_interface *xc = NULL; >>> + xenforeignmemory_handle *xfmem; >>> + xenevtchn_handle *xe; >>> + xengnttab_handle *xg; >>> + xen_domain_handle_t handle; >>> + xengnttab_grant_copy_segment_t* seg = NULL; >>> + >>> + xs_daemon_open(); >>> + >>> + xc = xc_interface_open(0, 0, 0); >>> + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); >>> + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); >>> + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); >>> + xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, >>> NULL); >>> + xc_domain_create(xc, 0, handle, 0, NULL, NULL); >>> + >>> + xfmem = xenforeignmemory_open(0, 0); >>> + xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0); >>> + >>> + xe = xenevtchn_open(0, 0); >>> + xenevtchn_fd(xe); >>> + >>> + xg = xengnttab_open(0, 0); >>> + xengnttab_grant_copy(xg, 0, seg); >>> + >>> + return 0; >>> +} >>> +EOF >>> + compile_prog "" "$xen_libs $xen_stable_libs" >>> + then >>> + xen_ctrl_version=480 >>> + xen=yes >>> + elif >>> + cat > $TMPC <>> +/* >>> + * If we have stable libs the we don't want the libxc compat >>> + * layers, regardless of what CFLAGS we may have been given. >>> */ >>> #undef XC_WANT_COMPAT_EVTCHN_API >>> #undef XC_WANT_COMPAT_GNTTAB_API >>> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c >>> index 3b8ad33..3739e13 100644 >>> --- a/hw/block/xen_disk.c >>> +++ b/hw/block/xen_disk.c >>> @@ -119,6 +119,9 @@ struct XenBlkDev { >>> unsigned int persistent_gnt_count; >>> unsigned int max_grants; >>> >>> + /* Grant copy */ >>> + gboolean feature_grant_copy; >>> + >>> /* qemu block driver */ >>> DriveInfo *dinfo; >>> BlockBackend *blk; >>> @@ -489,6 +492,108 @@ static int ioreq_map(struct ioreq *ioreq) >>> return 0; >>> } >>> >>> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 480 >> >> In general I prefer to avoid this kind of #ifdef in xen_disk.c, but I >> see that Anthony suggested it for a good reason. The only alternartive I >> can think of would be to introduce two static inline functions in >> xen_common.h to set a xengnttab_grant_copy_segment_t seg. But this is >> also OK. >> > The functions take as parameters pointers to struct ioreq defined in > xen_disk.c which members are used to fill the > xengnttab_grant_copy_segment_t. There would be some overhead to move the > functions to the header. >> >>> +static void free_buffers(struct ioreq *ioreq) >> >> Please name this function ioreq_free_copy_buffers to make it clearer >> that has to do with the same buffers initialized below. >> >> >>> +{ >>> + int i; >>> + >>> + for (i = 0; i < ioreq->v.niov; i++) { >>> + ioreq->page[i] = NULL; >>> + } >>> + >>> + qemu_vfree(ioreq->pages); >>> +} >>> + >>> +static int ioreq_init_copy_buffers(struct ioreq *ioreq) >>> +{ >>> + int i; >>> + >>> + if (ioreq->v.niov == 0) { >>> + return 0; >>> + } >>> + >>> + ioreq->pages = qemu_memalign(XC_PAGE_SIZE, ioreq->v.niov * >>> XC_PAGE_SIZE); >>> + >>> + for (i = 0; i < ioreq->v.niov; i++) { >>> + ioreq->page[i] = ioreq->pages + i * XC_PAGE_SIZE; >>> + ioreq->v.iov[i].iov_base = ioreq->page[i]; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static int ioreq_copy(struct ioreq *ioreq) >> >> Please name this function in a way that makes it clear that it has >> something to do with grant copies. Like for example ioreq_grant_copy. >> > I will change the names of both functions and remove the blank line > pointed below. >> >>> +{ >>> + xengnttab_handle *gnt = ioreq->blkdev->xendev.gnttabdev; >>> + xengnttab_grant_copy_segment_t >>> segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; >>> + int i, count, rc; >>> + int64_t file_blk = ioreq->blkdev->file_blk; >>> + >>> + if (ioreq->v.niov == 0) { >>> + return 0; >>> + } >>> + >>> + count = ioreq->v.niov; >>> + >>> + for (i = 0; i < count; i++) { >>> + >>> + if (ioreq->req.operation == BLKIF_OP_READ) { >>> + segs[i].flags = GNTCOPY_dest_gref; >>> + segs[i].dest.foreign.ref = ioreq->refs[i]; >>> + segs[i].dest.foreign.domid = ioreq->domids[i]; >>> + segs[i].dest.foreign.offset = >>> ioreq->req.seg[i].first_sect * file_blk; >>> + segs[i].source.virt = ioreq->v.iov[i].iov_base; >>> + } else { >>> + segs[i].flags = GNTCOPY_source_gref; >>> + segs[i].source.foreign.ref = ioreq->refs[i]; >>> + segs[i].source.foreign.domid = ioreq->domids[i]; >>> + segs[i].source.foreign.offset = >>> ioreq->req.seg[i].first_sect * file_blk; >>> + segs[i].dest.virt = ioreq->v.iov[i].iov_base; >>> + } >>> + segs[i].len = (ioreq->req.seg[i].last_sect >>> + - ioreq->req.seg[i].first_sect + 1) * file_blk; >>> + >>> + } >>> + >>> + rc = xengnttab_grant_copy(gnt, count, segs); >>> + >>> + if (rc) { >>> + xen_be_printf(&ioreq->blkdev->xendev, 0, >>> + "failed to copy data %d\n", rc); >>> + ioreq->aio_errors++; >>> + return -1; >>> + } >>> + >>> + for (i = 0; i < count; i++) { >>> + if (segs[i].status != GNTST_okay) { >>> + xen_be_printf(&ioreq->blkdev->xendev, 3, >>> + "failed to copy data %d for gref %d, domid >>> %d\n", >>> + segs[i].status, ioreq->refs[i], >>> ioreq->domids[i]); >>> + ioreq->aio_errors++; >>> + rc = -1; >>> + } >>> + } >>> + >>> + return rc; >>> +} >>> +#else >>> +static void free_buffers(struct ioreq *ioreq) >>> +{ >>> + abort(); >>> +} >>> + >>> +static int ioreq_init_copy_buffers(struct ioreq *ioreq) >>> +{ >>> + abort(); >>> +} >>> + >>> +static int ioreq_copy(struct ioreq *ioreq) >>> +{ >>> + abort(); >>> +} >>> +#endif >>> + >>> static int ioreq_runio_qemu_aio(struct ioreq *ioreq); >>> >>> static void qemu_aio_complete(void *opaque, int ret) >>> @@ -511,8 +616,31 @@ static void qemu_aio_complete(void *opaque, int >>> ret) >>> return; >>> } >>> >>> + if (ioreq->blkdev->feature_grant_copy) { >>> + switch (ioreq->req.operation) { >>> + case BLKIF_OP_READ: >>> + /* in case of failure ioreq->aio_errors is increased */ >>> + if (ret == 0) { >>> + ioreq_copy(ioreq); >>> + } >>> + free_buffers(ioreq); >>> + break; >>> + case BLKIF_OP_WRITE: >>> + case BLKIF_OP_FLUSH_DISKCACHE: >>> + if (!ioreq->req.nr_segments) { >>> + break; >>> + } >>> + free_buffers(ioreq); >>> + break; >>> + default: >>> + break; >>> + } >>> + } >>> + >>> ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : >>> BLKIF_RSP_OKAY; >>> - ioreq_unmap(ioreq); >>> + if (!ioreq->blkdev->feature_grant_copy) { >>> + ioreq_unmap(ioreq); >>> + } >>> ioreq_finish(ioreq); >>> switch (ioreq->req.operation) { >>> case BLKIF_OP_WRITE: >>> @@ -538,8 +666,20 @@ static int ioreq_runio_qemu_aio(struct ioreq >>> *ioreq) >>> { >>> struct XenBlkDev *blkdev = ioreq->blkdev; >>> >>> - if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) { >>> - goto err_no_map; >>> + if (ioreq->blkdev->feature_grant_copy) { >>> + ioreq_init_copy_buffers(ioreq); >>> + if (ioreq->req.nr_segments && (ioreq->req.operation == >>> BLKIF_OP_WRITE || >>> + ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE)) { >>> + if (ioreq_copy(ioreq)) { >>> + free_buffers(ioreq); >>> + goto err; >>> + } >>> + } >>> + >> >> Please remove blank this line (it looks a bit odd) >> >> >>> + } else { >>> + if (ioreq->req.nr_segments && ioreq_map(ioreq)) { >>> + goto err; >>> + } >>> } >>> >>> ioreq->aio_inflight++; >>> @@ -582,6 +722,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) >>> } >>> default: >>> /* unknown operation (shouldn't happen -- parse catches >>> this) */ >>> + if (!ioreq->blkdev->feature_grant_copy) { >>> + ioreq_unmap(ioreq); >>> + } >> >> Why are you adding this? Is it a bug fix? If so, please explain in the >> commit message. >> > It is not a bug fix. In the ioreq_runio_qemu_aio there were two error > labels 'err_no_map' and 'err' each of them used once. So before the > patch the labels are looking this way: > err: > ioreq_unmap(ioreq); > err_no_map: > ioreq_finish(ioreq); > ioreq->status = BLKIF_RSP_ERROR; > return -1; > > I removed the 'err_no_map' label and from the 'err' section I removed > the ioreq_unmap. The 'err' label was previously used in that default > section of the switch because the grant_map is called regardless the > ioreq->req.operation. > > In the patch, there is no need for any special behavior for grant_copy, > because buffers were not allocated in this case, so there is only jump > to 'err'. > > An advantage of this change is one unified error path for both grant > operations. >> >>> goto err; >>> } >>> >>> @@ -590,8 +733,6 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) >>> return 0; >>> >>> err: >>> - ioreq_unmap(ioreq); >>> -err_no_map: >>> ioreq_finish(ioreq); >>> ioreq->status = BLKIF_RSP_ERROR; >>> return -1; >>> @@ -1032,6 +1173,12 @@ static int blk_connect(struct XenDevice *xendev) >>> >>> xen_be_bind_evtchn(&blkdev->xendev); >>> >>> + blkdev->feature_grant_copy = >>> + (xengnttab_grant_copy(blkdev->xendev.gnttabdev, 0, >>> NULL) == 0); >>> + >>> + xen_be_printf(&blkdev->xendev, 3, "grant copy operation %s\n", >>> + blkdev->feature_grant_copy ? "enabled" : "disabled"); >>> + >>> xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, " >>> "remote port %d, local port %d\n", >>> blkdev->xendev.protocol, blkdev->ring_ref, >>> diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h >>> index bd39287..8e1580d 100644 >>> --- a/include/hw/xen/xen_common.h >>> +++ b/include/hw/xen/xen_common.h >>> @@ -424,4 +424,18 @@ static inline int xen_domain_create(xc_interface >>> *xc, uint32_t ssidref, >>> #endif >>> #endif >>> >>> +/* Xen before 4.8 */ >>> + >>> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 480 >>> + >>> + >>> +typedef void *xengnttab_grant_copy_segment_t; >>> + >>> +static inline int xengnttab_grant_copy(xengnttab_handle *xgt, >>> uint32_t count, >>> + >>> xengnttab_grant_copy_segment_t *segs) >>> +{ >>> + return -ENOSYS; >>> +} >>> +#endif >>> + >>> #endif /* QEMU_HW_XEN_COMMON_H */ >>> -- >>> 1.9.1 >>> > > Paulina Paulina From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paulina Szubarczyk Subject: Re: [PATCH v6 2/2] qdisk - hw/block/xen_disk: grant copy implementation Date: Fri, 9 Sep 2016 14:32:41 +0200 Message-ID: <57D2ABE9.9070800@gmail.com> References: <1473244860-6072-1-git-send-email-paulinaszubarczyk@gmail.com> <1473244860-6072-3-git-send-email-paulinaszubarczyk@gmail.com> <57D08E12.4080607@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1biKzE-0002L2-H8 for xen-devel@lists.xenproject.org; Fri, 09 Sep 2016 12:32:52 +0000 Received: by mail-lf0-f67.google.com with SMTP id l131so2697914lfl.0 for ; Fri, 09 Sep 2016 05:32:50 -0700 (PDT) In-Reply-To: <57D08E12.4080607@gmail.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: roger.pau@citrix.com Cc: Stefano Stabellini , wei.liu2@citrix.com, ian.jackson@eu.citrix.com, qemu-devel@nongnu.org, david.vrabel@citrix.com, anthony.perard@citrix.com, xen-devel@lists.xenproject.org List-Id: xen-devel@lists.xenproject.org CgpPbiAwOS8wOC8yMDE2IDEyOjAwIEFNLCBQYXVsaW5hIFN6dWJhcmN6eWsgd3JvdGU6Cj4KPiBP biAwOS8wNy8yMDE2IDEwOjU2IFBNLCBTdGVmYW5vIFN0YWJlbGxpbmkgd3JvdGU6Cj4+IE9uIFdl ZCwgNyBTZXAgMjAxNiwgUGF1bGluYSBTenViYXJjenlrIHdyb3RlOgo+Pj4gQ29weSBkYXRhIG9w ZXJhdGVkIG9uIGR1cmluZyByZXF1ZXN0IGZyb20vdG8gbG9jYWwgYnVmZmVycyB0by9mcm9tCj4+ PiB0aGUgZ3JhbnQgcmVmZXJlbmNlcy4KPj4+Cj4+PiBCZWZvcmUgZ3JhbnQgY29weSBvcGVyYXRp b24gbG9jYWwgYnVmZmVycyBtdXN0IGJlIGFsbG9jYXRlZCB3aGF0IGlzCj4+PiBkb25lIGJ5IGNh bGxpbmcgaW9yZXFfaW5pdF9jb3B5X2J1ZmZlcnMuIEZvciB0aGUgJ3JlYWQnIG9wZXJhdGlvbiwK Pj4+IGZpcnN0LCB0aGUgcWVtdSBkZXZpY2UgaW52b2tlcyB0aGUgcmVhZCBvcGVyYXRpb24gb24g bG9jYWwgYnVmZmVycwo+Pj4gYW5kIG9uIHRoZSBjb21wbGV0aW9uIGdyYW50IGNvcHkgaXMgY2Fs bGVkIGFuZCBidWZmZXJzIGFyZSBmcmVlZC4KPj4+IEZvciB0aGUgJ3dyaXRlJyBvcGVyYXRpb24g Z3JhbnQgY29weSBpcyBwZXJmb3JtZWQgYmVmb3JlIGludm9raW5nCj4+PiB3cml0ZSBieSBxZW11 IGRldmljZS4KPj4+Cj4+PiBBIG5ldyB2YWx1ZSAnZmVhdHVyZV9ncmFudF9jb3B5JyBpcyBhZGRl ZCB0byByZWNvZ25pemUgd2hlbiB0aGUKPj4+IGdyYW50IGNvcHkgb3BlcmF0aW9uIGlzIHN1cHBv cnRlZCBieSBhIGd1ZXN0Lgo+Pj4KPj4+IFNpZ25lZC1vZmYtYnk6IFBhdWxpbmEgU3p1YmFyY3p5 ayA8cGF1bGluYXN6dWJhcmN6eWtAZ21haWwuY29tPgo+Pj4gLS0tCj4+PiBDaGFuZ2VzIHNpbmNl IHY1Ogo+Pj4gLWFkZGVkIGNoZWNraW5nIG9mIGV2ZXJ5IGludGVyZmFjZSBpbiB0aGUgY29uZmln dXJlIGZpbGUuIEJhc2VkIG9uCj4+PiAgIHRoZSBSb2dlcidzIGNvbW1lbnQgdGhhdCB4ZW5nbnR0 YWJfbWFwX2dyYW50X3JlZiB3YXMgYWRkZWQgcHJpb3IKPj4+ICAgeGVuZ250dGFiX2dyYW50X2Nv cHksIHRodXMgZG8gbm90IG5lZWQgdG8gYmUgY2hlY2sgYWdhaW4gaGVyZQo+Pj4gICBJIGRyb3Bw ZWQgdGhpcyBjaGVjay4KPj4+Cj4+Cj4+IFRoYW5rIHlvdSBQYXVsaW5hLCB0aGUgcGF0Y2ggaXMg Z29vZC4gVGhhbmtzIGZvciB5b3VyIHdvcmshIFNvcnJ5IGZvcgo+PiBjb21pbmcgaW4gbGF0ZSBp biB0aGUgcmV2aWV3OyBJIGhhdmUgYSBjb3VwbGUgb2YgbWlub3Igc3VnZ2VzdGlvbnMKPj4gYmVs b3cuCj4+Cj4gSXQgaGFkIG5vdCBiZWVuIHBvc3NpYmxlIHdpdGhvdXQgYWxsIHRoZSBoZWxwIEkg aGF2ZSBnb3QuIEkgYW0gdmVyeQo+IGdyYXRlZnVsIGZvciBpdC4KPgo+PiBJbiBhZGRpdGlvbiB0 byBBbnRob255J3MgYWNrLCBpdCB3b3VsZCBiZSBhbHNvIG5pY2UgdG8gaGF2ZSBSb2dlcidzIGFj awo+PiBvbiB0aGlzIHBhdGNoLgo+PgpSb2dlciwgd2lsbCB5b3UgbmVlZCBtb3JlIHRpbWUgdG8g dGFrZSBhIGxvb2sgYXQgdGhlIHBhdGNoIG9yIG1heSBJIHNlbmQgCmEgbmV3IHZlcnNpb24gd2l0 aCBhcHBsaWVkIFN0ZWZhbm8gY29tbWVudHM/Cgo+Pgo+Pj4gICBjb25maWd1cmUgICAgICAgICAg ICAgICAgICAgfCAgNTUgKysrKysrKysrKysrKysrKwo+Pj4gICBody9ibG9jay94ZW5fZGlzay5j ICAgICAgICAgfCAxNTcKPj4+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKy0tCj4+PiAgIGluY2x1ZGUvaHcveGVuL3hlbl9jb21tb24uaCB8ICAxNCArKysrCj4+PiAg IDMgZmlsZXMgY2hhbmdlZCwgMjIxIGluc2VydGlvbnMoKyksIDUgZGVsZXRpb25zKC0pCj4+Pgo+ Pj4gZGlmZiAtLWdpdCBhL2NvbmZpZ3VyZSBiL2NvbmZpZ3VyZQo+Pj4gaW5kZXggNGI4MDhmOS4u M2Y0NGQzOCAxMDA3NTUKPj4+IC0tLSBhL2NvbmZpZ3VyZQo+Pj4gKysrIGIvY29uZmlndXJlCj4+ PiBAQCAtMTk1Niw2ICsxOTU2LDYxIEBAIEVPRgo+Pj4gICAvKgo+Pj4gICAgKiBJZiB3ZSBoYXZl IHN0YWJsZSBsaWJzIHRoZSB3ZSBkb24ndCB3YW50IHRoZSBsaWJ4YyBjb21wYXQKPj4+ICAgICog bGF5ZXJzLCByZWdhcmRsZXNzIG9mIHdoYXQgQ0ZMQUdTIHdlIG1heSBoYXZlIGJlZW4gZ2l2ZW4u Cj4+PiArICoKPj4+ICsgKiBBbHNvLCBjaGVjayBpZiB4ZW5nbnR0YWJfZ3JhbnRfY29weV9zZWdt ZW50X3QgaXMgZGVmaW5lZCBhbmQKPj4+ICsgKiBncmFudCBjb3B5IG9wZXJhdGlvbiBpcyBpbXBs ZW1lbnRlZC4KPj4+ICsgKi8KPj4+ICsjdW5kZWYgWENfV0FOVF9DT01QQVRfRVZUQ0hOX0FQSQo+ Pj4gKyN1bmRlZiBYQ19XQU5UX0NPTVBBVF9HTlRUQUJfQVBJCj4+PiArI3VuZGVmIFhDX1dBTlRf Q09NUEFUX01BUF9GT1JFSUdOX0FQSQo+Pj4gKyNpbmNsdWRlIDx4ZW5jdHJsLmg+Cj4+PiArI2lu Y2x1ZGUgPHhlbnN0b3JlLmg+Cj4+PiArI2luY2x1ZGUgPHhlbmV2dGNobi5oPgo+Pj4gKyNpbmNs dWRlIDx4ZW5nbnR0YWIuaD4KPj4+ICsjaW5jbHVkZSA8eGVuZm9yZWlnbm1lbW9yeS5oPgo+Pj4g KyNpbmNsdWRlIDxzdGRpbnQuaD4KPj4+ICsjaW5jbHVkZSA8eGVuL2h2bS9odm1faW5mb190YWJs ZS5oPgo+Pj4gKyNpZiAhZGVmaW5lZChIVk1fTUFYX1ZDUFVTKQo+Pj4gKyMgZXJyb3IgSFZNX01B WF9WQ1BVUyBub3QgZGVmaW5lZAo+Pj4gKyNlbmRpZgo+Pj4gK2ludCBtYWluKHZvaWQpIHsKPj4+ ICsgIHhjX2ludGVyZmFjZSAqeGMgPSBOVUxMOwo+Pj4gKyAgeGVuZm9yZWlnbm1lbW9yeV9oYW5k bGUgKnhmbWVtOwo+Pj4gKyAgeGVuZXZ0Y2huX2hhbmRsZSAqeGU7Cj4+PiArICB4ZW5nbnR0YWJf aGFuZGxlICp4ZzsKPj4+ICsgIHhlbl9kb21haW5faGFuZGxlX3QgaGFuZGxlOwo+Pj4gKyAgeGVu Z250dGFiX2dyYW50X2NvcHlfc2VnbWVudF90KiBzZWcgPSBOVUxMOwo+Pj4gKwo+Pj4gKyAgeHNf ZGFlbW9uX29wZW4oKTsKPj4+ICsKPj4+ICsgIHhjID0geGNfaW50ZXJmYWNlX29wZW4oMCwgMCwg MCk7Cj4+PiArICB4Y19odm1fc2V0X21lbV90eXBlKDAsIDAsIEhWTU1FTV9yYW1fcm8sIDAsIDAp Owo+Pj4gKyAgeGNfZG9tYWluX2FkZF90b19waHlzbWFwKDAsIDAsIFhFTk1BUFNQQUNFX2dtZm4s IDAsIDApOwo+Pj4gKyAgeGNfaHZtX2luamVjdF9tc2koeGMsIDAsIDB4ZjAwMDAwMDAsIDB4MDAw MDAwMDApOwo+Pj4gKyAgeGNfaHZtX2NyZWF0ZV9pb3JlcV9zZXJ2ZXIoeGMsIDAsIEhWTV9JT1JF UVNSVl9CVUZJT1JFUV9BVE9NSUMsCj4+PiBOVUxMKTsKPj4+ICsgIHhjX2RvbWFpbl9jcmVhdGUo eGMsIDAsIGhhbmRsZSwgMCwgTlVMTCwgTlVMTCk7Cj4+PiArCj4+PiArICB4Zm1lbSA9IHhlbmZv cmVpZ25tZW1vcnlfb3BlbigwLCAwKTsKPj4+ICsgIHhlbmZvcmVpZ25tZW1vcnlfbWFwKHhmbWVt LCAwLCAwLCAwLCAwLCAwKTsKPj4+ICsKPj4+ICsgIHhlID0geGVuZXZ0Y2huX29wZW4oMCwgMCk7 Cj4+PiArICB4ZW5ldnRjaG5fZmQoeGUpOwo+Pj4gKwo+Pj4gKyAgeGcgPSB4ZW5nbnR0YWJfb3Bl bigwLCAwKTsKPj4+ICsgIHhlbmdudHRhYl9ncmFudF9jb3B5KHhnLCAwLCBzZWcpOwo+Pj4gKwo+ Pj4gKyAgcmV0dXJuIDA7Cj4+PiArfQo+Pj4gK0VPRgo+Pj4gKyAgICAgIGNvbXBpbGVfcHJvZyAi IiAiJHhlbl9saWJzICR4ZW5fc3RhYmxlX2xpYnMiCj4+PiArICAgIHRoZW4KPj4+ICsgICAgeGVu X2N0cmxfdmVyc2lvbj00ODAKPj4+ICsgICAgeGVuPXllcwo+Pj4gKyAgZWxpZgo+Pj4gKyAgICAg IGNhdCA+ICRUTVBDIDw8RU9GICYmCj4+PiArLyoKPj4+ICsgKiBJZiB3ZSBoYXZlIHN0YWJsZSBs aWJzIHRoZSB3ZSBkb24ndCB3YW50IHRoZSBsaWJ4YyBjb21wYXQKPj4+ICsgKiBsYXllcnMsIHJl Z2FyZGxlc3Mgb2Ygd2hhdCBDRkxBR1Mgd2UgbWF5IGhhdmUgYmVlbiBnaXZlbi4KPj4+ICAgICov Cj4+PiAgICN1bmRlZiBYQ19XQU5UX0NPTVBBVF9FVlRDSE5fQVBJCj4+PiAgICN1bmRlZiBYQ19X QU5UX0NPTVBBVF9HTlRUQUJfQVBJCj4+PiBkaWZmIC0tZ2l0IGEvaHcvYmxvY2sveGVuX2Rpc2su YyBiL2h3L2Jsb2NrL3hlbl9kaXNrLmMKPj4+IGluZGV4IDNiOGFkMzMuLjM3MzllMTMgMTAwNjQ0 Cj4+PiAtLS0gYS9ody9ibG9jay94ZW5fZGlzay5jCj4+PiArKysgYi9ody9ibG9jay94ZW5fZGlz ay5jCj4+PiBAQCAtMTE5LDYgKzExOSw5IEBAIHN0cnVjdCBYZW5CbGtEZXYgewo+Pj4gICAgICAg dW5zaWduZWQgaW50ICAgICAgICBwZXJzaXN0ZW50X2dudF9jb3VudDsKPj4+ICAgICAgIHVuc2ln bmVkIGludCAgICAgICAgbWF4X2dyYW50czsKPj4+Cj4+PiArICAgIC8qIEdyYW50IGNvcHkgKi8K Pj4+ICsgICAgZ2Jvb2xlYW4gICAgICAgICAgICBmZWF0dXJlX2dyYW50X2NvcHk7Cj4+PiArCj4+ PiAgICAgICAvKiBxZW11IGJsb2NrIGRyaXZlciAqLwo+Pj4gICAgICAgRHJpdmVJbmZvICAgICAg ICAgICAqZGluZm87Cj4+PiAgICAgICBCbG9ja0JhY2tlbmQgICAgICAgICpibGs7Cj4+PiBAQCAt NDg5LDYgKzQ5MiwxMDggQEAgc3RhdGljIGludCBpb3JlcV9tYXAoc3RydWN0IGlvcmVxICppb3Jl cSkKPj4+ICAgICAgIHJldHVybiAwOwo+Pj4gICB9Cj4+Pgo+Pj4gKyNpZiBDT05GSUdfWEVOX0NU UkxfSU5URVJGQUNFX1ZFUlNJT04gPj0gNDgwCj4+Cj4+IEluIGdlbmVyYWwgSSBwcmVmZXIgdG8g YXZvaWQgdGhpcyBraW5kIG9mICNpZmRlZiBpbiB4ZW5fZGlzay5jLCBidXQgSQo+PiBzZWUgdGhh dCBBbnRob255IHN1Z2dlc3RlZCBpdCBmb3IgYSBnb29kIHJlYXNvbi4gVGhlIG9ubHkgYWx0ZXJu YXJ0aXZlIEkKPj4gY2FuIHRoaW5rIG9mIHdvdWxkIGJlIHRvIGludHJvZHVjZSB0d28gc3RhdGlj IGlubGluZSBmdW5jdGlvbnMgaW4KPj4geGVuX2NvbW1vbi5oIHRvIHNldCBhIHhlbmdudHRhYl9n cmFudF9jb3B5X3NlZ21lbnRfdCBzZWcuIEJ1dCB0aGlzIGlzCj4+IGFsc28gT0suCj4+Cj4gVGhl IGZ1bmN0aW9ucyB0YWtlIGFzIHBhcmFtZXRlcnMgcG9pbnRlcnMgdG8gc3RydWN0IGlvcmVxIGRl ZmluZWQgaW4KPiB4ZW5fZGlzay5jIHdoaWNoIG1lbWJlcnMgYXJlIHVzZWQgdG8gZmlsbCB0aGUK PiB4ZW5nbnR0YWJfZ3JhbnRfY29weV9zZWdtZW50X3QuIFRoZXJlIHdvdWxkIGJlIHNvbWUgb3Zl cmhlYWQgdG8gbW92ZSB0aGUKPiBmdW5jdGlvbnMgdG8gdGhlIGhlYWRlci4KPj4KPj4+ICtzdGF0 aWMgdm9pZCBmcmVlX2J1ZmZlcnMoc3RydWN0IGlvcmVxICppb3JlcSkKPj4KPj4gUGxlYXNlIG5h bWUgdGhpcyBmdW5jdGlvbiBpb3JlcV9mcmVlX2NvcHlfYnVmZmVycyB0byBtYWtlIGl0IGNsZWFy ZXIKPj4gdGhhdCBoYXMgdG8gZG8gd2l0aCB0aGUgc2FtZSBidWZmZXJzIGluaXRpYWxpemVkIGJl bG93Lgo+Pgo+Pgo+Pj4gK3sKPj4+ICsgICAgaW50IGk7Cj4+PiArCj4+PiArICAgIGZvciAoaSA9 IDA7IGkgPCBpb3JlcS0+di5uaW92OyBpKyspIHsKPj4+ICsgICAgICAgIGlvcmVxLT5wYWdlW2ld ID0gTlVMTDsKPj4+ICsgICAgfQo+Pj4gKwo+Pj4gKyAgICBxZW11X3ZmcmVlKGlvcmVxLT5wYWdl cyk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQgaW9yZXFfaW5pdF9jb3B5X2J1ZmZlcnMo c3RydWN0IGlvcmVxICppb3JlcSkKPj4+ICt7Cj4+PiArICAgIGludCBpOwo+Pj4gKwo+Pj4gKyAg ICBpZiAoaW9yZXEtPnYubmlvdiA9PSAwKSB7Cj4+PiArICAgICAgICByZXR1cm4gMDsKPj4+ICsg ICAgfQo+Pj4gKwo+Pj4gKyAgICBpb3JlcS0+cGFnZXMgPSBxZW11X21lbWFsaWduKFhDX1BBR0Vf U0laRSwgaW9yZXEtPnYubmlvdiAqCj4+PiBYQ19QQUdFX1NJWkUpOwo+Pj4gKwo+Pj4gKyAgICBm b3IgKGkgPSAwOyBpIDwgaW9yZXEtPnYubmlvdjsgaSsrKSB7Cj4+PiArICAgICAgICBpb3JlcS0+ cGFnZVtpXSA9IGlvcmVxLT5wYWdlcyArIGkgKiBYQ19QQUdFX1NJWkU7Cj4+PiArICAgICAgICBp b3JlcS0+di5pb3ZbaV0uaW92X2Jhc2UgPSBpb3JlcS0+cGFnZVtpXTsKPj4+ICsgICAgfQo+Pj4g Kwo+Pj4gKyAgICByZXR1cm4gMDsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGludCBpb3JlcV9j b3B5KHN0cnVjdCBpb3JlcSAqaW9yZXEpCj4+Cj4+IFBsZWFzZSBuYW1lIHRoaXMgZnVuY3Rpb24g aW4gYSB3YXkgdGhhdCBtYWtlcyBpdCBjbGVhciB0aGF0IGl0IGhhcwo+PiBzb21ldGhpbmcgdG8g ZG8gd2l0aCBncmFudCBjb3BpZXMuIExpa2UgZm9yIGV4YW1wbGUgaW9yZXFfZ3JhbnRfY29weS4K Pj4KPiBJIHdpbGwgY2hhbmdlIHRoZSBuYW1lcyBvZiBib3RoIGZ1bmN0aW9ucyBhbmQgcmVtb3Zl IHRoZSBibGFuayBsaW5lCj4gcG9pbnRlZCBiZWxvdy4KPj4KPj4+ICt7Cj4+PiArICAgIHhlbmdu dHRhYl9oYW5kbGUgKmdudCA9IGlvcmVxLT5ibGtkZXYtPnhlbmRldi5nbnR0YWJkZXY7Cj4+PiAr ICAgIHhlbmdudHRhYl9ncmFudF9jb3B5X3NlZ21lbnRfdAo+Pj4gc2Vnc1tCTEtJRl9NQVhfU0VH TUVOVFNfUEVSX1JFUVVFU1RdOwo+Pj4gKyAgICBpbnQgaSwgY291bnQsIHJjOwo+Pj4gKyAgICBp bnQ2NF90IGZpbGVfYmxrID0gaW9yZXEtPmJsa2Rldi0+ZmlsZV9ibGs7Cj4+PiArCj4+PiArICAg IGlmIChpb3JlcS0+di5uaW92ID09IDApIHsKPj4+ICsgICAgICAgIHJldHVybiAwOwo+Pj4gKyAg ICB9Cj4+PiArCj4+PiArICAgIGNvdW50ID0gaW9yZXEtPnYubmlvdjsKPj4+ICsKPj4+ICsgICAg Zm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKPj4+ICsKPj4+ICsgICAgICAgIGlmIChpb3Jl cS0+cmVxLm9wZXJhdGlvbiA9PSBCTEtJRl9PUF9SRUFEKSB7Cj4+PiArICAgICAgICAgICAgc2Vn c1tpXS5mbGFncyA9IEdOVENPUFlfZGVzdF9ncmVmOwo+Pj4gKyAgICAgICAgICAgIHNlZ3NbaV0u ZGVzdC5mb3JlaWduLnJlZiA9IGlvcmVxLT5yZWZzW2ldOwo+Pj4gKyAgICAgICAgICAgIHNlZ3Nb aV0uZGVzdC5mb3JlaWduLmRvbWlkID0gaW9yZXEtPmRvbWlkc1tpXTsKPj4+ICsgICAgICAgICAg ICBzZWdzW2ldLmRlc3QuZm9yZWlnbi5vZmZzZXQgPQo+Pj4gaW9yZXEtPnJlcS5zZWdbaV0uZmly c3Rfc2VjdCAqIGZpbGVfYmxrOwo+Pj4gKyAgICAgICAgICAgIHNlZ3NbaV0uc291cmNlLnZpcnQg PSBpb3JlcS0+di5pb3ZbaV0uaW92X2Jhc2U7Cj4+PiArICAgICAgICB9IGVsc2Ugewo+Pj4gKyAg ICAgICAgICAgIHNlZ3NbaV0uZmxhZ3MgPSBHTlRDT1BZX3NvdXJjZV9ncmVmOwo+Pj4gKyAgICAg ICAgICAgIHNlZ3NbaV0uc291cmNlLmZvcmVpZ24ucmVmID0gaW9yZXEtPnJlZnNbaV07Cj4+PiAr ICAgICAgICAgICAgc2Vnc1tpXS5zb3VyY2UuZm9yZWlnbi5kb21pZCA9IGlvcmVxLT5kb21pZHNb aV07Cj4+PiArICAgICAgICAgICAgc2Vnc1tpXS5zb3VyY2UuZm9yZWlnbi5vZmZzZXQgPQo+Pj4g aW9yZXEtPnJlcS5zZWdbaV0uZmlyc3Rfc2VjdCAqIGZpbGVfYmxrOwo+Pj4gKyAgICAgICAgICAg IHNlZ3NbaV0uZGVzdC52aXJ0ID0gaW9yZXEtPnYuaW92W2ldLmlvdl9iYXNlOwo+Pj4gKyAgICAg ICAgfQo+Pj4gKyAgICAgICAgc2Vnc1tpXS5sZW4gPSAoaW9yZXEtPnJlcS5zZWdbaV0ubGFzdF9z ZWN0Cj4+PiArICAgICAgICAgICAgICAgICAgICAgICAtIGlvcmVxLT5yZXEuc2VnW2ldLmZpcnN0 X3NlY3QgKyAxKSAqIGZpbGVfYmxrOwo+Pj4gKwo+Pj4gKyAgICB9Cj4+PiArCj4+PiArICAgIHJj ID0geGVuZ250dGFiX2dyYW50X2NvcHkoZ250LCBjb3VudCwgc2Vncyk7Cj4+PiArCj4+PiArICAg IGlmIChyYykgewo+Pj4gKyAgICAgICAgeGVuX2JlX3ByaW50ZigmaW9yZXEtPmJsa2Rldi0+eGVu ZGV2LCAwLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAiZmFpbGVkIHRvIGNvcHkgZGF0YSAl ZFxuIiwgcmMpOwo+Pj4gKyAgICAgICAgaW9yZXEtPmFpb19lcnJvcnMrKzsKPj4+ICsgICAgICAg IHJldHVybiAtMTsKPj4+ICsgICAgfQo+Pj4gKwo+Pj4gKyAgICBmb3IgKGkgPSAwOyBpIDwgY291 bnQ7IGkrKykgewo+Pj4gKyAgICAgICAgaWYgKHNlZ3NbaV0uc3RhdHVzICE9IEdOVFNUX29rYXkp IHsKPj4+ICsgICAgICAgICAgICB4ZW5fYmVfcHJpbnRmKCZpb3JlcS0+YmxrZGV2LT54ZW5kZXYs IDMsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAiZmFpbGVkIHRvIGNvcHkgZGF0YSAl ZCBmb3IgZ3JlZiAlZCwgZG9taWQKPj4+ICVkXG4iLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgc2Vnc1tpXS5zdGF0dXMsIGlvcmVxLT5yZWZzW2ldLAo+Pj4gaW9yZXEtPmRvbWlkc1tp XSk7Cj4+PiArICAgICAgICAgICAgaW9yZXEtPmFpb19lcnJvcnMrKzsKPj4+ICsgICAgICAgICAg ICByYyA9IC0xOwo+Pj4gKyAgICAgICAgfQo+Pj4gKyAgICB9Cj4+PiArCj4+PiArICAgIHJldHVy biByYzsKPj4+ICt9Cj4+PiArI2Vsc2UKPj4+ICtzdGF0aWMgdm9pZCBmcmVlX2J1ZmZlcnMoc3Ry dWN0IGlvcmVxICppb3JlcSkKPj4+ICt7Cj4+PiArICAgIGFib3J0KCk7Cj4+PiArfQo+Pj4gKwo+ Pj4gK3N0YXRpYyBpbnQgaW9yZXFfaW5pdF9jb3B5X2J1ZmZlcnMoc3RydWN0IGlvcmVxICppb3Jl cSkKPj4+ICt7Cj4+PiArICAgIGFib3J0KCk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQg aW9yZXFfY29weShzdHJ1Y3QgaW9yZXEgKmlvcmVxKQo+Pj4gK3sKPj4+ICsgICAgYWJvcnQoKTsK Pj4+ICt9Cj4+PiArI2VuZGlmCj4+PiArCj4+PiAgIHN0YXRpYyBpbnQgaW9yZXFfcnVuaW9fcWVt dV9haW8oc3RydWN0IGlvcmVxICppb3JlcSk7Cj4+Pgo+Pj4gICBzdGF0aWMgdm9pZCBxZW11X2Fp b19jb21wbGV0ZSh2b2lkICpvcGFxdWUsIGludCByZXQpCj4+PiBAQCAtNTExLDggKzYxNiwzMSBA QCBzdGF0aWMgdm9pZCBxZW11X2Fpb19jb21wbGV0ZSh2b2lkICpvcGFxdWUsIGludAo+Pj4gcmV0 KQo+Pj4gICAgICAgICAgIHJldHVybjsKPj4+ICAgICAgIH0KPj4+Cj4+PiArICAgIGlmIChpb3Jl cS0+YmxrZGV2LT5mZWF0dXJlX2dyYW50X2NvcHkpIHsKPj4+ICsgICAgICAgIHN3aXRjaCAoaW9y ZXEtPnJlcS5vcGVyYXRpb24pIHsKPj4+ICsgICAgICAgIGNhc2UgQkxLSUZfT1BfUkVBRDoKPj4+ ICsgICAgICAgICAgICAvKiBpbiBjYXNlIG9mIGZhaWx1cmUgaW9yZXEtPmFpb19lcnJvcnMgaXMg aW5jcmVhc2VkICovCj4+PiArICAgICAgICAgICAgaWYgKHJldCA9PSAwKSB7Cj4+PiArICAgICAg ICAgICAgICAgIGlvcmVxX2NvcHkoaW9yZXEpOwo+Pj4gKyAgICAgICAgICAgIH0KPj4+ICsgICAg ICAgICAgICBmcmVlX2J1ZmZlcnMoaW9yZXEpOwo+Pj4gKyAgICAgICAgICAgIGJyZWFrOwo+Pj4g KyAgICAgICAgY2FzZSBCTEtJRl9PUF9XUklURToKPj4+ICsgICAgICAgIGNhc2UgQkxLSUZfT1Bf RkxVU0hfRElTS0NBQ0hFOgo+Pj4gKyAgICAgICAgICAgIGlmICghaW9yZXEtPnJlcS5ucl9zZWdt ZW50cykgewo+Pj4gKyAgICAgICAgICAgICAgICBicmVhazsKPj4+ICsgICAgICAgICAgICB9Cj4+ PiArICAgICAgICAgICAgZnJlZV9idWZmZXJzKGlvcmVxKTsKPj4+ICsgICAgICAgICAgICBicmVh azsKPj4+ICsgICAgICAgIGRlZmF1bHQ6Cj4+PiArICAgICAgICAgICAgYnJlYWs7Cj4+PiArICAg ICAgICB9Cj4+PiArICAgIH0KPj4+ICsKPj4+ICAgICAgIGlvcmVxLT5zdGF0dXMgPSBpb3JlcS0+ YWlvX2Vycm9ycyA/IEJMS0lGX1JTUF9FUlJPUiA6Cj4+PiBCTEtJRl9SU1BfT0tBWTsKPj4+IC0g ICAgaW9yZXFfdW5tYXAoaW9yZXEpOwo+Pj4gKyAgICBpZiAoIWlvcmVxLT5ibGtkZXYtPmZlYXR1 cmVfZ3JhbnRfY29weSkgewo+Pj4gKyAgICAgICAgaW9yZXFfdW5tYXAoaW9yZXEpOwo+Pj4gKyAg ICB9Cj4+PiAgICAgICBpb3JlcV9maW5pc2goaW9yZXEpOwo+Pj4gICAgICAgc3dpdGNoIChpb3Jl cS0+cmVxLm9wZXJhdGlvbikgewo+Pj4gICAgICAgY2FzZSBCTEtJRl9PUF9XUklURToKPj4+IEBA IC01MzgsOCArNjY2LDIwIEBAIHN0YXRpYyBpbnQgaW9yZXFfcnVuaW9fcWVtdV9haW8oc3RydWN0 IGlvcmVxCj4+PiAqaW9yZXEpCj4+PiAgIHsKPj4+ICAgICAgIHN0cnVjdCBYZW5CbGtEZXYgKmJs a2RldiA9IGlvcmVxLT5ibGtkZXY7Cj4+Pgo+Pj4gLSAgICBpZiAoaW9yZXEtPnJlcS5ucl9zZWdt ZW50cyAmJiBpb3JlcV9tYXAoaW9yZXEpID09IC0xKSB7Cj4+PiAtICAgICAgICBnb3RvIGVycl9u b19tYXA7Cj4+PiArICAgIGlmIChpb3JlcS0+YmxrZGV2LT5mZWF0dXJlX2dyYW50X2NvcHkpIHsK Pj4+ICsgICAgICAgIGlvcmVxX2luaXRfY29weV9idWZmZXJzKGlvcmVxKTsKPj4+ICsgICAgICAg IGlmIChpb3JlcS0+cmVxLm5yX3NlZ21lbnRzICYmIChpb3JlcS0+cmVxLm9wZXJhdGlvbiA9PQo+ Pj4gQkxLSUZfT1BfV1JJVEUgfHwKPj4+ICsgICAgICAgICAgICBpb3JlcS0+cmVxLm9wZXJhdGlv biA9PSBCTEtJRl9PUF9GTFVTSF9ESVNLQ0FDSEUpKSB7Cj4+PiArICAgICAgICAgICAgaWYgKGlv cmVxX2NvcHkoaW9yZXEpKSB7Cj4+PiArICAgICAgICAgICAgICAgIGZyZWVfYnVmZmVycyhpb3Jl cSk7Cj4+PiArICAgICAgICAgICAgICAgIGdvdG8gZXJyOwo+Pj4gKyAgICAgICAgICAgIH0KPj4+ ICsgICAgICAgIH0KPj4+ICsKPj4KPj4gUGxlYXNlIHJlbW92ZSBibGFuayB0aGlzIGxpbmUgKGl0 IGxvb2tzIGEgYml0IG9kZCkKPj4KPj4KPj4+ICsgICAgfSBlbHNlIHsKPj4+ICsgICAgICAgIGlm IChpb3JlcS0+cmVxLm5yX3NlZ21lbnRzICYmIGlvcmVxX21hcChpb3JlcSkpIHsKPj4+ICsgICAg ICAgICAgICBnb3RvIGVycjsKPj4+ICsgICAgICAgIH0KPj4+ICAgICAgIH0KPj4+Cj4+PiAgICAg ICBpb3JlcS0+YWlvX2luZmxpZ2h0Kys7Cj4+PiBAQCAtNTgyLDYgKzcyMiw5IEBAIHN0YXRpYyBp bnQgaW9yZXFfcnVuaW9fcWVtdV9haW8oc3RydWN0IGlvcmVxICppb3JlcSkKPj4+ICAgICAgIH0K Pj4+ICAgICAgIGRlZmF1bHQ6Cj4+PiAgICAgICAgICAgLyogdW5rbm93biBvcGVyYXRpb24gKHNo b3VsZG4ndCBoYXBwZW4gLS0gcGFyc2UgY2F0Y2hlcwo+Pj4gdGhpcykgKi8KPj4+ICsgICAgICAg IGlmICghaW9yZXEtPmJsa2Rldi0+ZmVhdHVyZV9ncmFudF9jb3B5KSB7Cj4+PiArICAgICAgICAg ICAgaW9yZXFfdW5tYXAoaW9yZXEpOwo+Pj4gKyAgICAgICAgfQo+Pgo+PiBXaHkgYXJlIHlvdSBh ZGRpbmcgdGhpcz8gSXMgaXQgYSBidWcgZml4PyBJZiBzbywgcGxlYXNlIGV4cGxhaW4gaW4gdGhl Cj4+IGNvbW1pdCBtZXNzYWdlLgo+Pgo+IEl0IGlzIG5vdCBhIGJ1ZyBmaXguIEluIHRoZSBpb3Jl cV9ydW5pb19xZW11X2FpbyB0aGVyZSB3ZXJlIHR3byBlcnJvcgo+IGxhYmVscyAnZXJyX25vX21h cCcgYW5kICdlcnInIGVhY2ggb2YgdGhlbSB1c2VkIG9uY2UuIFNvIGJlZm9yZSB0aGUKPiBwYXRj aCB0aGUgbGFiZWxzIGFyZSBsb29raW5nIHRoaXMgd2F5Ogo+IGVycjoKPiAgICAgIGlvcmVxX3Vu bWFwKGlvcmVxKTsKPiBlcnJfbm9fbWFwOgo+ICAgICAgaW9yZXFfZmluaXNoKGlvcmVxKTsKPiAg ICAgIGlvcmVxLT5zdGF0dXMgPSBCTEtJRl9SU1BfRVJST1I7Cj4gICAgICByZXR1cm4gLTE7Cj4K PiBJIHJlbW92ZWQgdGhlICdlcnJfbm9fbWFwJyBsYWJlbCBhbmQgZnJvbSB0aGUgJ2Vycicgc2Vj dGlvbiBJIHJlbW92ZWQKPiB0aGUgaW9yZXFfdW5tYXAuIFRoZSAnZXJyJyBsYWJlbCB3YXMgcHJl dmlvdXNseSB1c2VkIGluIHRoYXQgZGVmYXVsdAo+IHNlY3Rpb24gb2YgdGhlIHN3aXRjaCBiZWNh dXNlIHRoZSBncmFudF9tYXAgaXMgY2FsbGVkIHJlZ2FyZGxlc3MgdGhlCj4gaW9yZXEtPnJlcS5v cGVyYXRpb24uCj4KPiBJbiB0aGUgcGF0Y2gsIHRoZXJlIGlzIG5vIG5lZWQgZm9yIGFueSBzcGVj aWFsIGJlaGF2aW9yIGZvciBncmFudF9jb3B5LAo+IGJlY2F1c2UgYnVmZmVycyB3ZXJlIG5vdCBh bGxvY2F0ZWQgaW4gdGhpcyBjYXNlLCBzbyB0aGVyZSBpcyBvbmx5IGp1bXAKPiB0byAnZXJyJy4K Pgo+IEFuIGFkdmFudGFnZSBvZiB0aGlzIGNoYW5nZSBpcyBvbmUgdW5pZmllZCBlcnJvciBwYXRo IGZvciBib3RoIGdyYW50Cj4gb3BlcmF0aW9ucy4KPj4KPj4+ICAgICAgICAgICBnb3RvIGVycjsK Pj4+ICAgICAgIH0KPj4+Cj4+PiBAQCAtNTkwLDggKzczMyw2IEBAIHN0YXRpYyBpbnQgaW9yZXFf cnVuaW9fcWVtdV9haW8oc3RydWN0IGlvcmVxICppb3JlcSkKPj4+ICAgICAgIHJldHVybiAwOwo+ Pj4KPj4+ICAgZXJyOgo+Pj4gLSAgICBpb3JlcV91bm1hcChpb3JlcSk7Cj4+PiAtZXJyX25vX21h cDoKPj4+ICAgICAgIGlvcmVxX2ZpbmlzaChpb3JlcSk7Cj4+PiAgICAgICBpb3JlcS0+c3RhdHVz ID0gQkxLSUZfUlNQX0VSUk9SOwo+Pj4gICAgICAgcmV0dXJuIC0xOwo+Pj4gQEAgLTEwMzIsNiAr MTE3MywxMiBAQCBzdGF0aWMgaW50IGJsa19jb25uZWN0KHN0cnVjdCBYZW5EZXZpY2UgKnhlbmRl dikKPj4+Cj4+PiAgICAgICB4ZW5fYmVfYmluZF9ldnRjaG4oJmJsa2Rldi0+eGVuZGV2KTsKPj4+ Cj4+PiArICAgIGJsa2Rldi0+ZmVhdHVyZV9ncmFudF9jb3B5ID0KPj4+ICsgICAgICAgICAgICAg ICAgKHhlbmdudHRhYl9ncmFudF9jb3B5KGJsa2Rldi0+eGVuZGV2LmdudHRhYmRldiwgMCwKPj4+ IE5VTEwpID09IDApOwo+Pj4gKwo+Pj4gKyAgICB4ZW5fYmVfcHJpbnRmKCZibGtkZXYtPnhlbmRl diwgMywgImdyYW50IGNvcHkgb3BlcmF0aW9uICVzXG4iLAo+Pj4gKyAgICAgICAgICAgICAgICAg IGJsa2Rldi0+ZmVhdHVyZV9ncmFudF9jb3B5ID8gImVuYWJsZWQiIDogImRpc2FibGVkIik7Cj4+ PiArCj4+PiAgICAgICB4ZW5fYmVfcHJpbnRmKCZibGtkZXYtPnhlbmRldiwgMSwgIm9rOiBwcm90 byAlcywgcmluZy1yZWYgJWQsICIKPj4+ICAgICAgICAgICAgICAgICAgICAgInJlbW90ZSBwb3J0 ICVkLCBsb2NhbCBwb3J0ICVkXG4iLAo+Pj4gICAgICAgICAgICAgICAgICAgICBibGtkZXYtPnhl bmRldi5wcm90b2NvbCwgYmxrZGV2LT5yaW5nX3JlZiwKPj4+IGRpZmYgLS1naXQgYS9pbmNsdWRl L2h3L3hlbi94ZW5fY29tbW9uLmggYi9pbmNsdWRlL2h3L3hlbi94ZW5fY29tbW9uLmgKPj4+IGlu ZGV4IGJkMzkyODcuLjhlMTU4MGQgMTAwNjQ0Cj4+PiAtLS0gYS9pbmNsdWRlL2h3L3hlbi94ZW5f Y29tbW9uLmgKPj4+ICsrKyBiL2luY2x1ZGUvaHcveGVuL3hlbl9jb21tb24uaAo+Pj4gQEAgLTQy NCw0ICs0MjQsMTggQEAgc3RhdGljIGlubGluZSBpbnQgeGVuX2RvbWFpbl9jcmVhdGUoeGNfaW50 ZXJmYWNlCj4+PiAqeGMsIHVpbnQzMl90IHNzaWRyZWYsCj4+PiAgICNlbmRpZgo+Pj4gICAjZW5k aWYKPj4+Cj4+PiArLyogWGVuIGJlZm9yZSA0LjggKi8KPj4+ICsKPj4+ICsjaWYgQ09ORklHX1hF Tl9DVFJMX0lOVEVSRkFDRV9WRVJTSU9OIDwgNDgwCj4+PiArCj4+PiArCj4+PiArdHlwZWRlZiB2 b2lkICp4ZW5nbnR0YWJfZ3JhbnRfY29weV9zZWdtZW50X3Q7Cj4+PiArCj4+PiArc3RhdGljIGlu bGluZSBpbnQgeGVuZ250dGFiX2dyYW50X2NvcHkoeGVuZ250dGFiX2hhbmRsZSAqeGd0LAo+Pj4g dWludDMyX3QgY291bnQsCj4+PiArCj4+PiB4ZW5nbnR0YWJfZ3JhbnRfY29weV9zZWdtZW50X3Qg KnNlZ3MpCj4+PiArewo+Pj4gKyAgICByZXR1cm4gLUVOT1NZUzsKPj4+ICt9Cj4+PiArI2VuZGlm Cj4+PiArCj4+PiAgICNlbmRpZiAvKiBRRU1VX0hXX1hFTl9DT01NT05fSCAqLwo+Pj4gLS0KPj4+ IDEuOS4xCj4+Pgo+Cj4gUGF1bGluYQpQYXVsaW5hCgpfX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fXwpYZW4tZGV2ZWwgbWFpbGluZyBsaXN0Clhlbi1kZXZlbEBs aXN0cy54ZW4ub3JnCmh0dHBzOi8vbGlzdHMueGVuLm9yZy94ZW4tZGV2ZWwK