From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.nokia.com ([192.100.122.233] helo=mgw-mx06.nokia.com) by bombadil.infradead.org with esmtps (Exim 4.69 #1 (Red Hat Linux)) id 1O7RYi-0008WO-F2 for linux-mtd@lists.infradead.org; Thu, 29 Apr 2010 11:05:35 +0000 Subject: Re: UBIFS, Memory fragmentation problem From: Artem Bityutskiy To: Tomasz Stanislawski In-Reply-To: <4BD59783.8020800@samsung.com> References: <4BD59783.8020800@samsung.com> Content-Type: text/plain; charset="UTF-8" Date: Thu, 29 Apr 2010 14:00:40 +0300 Message-ID: <1272538840.26440.42.camel@localhost> Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Cc: linux-fsdevel , kyungmin.park@samsung.com, Tomasz Fujak , linux-mtd@lists.infradead.org, Marek Szyprowski Reply-To: dedekind1@gmail.com List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , CCing fs-devel, in case other people can give good suggestions. On Mon, 2010-04-26 at 15:39 +0200, Tomasz Stanislawski wrote: > Dear Mr. Artem Bityutskiy, > Recently, I was developing a platform that utilizes UBIFS. An > interesting problem > was encountered. During booting, UBIFS generates error messages and it sets > file system into read only mode. Please look to appendix A. I have > investigated > problem and according to my analysis observed problems are caused by severe > memory fragmentation. The platform is based on kernel 2.6.29. > > Few kernel errors where found in system logs. Please look to appendix A. > It looks > that this failure was caused by memory fragmentation. Look at two > following lines: > > DMA: 186*4kB 2*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB > 0*2048kB 0*4096kB 0*8192kB = 760kB > DMA: 998*4kB 146*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB > 0*2048kB 0*4096kB 0*8192kB = 5160kB > > There is no contiguous memory block of size 16 kB. Please consider > following > scenario: > > Assume that program reached line 916 in file.c (look to Appendix B). > Now do_writepage function is executed. Now function > ubifs_jnl_write_data is > called. Inside function ubifs_jnl_write_data operation kmalloc is called > (Appendix C, line 697). Driver tries to allocate slightly more than 8 kiB. > Unfortunately, allocator finds no contiguous memory block long enough. It > wakes up kswapd daemon. The daemon tries to drop page cache to disk. > Storing > data to ubifs partition calls ubifs_jnl_write_data again. Once again it > tries > to allocate slightly more than 8 KiB. Allocator detects allocation > operation > from procedure called to retain memory. In order to avoid endless loop > stack > dump is generated and kmalloc fails. Failure of ubifs_jnl_write_data causes > failure of kswapd action. Ubifs driver executes code in lines 926-929 > setting > UBI partition in read-only mode. Since now system becomes unstable, all > writing > operation to root file system are denied. > > Simple workaround for this problem is changing all kmalloc/kfree to > vmalloc/vfree. This functions creates virtual memory mapping, so there > is no > need to find contiguous memory blocks. Such a patch was attached in the > file > 'kmalloc2vmalloc.patch'. Function kmalloc is used often is ubifs driver > so it is > possible that the problem might appear somewhere else. Static buffer cannot > be used because function ubifs_jnl_write_data is both reentrant and in some > sense 'recursive'. Reentrant - yes, recursive - no. If kmalloc() cannot find space, it just returns error, and GFP_NOFS makes sure . There is no recursion. kswapd is a separate independent process. > Function ubifs_jnl_write_data calls kmalloc, which calls > __alloc_pages_internal. This function wakes up kswapd daemon. In order > to drop > page cache or buffers it tries to initiate UBIFS operations which include > calling ubifs_jnl_write_data. This is indeed a work-around. But I do not want to go for vmalloc, because lower-level MTD drivers may have difficulties with doing DMA on vmalloc'ed buffers. Well, there are few places where we use vmalloced buffers for I/O, and those should be fixed, but I do not want to add more. Also, vmalloc has its own issues - the virtual address range for vmalloc on 32-bit systems is very limited (128MiB or something like that), and we can start hitting these errors. But I do not see why 'static buffer' cannot be used. Quite the opposite, this approach can be used. You can do something like we do in 'ubifs_bulk_read()': 1. Pre-allocate a 16KiB buffer at mount time (c->write_reserve). Add a mutex to protect this buffer (c->write_reserve_mutex). 2. in 'ubifs_jnl_write_data()', try to allocate the buffer with 'kmalloc(GFP_NOFS | __GFP_NOWARN)' flag. 3. if it fails, then use 'c->write_reserve' under 'c->write_reserve_mutex' We could try to use mempools (see mm/mempools.c), but they are designed for constant size allocations. > Proposed solution is not sufficient IMHO. A failure of kmalloc > operations may occur > sooner or later, causing system crash or malfunction. There are numerous > calls to kmalloc inside UBIFS code. I wanted to ask you if it makes > sense to change > all of them to vmalloc interface. Have you run into such problems with > memory > fragmentation? No, we did not see it. But I do agree we should make UBIFS be more tolerant to high memory pressure conditions by being ready to not allocate in the write pat > > I hope you find this information useful. > > Yours sincerely, > Tomasz Stanislawski > > > * Appendix A * > > <4>[ 1018.882720] <4>kswapd0: page allocation failure. order:2, mode:0x4050 > <4>[ 1018.887611] [] (dump_stack+0x0/0x14) from [] > (__alloc_pages_internal+0x3a8/0x3d4) > <4>[ 1018.896906] [] (__alloc_pages_internal+0x0/0x3d4) from > [] (__get_free_pages+0x20/0x68) > <4>[ 1018.906296] [] (__get_free_pages+0x0/0x68) from > [] (ubifs_jnl_write_data+0x30/0x1a4) > <4>[ 1018.915751] [] (ubifs_jnl_write_data+0x0/0x1a4) from > [] (do_writepage+0x9c/0x188) > <4>[ 1018.924943] [] (do_writepage+0x0/0x188) from > [] (ubifs_writepage+0x16c/0x190) > <4>[ 1018.933838] r7:c4258000 r6:000009e3 r5:00000000 r4:c0730fa0 > <4>[ 1018.939426] [] (ubifs_writepage+0x0/0x190) from > [] (shrink_page_list+0x3e4/0x7c4) > <4>[ 1018.948680] [] (shrink_page_list+0x0/0x7c4) from > [] (shrink_list+0x29c/0x5ac) > <4>[ 1018.957513] [] (shrink_list+0x0/0x5ac) from [] > (shrink_zone+0x290/0x344) > <4>[ 1018.965909] [] (shrink_zone+0x0/0x344) from [] > (kswapd+0x3c4/0x560) > <4>[ 1018.973907] [] (kswapd+0x0/0x560) from [] > (kthread+0x54/0x80) > <4>[ 1018.981504] [] (kthread+0x0/0x80) from [] > (do_exit+0x0/0x640) > <4>[ 1018.988826] r5:00000000 r4:00000000 > <4>[ 1018.992331] Mem-info: > <4>[ 1018.994590] DMA per-cpu: > <4>[ 1018.997173] CPU 0: hi: 18, btch: 3 usd: 16 > <4>[ 1019.001891] DMA per-cpu: > <4>[ 1019.004440] CPU 0: hi: 90, btch: 15 usd: 76 > <4>[ 1019.009249] <4>[ 1019.009281] <4>[ 1019.009315] Active_anon:10728 > active_file:3486 inactive_anon:10797 > inactive_file:6444 unevictable:3641 dirty:1 writeback:1 unstable:0 > free:1480 slab:2573 mapped:12344 pagetables:1118 bounce:0 > <4>[ 1019.029203] DMA free:760kB min:548kB low:684kB high:820kB > active_anon:608kB inactive_anon:688kB active_file:52kB inactive_file:0kB > unevictable:516kB present:80264kB pages_scanned:2 all_unreclaimable? no > <4>[ 1019.047162] lowmem_reserve[]: 0 0 0 > <4>[ 1019.050559] DMA free:5160kB min:1780kB low:2224kB high:2668kB > active_anon:42304kB inactive_anon:42500kB active_file:13892kB > inactive_file:25776kB unevictable:14048kB present:260096kB > pages_scanned:0 all_unreclaimable? no > <4>[ 1019.070274] lowmem_reserve[]: 0 0 0 > <4>[ 1019.073514] DMA: 186*4kB 2*8kB 0*16kB 0*32kB 0*64kB 0*128kB > 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB = 760kB > <4>[ 1019.084267] DMA: 998*4kB 146*8kB 0*16kB 0*32kB 0*64kB 0*128kB > 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB = 5160kB > <4>[ 1019.095285] 19144 total pagecache pages > <4>[ 1019.099144] 4569 pages in swap cache > <4>[ 1019.102719] Swap cache stats: add 66771, delete 62202, find 8700/13664 > <4>[ 1019.109204] Free swap = 13540kB > <4>[ 1019.112412] Total swap = 99992kB > <4>[ 1019.133396] 85760 pages of RAM > <4>[ 1019.135006] 1943 free pages > <4>[ 1019.137860] 32559 reserved pages > <4>[ 1019.140990] 2129 slab pages > <4>[ 1019.143814] 41254 pages shared > <4>[ 1019.146801] 4569 pages swap cached > <4>[ 1019.150247] <3>UBIFS error (pid 395): do_writepage: cannot write > page 1 of inode 13633, error -12 > <4>[ 1019.159087] <4>UBIFS warning (pid 395): ubifs_ro_mode: switched to > read-only mode, error -12 > <4>[ 1019.306567] <3>UBIFS error (pid 395): make_reservation: cannot > reserve 529 bytes in jhead 2, error -30 > <4>[ 1019.314216] <3>UBIFS error (pid 395): do_writepage: cannot write > page 0 of inode 13633, error -30 > > > * Appendix B * > > File fs/ubifs/file.c:910 > 910 addr = kmap(page); > 911 block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; > 912 i = 0; > 913 while (len) { > 914 blen = min_t(int, len, UBIFS_BLOCK_SIZE); > 915 data_key_init(c, &key, inode->i_ino, block); > 916 err = ubifs_jnl_write_data(c, inode, &key, addr, > blen); > 917 if (err) > 918 break; > 919 if (++i >= UBIFS_BLOCKS_PER_PAGE) > 920 break; > 921 block += 1; > 922 addr += blen; > 923 len -= blen; > 924 } > 925 if (err) { > 926 SetPageError(page); > 927 ubifs_err("cannot write page %lu of inode %lu, > error %d", > 928 page->index, inode->i_ino, err); > 929 ubifs_ro_mode(c, err); > 930 } > > * Appendix C * > > File fs/ubifs/journal.c:684 > 684 int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode > *inode, > 685 const union ubifs_key *key, const void > *buf, int len) > 686 { > 687 struct ubifs_data_node *data; > 688 int err, lnum, offs, compr_type, out_len; > 689 int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * > WORST_COMPR_FACTOR; > 690 struct ubifs_inode *ui = ubifs_inode(inode); > 691 692 dbg_jnl("ino %lu, blk %u, len %d, key %s", > 693 (unsigned long)key_inum(c, key), key_block(c, > key), len, > 694 DBGKEY(key)); > 695 ubifs_assert(len <= UBIFS_BLOCK_SIZE); > 696 697 data = kmalloc(dlen, GFP_NOFS); > 698 if (!data) > 699 return -ENOMEM; > 700 701 data->ch.node_type = UBIFS_DATA_NODE; > > differences between files attachment (kmalloc2vmalloc.patch) > From 44a4267d6f9df2a65c7b2a6d45942a2ddd587309 Mon Sep 17 00:00:00 2001 > From: Tomasz Stanislawski > Date: Wed, 21 Apr 2010 14:59:33 +0200 > Subject: [PATCH] changed kmalloc to vmalloc to fix fragmentation problem > > --- > fs/ubifs/journal.c | 6 +++--- > 1 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c > index 64b5f3a..29d3db1 100644 > --- a/fs/ubifs/journal.c > +++ b/fs/ubifs/journal.c > @@ -694,7 +694,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, > DBGKEY(key)); > ubifs_assert(len <= UBIFS_BLOCK_SIZE); > > - data = kmalloc(dlen, GFP_NOFS); > + data = vmalloc(dlen); > if (!data) > return -ENOMEM; > > @@ -732,7 +732,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, > goto out_ro; > > finish_reservation(c); > - kfree(data); > + vfree(data); > return 0; > > out_release: > @@ -741,7 +741,7 @@ out_ro: > ubifs_ro_mode(c, err); > finish_reservation(c); > out_free: > - kfree(data); > + vfree(data); > return err; > } > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ -- Best Regards, Artem Bityutskiy (Артём Битюцкий) From mboxrd@z Thu Jan 1 00:00:00 1970 From: Artem Bityutskiy Subject: Re: UBIFS, Memory fragmentation problem Date: Thu, 29 Apr 2010 14:00:40 +0300 Message-ID: <1272538840.26440.42.camel@localhost> References: <4BD59783.8020800@samsung.com> Reply-To: dedekind1@gmail.com Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Cc: linux-fsdevel , kyungmin.park@samsung.com, Tomasz Fujak , linux-mtd@lists.infradead.org, Marek Szyprowski To: Tomasz Stanislawski Return-path: In-Reply-To: <4BD59783.8020800@samsung.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+gldm-linux-mtd-36=gmane.org@lists.infradead.org List-Id: linux-fsdevel.vger.kernel.org Q0NpbmcgZnMtZGV2ZWwsIGluIGNhc2Ugb3RoZXIgcGVvcGxlIGNhbiBnaXZlIGdvb2Qgc3VnZ2Vz dGlvbnMuCgpPbiBNb24sIDIwMTAtMDQtMjYgYXQgMTU6MzkgKzAyMDAsIFRvbWFzeiBTdGFuaXNs YXdza2kgd3JvdGU6Cj4gRGVhciBNci4gQXJ0ZW0gQml0eXV0c2tpeSwKPiBSZWNlbnRseSwgSSB3 YXMgZGV2ZWxvcGluZyBhIHBsYXRmb3JtIHRoYXQgdXRpbGl6ZXMgVUJJRlMuIEFuIAo+IGludGVy ZXN0aW5nIHByb2JsZW0KPiB3YXMgZW5jb3VudGVyZWQuIER1cmluZyBib290aW5nLCBVQklGUyBn ZW5lcmF0ZXMgZXJyb3IgbWVzc2FnZXMgYW5kIGl0IHNldHMKPiBmaWxlIHN5c3RlbSBpbnRvIHJl YWQgb25seSBtb2RlLiBQbGVhc2UgbG9vayB0byBhcHBlbmRpeCBBLiBJIGhhdmUgCj4gaW52ZXN0 aWdhdGVkCj4gcHJvYmxlbSBhbmQgYWNjb3JkaW5nIHRvIG15IGFuYWx5c2lzIG9ic2VydmVkIHBy b2JsZW1zIGFyZSBjYXVzZWQgYnkgc2V2ZXJlCj4gbWVtb3J5IGZyYWdtZW50YXRpb24uIFRoZSBw bGF0Zm9ybSBpcyBiYXNlZCBvbiBrZXJuZWwgMi42LjI5Lgo+IAo+IEZldyBrZXJuZWwgZXJyb3Jz IHdoZXJlIGZvdW5kIGluIHN5c3RlbSBsb2dzLiBQbGVhc2UgbG9vayB0byBhcHBlbmRpeCBBLiAK PiBJdCBsb29rcwo+IHRoYXQgdGhpcyBmYWlsdXJlIHdhcyBjYXVzZWQgYnkgbWVtb3J5IGZyYWdt ZW50YXRpb24uIExvb2sgYXQgdHdvIAo+IGZvbGxvd2luZyBsaW5lczoKPiAKPiBETUE6IDE4Nio0 a0IgMio4a0IgMCoxNmtCIDAqMzJrQiAwKjY0a0IgMCoxMjhrQiAwKjI1NmtCIDAqNTEya0IgMCox MDI0a0IKPiAgICAwKjIwNDhrQiAwKjQwOTZrQiAwKjgxOTJrQiA9IDc2MGtCCj4gRE1BOiA5OTgq NGtCIDE0Nio4a0IgMCoxNmtCIDAqMzJrQiAwKjY0a0IgMCoxMjhrQiAwKjI1NmtCIDAqNTEya0Ig MCoxMDI0a0IKPiAgICAwKjIwNDhrQiAwKjQwOTZrQiAwKjgxOTJrQiA9IDUxNjBrQgo+IAo+IFRo ZXJlIGlzIG5vIGNvbnRpZ3VvdXMgbWVtb3J5IGJsb2NrIG9mIHNpemUgMTYga0IuIFBsZWFzZSBj b25zaWRlciAKPiBmb2xsb3dpbmcKPiBzY2VuYXJpbzoKPiAKPiAgIEFzc3VtZSB0aGF0IHByb2dy YW0gcmVhY2hlZCBsaW5lIDkxNiBpbiBmaWxlLmMgKGxvb2sgdG8gQXBwZW5kaXggQikuCj4gTm93 IGRvX3dyaXRlcGFnZSBmdW5jdGlvbiBpcyBleGVjdXRlZC4gIE5vdyBmdW5jdGlvbiAKPiB1Ymlm c19qbmxfd3JpdGVfZGF0YSBpcwo+IGNhbGxlZC4gSW5zaWRlIGZ1bmN0aW9uIHViaWZzX2pubF93 cml0ZV9kYXRhIG9wZXJhdGlvbiBrbWFsbG9jIGlzIGNhbGxlZAo+IChBcHBlbmRpeCBDLCBsaW5l IDY5NykuIERyaXZlciB0cmllcyB0byBhbGxvY2F0ZSBzbGlnaHRseSBtb3JlIHRoYW4gOCBraUIu Cj4gVW5mb3J0dW5hdGVseSwgYWxsb2NhdG9yIGZpbmRzIG5vIGNvbnRpZ3VvdXMgbWVtb3J5IGJs b2NrIGxvbmcgZW5vdWdoLiAgSXQKPiB3YWtlcyB1cCBrc3dhcGQgZGFlbW9uLiBUaGUgZGFlbW9u IHRyaWVzIHRvIGRyb3AgcGFnZSBjYWNoZSB0byBkaXNrLiAgCj4gU3RvcmluZwo+IGRhdGEgdG8g dWJpZnMgcGFydGl0aW9uIGNhbGxzIHViaWZzX2pubF93cml0ZV9kYXRhIGFnYWluLiAgT25jZSBh Z2FpbiBpdCAKPiB0cmllcwo+IHRvIGFsbG9jYXRlIHNsaWdodGx5IG1vcmUgdGhhbiA4IEtpQi4g QWxsb2NhdG9yIGRldGVjdHMgYWxsb2NhdGlvbiAKPiBvcGVyYXRpb24KPiBmcm9tIHByb2NlZHVy ZSBjYWxsZWQgdG8gcmV0YWluIG1lbW9yeS4gSW4gb3JkZXIgdG8gYXZvaWQgZW5kbGVzcyBsb29w IAo+IHN0YWNrCj4gZHVtcCBpcyBnZW5lcmF0ZWQgYW5kIGttYWxsb2MgZmFpbHMuIEZhaWx1cmUg b2YgdWJpZnNfam5sX3dyaXRlX2RhdGEgY2F1c2VzCj4gZmFpbHVyZSBvZiBrc3dhcGQgYWN0aW9u LiBVYmlmcyBkcml2ZXIgZXhlY3V0ZXMgY29kZSBpbiBsaW5lcyA5MjYtOTI5IAo+IHNldHRpbmcK PiBVQkkgcGFydGl0aW9uIGluIHJlYWQtb25seSBtb2RlLiBTaW5jZSBub3cgc3lzdGVtIGJlY29t ZXMgdW5zdGFibGUsIGFsbCAKPiB3cml0aW5nCj4gb3BlcmF0aW9uIHRvIHJvb3QgZmlsZSBzeXN0 ZW0gYXJlIGRlbmllZC4KPiAKPiAgIFNpbXBsZSB3b3JrYXJvdW5kIGZvciB0aGlzIHByb2JsZW0g aXMgY2hhbmdpbmcgYWxsIGttYWxsb2Mva2ZyZWUgdG8KPiB2bWFsbG9jL3ZmcmVlLiBUaGlzIGZ1 bmN0aW9ucyBjcmVhdGVzIHZpcnR1YWwgbWVtb3J5IG1hcHBpbmcsIHNvIHRoZXJlIAo+IGlzIG5v Cj4gbmVlZCB0byBmaW5kIGNvbnRpZ3VvdXMgbWVtb3J5IGJsb2Nrcy4gU3VjaCBhIHBhdGNoIHdh cyBhdHRhY2hlZCBpbiB0aGUgCj4gZmlsZQo+ICdrbWFsbG9jMnZtYWxsb2MucGF0Y2gnLiBGdW5j dGlvbiBrbWFsbG9jIGlzIHVzZWQgb2Z0ZW4gaXMgdWJpZnMgZHJpdmVyIAo+IHNvIGl0IGlzCj4g cG9zc2libGUgdGhhdCB0aGUgcHJvYmxlbSBtaWdodCBhcHBlYXIgc29tZXdoZXJlIGVsc2UuIFN0 YXRpYyBidWZmZXIgY2Fubm90Cj4gYmUgdXNlZCBiZWNhdXNlIGZ1bmN0aW9uIHViaWZzX2pubF93 cml0ZV9kYXRhIGlzIGJvdGggcmVlbnRyYW50IGFuZCBpbiBzb21lCj4gc2Vuc2UgJ3JlY3Vyc2l2 ZScuCgpSZWVudHJhbnQgLSB5ZXMsIHJlY3Vyc2l2ZSAtIG5vLiBJZiBrbWFsbG9jKCkgY2Fubm90 IGZpbmQgc3BhY2UsIGl0IGp1c3QKcmV0dXJucyBlcnJvciwgYW5kIEdGUF9OT0ZTIG1ha2VzIHN1 cmUgLiBUaGVyZSBpcyBubyByZWN1cnNpb24uIGtzd2FwZAppcyBhIHNlcGFyYXRlIGluZGVwZW5k ZW50IHByb2Nlc3MuCgo+ICBGdW5jdGlvbiB1Ymlmc19qbmxfd3JpdGVfZGF0YSBjYWxscyBrbWFs bG9jLCB3aGljaCBjYWxscwo+IF9fYWxsb2NfcGFnZXNfaW50ZXJuYWwuICBUaGlzIGZ1bmN0aW9u IHdha2VzIHVwIGtzd2FwZCBkYWVtb24uIEluIG9yZGVyIAo+IHRvIGRyb3AKPiBwYWdlIGNhY2hl IG9yIGJ1ZmZlcnMgaXQgdHJpZXMgdG8gaW5pdGlhdGUgVUJJRlMgb3BlcmF0aW9ucyB3aGljaCBp bmNsdWRlCj4gY2FsbGluZyB1Ymlmc19qbmxfd3JpdGVfZGF0YS4KClRoaXMgaXMgaW5kZWVkIGEg d29yay1hcm91bmQuIEJ1dCBJIGRvIG5vdCB3YW50IHRvIGdvIGZvciB2bWFsbG9jLApiZWNhdXNl IGxvd2VyLWxldmVsIE1URCBkcml2ZXJzIG1heSBoYXZlIGRpZmZpY3VsdGllcyB3aXRoIGRvaW5n IERNQSBvbgp2bWFsbG9jJ2VkIGJ1ZmZlcnMuIFdlbGwsIHRoZXJlIGFyZSBmZXcgcGxhY2VzIHdo ZXJlIHdlIHVzZSB2bWFsbG9jZWQKYnVmZmVycyBmb3IgSS9PLCBhbmQgdGhvc2Ugc2hvdWxkIGJl IGZpeGVkLCBidXQgSSBkbyBub3Qgd2FudCB0byBhZGQKbW9yZS4KCkFsc28sIHZtYWxsb2MgaGFz IGl0cyBvd24gaXNzdWVzIC0gdGhlIHZpcnR1YWwgYWRkcmVzcyByYW5nZSBmb3Igdm1hbGxvYwpv biAzMi1iaXQgc3lzdGVtcyBpcyB2ZXJ5IGxpbWl0ZWQgKDEyOE1pQiBvciBzb21ldGhpbmcgbGlr ZSB0aGF0KSwgYW5kCndlIGNhbiBzdGFydCBoaXR0aW5nIHRoZXNlIGVycm9ycy4KCkJ1dCBJIGRv IG5vdCBzZWUgd2h5ICdzdGF0aWMgYnVmZmVyJyBjYW5ub3QgYmUgdXNlZC4gUXVpdGUgdGhlIG9w cG9zaXRlLAp0aGlzIGFwcHJvYWNoIGNhbiBiZSB1c2VkLgoKWW91IGNhbiBkbyBzb21ldGhpbmcg bGlrZSB3ZSBkbyBpbiAndWJpZnNfYnVsa19yZWFkKCknOgoKMS4gUHJlLWFsbG9jYXRlIGEgMTZL aUIgYnVmZmVyIGF0IG1vdW50IHRpbWUgKGMtPndyaXRlX3Jlc2VydmUpLiBBZGQgYQptdXRleCB0 byBwcm90ZWN0IHRoaXMgYnVmZmVyIChjLT53cml0ZV9yZXNlcnZlX211dGV4KS4KMi4gaW4gJ3Vi aWZzX2pubF93cml0ZV9kYXRhKCknLCB0cnkgdG8gYWxsb2NhdGUgdGhlIGJ1ZmZlciB3aXRoCidr bWFsbG9jKEdGUF9OT0ZTIHwgX19HRlBfTk9XQVJOKScgZmxhZy4KMy4gaWYgaXQgZmFpbHMsIHRo ZW4gdXNlICdjLT53cml0ZV9yZXNlcnZlJyB1bmRlcgonYy0+d3JpdGVfcmVzZXJ2ZV9tdXRleCcK CldlIGNvdWxkIHRyeSB0byB1c2UgbWVtcG9vbHMgKHNlZSBtbS9tZW1wb29scy5jKSwgYnV0IHRo ZXkgYXJlIGRlc2lnbmVkCmZvciBjb25zdGFudCBzaXplIGFsbG9jYXRpb25zLgoKPiAgIFByb3Bv c2VkIHNvbHV0aW9uIGlzIG5vdCBzdWZmaWNpZW50IElNSE8uIEEgZmFpbHVyZSBvZiBrbWFsbG9j IAo+IG9wZXJhdGlvbnMgbWF5IG9jY3VyCj4gc29vbmVyIG9yIGxhdGVyLCBjYXVzaW5nIHN5c3Rl bSBjcmFzaCBvciBtYWxmdW5jdGlvbi4gVGhlcmUgYXJlIG51bWVyb3VzCj4gY2FsbHMgdG8ga21h bGxvYyBpbnNpZGUgVUJJRlMgY29kZS4gSSB3YW50ZWQgdG8gYXNrIHlvdSBpZiBpdCBtYWtlcyAK PiBzZW5zZSB0byBjaGFuZ2UKPiBhbGwgb2YgdGhlbSB0byB2bWFsbG9jIGludGVyZmFjZS4gSGF2 ZSB5b3UgcnVuIGludG8gc3VjaCBwcm9ibGVtcyB3aXRoIAo+IG1lbW9yeQo+IGZyYWdtZW50YXRp b24/CgpObywgd2UgZGlkIG5vdCBzZWUgaXQuIEJ1dCBJIGRvIGFncmVlIHdlIHNob3VsZCBtYWtl IFVCSUZTIGJlIG1vcmUKdG9sZXJhbnQgdG8gaGlnaCBtZW1vcnkgcHJlc3N1cmUgY29uZGl0aW9u cyBieSBiZWluZyByZWFkeSB0byBub3QKYWxsb2NhdGUgaW4gdGhlIHdyaXRlIHBhdCAKPiAKPiBJ IGhvcGUgeW91IGZpbmQgdGhpcyBpbmZvcm1hdGlvbiB1c2VmdWwuCj4gCj4gWW91cnMgc2luY2Vy ZWx5LAo+IFRvbWFzeiBTdGFuaXNsYXdza2kKPiAKPiAKPiAgICogQXBwZW5kaXggQSAqCj4gCj4g PDQ+WyAxMDE4Ljg4MjcyMF0gPDQ+a3N3YXBkMDogcGFnZSBhbGxvY2F0aW9uIGZhaWx1cmUuIG9y ZGVyOjIsIG1vZGU6MHg0MDUwCj4gPDQ+WyAxMDE4Ljg4NzYxMV0gWzxjMDQ3ZmVjND5dIChkdW1w X3N0YWNrKzB4MC8weDE0KSBmcm9tIFs8YzAxYTFiMzA+XSAKPiAoX19hbGxvY19wYWdlc19pbnRl cm5hbCsweDNhOC8weDNkNCkKPiA8ND5bIDEwMTguODk2OTA2XSBbPGMwMWExNzg4Pl0gKF9fYWxs b2NfcGFnZXNfaW50ZXJuYWwrMHgwLzB4M2Q0KSBmcm9tIAo+IFs8YzAxYTFiZGM+XSAoX19nZXRf ZnJlZV9wYWdlcysweDIwLzB4NjgpCj4gPDQ+WyAxMDE4LjkwNjI5Nl0gWzxjMDFhMWJiYz5dIChf X2dldF9mcmVlX3BhZ2VzKzB4MC8weDY4KSBmcm9tIAo+IFs8YzAyNTliOGM+XSAodWJpZnNfam5s X3dyaXRlX2RhdGErMHgzMC8weDFhNCkKPiA8ND5bIDEwMTguOTE1NzUxXSBbPGMwMjU5YjVjPl0g KHViaWZzX2pubF93cml0ZV9kYXRhKzB4MC8weDFhNCkgZnJvbSAKPiBbPGMwMjViM2E0Pl0gKGRv X3dyaXRlcGFnZSsweDljLzB4MTg4KQo+IDw0PlsgMTAxOC45MjQ5NDNdIFs8YzAyNWIzMDg+XSAo ZG9fd3JpdGVwYWdlKzB4MC8weDE4OCkgZnJvbSAKPiBbPGMwMjViNWZjPl0gKHViaWZzX3dyaXRl cGFnZSsweDE2Yy8weDE5MCkKPiA8ND5bIDEwMTguOTMzODM4XSAgcjc6YzQyNTgwMDAgcjY6MDAw MDA5ZTMgcjU6MDAwMDAwMDAgcjQ6YzA3MzBmYTAKPiA8ND5bIDEwMTguOTM5NDI2XSBbPGMwMjVi NDkwPl0gKHViaWZzX3dyaXRlcGFnZSsweDAvMHgxOTApIGZyb20gCj4gWzxjMDFhNmY3MD5dIChz aHJpbmtfcGFnZV9saXN0KzB4M2U0LzB4N2M0KQo+IDw0PlsgMTAxOC45NDg2ODBdIFs8YzAxYTZi OGM+XSAoc2hyaW5rX3BhZ2VfbGlzdCsweDAvMHg3YzQpIGZyb20gCj4gWzxjMDFhNzVlYz5dIChz aHJpbmtfbGlzdCsweDI5Yy8weDVhYykKPiA8ND5bIDEwMTguOTU3NTEzXSBbPGMwMWE3MzUwPl0g KHNocmlua19saXN0KzB4MC8weDVhYykgZnJvbSBbPGMwMWE3YjhjPl0gCj4gKHNocmlua196b25l KzB4MjkwLzB4MzQ0KQo+IDw0PlsgMTAxOC45NjU5MDldIFs8YzAxYTc4ZmM+XSAoc2hyaW5rX3pv bmUrMHgwLzB4MzQ0KSBmcm9tIFs8YzAxYTgxN2M+XSAKPiAoa3N3YXBkKzB4M2M0LzB4NTYwKQo+ IDw0PlsgMTAxOC45NzM5MDddIFs8YzAxYTdkYjg+XSAoa3N3YXBkKzB4MC8weDU2MCkgZnJvbSBb PGMwMTcxMzE4Pl0gCj4gKGt0aHJlYWQrMHg1NC8weDgwKQo+IDw0PlsgMTAxOC45ODE1MDRdIFs8 YzAxNzEyYzQ+XSAoa3RocmVhZCsweDAvMHg4MCkgZnJvbSBbPGMwMTVmZGJjPl0gCj4gKGRvX2V4 aXQrMHgwLzB4NjQwKQo+IDw0PlsgMTAxOC45ODg4MjZdICByNTowMDAwMDAwMCByNDowMDAwMDAw MAo+IDw0PlsgMTAxOC45OTIzMzFdIE1lbS1pbmZvOgo+IDw0PlsgMTAxOC45OTQ1OTBdIERNQSBw ZXItY3B1Ogo+IDw0PlsgMTAxOC45OTcxNzNdIENQVSAgICAwOiBoaTogICAxOCwgYnRjaDogICAz IHVzZDogIDE2Cj4gPDQ+WyAxMDE5LjAwMTg5MV0gRE1BIHBlci1jcHU6Cj4gPDQ+WyAxMDE5LjAw NDQ0MF0gQ1BVICAgIDA6IGhpOiAgIDkwLCBidGNoOiAgMTUgdXNkOiAgNzYKPiA8ND5bIDEwMTku MDA5MjQ5XSA8ND5bIDEwMTkuMDA5MjgxXSA8ND5bIDEwMTkuMDA5MzE1XSBBY3RpdmVfYW5vbjox MDcyOCAKPiBhY3RpdmVfZmlsZTozNDg2IGluYWN0aXZlX2Fub246MTA3OTcKPiAgaW5hY3RpdmVf ZmlsZTo2NDQ0IHVuZXZpY3RhYmxlOjM2NDEgZGlydHk6MSB3cml0ZWJhY2s6MSB1bnN0YWJsZTow Cj4gIGZyZWU6MTQ4MCBzbGFiOjI1NzMgbWFwcGVkOjEyMzQ0IHBhZ2V0YWJsZXM6MTExOCBib3Vu Y2U6MAo+IDw0PlsgMTAxOS4wMjkyMDNdIERNQSBmcmVlOjc2MGtCIG1pbjo1NDhrQiBsb3c6Njg0 a0IgaGlnaDo4MjBrQiAKPiBhY3RpdmVfYW5vbjo2MDhrQiBpbmFjdGl2ZV9hbm9uOjY4OGtCIGFj dGl2ZV9maWxlOjUya0IgaW5hY3RpdmVfZmlsZTowa0IgCj4gdW5ldmljdGFibGU6NTE2a0IgcHJl c2VudDo4MDI2NGtCIHBhZ2VzX3NjYW5uZWQ6MiBhbGxfdW5yZWNsYWltYWJsZT8gbm8KPiA8ND5b IDEwMTkuMDQ3MTYyXSBsb3dtZW1fcmVzZXJ2ZVtdOiAwIDAgMAo+IDw0PlsgMTAxOS4wNTA1NTld IERNQSBmcmVlOjUxNjBrQiBtaW46MTc4MGtCIGxvdzoyMjI0a0IgaGlnaDoyNjY4a0IgCj4gYWN0 aXZlX2Fub246NDIzMDRrQiBpbmFjdGl2ZV9hbm9uOjQyNTAwa0IgYWN0aXZlX2ZpbGU6MTM4OTJr QiAKPiBpbmFjdGl2ZV9maWxlOjI1Nzc2a0IgdW5ldmljdGFibGU6MTQwNDhrQiBwcmVzZW50OjI2 MDA5NmtCIAo+IHBhZ2VzX3NjYW5uZWQ6MCBhbGxfdW5yZWNsYWltYWJsZT8gbm8KPiA8ND5bIDEw MTkuMDcwMjc0XSBsb3dtZW1fcmVzZXJ2ZVtdOiAwIDAgMAo+IDw0PlsgMTAxOS4wNzM1MTRdIERN QTogMTg2KjRrQiAyKjhrQiAwKjE2a0IgMCozMmtCIDAqNjRrQiAwKjEyOGtCIAo+IDAqMjU2a0Ig MCo1MTJrQiAwKjEwMjRrQiAwKjIwNDhrQiAwKjQwOTZrQiAwKjgxOTJrQiA9IDc2MGtCCj4gPDQ+ WyAxMDE5LjA4NDI2N10gRE1BOiA5OTgqNGtCIDE0Nio4a0IgMCoxNmtCIDAqMzJrQiAwKjY0a0Ig MCoxMjhrQiAKPiAwKjI1NmtCIDAqNTEya0IgMCoxMDI0a0IgMCoyMDQ4a0IgMCo0MDk2a0IgMCo4 MTkya0IgPSA1MTYwa0IKPiA8ND5bIDEwMTkuMDk1Mjg1XSAxOTE0NCB0b3RhbCBwYWdlY2FjaGUg cGFnZXMKPiA8ND5bIDEwMTkuMDk5MTQ0XSA0NTY5IHBhZ2VzIGluIHN3YXAgY2FjaGUKPiA8ND5b IDEwMTkuMTAyNzE5XSBTd2FwIGNhY2hlIHN0YXRzOiBhZGQgNjY3NzEsIGRlbGV0ZSA2MjIwMiwg ZmluZCA4NzAwLzEzNjY0Cj4gPDQ+WyAxMDE5LjEwOTIwNF0gRnJlZSBzd2FwICA9IDEzNTQwa0IK PiA8ND5bIDEwMTkuMTEyNDEyXSBUb3RhbCBzd2FwID0gOTk5OTJrQgo+IDw0PlsgMTAxOS4xMzMz OTZdIDg1NzYwIHBhZ2VzIG9mIFJBTQo+IDw0PlsgMTAxOS4xMzUwMDZdIDE5NDMgZnJlZSBwYWdl cwo+IDw0PlsgMTAxOS4xMzc4NjBdIDMyNTU5IHJlc2VydmVkIHBhZ2VzCj4gPDQ+WyAxMDE5LjE0 MDk5MF0gMjEyOSBzbGFiIHBhZ2VzCj4gPDQ+WyAxMDE5LjE0MzgxNF0gNDEyNTQgcGFnZXMgc2hh cmVkCj4gPDQ+WyAxMDE5LjE0NjgwMV0gNDU2OSBwYWdlcyBzd2FwIGNhY2hlZAo+IDw0PlsgMTAx OS4xNTAyNDddIDwzPlVCSUZTIGVycm9yIChwaWQgMzk1KTogZG9fd3JpdGVwYWdlOiBjYW5ub3Qg d3JpdGUgCj4gcGFnZSAxIG9mIGlub2RlIDEzNjMzLCBlcnJvciAtMTIKPiA8ND5bIDEwMTkuMTU5 MDg3XSA8ND5VQklGUyB3YXJuaW5nIChwaWQgMzk1KTogdWJpZnNfcm9fbW9kZTogc3dpdGNoZWQg dG8gCj4gcmVhZC1vbmx5IG1vZGUsIGVycm9yIC0xMgo+IDw0PlsgMTAxOS4zMDY1NjddIDwzPlVC SUZTIGVycm9yIChwaWQgMzk1KTogbWFrZV9yZXNlcnZhdGlvbjogY2Fubm90IAo+IHJlc2VydmUg NTI5IGJ5dGVzIGluIGpoZWFkIDIsIGVycm9yIC0zMAo+IDw0PlsgMTAxOS4zMTQyMTZdIDwzPlVC SUZTIGVycm9yIChwaWQgMzk1KTogZG9fd3JpdGVwYWdlOiBjYW5ub3Qgd3JpdGUgCj4gcGFnZSAw IG9mIGlub2RlIDEzNjMzLCBlcnJvciAtMzAKPiAKPiAKPiAgICogQXBwZW5kaXggQiAqCj4gCj4g RmlsZSBmcy91Ymlmcy9maWxlLmM6OTEwCj4gICA5MTAgICAgICAgICBhZGRyID0ga21hcChwYWdl KTsKPiAgIDkxMSAgICAgICAgIGJsb2NrID0gcGFnZS0+aW5kZXggPDwgVUJJRlNfQkxPQ0tTX1BF Ul9QQUdFX1NISUZUOwo+ICAgOTEyICAgICAgICAgaSA9IDA7Cj4gICA5MTMgICAgICAgICB3aGls ZSAobGVuKSB7Cj4gICA5MTQgICAgICAgICAgICAgICAgIGJsZW4gPSBtaW5fdChpbnQsIGxlbiwg VUJJRlNfQkxPQ0tfU0laRSk7Cj4gICA5MTUgICAgICAgICAgICAgICAgIGRhdGFfa2V5X2luaXQo YywgJmtleSwgaW5vZGUtPmlfaW5vLCBibG9jayk7Cj4gICA5MTYgICAgICAgICAgICAgICAgIGVy ciA9IHViaWZzX2pubF93cml0ZV9kYXRhKGMsIGlub2RlLCAma2V5LCBhZGRyLCAKPiBibGVuKTsK PiAgIDkxNyAgICAgICAgICAgICAgICAgaWYgKGVycikKPiAgIDkxOCAgICAgICAgICAgICAgICAg ICAgICAgICBicmVhazsKPiAgIDkxOSAgICAgICAgICAgICAgICAgaWYgKCsraSA+PSBVQklGU19C TE9DS1NfUEVSX1BBR0UpCj4gICA5MjAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7Cj4g ICA5MjEgICAgICAgICAgICAgICAgIGJsb2NrICs9IDE7Cj4gICA5MjIgICAgICAgICAgICAgICAg IGFkZHIgKz0gYmxlbjsKPiAgIDkyMyAgICAgICAgICAgICAgICAgbGVuIC09IGJsZW47Cj4gICA5 MjQgICAgICAgICB9Cj4gICA5MjUgICAgICAgICBpZiAoZXJyKSB7Cj4gICA5MjYgICAgICAgICAg ICAgICAgIFNldFBhZ2VFcnJvcihwYWdlKTsKPiAgIDkyNyAgICAgICAgICAgICAgICAgdWJpZnNf ZXJyKCJjYW5ub3Qgd3JpdGUgcGFnZSAlbHUgb2YgaW5vZGUgJWx1LCAKPiBlcnJvciAlZCIsCj4g ICA5MjggICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlLT5pbmRleCwgaW5vZGUtPmlfaW5v LCBlcnIpOwo+ICAgOTI5ICAgICAgICAgICAgICAgICB1Ymlmc19yb19tb2RlKGMsIGVycik7Cj4g ICA5MzAgICAgICAgICB9Cj4gCj4gICAqIEFwcGVuZGl4IEMgKgo+IAo+IEZpbGUgZnMvdWJpZnMv am91cm5hbC5jOjY4NAo+ICAgNjg0IGludCB1Ymlmc19qbmxfd3JpdGVfZGF0YShzdHJ1Y3QgdWJp ZnNfaW5mbyAqYywgY29uc3Qgc3RydWN0IGlub2RlIAo+ICppbm9kZSwKPiAgIDY4NSAgICAgICAg ICAgICAgICAgICAgICAgICAgY29uc3QgdW5pb24gdWJpZnNfa2V5ICprZXksIGNvbnN0IHZvaWQg Cj4gKmJ1ZiwgaW50IGxlbikKPiAgIDY4NiB7Cj4gICA2ODcgICAgICAgICBzdHJ1Y3QgdWJpZnNf ZGF0YV9ub2RlICpkYXRhOwo+ICAgNjg4ICAgICAgICAgaW50IGVyciwgbG51bSwgb2ZmcywgY29t cHJfdHlwZSwgb3V0X2xlbjsKPiAgIDY4OSAgICAgICAgIGludCBkbGVuID0gVUJJRlNfREFUQV9O T0RFX1NaICsgVUJJRlNfQkxPQ0tfU0laRSAqIAo+IFdPUlNUX0NPTVBSX0ZBQ1RPUjsKPiAgIDY5 MCAgICAgICAgIHN0cnVjdCB1Ymlmc19pbm9kZSAqdWkgPSB1Ymlmc19pbm9kZShpbm9kZSk7Cj4g ICA2OTEgICAgICAgICAgNjkyICAgICAgICAgZGJnX2pubCgiaW5vICVsdSwgYmxrICV1LCBsZW4g JWQsIGtleSAlcyIsCj4gICA2OTMgICAgICAgICAgICAgICAgICh1bnNpZ25lZCBsb25nKWtleV9p bnVtKGMsIGtleSksIGtleV9ibG9jayhjLCAKPiBrZXkpLCBsZW4sCj4gICA2OTQgICAgICAgICAg ICAgICAgIERCR0tFWShrZXkpKTsKPiAgIDY5NSAgICAgICAgIHViaWZzX2Fzc2VydChsZW4gPD0g VUJJRlNfQkxPQ0tfU0laRSk7Cj4gICA2OTYgICAgICAgICAgICAgICAgICA2OTcgICAgICAgICBk YXRhID0ga21hbGxvYyhkbGVuLCBHRlBfTk9GUyk7Cj4gICA2OTggICAgICAgICBpZiAoIWRhdGEp Cj4gICA2OTkgICAgICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOwo+ICAgNzAwICAgICAgICAg IDcwMSAgICAgICAgIGRhdGEtPmNoLm5vZGVfdHlwZSA9IFVCSUZTX0RBVEFfTk9ERTsKPiAKPiBk aWZmZXJlbmNlcyBiZXR3ZWVuIGZpbGVzIGF0dGFjaG1lbnQgKGttYWxsb2Mydm1hbGxvYy5wYXRj aCkKPiBGcm9tIDQ0YTQyNjdkNmY5ZGYyYTY1YzdiMmE2ZDQ1OTQyYTJkZGQ1ODczMDkgTW9uIFNl cCAxNyAwMDowMDowMCAyMDAxCj4gRnJvbTogVG9tYXN6IFN0YW5pc2xhd3NraSA8dC5zdGFuaXNs YXdzQHNhbXN1bmcuY29tPgo+IERhdGU6IFdlZCwgMjEgQXByIDIwMTAgMTQ6NTk6MzMgKzAyMDAK PiBTdWJqZWN0OiBbUEFUQ0hdIGNoYW5nZWQga21hbGxvYyB0byB2bWFsbG9jIHRvIGZpeCBmcmFn bWVudGF0aW9uIHByb2JsZW0KPiAKPiAtLS0KPiAgZnMvdWJpZnMvam91cm5hbC5jIHwgICAgNiAr KystLS0KPiAgMSBmaWxlcyBjaGFuZ2VkLCAzIGluc2VydGlvbnMoKyksIDMgZGVsZXRpb25zKC0p Cj4gCj4gZGlmZiAtLWdpdCBhL2ZzL3ViaWZzL2pvdXJuYWwuYyBiL2ZzL3ViaWZzL2pvdXJuYWwu Ywo+IGluZGV4IDY0YjVmM2EuLjI5ZDNkYjEgMTAwNjQ0Cj4gLS0tIGEvZnMvdWJpZnMvam91cm5h bC5jCj4gKysrIGIvZnMvdWJpZnMvam91cm5hbC5jCj4gQEAgLTY5NCw3ICs2OTQsNyBAQCBpbnQg dWJpZnNfam5sX3dyaXRlX2RhdGEoc3RydWN0IHViaWZzX2luZm8gKmMsIGNvbnN0IHN0cnVjdCBp bm9kZSAqaW5vZGUsCj4gIAkJREJHS0VZKGtleSkpOwo+ICAJdWJpZnNfYXNzZXJ0KGxlbiA8PSBV QklGU19CTE9DS19TSVpFKTsKPiAgCj4gLQlkYXRhID0ga21hbGxvYyhkbGVuLCBHRlBfTk9GUyk7 Cj4gKwlkYXRhID0gdm1hbGxvYyhkbGVuKTsKPiAgCWlmICghZGF0YSkKPiAgCQlyZXR1cm4gLUVO T01FTTsKPiAgCj4gQEAgLTczMiw3ICs3MzIsNyBAQCBpbnQgdWJpZnNfam5sX3dyaXRlX2RhdGEo c3RydWN0IHViaWZzX2luZm8gKmMsIGNvbnN0IHN0cnVjdCBpbm9kZSAqaW5vZGUsCj4gIAkJZ290 byBvdXRfcm87Cj4gIAo+ICAJZmluaXNoX3Jlc2VydmF0aW9uKGMpOwo+IC0Ja2ZyZWUoZGF0YSk7 Cj4gKwl2ZnJlZShkYXRhKTsKPiAgCXJldHVybiAwOwo+ICAKPiAgb3V0X3JlbGVhc2U6Cj4gQEAg LTc0MSw3ICs3NDEsNyBAQCBvdXRfcm86Cj4gIAl1Ymlmc19yb19tb2RlKGMsIGVycik7Cj4gIAlm aW5pc2hfcmVzZXJ2YXRpb24oYyk7Cj4gIG91dF9mcmVlOgo+IC0Ja2ZyZWUoZGF0YSk7Cj4gKwl2 ZnJlZShkYXRhKTsKPiAgCXJldHVybiBlcnI7Cj4gIH0KPiAgCj4gX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCj4gTGludXggTVREIGRpc2N1c3Np b24gbWFpbGluZyBsaXN0Cj4gaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0 aW5mby9saW51eC1tdGQvCgotLSAKQmVzdCBSZWdhcmRzLApBcnRlbSBCaXR5dXRza2l5ICjQkNGA 0YLRkdC8INCR0LjRgtGO0YbQutC40LkpCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fCkxpbnV4IE1URCBkaXNjdXNzaW9uIG1haWxpbmcgbGlz dApodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW10ZC8K