Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932592AbdD0QkR (ORCPT ); Thu, 27 Apr 2017 12:40:17 -0400 Received: from mail-bn3nam01on0091.outbound.protection.outlook.com ([104.47.33.91]:63303 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751762AbdD0QkK (ORCPT ); Thu, 27 Apr 2017 12:40:10 -0400 Authentication-Results: ah.jp.nec.com; dkim=none (message not signed) header.d=none;ah.jp.nec.com; dmarc=none action=none header.from=cs.rutgers.edu; Message-ID: <59021EC1.8070500@cs.rutgers.edu> Date: Thu, 27 Apr 2017 11:39:29 -0500 From: Zi Yan User-Agent: Postbox 5.0.12 (Windows/20170323) MIME-Version: 1.0 To: Naoya Horiguchi CC: Anshuman Khandual , Zi Yan , "kirill.shutemov@linux.intel.com" , "linux-kernel@vger.kernel.org" , "linux-mm@kvack.org" , "akpm@linux-foundation.org" , "minchan@kernel.org" , "vbabka@suse.cz" , "mgorman@techsingularity.net" , "mhocko@kernel.org" , "dnellans@nvidia.com" Subject: Re: [PATCH v5 08/11] mm: hwpoison: soft offline supports thp migration References: <20170420204752.79703-1-zi.yan@sent.com> <20170420204752.79703-9-zi.yan@sent.com> <62d7eea3-96c8-3230-3e1b-fdc2bfbea6bd@linux.vnet.ibm.com> <58FA2B85.5040904@cs.rutgers.edu> <20170427044112.GA18781@hori1.linux.bs1.fc.nec.co.jp> In-Reply-To: <20170427044112.GA18781@hori1.linux.bs1.fc.nec.co.jp> X-Enigmail-Version: 1.2.3 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="------------enigDA12915245F7B5AF1519DADD" X-Originating-IP: [12.1.252.66] X-ClientProxiedBy: MWHPR1301CA0007.namprd13.prod.outlook.com (10.174.164.148) To MWHPR14MB1664.namprd14.prod.outlook.com (10.171.146.146) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5edfafd5-740c-4979-8fe4-08d48d8c0fa5 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(201703131423075)(201703031133081);SRVR:MWHPR14MB1664; X-Microsoft-Exchange-Diagnostics: 1;MWHPR14MB1664;3:UZmyPuuZXvpNRAbuKalnuU4VAeTykj+Zc0CyD86HW5Wxcxch+M10LkI4JEnSkvbqQf1QWUMRUCuod9UAyEMg6LexJpnMF2Ufku/x011djHMAKxmjSDACguq4WHwUPx3aiudnVOQ4vDHJ6RDTgkp1yGwQ5D01DXa745IR52EJR69yS10PoD1G637D2E/rbmLZcEHttZlpy5F2rpYEb6WMNCyBWIpmITSJHgK7V69rDUz3+xvR+i6yNKIjCPv6EhGW/U3WWingwPK3epM5Q7bhNB8U+oCPk4gOr0xw0/pzq9VXzbA0qdULpdOrIsBoCI2C94QInVeRnK+xVkVxTuOxXQ==;25:Mq9nCyM6uJ5vN6c4q2sXgkXo/VtnMHN7fuIlvO1wxtnuEPgDSj1CoZBb9lc6yhwB3nQNKCDCMX6Ii/eHdicIQ4M6PZWgVh+Hp4borsUo0Vo6A3UonURmK0NGAh2EjUZ1IZjrEozN1Uw2z+86oQ7E1/aJnniQQ9SpotYSXlWtI+dW1FJNR/gKbSBbLoKIP4vxT50zrhleBU39XTYlH73qMxu9XrLSo1DDNK2fis5JKyeyDGLS9gyS8MIHYiQZM35AKHURq+LbBsP2coSAH/hDufVarFqBkqTT8W2Rlk92kx3FFwHiRAnN35qgRAw0gsQT8ahCBFhJXfNOyQJoH7Jp5WYv1oHucn0wYg+qbudAOe/G7Zj14j00iJm/6i+t4leTP3+GhEWv5tuiWqhLIQdsQYSAxEHUG4TGs/F1Jt3jVh8knjJvTrr3bypkki8tUMuuxHXHHD7974mqnpCu5hsDQA== X-Microsoft-Exchange-Diagnostics: 1;MWHPR14MB1664;31:caqCJErw4oQPI6eOINeJozcgkGHNGlj7HqveYvz5kr+OZRNCWAP/n9cxYSkzcdBeYiogscIcLMHuJ8Jlzz78juY90XrLJF/O6nS+ikBKryLdi+h5yiSBW9h0vkGXa94Rbc1mVUcWfk7DI4l+yoT47Dc/mtz4VB2h0ihv8efSDtDJv6BznMFAWUbiL2ZjZm5LAXGvM0/dQCTsDUllHOn2MWHTiLjQkER0GD1gK4iSL3KwQmvxDVv/hgA6xp0Nmgt4;20:6hoVBKkmIEUdQy/owxjCuH3+SKGK/X7uRKNPzCCc3LYaYgWMubaY5KwGlVaAX1yW4xtoItVzt2BvXF6WSRRMinYPctIBaBjYXXjUoUBRnUhP/iLnzFmBkMgapIKUvvahFS/WNLKynS9YqxxmZWPUIFaAGR1weaw1dDSQ346Ywz8oNE7H5MJwnQvlJ0/MsTXHyNsKkZnl31ytJ/TBy8VEDMlhSM1GamPGdLXb6lNPKN+pIA9o0LbhWTB0am4w1cqFVNPKL90X0EXN+uqWm0ARN6NAzSft/v7/49ZTilp07DngaVQXqF67+guktIM/4sMnLpTU+e02kVf63EoNuFrdmK6ZBkjY39M2DQPatQr0uUJjfTTO2oFL4sN0/OazHhnrDVNdndTVzApzzbgL6ntcuy0ZUEsGgYaBgRkVJgF1Gf5ZY/jTrGzca6l+4y74gra3DjMn+1kH1L5cUuCDhrrHBN0K8v885ip2A7JnqW23etTAaAUhQz5AmbLf+Qzs0ljN X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040450)(601004)(2401047)(5005006)(8121501046)(93006095)(93001095)(10201501046)(3002001)(6041248)(201703131423075)(201702281529075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(20161123564025)(20161123560025)(20161123562025)(20161123555025)(6072148);SRVR:MWHPR14MB1664;BCL:0;PCL:0;RULEID:;SRVR:MWHPR14MB1664; X-Microsoft-Exchange-Diagnostics: 1;MWHPR14MB1664;4:XyT+3m6dv/O+Z91oME7wL+jT07ieZ+P4Mtp0sf7KkBJSvfbt/7m/0FsNzY8P+xEkasdIYK569hccAtJ7B+EGzAA7QGhGvqqyv2k42hAJkpJK+USUaN1E2xB5486MuBOMt8eRY2VYO5gxVG22MdhtRkvihazL6EBnXI2cCCkkA15baQLDAme/C1BGsOaOdthG2xihgfJf5bwx2KEERS3K867HFy6L2r2G0K/MjjChExDSufYxQQWcIgyK2gsnv5lqutEtjJOAfLFvGqffT6qXU7j0FU+AZXmb4cEWDDVGDBUkPBt7bUyNdVCNncdE2eGdOahWRApNxTdmxSXfBjRgxq39kSr3nRI0C14iue4uyClroEQ7/V2+mltKbCYLrjryx61DgpBOR0cujKYbMZ60eiO7wAJG7kro/pXT+AyXeFDA9Ke0yPWaqfGs5wIG9vgDEaTtdvobFf+VyRWj0i2rhQ2zrT/mnRtlN3E9mGZlRoXWvFwwXXQyfUzGLKhRFeUOaoL2P+Q7aBb8tTHVkEP7NtULDFWV4+1ZKVxaCYigHAOhxwLdZMPLR37ye++aSrRYulNOyNHfWbs85KYJXjo+PXHfQyQRhxKyAGBLXI1monIjkpNCoc/Q++L0E25vEmRblcls/w/6bGEduvlwHelHGT78kMekw1UpcWDB7YMWDHzSQutAu+2Bfu+i+6mqIdOuC9xIeTZepODSV+TwhsMM8ZYCOzLSKbJNtALIakoSiVlmpftOYoBStJRxWx8ROTIYgbuwjUpu3TikPtTmEmb7XysDhjHMxZif7PUMGi3L6JLTxorQbuM/e7icA/dQ4tON X-Forefront-PRVS: 029097202E X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(6049001)(39410400002)(39400400002)(39840400002)(39450400003)(39850400002)(39860400002)(377454003)(76104003)(24454002)(229853002)(80316001)(84326002)(42882006)(2950100002)(93886004)(6666003)(6916009)(5660300001)(59896002)(54906002)(77096006)(7416002)(6486002)(53936002)(90366009)(8676002)(81166006)(8656002)(21480400002)(38730400002)(6246003)(110136004)(305945005)(54356999)(6116002)(50986999)(53546009)(5890100001)(86362001)(7736002)(33656002)(83506001)(2906002)(88552002)(66066001)(568964002)(87266999)(4001350100001)(3846002)(25786009)(42186005)(65816999)(189998001)(76176999)(4326008)(75432002);DIR:OUT;SFP:1102;SCL:1;SRVR:MWHPR14MB1664;H:[10.20.179.109];FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;MWHPR14MB1664;23:05h5bmcDPLGkYNziyMhSiJl3OGqy/96eBCp5vSoEI?= =?us-ascii?Q?Jjn30XrgbLId6tnruhYapFktR5exfIaiUIUizxyt4LAxXk8auDHyWCK1bb/X?= =?us-ascii?Q?/FzHTExNfo6zVyb9wm7ZneLPZxBestooDE1JVLs8SpkY7C4oYZV1kLiZbqka?= =?us-ascii?Q?Za4xyRwcoD4nV57HfUOlzqbnc6UrobffSdqrB9Xy5gp1qZ0heP3VjzpX90qU?= =?us-ascii?Q?sjlU0xCW37/iiZa6AA2RKBX+S9pW1JWOY4qTyia+gEWwBmIwIIRorRdgrqeD?= =?us-ascii?Q?3G7xc5vwUmIuaBJQGzv+BKNVwoiCGxjaST4MBzdVg+pSu9mOH1JeRWNVJvam?= =?us-ascii?Q?tw3HND5eAFCKpVjZqF5PiV4/outdBEnNom/JxikYZcJU3gOb1tX+Ck2bGoGn?= =?us-ascii?Q?CiUkwj4cm/Kl2ZpPAVdyANOSLHJHT2GMYrZ7QgqU1R9AaHY4FGLXeoos9kEp?= =?us-ascii?Q?7LLzTdbNFh8ZRdT9nueXkjuo74vL7RTZVciBUFMcS6nQyDCPcIs1Espa7OXE?= =?us-ascii?Q?Cgr8pXiTYj2ZHh+u8sdHiwaBL6Zyfd2WaZyU30zDWwVEh5TveV/0UndfPWOU?= =?us-ascii?Q?aGvJXXeZhM2fj+adIRzceTQI5s406eEak1tk0QzpXpT/0uBCPeikn84R465v?= =?us-ascii?Q?iKlpzmMz3uVQtiJ40pWR7bvgyuIuyO24njHNI70q/rnu2/bTZklA0sBJ8Hkt?= =?us-ascii?Q?iYuYE8y6c6cn1E77gmwVIk02RysTnS6Yc+6nNnbGY1FusuF9JUW4nQzE2DKu?= =?us-ascii?Q?1iDqR99612THBWsALr0ulXDjPMjvILapp0+6fsP9KBWrDx4jfKNUjPsuTT0U?= =?us-ascii?Q?8dJlhFeJKMWie/lvfUsFaEI2hJnXFMkauwBe38/+WBA50XhqVk0JVAm/ye3r?= =?us-ascii?Q?GoU22Ud42zkxaTcs+TSO7LCGgRtGvUSgVYbneclrpVtGWjoWPIno7QolDUyN?= =?us-ascii?Q?tiV1WIGatGzC+WBmr3tBCoX2dZv5oZTGQ6/GRS3/N8eCv6tIsVfkuHQk87xi?= =?us-ascii?Q?uLB02GxnKP89/6Am99cKDWS9EbEnujGt/E/wiCDtEJfmQAeOF6OiJGOeFC/g?= =?us-ascii?Q?VquHj5l5VoEzSrakk/sgRuraW+oNng6ApiJ04HmmBqLiA2GShpvBk1tYxKws?= =?us-ascii?Q?moEjwNmNgOokfrquXCqGHuJxO2HKuCr2nR5+Npmsxed+Y/ZJ2qcMsVYOV8Mo?= =?us-ascii?Q?4kQE9IiYi/gQIn7YI2sTcLou2I5EW2TsuvVq9lkDdV4CiAMGT4JO2H8LceX0?= =?us-ascii?Q?REom2dDuIgrRfM72WVh6OzYTVPKnz3+sagfRqsVi2ObjwOUw8qBfilkRndgM?= =?us-ascii?Q?Gl1Qq0bnSH6mGelcfdpcVgPETnevp+FDrIRLYoWlzxEoj+hZczP9kT3jm7Mq?= =?us-ascii?Q?3yCCdgXyicAtFVNXVoinPPdt339YxTzXMjYkOWawhx/1YhO4dKX8euxH1MU6?= =?us-ascii?Q?XBydQ0eK+oFzlSU56fpGNEdxO+WnLY=3D?= X-Microsoft-Exchange-Diagnostics: 1;MWHPR14MB1664;6:AwXImidu7l3GiJ1QqRsTysk8/wO6nP8hRLR4gdOJtoEf5yVnIVrNXIltJ9+ggFKvlLtP9zIpCFPsbHI5ofuXFjWtjqIdMk6IFxCs4xfe6BcsDctmDHboGKk712OH5gsaBGsFdg0gYjHgvXWJir8FCEAwgD0R3KVi8sH59qe85I8LQOGp1S0YmlEqa/ztVjAuXxSRIBxM+bhIui116ajWMNJ6iDq1qzVasxUYwVdmdvXBL5EdB6rR49PaxK7t7CITx7OlQa6FZjyLbI9cwEGfT8IKLbvWdVJ2Nrdytrn9FqmlNElLdWyZbgpZdMX2QSWjl7FbsMpxb5uyk5eo1oHKhXuvwoZN3zdbRkehnYHf1ps9wpBdO7uoNsIxHymtr9RO0IYHGYcObr0TSGG9IpHqJWcg5lxR3/zMsZiUTiP7Zvwjz/Zy7dsirxX0T6i+QwjMc0LwLJeESU6pvyKYX2364xdNGygBGdesi1VC86plsTz6L0sOpm83PivUHROUXRfFYtrNpy/cTmvJhI6fu7YqMQ==;5:f0aQxSuF6JDHXLARqVjJdBgZe60oVnJ+28SUkYFopXILNbZpJU58d2ScfTTZrVjBqB0Y+hXt+DebnS4fxZg5FA4FLrNoa7TvQ5ALjoWDku96ordyVtNMQ3Q8VdPI2Sa0mEkH6RT1vkrky7qyaUfONg==;24:VNVv0K89WkBD4a/FDV8DRdjBH6Qb8K5l2AACjMFU1ekRSXZMncBnGgxaXlYTDTlZ2H6jxZq8cQd8RUoBZHotBNBwtV9mGuCLHmLI5QeLRJk= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;MWHPR14MB1664;7:hOpL9ZDOWAXgn7JOmM0Z1iczp5KkbP4E2x088dc0OOuw9MOL4WbwOZd4OWj9R4Fh2LbiC3Gk381v0OTw02axWtDzfIdQZCOuhUZzX6pqe3HUihnjL2goauKoWLb7nS2IhXDjZiAnhL4UbukkBvZdEyyf9jCdyWPD4CGM/YhLdfF15NqyixdBTLyOmEriAxd9s+B1o7kj27ypvbK2FltDQCrtH+MsN8d2ZwPVekW8ULqeFga0Jbuo+sZn5DI/gSPLCY4jAvVxFu1TyCCiHughQHl7UTjFioHedRrtyrQaled6PBTbn+9zIbBqor65wMVE+8/VMjD6JSj5mc2v7bLjNA== X-OriginatorOrg: cs.rutgers.edu X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Apr 2017 16:40:04.6344 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR14MB1664 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6930 Lines: 189 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigDA12915245F7B5AF1519DADD Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Naoya Horiguchi wrote: > On Fri, Apr 21, 2017 at 10:55:49AM -0500, Zi Yan wrote: >> >> Anshuman Khandual wrote: >>> On 04/21/2017 02:17 AM, Zi Yan wrote: >>>> From: Naoya Horiguchi >>>> >>>> This patch enables thp migration for soft offline. >>>> >>>> Signed-off-by: Naoya Horiguchi >>>> >>>> ChangeLog: v1 -> v5: >>>> - fix page isolation counting error >>>> >>>> Signed-off-by: Zi Yan >>>> --- >>>> mm/memory-failure.c | 35 ++++++++++++++--------------------- >>>> 1 file changed, 14 insertions(+), 21 deletions(-) >>>> >>>> diff --git a/mm/memory-failure.c b/mm/memory-failure.c >>>> index 9b77476ef31f..23ff02eb3ed4 100644 >>>> --- a/mm/memory-failure.c >>>> +++ b/mm/memory-failure.c >>>> @@ -1481,7 +1481,17 @@ static struct page *new_page(struct page *p, = unsigned long private, int **x) >>>> if (PageHuge(p)) >>>> return alloc_huge_page_node(page_hstate(compound_head(p)), >>>> nid); >>>> - else >>>> + else if (thp_migration_supported() && PageTransHuge(p)) { >>>> + struct page *thp; >>>> + >>>> + thp =3D alloc_pages_node(nid, >>>> + (GFP_TRANSHUGE | __GFP_THISNODE) & ~__GFP_RECLAIM, >>> Why not __GFP_RECLAIM ? Its soft offline path we wait a bit before >>> declaring that THP page cannot be allocated and hence should invoke >>> reclaim methods as well. >> I am not sure how much effort the kernel wants to put here to soft >> offline a THP. Naoya knows more here. >=20 > What I thought at first was that soft offline is not an urgent user > and no need to reclaim (i.e. give a little impact on other thread.) > But that's not a strong opinion, so if you like __GFP_RECLAIM here, > I'm fine about that. OK, I will add __GFP_RECLAIM. >=20 >> >>>> + HPAGE_PMD_ORDER); >>>> + if (!thp) >>>> + return NULL; >>>> + prep_transhuge_page(thp); >>>> + return thp; >>>> + } else >>>> return __alloc_pages_node(nid, GFP_HIGHUSER_MOVABLE, 0); >>>> } >>>> =20 >>>> @@ -1665,8 +1675,8 @@ static int __soft_offline_page(struct page *pa= ge, int flags) >>>> * cannot have PAGE_MAPPING_MOVABLE. >>>> */ >>>> if (!__PageMovable(page)) >>>> - inc_node_page_state(page, NR_ISOLATED_ANON + >>>> - page_is_file_cache(page)); >>>> + mod_node_page_state(page_pgdat(page), NR_ISOLATED_ANON + >>>> + page_is_file_cache(page), hpage_nr_pages(page)); >>>> list_add(&page->lru, &pagelist); >>>> ret =3D migrate_pages(&pagelist, new_page, NULL, MPOL_MF_MOVE_ALL= , >>>> MIGRATE_SYNC, MR_MEMORY_FAILURE); >>>> @@ -1689,28 +1699,11 @@ static int __soft_offline_page(struct page *= page, int flags) >>>> static int soft_offline_in_use_page(struct page *page, int flags) >>>> { >>>> int ret; >>>> - struct page *hpage =3D compound_head(page); >>>> - >>>> - if (!PageHuge(page) && PageTransHuge(hpage)) { >>>> - lock_page(hpage); >>>> - if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) { >>>> - unlock_page(hpage); >>>> - if (!PageAnon(hpage)) >>>> - pr_info("soft offline: %#lx: non anonymous thp\n", page_to_pfn(= page)); >>>> - else >>>> - pr_info("soft offline: %#lx: thp split failed\n", page_to_pfn(p= age)); >>>> - put_hwpoison_page(hpage); >>>> - return -EBUSY; >>>> - } >>>> - unlock_page(hpage); >>>> - get_hwpoison_page(page); >>>> - put_hwpoison_page(hpage); >>>> - } >>>> =20 >>>> if (PageHuge(page)) >>>> ret =3D soft_offline_huge_page(page, flags); >>>> else >>>> - ret =3D __soft_offline_page(page, flags); >>>> + ret =3D __soft_offline_page(compound_head(page), flags); >>> Hmm, what if the THP allocation fails in the new_page() path and >>> we fallback for general page allocation. In that case we will >>> always be still calling with the head page ? Because we dont >>> split the huge page any more. >> This could be a problem if the user wants to offline a TailPage but du= e >> to THP allocation failure, the HeadPage is offlined. >=20 > Right, "retry with split" part is unfinished, so we need some improveme= nt. >=20 >> It may be better to only soft offline THPs if page =3D=3D >> compound_head(page). If page !=3D compound_head(page), we still split = THPs >> like before. >> >> Because in migrate_pages(), we cannot guarantee any TailPages in that >> THP are migrated (1. THP allocation failure causes THP splitting, then= >> only HeadPage is going to be migrated; 2. even if we change existing >> migrate_pages() implementation to add all TailPages to migration list >> instead of LRU list, we still cannot guarantee the TailPage we want to= >> migrate is migrated.). >> >> Naoya, what do you think? >=20 > Maybe soft offline is a special caller of page migration because it > basically wants to migrate only one page, but thp migration still has > a benefit because we can avoid thp split. > So I like that we try thp migration at first, and if it fails we fall > back to split and migrate (only) a raw error page. This should be done > in caller side for soft offline, because it knows where the error page = is. Make sense. So when migrate_pages() sees the migrate reason is MR_MEMORY_FAILURE, it will not split THP when newpage allocation fails. Then, the soft offline caller will split failed THP and retry migrating the error subpage. I can do that. >=20 > As for generic case (for other migration callers which mainly want to > migrate multiple pages for their purpose,) thp split and retry can be > done in common migration code. After thp split, all subpages are linked= > to migration list, then we retry without returning to the caller. > So I think that split_huge_page() can be moved to (for example) for-loo= p > in migrate_pages(). >=20 > I tried to write a patch for it last year, but considering vm event > accounting, the patch might be large (~100 lines). Yes. I saw your code on your github. I can pick it up and send it for review after this patchset is merged, if you are OK with it. --=20 Best Regards, Yan Zi --------------enigDA12915245F7B5AF1519DADD Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBCAAGBQJZAh7gAAoJEEGLLxGcTqbMQJMH/24BAuvj58FK0lT7boCg8Rpn hDhVX03QqvcGXU47K3/DCL/SXizE7rOF70AMQcpC/TTL4JLUymE2n+peDB/qjKdl 2oO/UVzo5OwlReb1hziG3wsBZ698BNxjACCd6j8CwXr44JlCFpeD6krcwmhjGjTu vvs/HOvWJjeHO0sFFpgt4DJO99YxQM4rFMgQzGEF17tFQEbgtRF86ifM8UGlpHkT 8lSQJZ7cQbUR72q9kMi4AEEt1ngyBoGr4YL+non9jIQUGUY47K2ZVeh8qnpFCDPr ZQLLoKIRiBDcuYIuAUGiliseTCFXAzcYnYjokgjeXe8E1WmqqslMePvjksg40PA= =2Ci0 -----END PGP SIGNATURE----- --------------enigDA12915245F7B5AF1519DADD--