From mboxrd@z Thu Jan 1 00:00:00 1970 From: John Hubbard Subject: Re: [PATCH v2 05/18] mm/gup: introduce pin_user_pages*() and FOLL_PIN Date: Mon, 4 Nov 2019 11:04:38 -0800 Message-ID: References: <20191103211813.213227-1-jhubbard@nvidia.com> <20191103211813.213227-6-jhubbard@nvidia.com> <20191104173325.GD5134@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: quoted-printable Return-path: In-Reply-To: <20191104173325.GD5134@redhat.com> Content-Language: en-US Sender: netdev-owner@vger.kernel.org To: Jerome Glisse Cc: Andrew Morton , Al Viro , Alex Williamson , Benjamin Herrenschmidt , =?UTF-8?B?QmrDtnJuIFTDtnBlbA==?= , Christoph Hellwig , Dan Williams , Daniel Vetter , Dave Chinner , David Airlie , "David S . Miller" , Ira Weiny , Jan Kara , Jason Gunthorpe , Jens Axboe , Jonathan Corbet , Magnus Karlsson , Mauro Carvalho Chehab , Michael Ellerman , Michal Hocko List-Id: dri-devel@lists.freedesktop.org On 11/4/19 9:33 AM, Jerome Glisse wrote: ... >=20 > Few nitpick belows, nonetheless: >=20 > Reviewed-by: J=E9r=F4me Glisse > [...] >> + >> +CASE 3: ODP >> +----------- >> +(Mellanox/Infiniband On Demand Paging: the hardware supports >> +replayable page faulting). There are GUP references to pages serving as= DMA >> +buffers. For ODP, MMU notifiers are used to synchronize with page_mkcle= an() >> +and munmap(). Therefore, normal GUP calls are sufficient, so neither fl= ag >> +needs to be set. >=20 > I would not include ODP or anything like it here, they do not use > GUP anymore and i believe it is more confusing here. I would how- > ever include some text in this documentation explaining that hard- > ware that support page fault is superior as it does not incur any > of the issues described here. OK, agreed, here's a new write up that I'll put in v3: CASE 3: ODP ----------- Advanced, but non-CPU (DMA) hardware that supports replayable page faults. Here, a well-written driver doesn't normally need to pin pages at all. Howe= ver, if the driver does choose to do so, it can register MMU notifiers for the r= ange, and will be called back upon invalidation. Either way (avoiding page pinnin= g, or using MMU notifiers to unpin upon request), there is proper synchronization= with=20 both filesystem and mm (page_mkclean(), munmap(), etc). Therefore, neither flag needs to be set. It's worth mentioning here that pinning pages should not be the first desig= n choice. If page fault capable hardware is available, then the software shou= ld be written so that it does not pin pages. This allows mm and filesystems to operate more efficiently and reliably. > [...] >=20 >> diff --git a/mm/gup.c b/mm/gup.c >> index 199da99e8ffc..1aea48427879 100644 >> --- a/mm/gup.c >> +++ b/mm/gup.c >=20 > [...] >=20 >> @@ -1014,7 +1018,16 @@ static __always_inline long __get_user_pages_lock= ed(struct task_struct *tsk, >> BUG_ON(*locked !=3D 1); >> } >> =20 >> - if (pages) >> + /* >> + * FOLL_PIN and FOLL_GET are mutually exclusive. Traditional behavior >> + * is to set FOLL_GET if the caller wants pages[] filled in (but has >> + * carelessly failed to specify FOLL_GET), so keep doing that, but onl= y >> + * for FOLL_GET, not for the newer FOLL_PIN. >> + * >> + * FOLL_PIN always expects pages to be non-null, but no need to assert >> + * that here, as any failures will be obvious enough. >> + */ >> + if (pages && !(flags & FOLL_PIN)) >> flags |=3D FOLL_GET; >=20 > Did you look at user that have pages and not FOLL_GET set ? > I believe it would be better to first fix them to end up > with FOLL_GET set and then error out if pages is !=3D NULL but > nor FOLL_GET or FOLL_PIN is set. >=20 I was perhaps overly cautious, and didn't go there. However, it's probably doable, given that there was already the following in __get_user_pages(): VM_BUG_ON(!!pages !=3D !!(gup_flags & FOLL_GET)); ...which will have conditioned people and code to set FOLL_GET together wit= h pages. So I agree that the time is right. In order to make bisecting future failures simpler, I can insert a patch ri= ght=20 before this one, that changes the FOLL_GET setting into an assert, like thi= s: diff --git a/mm/gup.c b/mm/gup.c index 8f236a335ae9..be338961e80d 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1014,8 +1014,8 @@ static __always_inline long __get_user_pages_locked(s= truct task_struct *tsk, BUG_ON(*locked !=3D 1); } =20 - if (pages) - flags |=3D FOLL_GET; + if (pages && WARN_ON_ONCE(!(gup_flags & FOLL_GET))) + return -EINVAL; =20 pages_done =3D 0; lock_dropped =3D false; ...and then add in FOLL_PIN, with this patch. >> =20 >> pages_done =3D 0; >=20 >> @@ -2373,24 +2402,9 @@ static int __gup_longterm_unlocked(unsigned long = start, int nr_pages, >> return ret; >> } >> =20 >> -/** >> - * get_user_pages_fast() - pin user pages in memory >> - * @start: starting user address >> - * @nr_pages: number of pages from start to pin >> - * @gup_flags: flags modifying pin behaviour >> - * @pages: array that receives pointers to the pages pinned. >> - * Should be at least nr_pages long. >> - * >> - * Attempt to pin user pages in memory without taking mm->mmap_sem. >> - * If not successful, it will fall back to taking the lock and >> - * calling get_user_pages(). >> - * >> - * Returns number of pages pinned. This may be fewer than the number >> - * requested. If nr_pages is 0 or negative, returns 0. If no pages >> - * were pinned, returns -errno. >> - */ >> -int get_user_pages_fast(unsigned long start, int nr_pages, >> - unsigned int gup_flags, struct page **pages) >> +static int internal_get_user_pages_fast(unsigned long start, int nr_pag= es, >> + unsigned int gup_flags, >> + struct page **pages) >=20 > Usualy function are rename to _old_func_name ie add _ in front. So > here it would become _get_user_pages_fast but i know some people > don't like that as sometimes we endup with ___function_overloaded :) Exactly: the __get_user_pages* names were already used for *non*-internal routines, so I attempted to pick the next best naming prefix. >=20 >> { >> unsigned long addr, len, end; >> int nr =3D 0, ret =3D 0; >=20 >=20 >> @@ -2435,4 +2449,215 @@ int get_user_pages_fast(unsigned long start, int= nr_pages, >=20 > [...] >=20 >> +/** >> + * pin_user_pages_remote() - pin pages for (typically) use by Direct IO= , and >> + * return the pages to the user. >=20 > Not a fan of (typically) maybe: > pin_user_pages_remote() - pin pages of a remote process (task !=3D curren= t) >=20 > I think here the remote part if more important that DIO. Remote is use by > other thing that DIO. Yes, good point. I'll use your wording: * pin_user_pages_remote() - pin pages of a remote process (task !=3D curre= nt) >=20 >> + * >> + * Nearly the same as get_user_pages_remote(), except that FOLL_PIN is = set. See >> + * get_user_pages_remote() for documentation on the function arguments,= because >> + * the arguments here are identical. >> + * >> + * FOLL_PIN means that the pages must be released via put_user_page(). = Please >> + * see Documentation/vm/pin_user_pages.rst for details. >> + * >> + * This is intended for Case 1 (DIO) in Documentation/vm/pin_user_pages= .rst. It >> + * is NOT intended for Case 2 (RDMA: long-term pins). >> + */ >> +long pin_user_pages_remote(struct task_struct *tsk, struct mm_struct *m= m, >> + unsigned long start, unsigned long nr_pages, >> + unsigned int gup_flags, struct page **pages, >> + struct vm_area_struct **vmas, int *locked) >> +{ >> + /* FOLL_GET and FOLL_PIN are mutually exclusive. */ >> + if (WARN_ON_ONCE(gup_flags & FOLL_GET)) >> + return -EINVAL; >> + >> + gup_flags |=3D FOLL_TOUCH | FOLL_REMOTE | FOLL_PIN; >> + >> + return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas, >> + locked, gup_flags); >> +} >> +EXPORT_SYMBOL(pin_user_pages_remote); >> + >> +/** >> + * pin_longterm_pages_remote() - pin pages for (typically) use by Direc= t IO, and >> + * return the pages to the user. >=20 > I think you copy pasted this from pin_user_pages_remote() :) I admit to nothing, with respect to copy-paste! :) This one can simply be: * pin_longterm_pages_remote() - pin pages of a remote process (task !=3D c= urrent) >=20 >> + * >> + * Nearly the same as get_user_pages_remote(), but note that FOLL_TOUCH= is not >> + * set, and FOLL_PIN and FOLL_LONGTERM are set. See get_user_pages_remo= te() for >> + * documentation on the function arguments, because the arguments here = are >> + * identical. >> + * >> + * FOLL_PIN means that the pages must be released via put_user_page(). = Please >> + * see Documentation/vm/pin_user_pages.rst for further details. >> + * >> + * FOLL_LONGTERM means that the pages are being pinned for "long term" = use, >> + * typically by a non-CPU device, and we cannot be sure that waiting fo= r a >> + * pinned page to become unpin will be effective. >> + * >> + * This is intended for Case 2 (RDMA: long-term pins) in >> + * Documentation/vm/pin_user_pages.rst. >> + */ >> +long pin_longterm_pages_remote(struct task_struct *tsk, struct mm_struc= t *mm, >> + unsigned long start, unsigned long nr_pages, >> + unsigned int gup_flags, struct page **pages, >> + struct vm_area_struct **vmas, int *locked) >> +{ >> + /* FOLL_GET and FOLL_PIN are mutually exclusive. */ >> + if (WARN_ON_ONCE(gup_flags & FOLL_GET)) >> + return -EINVAL; >> + >> + /* >> + * FIXME: as noted in the get_user_pages_remote() implementation, it >> + * is not yet possible to safely set FOLL_LONGTERM here. FOLL_LONGTERM >> + * needs to be set, but for now the best we can do is a "TODO" item. >> + */ >> + gup_flags |=3D FOLL_REMOTE | FOLL_PIN; >=20 > Wouldn't it be better to not add pin_longterm_pages_remote() until > it can be properly implemented ? >=20 Well, the problem is that I need each call site that requires FOLL_PIN to use a proper wrapper. It's the FOLL_PIN that is the focus here, because there is a hard, bright rule, which is: if and only if a caller sets FOLL_PIN, then the dma-page tracking happens, and put_user_page() must be called. So this leaves me with only two reasonable choices: a) Convert the call site as above: pin_longterm_pages_remote(), which sets FOLL_PIN (the key point!), and leaves the FOLL_LONGTERM situation exactly as it has been so far. When the FOLL_LONGTERM situation is fixed, the call site *might* not need any changes to adopt the working gup.c code. b) Convert the call site to pin_user_pages_remote(), which also sets FOLL_PIN, and also leaves the FOLL_LONGTERM situation exactly as before. There would also be a comment at the call site, to the effect of, "this is the wrong call to make: it really requires FOLL_LONGTERM behavior". When the FOLL_LONGTERM situation is fixed, the call site will need to be changed to pin_longterm_pages_remote(). So you can probably see why I picked (a). thanks, John Hubbard NVIDIA From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B47D3CA9EB5 for ; Mon, 4 Nov 2019 19:35:16 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6B52B214D8 for ; Mon, 4 Nov 2019 19:35:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6B52B214D8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nvidia.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B9EA96E83A; Mon, 4 Nov 2019 19:35:12 +0000 (UTC) Received: from hqemgate16.nvidia.com (hqemgate16.nvidia.com [216.228.121.65]) by gabe.freedesktop.org (Postfix) with ESMTPS id 443846E823 for ; Mon, 4 Nov 2019 19:04:40 +0000 (UTC) Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqemgate16.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Mon, 04 Nov 2019 11:04:46 -0800 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Mon, 04 Nov 2019 11:04:39 -0800 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Mon, 04 Nov 2019 11:04:39 -0800 Received: from [10.110.48.28] (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Mon, 4 Nov 2019 19:04:38 +0000 Subject: Re: [PATCH v2 05/18] mm/gup: introduce pin_user_pages*() and FOLL_PIN To: Jerome Glisse References: <20191103211813.213227-1-jhubbard@nvidia.com> <20191103211813.213227-6-jhubbard@nvidia.com> <20191104173325.GD5134@redhat.com> From: John Hubbard X-Nvconfidentiality: public Message-ID: Date: Mon, 4 Nov 2019 11:04:38 -0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: <20191104173325.GD5134@redhat.com> X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) Content-Language: en-US X-Mailman-Approved-At: Mon, 04 Nov 2019 19:35:10 +0000 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1572894286; bh=kXFfoa96CjeMxu/yNlagPA6LLNAu70eBUsA06ExlOtg=; h=X-PGP-Universal:Subject:To:CC:References:From:X-Nvconfidentiality: Message-ID:Date:User-Agent:MIME-Version:In-Reply-To: X-Originating-IP:X-ClientProxiedBy:Content-Type:Content-Language: Content-Transfer-Encoding; b=CGhErLefJ4Rd4fl6xSTC12CgERoyFjHWQGLEBwXbgJ2nZYGGuplhwaAucXTJzeeNK 7KRJyNQnA11L4vItnHz1sLBsORlDWdAkA/ZWVdCe/zvdJMM52vn/1Yk2OBp/W/Dq1T cFSSDEh86RVrVz/0q78GLgUN0uUGLFJZUZdX2Fl6rpKC6TlU/Ir0hTy7uItCyFW8Za W+S8GdUZi+MhpaV5QT4z4khopwYOYhIHRBDl1hUf1rvr4b1dc8B1ZAcRLRgjjchNom s2Ey6jwAxh3PTYyEBkc6VY0f/i8pk0d/xLfZmGpLvA4HcRrg88VOSkXk7tAEv24uKR Y51dSM7lMwnHw== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michal Hocko , Jan Kara , kvm@vger.kernel.org, linux-doc@vger.kernel.org, David Airlie , Dave Chinner , dri-devel@lists.freedesktop.org, linux-mm@kvack.org, Paul Mackerras , linux-kselftest@vger.kernel.org, Ira Weiny , Jonathan Corbet , linux-rdma@vger.kernel.org, Michael Ellerman , Christoph Hellwig , Jason Gunthorpe , Vlastimil Babka , =?UTF-8?B?QmrDtnJuIFTDtnBlbA==?= , linux-media@vger.kernel.org, Shuah Khan , linux-block@vger.kernel.org, Alex Williamson , Al Viro , Dan Williams , Mauro Carvalho Chehab , bpf@vger.kernel.org, Magnus Karlsson , Jens Axboe , netdev@vger.kernel.org, LKML , linux-fsdevel@vger.kernel.org, Andrew Morton , linuxppc-dev@lists.ozlabs.org, "David S . Miller" , Mike Kravetz Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Message-ID: <20191104190438._0S5rH0Sh4UGgubc4dYKMaQG-mYxXbS9hxSsqaGZDVs@z> T24gMTEvNC8xOSA5OjMzIEFNLCBKZXJvbWUgR2xpc3NlIHdyb3RlOgouLi4KPiAKPiBGZXcgbml0 cGljayBiZWxvd3MsIG5vbmV0aGVsZXNzOgo+IAo+IFJldmlld2VkLWJ5OiBKw6lyw7RtZSBHbGlz c2UgPGpnbGlzc2VAcmVkaGF0LmNvbT4KPiBbLi4uXQo+PiArCj4+ICtDQVNFIDM6IE9EUAo+PiAr LS0tLS0tLS0tLS0KPj4gKyhNZWxsYW5veC9JbmZpbmliYW5kIE9uIERlbWFuZCBQYWdpbmc6IHRo ZSBoYXJkd2FyZSBzdXBwb3J0cwo+PiArcmVwbGF5YWJsZSBwYWdlIGZhdWx0aW5nKS4gVGhlcmUg YXJlIEdVUCByZWZlcmVuY2VzIHRvIHBhZ2VzIHNlcnZpbmcgYXMgRE1BCj4+ICtidWZmZXJzLiBG b3IgT0RQLCBNTVUgbm90aWZpZXJzIGFyZSB1c2VkIHRvIHN5bmNocm9uaXplIHdpdGggcGFnZV9t a2NsZWFuKCkKPj4gK2FuZCBtdW5tYXAoKS4gVGhlcmVmb3JlLCBub3JtYWwgR1VQIGNhbGxzIGFy ZSBzdWZmaWNpZW50LCBzbyBuZWl0aGVyIGZsYWcKPj4gK25lZWRzIHRvIGJlIHNldC4KPiAKPiBJ IHdvdWxkIG5vdCBpbmNsdWRlIE9EUCBvciBhbnl0aGluZyBsaWtlIGl0IGhlcmUsIHRoZXkgZG8g bm90IHVzZQo+IEdVUCBhbnltb3JlIGFuZCBpIGJlbGlldmUgaXQgaXMgbW9yZSBjb25mdXNpbmcg aGVyZS4gSSB3b3VsZCBob3ctCj4gZXZlciBpbmNsdWRlIHNvbWUgdGV4dCBpbiB0aGlzIGRvY3Vt ZW50YXRpb24gZXhwbGFpbmluZyB0aGF0IGhhcmQtCj4gd2FyZSB0aGF0IHN1cHBvcnQgcGFnZSBm YXVsdCBpcyBzdXBlcmlvciBhcyBpdCBkb2VzIG5vdCBpbmN1ciBhbnkKPiBvZiB0aGUgaXNzdWVz IGRlc2NyaWJlZCBoZXJlLgoKT0ssIGFncmVlZCwgaGVyZSdzIGEgbmV3IHdyaXRlIHVwIHRoYXQg SSdsbCBwdXQgaW4gdjM6CgoKQ0FTRSAzOiBPRFAKLS0tLS0tLS0tLS0KQWR2YW5jZWQsIGJ1dCBu b24tQ1BVIChETUEpIGhhcmR3YXJlIHRoYXQgc3VwcG9ydHMgcmVwbGF5YWJsZSBwYWdlIGZhdWx0 cy4KSGVyZSwgYSB3ZWxsLXdyaXR0ZW4gZHJpdmVyIGRvZXNuJ3Qgbm9ybWFsbHkgbmVlZCB0byBw aW4gcGFnZXMgYXQgYWxsLiBIb3dldmVyLAppZiB0aGUgZHJpdmVyIGRvZXMgY2hvb3NlIHRvIGRv IHNvLCBpdCBjYW4gcmVnaXN0ZXIgTU1VIG5vdGlmaWVycyBmb3IgdGhlIHJhbmdlLAphbmQgd2ls bCBiZSBjYWxsZWQgYmFjayB1cG9uIGludmFsaWRhdGlvbi4gRWl0aGVyIHdheSAoYXZvaWRpbmcg cGFnZSBwaW5uaW5nLCBvcgp1c2luZyBNTVUgbm90aWZpZXJzIHRvIHVucGluIHVwb24gcmVxdWVz dCksIHRoZXJlIGlzIHByb3BlciBzeW5jaHJvbml6YXRpb24gd2l0aCAKYm90aCBmaWxlc3lzdGVt IGFuZCBtbSAocGFnZV9ta2NsZWFuKCksIG11bm1hcCgpLCBldGMpLgoKVGhlcmVmb3JlLCBuZWl0 aGVyIGZsYWcgbmVlZHMgdG8gYmUgc2V0LgoKSXQncyB3b3J0aCBtZW50aW9uaW5nIGhlcmUgdGhh dCBwaW5uaW5nIHBhZ2VzIHNob3VsZCBub3QgYmUgdGhlIGZpcnN0IGRlc2lnbgpjaG9pY2UuIElm IHBhZ2UgZmF1bHQgY2FwYWJsZSBoYXJkd2FyZSBpcyBhdmFpbGFibGUsIHRoZW4gdGhlIHNvZnR3 YXJlIHNob3VsZApiZSB3cml0dGVuIHNvIHRoYXQgaXQgZG9lcyBub3QgcGluIHBhZ2VzLiBUaGlz IGFsbG93cyBtbSBhbmQgZmlsZXN5c3RlbXMgdG8Kb3BlcmF0ZSBtb3JlIGVmZmljaWVudGx5IGFu ZCByZWxpYWJseS4KCj4gWy4uLl0KPiAKPj4gZGlmZiAtLWdpdCBhL21tL2d1cC5jIGIvbW0vZ3Vw LmMKPj4gaW5kZXggMTk5ZGE5OWU4ZmZjLi4xYWVhNDg0Mjc4NzkgMTAwNjQ0Cj4+IC0tLSBhL21t L2d1cC5jCj4+ICsrKyBiL21tL2d1cC5jCj4gCj4gWy4uLl0KPiAKPj4gQEAgLTEwMTQsNyArMTAx OCwxNiBAQCBzdGF0aWMgX19hbHdheXNfaW5saW5lIGxvbmcgX19nZXRfdXNlcl9wYWdlc19sb2Nr ZWQoc3RydWN0IHRhc2tfc3RydWN0ICp0c2ssCj4+ICAJCUJVR19PTigqbG9ja2VkICE9IDEpOwo+ PiAgCX0KPj4gIAo+PiAtCWlmIChwYWdlcykKPj4gKwkvKgo+PiArCSAqIEZPTExfUElOIGFuZCBG T0xMX0dFVCBhcmUgbXV0dWFsbHkgZXhjbHVzaXZlLiBUcmFkaXRpb25hbCBiZWhhdmlvcgo+PiAr CSAqIGlzIHRvIHNldCBGT0xMX0dFVCBpZiB0aGUgY2FsbGVyIHdhbnRzIHBhZ2VzW10gZmlsbGVk IGluIChidXQgaGFzCj4+ICsJICogY2FyZWxlc3NseSBmYWlsZWQgdG8gc3BlY2lmeSBGT0xMX0dF VCksIHNvIGtlZXAgZG9pbmcgdGhhdCwgYnV0IG9ubHkKPj4gKwkgKiBmb3IgRk9MTF9HRVQsIG5v dCBmb3IgdGhlIG5ld2VyIEZPTExfUElOLgo+PiArCSAqCj4+ICsJICogRk9MTF9QSU4gYWx3YXlz IGV4cGVjdHMgcGFnZXMgdG8gYmUgbm9uLW51bGwsIGJ1dCBubyBuZWVkIHRvIGFzc2VydAo+PiAr CSAqIHRoYXQgaGVyZSwgYXMgYW55IGZhaWx1cmVzIHdpbGwgYmUgb2J2aW91cyBlbm91Z2guCj4+ ICsJICovCj4+ICsJaWYgKHBhZ2VzICYmICEoZmxhZ3MgJiBGT0xMX1BJTikpCj4+ICAJCWZsYWdz IHw9IEZPTExfR0VUOwo+IAo+IERpZCB5b3UgbG9vayBhdCB1c2VyIHRoYXQgaGF2ZSBwYWdlcyBh bmQgbm90IEZPTExfR0VUIHNldCA/Cj4gSSBiZWxpZXZlIGl0IHdvdWxkIGJlIGJldHRlciB0byBm aXJzdCBmaXggdGhlbSB0byBlbmQgdXAKPiB3aXRoIEZPTExfR0VUIHNldCBhbmQgdGhlbiBlcnJv ciBvdXQgaWYgcGFnZXMgaXMgIT0gTlVMTCBidXQKPiBub3IgRk9MTF9HRVQgb3IgRk9MTF9QSU4g aXMgc2V0Lgo+IAoKSSB3YXMgcGVyaGFwcyBvdmVybHkgY2F1dGlvdXMsIGFuZCBkaWRuJ3QgZ28g dGhlcmUuIEhvd2V2ZXIsIGl0J3MgcHJvYmFibHkKZG9hYmxlLCBnaXZlbiB0aGF0IHRoZXJlIHdh cyBhbHJlYWR5IHRoZSBmb2xsb3dpbmcgaW4gX19nZXRfdXNlcl9wYWdlcygpOgoKICAgIFZNX0JV R19PTighIXBhZ2VzICE9ICEhKGd1cF9mbGFncyAmIEZPTExfR0VUKSk7CgouLi53aGljaCB3aWxs IGhhdmUgY29uZGl0aW9uZWQgcGVvcGxlIGFuZCBjb2RlIHRvIHNldCBGT0xMX0dFVCB0b2dldGhl ciB3aXRoCnBhZ2VzLiBTbyBJIGFncmVlIHRoYXQgdGhlIHRpbWUgaXMgcmlnaHQuCgpJbiBvcmRl ciB0byBtYWtlIGJpc2VjdGluZyBmdXR1cmUgZmFpbHVyZXMgc2ltcGxlciwgSSBjYW4gaW5zZXJ0 IGEgcGF0Y2ggcmlnaHQgCmJlZm9yZSB0aGlzIG9uZSwgdGhhdCBjaGFuZ2VzIHRoZSBGT0xMX0dF VCBzZXR0aW5nIGludG8gYW4gYXNzZXJ0LCBsaWtlIHRoaXM6CgpkaWZmIC0tZ2l0IGEvbW0vZ3Vw LmMgYi9tbS9ndXAuYwppbmRleCA4ZjIzNmEzMzVhZTkuLmJlMzM4OTYxZTgwZCAxMDA2NDQKLS0t IGEvbW0vZ3VwLmMKKysrIGIvbW0vZ3VwLmMKQEAgLTEwMTQsOCArMTAxNCw4IEBAIHN0YXRpYyBf X2Fsd2F5c19pbmxpbmUgbG9uZyBfX2dldF91c2VyX3BhZ2VzX2xvY2tlZChzdHJ1Y3QgdGFza19z dHJ1Y3QgKnRzaywKICAgICAgICAgICAgICAgIEJVR19PTigqbG9ja2VkICE9IDEpOwogICAgICAg IH0KIAotICAgICAgIGlmIChwYWdlcykKLSAgICAgICAgICAgICAgIGZsYWdzIHw9IEZPTExfR0VU OworICAgICAgIGlmIChwYWdlcyAmJiBXQVJOX09OX09OQ0UoIShndXBfZmxhZ3MgJiBGT0xMX0dF VCkpKQorICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7CiAKICAgICAgICBwYWdlc19kb25l ID0gMDsKICAgICAgICBsb2NrX2Ryb3BwZWQgPSBmYWxzZTsKCgouLi5hbmQgdGhlbiBhZGQgaW4g Rk9MTF9QSU4sIHdpdGggdGhpcyBwYXRjaC4KCj4+ICAKPj4gIAlwYWdlc19kb25lID0gMDsKPiAK Pj4gQEAgLTIzNzMsMjQgKzI0MDIsOSBAQCBzdGF0aWMgaW50IF9fZ3VwX2xvbmd0ZXJtX3VubG9j a2VkKHVuc2lnbmVkIGxvbmcgc3RhcnQsIGludCBucl9wYWdlcywKPj4gIAlyZXR1cm4gcmV0Owo+ PiAgfQo+PiAgCj4+IC0vKioKPj4gLSAqIGdldF91c2VyX3BhZ2VzX2Zhc3QoKSAtIHBpbiB1c2Vy IHBhZ2VzIGluIG1lbW9yeQo+PiAtICogQHN0YXJ0OglzdGFydGluZyB1c2VyIGFkZHJlc3MKPj4g LSAqIEBucl9wYWdlczoJbnVtYmVyIG9mIHBhZ2VzIGZyb20gc3RhcnQgdG8gcGluCj4+IC0gKiBA Z3VwX2ZsYWdzOglmbGFncyBtb2RpZnlpbmcgcGluIGJlaGF2aW91cgo+PiAtICogQHBhZ2VzOglh cnJheSB0aGF0IHJlY2VpdmVzIHBvaW50ZXJzIHRvIHRoZSBwYWdlcyBwaW5uZWQuCj4+IC0gKgkJ U2hvdWxkIGJlIGF0IGxlYXN0IG5yX3BhZ2VzIGxvbmcuCj4+IC0gKgo+PiAtICogQXR0ZW1wdCB0 byBwaW4gdXNlciBwYWdlcyBpbiBtZW1vcnkgd2l0aG91dCB0YWtpbmcgbW0tPm1tYXBfc2VtLgo+ PiAtICogSWYgbm90IHN1Y2Nlc3NmdWwsIGl0IHdpbGwgZmFsbCBiYWNrIHRvIHRha2luZyB0aGUg bG9jayBhbmQKPj4gLSAqIGNhbGxpbmcgZ2V0X3VzZXJfcGFnZXMoKS4KPj4gLSAqCj4+IC0gKiBS ZXR1cm5zIG51bWJlciBvZiBwYWdlcyBwaW5uZWQuIFRoaXMgbWF5IGJlIGZld2VyIHRoYW4gdGhl IG51bWJlcgo+PiAtICogcmVxdWVzdGVkLiBJZiBucl9wYWdlcyBpcyAwIG9yIG5lZ2F0aXZlLCBy ZXR1cm5zIDAuIElmIG5vIHBhZ2VzCj4+IC0gKiB3ZXJlIHBpbm5lZCwgcmV0dXJucyAtZXJybm8u Cj4+IC0gKi8KPj4gLWludCBnZXRfdXNlcl9wYWdlc19mYXN0KHVuc2lnbmVkIGxvbmcgc3RhcnQs IGludCBucl9wYWdlcywKPj4gLQkJCXVuc2lnbmVkIGludCBndXBfZmxhZ3MsIHN0cnVjdCBwYWdl ICoqcGFnZXMpCj4+ICtzdGF0aWMgaW50IGludGVybmFsX2dldF91c2VyX3BhZ2VzX2Zhc3QodW5z aWduZWQgbG9uZyBzdGFydCwgaW50IG5yX3BhZ2VzLAo+PiArCQkJCQl1bnNpZ25lZCBpbnQgZ3Vw X2ZsYWdzLAo+PiArCQkJCQlzdHJ1Y3QgcGFnZSAqKnBhZ2VzKQo+IAo+IFVzdWFseSBmdW5jdGlv biBhcmUgcmVuYW1lIHRvIF9vbGRfZnVuY19uYW1lIGllIGFkZCBfIGluIGZyb250LiBTbwo+IGhl cmUgaXQgd291bGQgYmVjb21lIF9nZXRfdXNlcl9wYWdlc19mYXN0IGJ1dCBpIGtub3cgc29tZSBw ZW9wbGUKPiBkb24ndCBsaWtlIHRoYXQgYXMgc29tZXRpbWVzIHdlIGVuZHVwIHdpdGggX19fZnVu Y3Rpb25fb3ZlcmxvYWRlZCA6KQoKRXhhY3RseTogdGhlIF9fZ2V0X3VzZXJfcGFnZXMqIG5hbWVz IHdlcmUgYWxyZWFkeSB1c2VkIGZvciAqbm9uKi1pbnRlcm5hbApyb3V0aW5lcywgc28gSSBhdHRl bXB0ZWQgdG8gcGljayB0aGUgbmV4dCBiZXN0IG5hbWluZyBwcmVmaXguCgo+IAo+PiAgewo+PiAg CXVuc2lnbmVkIGxvbmcgYWRkciwgbGVuLCBlbmQ7Cj4+ICAJaW50IG5yID0gMCwgcmV0ID0gMDsK PiAKPiAKPj4gQEAgLTI0MzUsNCArMjQ0OSwyMTUgQEAgaW50IGdldF91c2VyX3BhZ2VzX2Zhc3Qo dW5zaWduZWQgbG9uZyBzdGFydCwgaW50IG5yX3BhZ2VzLAo+IAo+IFsuLi5dCj4gCj4+ICsvKioK Pj4gKyAqIHBpbl91c2VyX3BhZ2VzX3JlbW90ZSgpIC0gcGluIHBhZ2VzIGZvciAodHlwaWNhbGx5 KSB1c2UgYnkgRGlyZWN0IElPLCBhbmQKPj4gKyAqIHJldHVybiB0aGUgcGFnZXMgdG8gdGhlIHVz ZXIuCj4gCj4gTm90IGEgZmFuIG9mICh0eXBpY2FsbHkpIG1heWJlOgo+IHBpbl91c2VyX3BhZ2Vz X3JlbW90ZSgpIC0gcGluIHBhZ2VzIG9mIGEgcmVtb3RlIHByb2Nlc3MgKHRhc2sgIT0gY3VycmVu dCkKPiAKPiBJIHRoaW5rIGhlcmUgdGhlIHJlbW90ZSBwYXJ0IGlmIG1vcmUgaW1wb3J0YW50IHRo YXQgRElPLiBSZW1vdGUgaXMgdXNlIGJ5Cj4gb3RoZXIgdGhpbmcgdGhhdCBESU8uCgpZZXMsIGdv b2QgcG9pbnQuIEknbGwgdXNlIHlvdXIgd29yZGluZzoKCiAqIHBpbl91c2VyX3BhZ2VzX3JlbW90 ZSgpIC0gcGluIHBhZ2VzIG9mIGEgcmVtb3RlIHByb2Nlc3MgKHRhc2sgIT0gY3VycmVudCkKCgoK PiAKPj4gKyAqCj4+ICsgKiBOZWFybHkgdGhlIHNhbWUgYXMgZ2V0X3VzZXJfcGFnZXNfcmVtb3Rl KCksIGV4Y2VwdCB0aGF0IEZPTExfUElOIGlzIHNldC4gU2VlCj4+ICsgKiBnZXRfdXNlcl9wYWdl c19yZW1vdGUoKSBmb3IgZG9jdW1lbnRhdGlvbiBvbiB0aGUgZnVuY3Rpb24gYXJndW1lbnRzLCBi ZWNhdXNlCj4+ICsgKiB0aGUgYXJndW1lbnRzIGhlcmUgYXJlIGlkZW50aWNhbC4KPj4gKyAqCj4+ ICsgKiBGT0xMX1BJTiBtZWFucyB0aGF0IHRoZSBwYWdlcyBtdXN0IGJlIHJlbGVhc2VkIHZpYSBw dXRfdXNlcl9wYWdlKCkuIFBsZWFzZQo+PiArICogc2VlIERvY3VtZW50YXRpb24vdm0vcGluX3Vz ZXJfcGFnZXMucnN0IGZvciBkZXRhaWxzLgo+PiArICoKPj4gKyAqIFRoaXMgaXMgaW50ZW5kZWQg Zm9yIENhc2UgMSAoRElPKSBpbiBEb2N1bWVudGF0aW9uL3ZtL3Bpbl91c2VyX3BhZ2VzLnJzdC4g SXQKPj4gKyAqIGlzIE5PVCBpbnRlbmRlZCBmb3IgQ2FzZSAyIChSRE1BOiBsb25nLXRlcm0gcGlu cykuCj4+ICsgKi8KPj4gK2xvbmcgcGluX3VzZXJfcGFnZXNfcmVtb3RlKHN0cnVjdCB0YXNrX3N0 cnVjdCAqdHNrLCBzdHJ1Y3QgbW1fc3RydWN0ICptbSwKPj4gKwkJCSAgIHVuc2lnbmVkIGxvbmcg c3RhcnQsIHVuc2lnbmVkIGxvbmcgbnJfcGFnZXMsCj4+ICsJCQkgICB1bnNpZ25lZCBpbnQgZ3Vw X2ZsYWdzLCBzdHJ1Y3QgcGFnZSAqKnBhZ2VzLAo+PiArCQkJICAgc3RydWN0IHZtX2FyZWFfc3Ry dWN0ICoqdm1hcywgaW50ICpsb2NrZWQpCj4+ICt7Cj4+ICsJLyogRk9MTF9HRVQgYW5kIEZPTExf UElOIGFyZSBtdXR1YWxseSBleGNsdXNpdmUuICovCj4+ICsJaWYgKFdBUk5fT05fT05DRShndXBf ZmxhZ3MgJiBGT0xMX0dFVCkpCj4+ICsJCXJldHVybiAtRUlOVkFMOwo+PiArCj4+ICsJZ3VwX2Zs YWdzIHw9IEZPTExfVE9VQ0ggfCBGT0xMX1JFTU9URSB8IEZPTExfUElOOwo+PiArCj4+ICsJcmV0 dXJuIF9fZ2V0X3VzZXJfcGFnZXNfbG9ja2VkKHRzaywgbW0sIHN0YXJ0LCBucl9wYWdlcywgcGFn ZXMsIHZtYXMsCj4+ICsJCQkJICAgICAgIGxvY2tlZCwgZ3VwX2ZsYWdzKTsKPj4gK30KPj4gK0VY UE9SVF9TWU1CT0wocGluX3VzZXJfcGFnZXNfcmVtb3RlKTsKPj4gKwo+PiArLyoqCj4+ICsgKiBw aW5fbG9uZ3Rlcm1fcGFnZXNfcmVtb3RlKCkgLSBwaW4gcGFnZXMgZm9yICh0eXBpY2FsbHkpIHVz ZSBieSBEaXJlY3QgSU8sIGFuZAo+PiArICogcmV0dXJuIHRoZSBwYWdlcyB0byB0aGUgdXNlci4K PiAKPiBJIHRoaW5rIHlvdSBjb3B5IHBhc3RlZCB0aGlzIGZyb20gcGluX3VzZXJfcGFnZXNfcmVt b3RlKCkgOikKCkkgYWRtaXQgdG8gbm90aGluZywgd2l0aCByZXNwZWN0IHRvIGNvcHktcGFzdGUh IDopCgpUaGlzIG9uZSBjYW4gc2ltcGx5IGJlOgoKICogcGluX2xvbmd0ZXJtX3BhZ2VzX3JlbW90 ZSgpIC0gcGluIHBhZ2VzIG9mIGEgcmVtb3RlIHByb2Nlc3MgKHRhc2sgIT0gY3VycmVudCkKCgo+ IAo+PiArICoKPj4gKyAqIE5lYXJseSB0aGUgc2FtZSBhcyBnZXRfdXNlcl9wYWdlc19yZW1vdGUo KSwgYnV0IG5vdGUgdGhhdCBGT0xMX1RPVUNIIGlzIG5vdAo+PiArICogc2V0LCBhbmQgRk9MTF9Q SU4gYW5kIEZPTExfTE9OR1RFUk0gYXJlIHNldC4gU2VlIGdldF91c2VyX3BhZ2VzX3JlbW90ZSgp IGZvcgo+PiArICogZG9jdW1lbnRhdGlvbiBvbiB0aGUgZnVuY3Rpb24gYXJndW1lbnRzLCBiZWNh dXNlIHRoZSBhcmd1bWVudHMgaGVyZSBhcmUKPj4gKyAqIGlkZW50aWNhbC4KPj4gKyAqCj4+ICsg KiBGT0xMX1BJTiBtZWFucyB0aGF0IHRoZSBwYWdlcyBtdXN0IGJlIHJlbGVhc2VkIHZpYSBwdXRf dXNlcl9wYWdlKCkuIFBsZWFzZQo+PiArICogc2VlIERvY3VtZW50YXRpb24vdm0vcGluX3VzZXJf cGFnZXMucnN0IGZvciBmdXJ0aGVyIGRldGFpbHMuCj4+ICsgKgo+PiArICogRk9MTF9MT05HVEVS TSBtZWFucyB0aGF0IHRoZSBwYWdlcyBhcmUgYmVpbmcgcGlubmVkIGZvciAibG9uZyB0ZXJtIiB1 c2UsCj4+ICsgKiB0eXBpY2FsbHkgYnkgYSBub24tQ1BVIGRldmljZSwgYW5kIHdlIGNhbm5vdCBi ZSBzdXJlIHRoYXQgd2FpdGluZyBmb3IgYQo+PiArICogcGlubmVkIHBhZ2UgdG8gYmVjb21lIHVu cGluIHdpbGwgYmUgZWZmZWN0aXZlLgo+PiArICoKPj4gKyAqIFRoaXMgaXMgaW50ZW5kZWQgZm9y IENhc2UgMiAoUkRNQTogbG9uZy10ZXJtIHBpbnMpIGluCj4+ICsgKiBEb2N1bWVudGF0aW9uL3Zt L3Bpbl91c2VyX3BhZ2VzLnJzdC4KPj4gKyAqLwo+PiArbG9uZyBwaW5fbG9uZ3Rlcm1fcGFnZXNf cmVtb3RlKHN0cnVjdCB0YXNrX3N0cnVjdCAqdHNrLCBzdHJ1Y3QgbW1fc3RydWN0ICptbSwKPj4g KwkJCSAgICAgICB1bnNpZ25lZCBsb25nIHN0YXJ0LCB1bnNpZ25lZCBsb25nIG5yX3BhZ2VzLAo+ PiArCQkJICAgICAgIHVuc2lnbmVkIGludCBndXBfZmxhZ3MsIHN0cnVjdCBwYWdlICoqcGFnZXMs Cj4+ICsJCQkgICAgICAgc3RydWN0IHZtX2FyZWFfc3RydWN0ICoqdm1hcywgaW50ICpsb2NrZWQp Cj4+ICt7Cj4+ICsJLyogRk9MTF9HRVQgYW5kIEZPTExfUElOIGFyZSBtdXR1YWxseSBleGNsdXNp dmUuICovCj4+ICsJaWYgKFdBUk5fT05fT05DRShndXBfZmxhZ3MgJiBGT0xMX0dFVCkpCj4+ICsJ CXJldHVybiAtRUlOVkFMOwo+PiArCj4+ICsJLyoKPj4gKwkgKiBGSVhNRTogYXMgbm90ZWQgaW4g dGhlIGdldF91c2VyX3BhZ2VzX3JlbW90ZSgpIGltcGxlbWVudGF0aW9uLCBpdAo+PiArCSAqIGlz IG5vdCB5ZXQgcG9zc2libGUgdG8gc2FmZWx5IHNldCBGT0xMX0xPTkdURVJNIGhlcmUuIEZPTExf TE9OR1RFUk0KPj4gKwkgKiBuZWVkcyB0byBiZSBzZXQsIGJ1dCBmb3Igbm93IHRoZSBiZXN0IHdl IGNhbiBkbyBpcyBhICJUT0RPIiBpdGVtLgo+PiArCSAqLwo+PiArCWd1cF9mbGFncyB8PSBGT0xM X1JFTU9URSB8IEZPTExfUElOOwo+IAo+IFdvdWxkbid0IGl0IGJlIGJldHRlciB0byBub3QgYWRk IHBpbl9sb25ndGVybV9wYWdlc19yZW1vdGUoKSB1bnRpbAo+IGl0IGNhbiBiZSBwcm9wZXJseSBp bXBsZW1lbnRlZCA/Cj4gCgpXZWxsLCB0aGUgcHJvYmxlbSBpcyB0aGF0IEkgbmVlZCBlYWNoIGNh bGwgc2l0ZSB0aGF0IHJlcXVpcmVzIEZPTExfUElOCnRvIHVzZSBhIHByb3BlciB3cmFwcGVyLiBJ dCdzIHRoZSBGT0xMX1BJTiB0aGF0IGlzIHRoZSBmb2N1cyBoZXJlLCBiZWNhdXNlCnRoZXJlIGlz IGEgaGFyZCwgYnJpZ2h0IHJ1bGUsIHdoaWNoIGlzOiBpZiBhbmQgb25seSBpZiBhIGNhbGxlciBz ZXRzCkZPTExfUElOLCB0aGVuIHRoZSBkbWEtcGFnZSB0cmFja2luZyBoYXBwZW5zLCBhbmQgcHV0 X3VzZXJfcGFnZSgpIG11c3QKYmUgY2FsbGVkLgoKU28gdGhpcyBsZWF2ZXMgbWUgd2l0aCBvbmx5 IHR3byByZWFzb25hYmxlIGNob2ljZXM6CgphKSBDb252ZXJ0IHRoZSBjYWxsIHNpdGUgYXMgYWJv dmU6IHBpbl9sb25ndGVybV9wYWdlc19yZW1vdGUoKSwgd2hpY2ggc2V0cwpGT0xMX1BJTiAodGhl IGtleSBwb2ludCEpLCBhbmQgbGVhdmVzIHRoZSBGT0xMX0xPTkdURVJNIHNpdHVhdGlvbiBleGFj dGx5CmFzIGl0IGhhcyBiZWVuIHNvIGZhci4gV2hlbiB0aGUgRk9MTF9MT05HVEVSTSBzaXR1YXRp b24gaXMgZml4ZWQsIHRoZSBjYWxsCnNpdGUgKm1pZ2h0KiBub3QgbmVlZCBhbnkgY2hhbmdlcyB0 byBhZG9wdCB0aGUgd29ya2luZyBndXAuYyBjb2RlLgoKYikgQ29udmVydCB0aGUgY2FsbCBzaXRl IHRvIHBpbl91c2VyX3BhZ2VzX3JlbW90ZSgpLCB3aGljaCBhbHNvIHNldHMKRk9MTF9QSU4sIGFu ZCBhbHNvIGxlYXZlcyB0aGUgRk9MTF9MT05HVEVSTSBzaXR1YXRpb24gZXhhY3RseSBhcyBiZWZv cmUuClRoZXJlIHdvdWxkIGFsc28gYmUgYSBjb21tZW50IGF0IHRoZSBjYWxsIHNpdGUsIHRvIHRo ZSBlZmZlY3Qgb2YsICJ0aGlzCmlzIHRoZSB3cm9uZyBjYWxsIHRvIG1ha2U6IGl0IHJlYWxseSBy ZXF1aXJlcyBGT0xMX0xPTkdURVJNIGJlaGF2aW9yIi4KCldoZW4gdGhlIEZPTExfTE9OR1RFUk0g c2l0dWF0aW9uIGlzIGZpeGVkLCB0aGUgY2FsbCBzaXRlIHdpbGwgbmVlZCB0byBiZQpjaGFuZ2Vk IHRvIHBpbl9sb25ndGVybV9wYWdlc19yZW1vdGUoKS4KClNvIHlvdSBjYW4gcHJvYmFibHkgc2Vl IHdoeSBJIHBpY2tlZCAoYSkuCgoKdGhhbmtzLAoKSm9obiBIdWJiYXJkCk5WSURJQQpfX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkcmktZGV2ZWwgbWFpbGlu ZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVl ZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWw=