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=-6.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 EFFBCC43331 for ; Sun, 10 Nov 2019 22:09:43 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 90B572075C for ; Sun, 10 Nov 2019 22:09:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NPruwezp" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 90B572075C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 0F8286B0005; Sun, 10 Nov 2019 17:09:43 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 0AA966B0006; Sun, 10 Nov 2019 17:09:43 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id ED93E6B0007; Sun, 10 Nov 2019 17:09:42 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0064.hostedemail.com [216.40.44.64]) by kanga.kvack.org (Postfix) with ESMTP id D3C966B0005 for ; Sun, 10 Nov 2019 17:09:42 -0500 (EST) Received: from smtpin26.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with SMTP id 817F72C84 for ; Sun, 10 Nov 2019 22:09:42 +0000 (UTC) X-FDA: 76141760604.26.soup05_71be1424c3f19 X-HE-Tag: soup05_71be1424c3f19 X-Filterd-Recvd-Size: 18549 Received: from mail-pf1-f194.google.com (mail-pf1-f194.google.com [209.85.210.194]) by imf23.hostedemail.com (Postfix) with ESMTP for ; Sun, 10 Nov 2019 22:09:41 +0000 (UTC) Received: by mail-pf1-f194.google.com with SMTP id p26so9252549pfq.8 for ; Sun, 10 Nov 2019 14:09:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=A/PCNbhbWIsvRDNq3tn47QbfH9upwi9GO+5sHvLnqSs=; b=NPruwezpfInJQUqvX0pozNAUwxrbZAwbOLQnCGpvE2TdYIm3or+uTKd6eN6wOlO+hV GiAoospZfCuHSYcxnUjz75In4fswbNfwfYUxCpR7ijRMwIYisWX1GdFgBCs8tGP/YXy2 3AY3bttoXVf0z23W0PnQIx2vA6CnEwBXdyyM+PtxUTH2fcHFW+QXesYPGOJHa58Yenst VbV7aPNS7WRU8pDHCPBcP5qzYvjqDAF1vTaaZU5mOdrNksvDC0WmCRfLP+7DuxfSXhUT NRy8RQWcRPgL9onz7HzKco/oU4CfwGEYgFKqryRx9hz6gU8S+zdiLxFUU4XZwISISNiw NKFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=A/PCNbhbWIsvRDNq3tn47QbfH9upwi9GO+5sHvLnqSs=; b=kP/VHyRmiR7jyZR3686SJXjxets1AanxgPhlHC7Is8eTJIlHUefIB3CL1LRJsaj0F1 eXUQQnofcwpsP8AXTWSwOzkpK3xfZ4LQxQJneaLPfpzPWO0i7//TkzGinjD2bGN3LH7F WccCwDTMcsTXbJDrKwPrA8sOCUp4Y5TZBTUNa2XqirRcdJGHOH8shVaXbihbiAeG7LBM BC83ks6A1mtHL2WQU3M8iJhgONtj2DepLk6DDgUiTKCGGU0lVGliNZSmQYeGWCcTU2z8 GLv+FNvGL5LPiPAXPGmFqMNzNSrLZuoAbG0zjhfoawcgz36C7My+7Fwc6bIqWgazS242 Y5kA== X-Gm-Message-State: APjAAAWY+hih/s23UcDYKtaGKRivNxE4WR4z/kne+XOIiAD+ipXpvk+3 8Z+zgPTq1nDVIEA775bXX0TsLGTXjHFx0iDiycE= X-Google-Smtp-Source: APXvYqzR+u5a1bUKyrEL82pja5TR7W/lRRN4jr0340yBnO21Nucc0DJowvjLbrDmO77+2kLIMysXIpcr+uJiNtw2bTc= X-Received: by 2002:a63:1303:: with SMTP id i3mr6033416pgl.430.1573423780356; Sun, 10 Nov 2019 14:09:40 -0800 (PST) MIME-Version: 1.0 Received: by 2002:a17:90a:344b:0:0:0:0 with HTTP; Sun, 10 Nov 2019 14:09:39 -0800 (PST) Received: by 2002:a17:90a:344b:0:0:0:0 with HTTP; Sun, 10 Nov 2019 14:09:39 -0800 (PST) In-Reply-To: <20191107205334.158354-2-hannes@cmpxchg.org> References: <20191107205334.158354-1-hannes@cmpxchg.org> <20191107205334.158354-2-hannes@cmpxchg.org> From: Khadarnimcaan Khadarnimcaan Date: Mon, 11 Nov 2019 01:09:39 +0300 Message-ID: Subject: Re: [PATCH 1/3] mm: vmscan: move file exhaustion detection to the node level To: Johannes Weiner Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, Michal Hocko , Andrey Ryabinin , Rik van Riel , kernel-team@fb.com, linux-kernel@vger.kernel.org, Andrew Morton , Suren Baghdasaryan , Shakeel Butt Content-Type: multipart/alternative; boundary="000000000000826bb50597054568" X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: --000000000000826bb50597054568 Content-Type: text/plain; charset="UTF-8" On Nov 7, 2019 11:54 PM, "Johannes Weiner" wrote: > When file pages are lower than the watermark on a node, we try to > force scan anonymous pages to counter-act the balancing algorithms > preference for new file pages when they are likely thrashing. This is > a node-level decision, but it's currently made each time we look at an > lruvec. This is unnecessarily expensive and also a layering violation > that makes the code harder to understand. > > Clean this up by making the check once per node and setting a flag in > the scan_control. > > Signed-off-by: Johannes Weiner > Reviewed-by: Shakeel Butt > --- > mm/vmscan.c | 80 ++++++++++++++++++++++++++++------------------------- > 1 file changed, 42 insertions(+), 38 deletions(-) > > diff --git a/mm/vmscan.c b/mm/vmscan.c > index d97985262dda..e8dd601e1fad 100644 > --- a/mm/vmscan.c > +++ b/mm/vmscan.c > @@ -101,6 +101,9 @@ struct scan_control { > /* One of the zones is ready for compaction */ > unsigned int compaction_ready:1; > > + /* The file pages on the current node are dangerously low */ > + unsigned int file_is_tiny:1; > + > /* Allocation order */ > s8 order; > > @@ -2289,45 +2292,16 @@ static void get_scan_count(struct lruvec *lruvec, > struct scan_control *sc, > } > > /* > - * Prevent the reclaimer from falling into the cache trap: as > - * cache pages start out inactive, every cache fault will tip > - * the scan balance towards the file LRU. And as the file LRU > - * shrinks, so does the window for rotation from references. > - * This means we have a runaway feedback loop where a tiny > - * thrashing file LRU becomes infinitely more attractive than > - * anon pages. Try to detect this based on file LRU size. > + * If the system is almost out of file pages, force-scan anon. > + * But only if there are enough inactive anonymous pages on > + * the LRU. Otherwise, the small LRU gets thrashed. > */ > - if (!cgroup_reclaim(sc)) { > - unsigned long pgdatfile; > - unsigned long pgdatfree; > - int z; > - unsigned long total_high_wmark = 0; > - > - pgdatfree = sum_zone_node_page_state(pgdat->node_id, > NR_FREE_PAGES); > - pgdatfile = node_page_state(pgdat, NR_ACTIVE_FILE) + > - node_page_state(pgdat, NR_INACTIVE_FILE); > - > - for (z = 0; z < MAX_NR_ZONES; z++) { > - struct zone *zone = &pgdat->node_zones[z]; > - if (!managed_zone(zone)) > - continue; > - > - total_high_wmark += high_wmark_pages(zone); > - } > - > - if (unlikely(pgdatfile + pgdatfree <= total_high_wmark)) { > - /* > - * Force SCAN_ANON if there are enough inactive > - * anonymous pages on the LRU in eligible zones. > - * Otherwise, the small LRU gets thrashed. > - */ > - if (!inactive_list_is_low(lruvec, false, sc, > false) && > - lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, > sc->reclaim_idx) > - >> sc->priority) { > - scan_balance = SCAN_ANON; > - goto out; > - } > - } > + if (sc->file_is_tiny && > + !inactive_list_is_low(lruvec, false, sc, false) && > + lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, > + sc->reclaim_idx) >> sc->priority) { > + scan_balance = SCAN_ANON; > + goto out; > } > > /* > @@ -2754,6 +2728,36 @@ static bool shrink_node(pg_data_t *pgdat, struct > scan_control *sc) > nr_reclaimed = sc->nr_reclaimed; > nr_scanned = sc->nr_scanned; > > + /* > + * Prevent the reclaimer from falling into the cache trap: as > + * cache pages start out inactive, every cache fault will tip > + * the scan balance towards the file LRU. And as the file LRU > + * shrinks, so does the window for rotation from references. > + * This means we have a runaway feedback loop where a tiny > + * thrashing file LRU becomes infinitely more attractive than > + * anon pages. Try to detect this based on file LRU size. > + */ > + if (!cgroup_reclaim(sc)) { > + unsigned long file; > + unsigned long free; > + int z; > + unsigned long total_high_wmark = 0; > + > + free = sum_zone_node_page_state(pgdat->node_id, > NR_FREE_PAGES); > + file = node_page_state(pgdat, NR_ACTIVE_FILE) + > + node_page_state(pgdat, NR_INACTIVE_FILE); > + > + for (z = 0; z < MAX_NR_ZONES; z++) { > + struct zone *zone = &pgdat->node_zones[z]; > + if (!managed_zone(zone)) > + continue; > + > + total_high_wmark += high_wmark_pages(zone); > + } > + > + sc->file_is_tiny = file + free <= total_high_wmark; > + } > + > shrink_node_memcgs(pgdat, sc); > > if (reclaim_state) { > -- > 2.24.0 > > --000000000000826bb50597054568 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUiPk9uIE5vdiA3LCAyMDE5IDExOjU0IFBNLCAmcXVvdDtK b2hhbm5lcyBXZWluZXImcXVvdDsgJmx0OzxhIGhyZWY9Im1haWx0bzpoYW5uZXNAY21weGNoZy5v cmciPmhhbm5lc0BjbXB4Y2hnLm9yZzwvYT4mZ3Q7IHdyb3RlOjxiciB0eXBlPSJhdHRyaWJ1dGlv biI+PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBzdHlsZT0ibWFyZ2luOjAgMCAwIC44 ZXg7Ym9yZGVyLWxlZnQ6MXB4ICNjY2Mgc29saWQ7cGFkZGluZy1sZWZ0OjFleCI+V2hlbiBmaWxl IHBhZ2VzIGFyZSBsb3dlciB0aGFuIHRoZSB3YXRlcm1hcmsgb24gYSBub2RlLCB3ZSB0cnkgdG88 YnI+DQpmb3JjZSBzY2FuIGFub255bW91cyBwYWdlcyB0byBjb3VudGVyLWFjdCB0aGUgYmFsYW5j aW5nIGFsZ29yaXRobXM8YnI+DQpwcmVmZXJlbmNlIGZvciBuZXcgZmlsZSBwYWdlcyB3aGVuIHRo ZXkgYXJlIGxpa2VseSB0aHJhc2hpbmcuIFRoaXMgaXM8YnI+DQphIG5vZGUtbGV2ZWwgZGVjaXNp b24sIGJ1dCBpdCYjMzk7cyBjdXJyZW50bHkgbWFkZSBlYWNoIHRpbWUgd2UgbG9vayBhdCBhbjxi cj4NCmxydXZlYy4gVGhpcyBpcyB1bm5lY2Vzc2FyaWx5IGV4cGVuc2l2ZSBhbmQgYWxzbyBhIGxh eWVyaW5nIHZpb2xhdGlvbjxicj4NCnRoYXQgbWFrZXMgdGhlIGNvZGUgaGFyZGVyIHRvIHVuZGVy c3RhbmQuPGJyPg0KPGJyPg0KQ2xlYW4gdGhpcyB1cCBieSBtYWtpbmcgdGhlIGNoZWNrIG9uY2Ug cGVyIG5vZGUgYW5kIHNldHRpbmcgYSBmbGFnIGluPGJyPg0KdGhlIHNjYW5fY29udHJvbC48YnI+ DQo8YnI+DQpTaWduZWQtb2ZmLWJ5OiBKb2hhbm5lcyBXZWluZXIgJmx0OzxhIGhyZWY9Im1haWx0 bzpoYW5uZXNAY21weGNoZy5vcmciPmhhbm5lc0BjbXB4Y2hnLm9yZzwvYT4mZ3Q7PGJyPg0KUmV2 aWV3ZWQtYnk6IFNoYWtlZWwgQnV0dCAmbHQ7PGEgaHJlZj0ibWFpbHRvOnNoYWtlZWxiQGdvb2ds ZS5jb20iPnNoYWtlZWxiQGdvb2dsZS5jb208L2E+Jmd0Ozxicj4NCi0tLTxicj4NCsKgbW0vdm1z Y2FuLmMgfCA4MCArKysrKysrKysrKysrKysrKysrKysrKysrKysrLS08d2JyPi0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tPGJyPg0KwqAxIGZpbGUgY2hhbmdlZCwgNDIgaW5zZXJ0aW9ucygrKSwgMzgg ZGVsZXRpb25zKC0pPGJyPg0KPGJyPg0KZGlmZiAtLWdpdCBhL21tL3Ztc2Nhbi5jIGIvbW0vdm1z Y2FuLmM8YnI+DQppbmRleCBkOTc5ODUyNjJkZGEuLmU4ZGQ2MDFlMWZhZCAxMDA2NDQ8YnI+DQot LS0gYS9tbS92bXNjYW4uYzxicj4NCisrKyBiL21tL3Ztc2Nhbi5jPGJyPg0KQEAgLTEwMSw2ICsx MDEsOSBAQCBzdHJ1Y3Qgc2Nhbl9jb250cm9sIHs8YnI+DQrCoCDCoCDCoCDCoCAvKiBPbmUgb2Yg dGhlIHpvbmVzIGlzIHJlYWR5IGZvciBjb21wYWN0aW9uICovPGJyPg0KwqAgwqAgwqAgwqAgdW5z aWduZWQgaW50IGNvbXBhY3Rpb25fcmVhZHk6MTs8YnI+DQo8YnI+DQorwqAgwqAgwqAgwqAvKiBU aGUgZmlsZSBwYWdlcyBvbiB0aGUgY3VycmVudCBub2RlIGFyZSBkYW5nZXJvdXNseSBsb3cgKi88 YnI+DQorwqAgwqAgwqAgwqB1bnNpZ25lZCBpbnQgZmlsZV9pc190aW55OjE7PGJyPg0KKzxicj4N CsKgIMKgIMKgIMKgIC8qIEFsbG9jYXRpb24gb3JkZXIgKi88YnI+DQrCoCDCoCDCoCDCoCBzOCBv cmRlcjs8YnI+DQo8YnI+DQpAQCAtMjI4OSw0NSArMjI5MiwxNiBAQCBzdGF0aWMgdm9pZCBnZXRf c2Nhbl9jb3VudChzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNj LDxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCAvKjxicj4NCi3CoCDC oCDCoCDCoCAqIFByZXZlbnQgdGhlIHJlY2xhaW1lciBmcm9tIGZhbGxpbmcgaW50byB0aGUgY2Fj aGUgdHJhcDogYXM8YnI+DQotwqAgwqAgwqAgwqAgKiBjYWNoZSBwYWdlcyBzdGFydCBvdXQgaW5h Y3RpdmUsIGV2ZXJ5IGNhY2hlIGZhdWx0IHdpbGwgdGlwPGJyPg0KLcKgIMKgIMKgIMKgICogdGhl IHNjYW4gYmFsYW5jZSB0b3dhcmRzIHRoZSBmaWxlIExSVS7CoCBBbmQgYXMgdGhlIGZpbGUgTFJV PGJyPg0KLcKgIMKgIMKgIMKgICogc2hyaW5rcywgc28gZG9lcyB0aGUgd2luZG93IGZvciByb3Rh dGlvbiBmcm9tIHJlZmVyZW5jZXMuPGJyPg0KLcKgIMKgIMKgIMKgICogVGhpcyBtZWFucyB3ZSBo YXZlIGEgcnVuYXdheSBmZWVkYmFjayBsb29wIHdoZXJlIGEgdGlueTxicj4NCi3CoCDCoCDCoCDC oCAqIHRocmFzaGluZyBmaWxlIExSVSBiZWNvbWVzIGluZmluaXRlbHkgbW9yZSBhdHRyYWN0aXZl IHRoYW48YnI+DQotwqAgwqAgwqAgwqAgKiBhbm9uIHBhZ2VzLsKgIFRyeSB0byBkZXRlY3QgdGhp cyBiYXNlZCBvbiBmaWxlIExSVSBzaXplLjxicj4NCivCoCDCoCDCoCDCoCAqIElmIHRoZSBzeXN0 ZW0gaXMgYWxtb3N0IG91dCBvZiBmaWxlIHBhZ2VzLCBmb3JjZS1zY2FuIGFub24uPGJyPg0KK8Kg IMKgIMKgIMKgICogQnV0IG9ubHkgaWYgdGhlcmUgYXJlIGVub3VnaCBpbmFjdGl2ZSBhbm9ueW1v dXMgcGFnZXMgb248YnI+DQorwqAgwqAgwqAgwqAgKiB0aGUgTFJVLiBPdGhlcndpc2UsIHRoZSBz bWFsbCBMUlUgZ2V0cyB0aHJhc2hlZC48YnI+DQrCoCDCoCDCoCDCoCDCoCovPGJyPg0KLcKgIMKg IMKgIMKgaWYgKCFjZ3JvdXBfcmVjbGFpbShzYykpIHs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqB1bnNpZ25lZCBsb25nIHBnZGF0ZmlsZTs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB1bnNpZ25lZCBsb25nIHBnZGF0ZnJlZTs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp bnQgejs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25nIHRvdGFsX2hp Z2hfd21hcmsgPSAwOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwZ2RhdGZy ZWUgPSBzdW1fem9uZV9ub2RlX3BhZ2Vfc3RhdGUoPHdicj5wZ2RhdC0mZ3Q7bm9kZV9pZCwgTlJf RlJFRV9QQUdFUyk7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGdkYXRmaWxlID0gbm9k ZV9wYWdlX3N0YXRlKHBnZGF0LCBOUl9BQ1RJVkVfRklMRSkgKzxicj4NCi3CoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBub2RlX3BhZ2Vfc3RhdGUocGdkYXQsIE5SX0lOQUNU SVZFX0ZJTEUpOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBmb3IgKHogPSAw OyB6ICZsdDsgTUFYX05SX1pPTkVTOyB6KyspIHs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBzdHJ1Y3Qgem9uZSAqem9uZSA9ICZhbXA7cGdkYXQtJmd0O25vZGVfem9u ZXNbel07PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKCFtYW5h Z2VkX3pvbmUoem9uZSkpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgY29udGludWU7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHRvdGFsX2hpZ2hfd21hcmsgKz0gaGlnaF93bWFya19wYWdlcyh6b25lKTs8 YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoCDC oCDCoCDCoCDCoGlmICh1bmxpa2VseShwZ2RhdGZpbGUgKyBwZ2RhdGZyZWUgJmx0Oz0gdG90YWxf aGlnaF93bWFyaykpIHs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAv Kjxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIEZvcmNlIFNDQU5f QU5PTiBpZiB0aGVyZSBhcmUgZW5vdWdoIGluYWN0aXZlPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgICogYW5vbnltb3VzIHBhZ2VzIG9uIHRoZSBMUlUgaW4gZWxpZ2li bGUgem9uZXMuPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICogT3Ro ZXJ3aXNlLCB0aGUgc21hbGwgTFJVIGdldHMgdGhyYXNoZWQuPGJyPg0KLcKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgaWYgKCFpbmFjdGl2ZV9saXN0X2lzX2xvdyhscnV2ZWMsIGZhbHNlLCBzYywgZmFs c2UpICZhbXA7JmFtcDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBscnV2ZWNfbHJ1X3NpemUobHJ1dmVjLCBMUlVfSU5BQ1RJVkVfQU5PTiwgc2MtJmd0O3Jl Y2xhaW1faWR4KTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCZndDsmZ3Q7IHNjLSZndDtwcmlvcml0eSkgezxicj4NCi3CoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHNjYW5fYmFsYW5jZSA9 IFNDQU5fQU5PTjs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBnb3RvIG91dDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB9PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoGlmIChz Yy0mZ3Q7ZmlsZV9pc190aW55ICZhbXA7JmFtcDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAhaW5h Y3RpdmVfbGlzdF9pc19sb3cobHJ1dmVjLCBmYWxzZSwgc2MsIGZhbHNlKSAmYW1wOyZhbXA7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgbHJ1dmVjX2xydV9zaXplKGxydXZlYywgTFJVX0lOQUNUSVZF X0FOT04sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2Mt Jmd0O3JlY2xhaW1faWR4KSAmZ3Q7Jmd0OyBzYy0mZ3Q7cHJpb3JpdHkpIHs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBzY2FuX2JhbGFuY2UgPSBTQ0FOX0FOT047PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgZ290byBvdXQ7PGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCjxicj4NCsKg IMKgIMKgIMKgIC8qPGJyPg0KQEAgLTI3NTQsNiArMjcyOCwzNiBAQCBzdGF0aWMgYm9vbCBzaHJp bmtfbm9kZShwZ19kYXRhX3QgKnBnZGF0LCBzdHJ1Y3Qgc2Nhbl9jb250cm9sICpzYyk8YnI+DQrC oCDCoCDCoCDCoCBucl9yZWNsYWltZWQgPSBzYy0mZ3Q7bnJfcmVjbGFpbWVkOzxicj4NCsKgIMKg IMKgIMKgIG5yX3NjYW5uZWQgPSBzYy0mZ3Q7bnJfc2Nhbm5lZDs8YnI+DQo8YnI+DQorwqAgwqAg wqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIFByZXZlbnQgdGhlIHJlY2xhaW1lciBmcm9tIGZh bGxpbmcgaW50byB0aGUgY2FjaGUgdHJhcDogYXM8YnI+DQorwqAgwqAgwqAgwqAgKiBjYWNoZSBw YWdlcyBzdGFydCBvdXQgaW5hY3RpdmUsIGV2ZXJ5IGNhY2hlIGZhdWx0IHdpbGwgdGlwPGJyPg0K K8KgIMKgIMKgIMKgICogdGhlIHNjYW4gYmFsYW5jZSB0b3dhcmRzIHRoZSBmaWxlIExSVS7CoCBB bmQgYXMgdGhlIGZpbGUgTFJVPGJyPg0KK8KgIMKgIMKgIMKgICogc2hyaW5rcywgc28gZG9lcyB0 aGUgd2luZG93IGZvciByb3RhdGlvbiBmcm9tIHJlZmVyZW5jZXMuPGJyPg0KK8KgIMKgIMKgIMKg ICogVGhpcyBtZWFucyB3ZSBoYXZlIGEgcnVuYXdheSBmZWVkYmFjayBsb29wIHdoZXJlIGEgdGlu eTxicj4NCivCoCDCoCDCoCDCoCAqIHRocmFzaGluZyBmaWxlIExSVSBiZWNvbWVzIGluZmluaXRl bHkgbW9yZSBhdHRyYWN0aXZlIHRoYW48YnI+DQorwqAgwqAgwqAgwqAgKiBhbm9uIHBhZ2VzLsKg IFRyeSB0byBkZXRlY3QgdGhpcyBiYXNlZCBvbiBmaWxlIExSVSBzaXplLjxicj4NCivCoCDCoCDC oCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoGlmICghY2dyb3VwX3JlY2xhaW0oc2MpKSB7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdW5zaWduZWQgbG9uZyBmaWxlOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHVuc2lnbmVkIGxvbmcgZnJlZTs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBpbnQgejs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25n IHRvdGFsX2hpZ2hfd21hcmsgPSAwOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBmcmVlID0gc3VtX3pvbmVfbm9kZV9wYWdlX3N0YXRlKDx3YnI+cGdkYXQtJmd0O25vZGVfaWQs IE5SX0ZSRUVfUEFHRVMpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZpbGUgPSBub2Rl X3BhZ2Vfc3RhdGUocGdkYXQsIE5SX0FDVElWRV9GSUxFKSArPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIG5vZGVfcGFnZV9zdGF0ZShwZ2RhdCwgTlJfSU5BQ1RJ VkVfRklMRSk7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZvciAoeiA9IDA7 IHogJmx0OyBNQVhfTlJfWk9ORVM7IHorKykgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHN0cnVjdCB6b25lICp6b25lID0gJmFtcDtwZ2RhdC0mZ3Q7bm9kZV96b25l c1t6XTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoIW1hbmFn ZWRfem9uZSh6b25lKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBjb250aW51ZTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgdG90YWxfaGlnaF93bWFyayArPSBoaWdoX3dtYXJrX3BhZ2VzKHpvbmUpOzxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgc2MtJmd0O2ZpbGVfaXNfdGlueSA9IGZpbGUgKyBmcmVlICZsdDs9IHRvdGFsX2hp Z2hfd21hcms7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCis8YnI+DQrCoCDCoCDCoCDCoCBzaHJp bmtfbm9kZV9tZW1jZ3MocGdkYXQsIHNjKTs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBpZiAocmVj bGFpbV9zdGF0ZSkgezxicj4NCi0tIDxicj4NCjIuMjQuMDxicj4NCjxicj4NCjwvYmxvY2txdW90 ZT48L2Rpdj4NCg== --000000000000826bb50597054568--