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=-1.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_PASS 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 93D8FC43387 for ; Mon, 24 Dec 2018 08:32:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 60D162173C for ; Mon, 24 Dec 2018 08:32:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726858AbeLXIcr (ORCPT ); Mon, 24 Dec 2018 03:32:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:37724 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725984AbeLXIcr (ORCPT ); Mon, 24 Dec 2018 03:32:47 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5B1B581DEA; Mon, 24 Dec 2018 08:32:46 +0000 (UTC) Received: from [10.72.12.206] (ovpn-12-206.pek2.redhat.com [10.72.12.206]) by smtp.corp.redhat.com (Postfix) with ESMTPS id F273919743; Mon, 24 Dec 2018 08:32:41 +0000 (UTC) Subject: Re: [PATCH net-next 0/3] vhost: accelerate metadata access through vmap() To: "Michael S. Tsirkin" Cc: kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org References: <20181213101022.12475-1-jasowang@redhat.com> <20181213102315-mutt-send-email-mst@kernel.org> <9459e227-a943-8553-732b-d7f5225a0f22@redhat.com> <20181214072334-mutt-send-email-mst@kernel.org> From: Jason Wang Message-ID: Date: Mon, 24 Dec 2018 16:32:39 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 In-Reply-To: <20181214072334-mutt-send-email-mst@kernel.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 24 Dec 2018 08:32:46 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2018/12/14 下午8:33, Michael S. Tsirkin wrote: > On Fri, Dec 14, 2018 at 11:42:18AM +0800, Jason Wang wrote: >> On 2018/12/13 下午11:27, Michael S. Tsirkin wrote: >>> On Thu, Dec 13, 2018 at 06:10:19PM +0800, Jason Wang wrote: >>>> Hi: >>>> >>>> This series tries to access virtqueue metadata through kernel virtual >>>> address instead of copy_user() friends since they had too much >>>> overheads like checks, spec barriers or even hardware feature >>>> toggling. >>> Userspace accesses through remapping tricks and next time there's a need >>> for a new barrier we are left to figure it out by ourselves. >> >> I don't get here, do you mean spec barriers? > I mean the next barrier people decide to put into userspace > memory accesses. > >> It's completely unnecessary for >> vhost which is kernel thread. > It's defence in depth. Take a look at the commit that added them. > And yes quite possibly in most cases we actually have a spec > barrier in the validation phase. If we do let's use the > unsafe variants so they can be found. unsafe variants can only work if you can batch userspace access. This is not necessarily the case for light load. > >> And even if you're right, vhost is not the >> only place, there's lots of vmap() based accessing in kernel. > For sure. But if one can get by without get user pages, one > really should. Witness recently uncovered mess with file > backed storage. We only pin metadata pages, I don't believe they will be used by any DMA. > >> Think in >> another direction, this means we won't suffer form unnecessary barriers for >> kthread like vhost in the future, we will manually pick the one we really >> need > I personally think we should err on the side of caution not on the side of > performance. So what you suggest may lead unnecessary performance regression (10%-20%) which is part of the goal of this series. We should audit and only use the one we really need instead of depending on copy_user() friends(). If we do it our own, it could be slow for for security fix but it's no less safe than before with performance kept. > >> (but it should have little possibility). > History seems to teach otherwise. What case did you mean here? > >> Please notice we only access metdata through remapping not the data itself. >> This idea has been used for high speed userspace backend for years, e.g >> packet socket or recent AF_XDP. > I think their justification for the higher risk is that they are mostly > designed for priveledged userspace. I think it's the same with TUN/TAP, privileged process can pass them to unprivileged ones. > >> The only difference is the page was remap to >> from kernel to userspace. > At least that avoids the g.u.p mess. I'm still not very clear at the point. We only pin 2 or 4 pages, they're several other cases that will pin much more. > >>> I don't >>> like the idea I have to say. As a first step, why don't we switch to >>> unsafe_put_user/unsafe_get_user etc? >> >> Several reasons: >> >> - They only have x86 variant, it won't have any difference for the rest of >> architecture. > Is there an issue on other architectures? If yes they can be extended > there. Consider the unexpected amount of work and in the best case it can give the same performance to vmap(). I'm not sure it's worth. > >> - unsafe_put_user/unsafe_get_user is not sufficient for accessing structures >> (e.g accessing descriptor) or arrays (batching). > So you want unsafe_copy_xxx_user? I can do this. Hang on will post. > >> - Unless we can batch at least the accessing of two places in three of >> avail, used and descriptor in one run. There will be no difference. E.g we >> can batch updating used ring, but it won't make any difference in this case. >> > So let's batch them all? Batching might not help for the case of light load. And we need to measure the gain/cost of batching itself. > > >>> That would be more of an apples to apples comparison, would it not? >> >> Apples to apples comparison only help if we are the No.1. But the fact is we >> are not. If we want to compete with e.g dpdk or AF_XDP, vmap() is the >> fastest method AFAIK. >> >> >> Thanks > We need to speed up the packet access itself too though. > You can't vmap all of guest memory. This series only pin and vmap very few pages (metadata). Thanks > > >>> >>>> Test shows about 24% improvement on TX PPS. It should benefit other >>>> cases as well. >>>> >>>> Please review >>>> >>>> Jason Wang (3): >>>> vhost: generalize adding used elem >>>> vhost: fine grain userspace memory accessors >>>> vhost: access vq metadata through kernel virtual address >>>> >>>> drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- >>>> drivers/vhost/vhost.h | 11 ++ >>>> 2 files changed, 266 insertions(+), 26 deletions(-) >>>> >>>> -- >>>> 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jason Wang Subject: Re: [PATCH net-next 0/3] vhost: accelerate metadata access through vmap() Date: Mon, 24 Dec 2018 16:32:39 +0800 Message-ID: References: <20181213101022.12475-1-jasowang@redhat.com> <20181213102315-mutt-send-email-mst@kernel.org> <9459e227-a943-8553-732b-d7f5225a0f22@redhat.com> <20181214072334-mutt-send-email-mst@kernel.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org To: "Michael S. Tsirkin" Return-path: In-Reply-To: <20181214072334-mutt-send-email-mst@kernel.org> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: virtualization-bounces@lists.linux-foundation.org Errors-To: virtualization-bounces@lists.linux-foundation.org List-Id: netdev.vger.kernel.org Ck9uIDIwMTgvMTIvMTQg5LiL5Y2IODozMywgTWljaGFlbCBTLiBUc2lya2luIHdyb3RlOgo+IE9u IEZyaSwgRGVjIDE0LCAyMDE4IGF0IDExOjQyOjE4QU0gKzA4MDAsIEphc29uIFdhbmcgd3JvdGU6 Cj4+IE9uIDIwMTgvMTIvMTMg5LiL5Y2IMTE6MjcsIE1pY2hhZWwgUy4gVHNpcmtpbiB3cm90ZToK Pj4+IE9uIFRodSwgRGVjIDEzLCAyMDE4IGF0IDA2OjEwOjE5UE0gKzA4MDAsIEphc29uIFdhbmcg d3JvdGU6Cj4+Pj4gSGk6Cj4+Pj4KPj4+PiBUaGlzIHNlcmllcyB0cmllcyB0byBhY2Nlc3Mgdmly dHF1ZXVlIG1ldGFkYXRhIHRocm91Z2gga2VybmVsIHZpcnR1YWwKPj4+PiBhZGRyZXNzIGluc3Rl YWQgb2YgY29weV91c2VyKCkgZnJpZW5kcyBzaW5jZSB0aGV5IGhhZCB0b28gbXVjaAo+Pj4+IG92 ZXJoZWFkcyBsaWtlIGNoZWNrcywgc3BlYyBiYXJyaWVycyBvciBldmVuIGhhcmR3YXJlIGZlYXR1 cmUKPj4+PiB0b2dnbGluZy4KPj4+IFVzZXJzcGFjZSBhY2Nlc3NlcyB0aHJvdWdoIHJlbWFwcGlu ZyB0cmlja3MgYW5kIG5leHQgdGltZSB0aGVyZSdzIGEgbmVlZAo+Pj4gZm9yIGEgbmV3IGJhcnJp ZXIgd2UgYXJlIGxlZnQgdG8gZmlndXJlIGl0IG91dCBieSBvdXJzZWx2ZXMuCj4+Cj4+IEkgZG9u J3QgZ2V0IGhlcmUsIGRvIHlvdSBtZWFuIHNwZWMgYmFycmllcnM/Cj4gSSBtZWFuIHRoZSBuZXh0 IGJhcnJpZXIgcGVvcGxlIGRlY2lkZSB0byBwdXQgaW50byB1c2Vyc3BhY2UKPiBtZW1vcnkgYWNj ZXNzZXMuCj4KPj4gSXQncyBjb21wbGV0ZWx5IHVubmVjZXNzYXJ5IGZvcgo+PiB2aG9zdCB3aGlj aCBpcyBrZXJuZWwgdGhyZWFkLgo+IEl0J3MgZGVmZW5jZSBpbiBkZXB0aC4gVGFrZSBhIGxvb2sg YXQgdGhlIGNvbW1pdCB0aGF0IGFkZGVkIHRoZW0uCj4gQW5kIHllcyBxdWl0ZSBwb3NzaWJseSBp biBtb3N0IGNhc2VzIHdlIGFjdHVhbGx5IGhhdmUgYSBzcGVjCj4gYmFycmllciBpbiB0aGUgdmFs aWRhdGlvbiBwaGFzZS4gSWYgd2UgZG8gbGV0J3MgdXNlIHRoZQo+IHVuc2FmZSB2YXJpYW50cyBz byB0aGV5IGNhbiBiZSBmb3VuZC4KCgp1bnNhZmUgdmFyaWFudHMgY2FuIG9ubHkgd29yayBpZiB5 b3UgY2FuIGJhdGNoIHVzZXJzcGFjZSBhY2Nlc3MuIFRoaXMgaXMgCm5vdCBuZWNlc3NhcmlseSB0 aGUgY2FzZSBmb3IgbGlnaHQgbG9hZC4KCgo+Cj4+IEFuZCBldmVuIGlmIHlvdSdyZSByaWdodCwg dmhvc3QgaXMgbm90IHRoZQo+PiBvbmx5IHBsYWNlLCB0aGVyZSdzIGxvdHMgb2Ygdm1hcCgpIGJh c2VkIGFjY2Vzc2luZyBpbiBrZXJuZWwuCj4gRm9yIHN1cmUuIEJ1dCBpZiBvbmUgY2FuIGdldCBi eSB3aXRob3V0IGdldCB1c2VyIHBhZ2VzLCBvbmUKPiByZWFsbHkgc2hvdWxkLiBXaXRuZXNzIHJl Y2VudGx5IHVuY292ZXJlZCBtZXNzIHdpdGggZmlsZQo+IGJhY2tlZCBzdG9yYWdlLgoKCldlIG9u bHkgcGluIG1ldGFkYXRhIHBhZ2VzLCBJIGRvbid0IGJlbGlldmUgdGhleSB3aWxsIGJlIHVzZWQg YnkgYW55IERNQS4KCgo+Cj4+IFRoaW5rIGluCj4+IGFub3RoZXIgZGlyZWN0aW9uLCB0aGlzIG1l YW5zIHdlIHdvbid0IHN1ZmZlciBmb3JtIHVubmVjZXNzYXJ5IGJhcnJpZXJzIGZvcgo+PiBrdGhy ZWFkIGxpa2Ugdmhvc3QgaW4gdGhlIGZ1dHVyZSwgd2Ugd2lsbCBtYW51YWxseSBwaWNrIHRoZSBv bmUgd2UgcmVhbGx5Cj4+IG5lZWQKPiBJIHBlcnNvbmFsbHkgdGhpbmsgd2Ugc2hvdWxkIGVyciBv biB0aGUgc2lkZSBvZiBjYXV0aW9uIG5vdCBvbiB0aGUgc2lkZSBvZgo+IHBlcmZvcm1hbmNlLgoK ClNvIHdoYXQgeW91IHN1Z2dlc3QgbWF5IGxlYWQgdW5uZWNlc3NhcnkgcGVyZm9ybWFuY2UgcmVn cmVzc2lvbiAKKDEwJS0yMCUpIHdoaWNoIGlzIHBhcnQgb2YgdGhlIGdvYWwgb2YgdGhpcyBzZXJp ZXMuIFdlIHNob3VsZCBhdWRpdCBhbmQgCm9ubHkgdXNlIHRoZSBvbmUgd2UgcmVhbGx5IG5lZWQg aW5zdGVhZCBvZiBkZXBlbmRpbmcgb24gY29weV91c2VyKCkgCmZyaWVuZHMoKS4KCklmIHdlIGRv IGl0IG91ciBvd24sIGl0IGNvdWxkIGJlIHNsb3cgZm9yIGZvciBzZWN1cml0eSBmaXggYnV0IGl0 J3Mgbm8gCmxlc3Mgc2FmZSB0aGFuIGJlZm9yZSB3aXRoIHBlcmZvcm1hbmNlIGtlcHQuCgoKPgo+ PiAoYnV0IGl0IHNob3VsZCBoYXZlIGxpdHRsZSBwb3NzaWJpbGl0eSkuCj4gSGlzdG9yeSBzZWVt cyB0byB0ZWFjaCBvdGhlcndpc2UuCgoKV2hhdCBjYXNlIGRpZCB5b3UgbWVhbiBoZXJlPwoKCj4K Pj4gUGxlYXNlIG5vdGljZSB3ZSBvbmx5IGFjY2VzcyBtZXRkYXRhIHRocm91Z2ggcmVtYXBwaW5n IG5vdCB0aGUgZGF0YSBpdHNlbGYuCj4+IFRoaXMgaWRlYSBoYXMgYmVlbiB1c2VkIGZvciBoaWdo IHNwZWVkIHVzZXJzcGFjZSBiYWNrZW5kIGZvciB5ZWFycywgZS5nCj4+IHBhY2tldCBzb2NrZXQg b3IgcmVjZW50IEFGX1hEUC4KPiBJIHRoaW5rIHRoZWlyIGp1c3RpZmljYXRpb24gZm9yIHRoZSBo aWdoZXIgcmlzayBpcyB0aGF0IHRoZXkgYXJlIG1vc3RseQo+IGRlc2lnbmVkIGZvciBwcml2ZWxl ZGdlZCB1c2Vyc3BhY2UuCgoKSSB0aGluayBpdCdzIHRoZSBzYW1lIHdpdGggVFVOL1RBUCwgcHJp dmlsZWdlZCBwcm9jZXNzIGNhbiBwYXNzIHRoZW0gdG8gCnVucHJpdmlsZWdlZCBvbmVzLgoKCj4K Pj4gVGhlIG9ubHkgZGlmZmVyZW5jZSBpcyB0aGUgcGFnZSB3YXMgcmVtYXAgdG8KPj4gZnJvbSBr ZXJuZWwgdG8gdXNlcnNwYWNlLgo+IEF0IGxlYXN0IHRoYXQgYXZvaWRzIHRoZSBnLnUucCBtZXNz LgoKCkknbSBzdGlsbCBub3QgdmVyeSBjbGVhciBhdCB0aGUgcG9pbnQuIFdlIG9ubHkgcGluIDIg b3IgNCBwYWdlcywgdGhleSdyZSAKc2V2ZXJhbCBvdGhlciBjYXNlcyB0aGF0IHdpbGwgcGluIG11 Y2ggbW9yZS4KCgo+Cj4+PiAgICAgSSBkb24ndAo+Pj4gbGlrZSB0aGUgaWRlYSBJIGhhdmUgdG8g c2F5LiAgQXMgYSBmaXJzdCBzdGVwLCB3aHkgZG9uJ3Qgd2Ugc3dpdGNoIHRvCj4+PiB1bnNhZmVf cHV0X3VzZXIvdW5zYWZlX2dldF91c2VyIGV0Yz8KPj4KPj4gU2V2ZXJhbCByZWFzb25zOgo+Pgo+ PiAtIFRoZXkgb25seSBoYXZlIHg4NiB2YXJpYW50LCBpdCB3b24ndCBoYXZlIGFueSBkaWZmZXJl bmNlIGZvciB0aGUgcmVzdCBvZgo+PiBhcmNoaXRlY3R1cmUuCj4gSXMgdGhlcmUgYW4gaXNzdWUg b24gb3RoZXIgYXJjaGl0ZWN0dXJlcz8gSWYgeWVzIHRoZXkgY2FuIGJlIGV4dGVuZGVkCj4gdGhl cmUuCgoKQ29uc2lkZXIgdGhlIHVuZXhwZWN0ZWQgYW1vdW50IG9mIHdvcmsgYW5kIGluIHRoZSBi ZXN0IGNhc2UgaXQgY2FuIGdpdmUgCnRoZSBzYW1lIHBlcmZvcm1hbmNlIHRvIHZtYXAoKS4gSSdt IG5vdCBzdXJlIGl0J3Mgd29ydGguCgoKPgo+PiAtIHVuc2FmZV9wdXRfdXNlci91bnNhZmVfZ2V0 X3VzZXIgaXMgbm90IHN1ZmZpY2llbnQgZm9yIGFjY2Vzc2luZyBzdHJ1Y3R1cmVzCj4+IChlLmcg YWNjZXNzaW5nIGRlc2NyaXB0b3IpIG9yIGFycmF5cyAoYmF0Y2hpbmcpLgo+IFNvIHlvdSB3YW50 IHVuc2FmZV9jb3B5X3h4eF91c2VyPyBJIGNhbiBkbyB0aGlzLiBIYW5nIG9uIHdpbGwgcG9zdC4K Pgo+PiAtIFVubGVzcyB3ZSBjYW4gYmF0Y2ggYXQgbGVhc3QgdGhlIGFjY2Vzc2luZyBvZiB0d28g cGxhY2VzIGluIHRocmVlIG9mCj4+IGF2YWlsLCB1c2VkIGFuZCBkZXNjcmlwdG9yIGluIG9uZSBy dW4uIFRoZXJlIHdpbGwgYmUgbm8gZGlmZmVyZW5jZS4gRS5nIHdlCj4+IGNhbiBiYXRjaCB1cGRh dGluZyB1c2VkIHJpbmcsIGJ1dCBpdCB3b24ndCBtYWtlIGFueSBkaWZmZXJlbmNlIGluIHRoaXMg Y2FzZS4KPj4KPiBTbyBsZXQncyBiYXRjaCB0aGVtIGFsbD8KCgpCYXRjaGluZyBtaWdodCBub3Qg aGVscCBmb3IgdGhlIGNhc2Ugb2YgbGlnaHQgbG9hZC4gQW5kIHdlIG5lZWQgdG8gCm1lYXN1cmUg dGhlIGdhaW4vY29zdCBvZiBiYXRjaGluZyBpdHNlbGYuCgoKPgo+Cj4+PiBUaGF0IHdvdWxkIGJl IG1vcmUgb2YgYW4gYXBwbGVzIHRvIGFwcGxlcyBjb21wYXJpc29uLCB3b3VsZCBpdCBub3Q/Cj4+ Cj4+IEFwcGxlcyB0byBhcHBsZXMgY29tcGFyaXNvbiBvbmx5IGhlbHAgaWYgd2UgYXJlIHRoZSBO by4xLiBCdXQgdGhlIGZhY3QgaXMgd2UKPj4gYXJlIG5vdC4gSWYgd2Ugd2FudCB0byBjb21wZXRl IHdpdGggZS5nIGRwZGsgb3IgQUZfWERQLCB2bWFwKCkgaXMgdGhlCj4+IGZhc3Rlc3QgbWV0aG9k IEFGQUlLLgo+Pgo+Pgo+PiBUaGFua3MKPiBXZSBuZWVkIHRvIHNwZWVkIHVwIHRoZSBwYWNrZXQg YWNjZXNzIGl0c2VsZiB0b28gdGhvdWdoLgo+IFlvdSBjYW4ndCB2bWFwIGFsbCBvZiBndWVzdCBt ZW1vcnkuCgoKVGhpcyBzZXJpZXMgb25seSBwaW4gYW5kIHZtYXAgdmVyeSBmZXcgcGFnZXMgKG1l dGFkYXRhKS4KClRoYW5rcwoKCj4KPgo+Pj4KPj4+PiBUZXN0IHNob3dzIGFib3V0IDI0JSBpbXBy b3ZlbWVudCBvbiBUWCBQUFMuIEl0IHNob3VsZCBiZW5lZml0IG90aGVyCj4+Pj4gY2FzZXMgYXMg d2VsbC4KPj4+Pgo+Pj4+IFBsZWFzZSByZXZpZXcKPj4+Pgo+Pj4+IEphc29uIFdhbmcgKDMpOgo+ Pj4+ICAgICB2aG9zdDogZ2VuZXJhbGl6ZSBhZGRpbmcgdXNlZCBlbGVtCj4+Pj4gICAgIHZob3N0 OiBmaW5lIGdyYWluIHVzZXJzcGFjZSBtZW1vcnkgYWNjZXNzb3JzCj4+Pj4gICAgIHZob3N0OiBh Y2Nlc3MgdnEgbWV0YWRhdGEgdGhyb3VnaCBrZXJuZWwgdmlydHVhbCBhZGRyZXNzCj4+Pj4KPj4+ PiAgICBkcml2ZXJzL3Zob3N0L3Zob3N0LmMgfCAyODEgKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKystLS0tCj4+Pj4gICAgZHJpdmVycy92aG9zdC92aG9zdC5oIHwgIDExICsr Cj4+Pj4gICAgMiBmaWxlcyBjaGFuZ2VkLCAyNjYgaW5zZXJ0aW9ucygrKSwgMjYgZGVsZXRpb25z KC0pCj4+Pj4KPj4+PiAtLSAKPj4+PiAyLjE3LjEKX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX18KVmlydHVhbGl6YXRpb24gbWFpbGluZyBsaXN0ClZpcnR1YWxp emF0aW9uQGxpc3RzLmxpbnV4LWZvdW5kYXRpb24ub3JnCmh0dHBzOi8vbGlzdHMubGludXhmb3Vu ZGF0aW9uLm9yZy9tYWlsbWFuL2xpc3RpbmZvL3ZpcnR1YWxpemF0aW9u