From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753475AbdBIPRO (ORCPT ); Thu, 9 Feb 2017 10:17:14 -0500 Received: from mail-bl2nam02on0113.outbound.protection.outlook.com ([104.47.38.113]:50461 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752079AbdBIPRK (ORCPT ); Thu, 9 Feb 2017 10:17:10 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=zi.yan@cs.rutgers.edu; From: Zi Yan To: Naoya Horiguchi CC: "linux-kernel@vger.kernel.org" , "linux-mm@kvack.org" , "kirill.shutemov@linux.intel.com" , "akpm@linux-foundation.org" , "minchan@kernel.org" , "vbabka@suse.cz" , "mgorman@techsingularity.net" , "khandual@linux.vnet.ibm.com" Subject: Re: [PATCH v3 08/14] mm: thp: enable thp migration in generic path Date: Thu, 9 Feb 2017 09:17:01 -0600 Message-ID: <7AE21E4F-EEEB-4C24-8158-473770119436@cs.rutgers.edu> In-Reply-To: <20170209091528.GB15649@hori1.linux.bs1.fc.nec.co.jp> References: <20170205161252.85004-1-zi.yan@sent.com> <20170205161252.85004-9-zi.yan@sent.com> <20170209091528.GB15649@hori1.linux.bs1.fc.nec.co.jp> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=_MailMate_250D46D4-7E4E-424F-A7BB-743748908B10_="; micalg=pgp-sha512; protocol="application/pgp-signature" X-Mailer: MailMate (2.0BETAr6076) X-Originating-IP: [12.1.252.66] X-ClientProxiedBy: BN6PR13CA0042.namprd13.prod.outlook.com (10.171.172.28) To CY4PR14MB1654.namprd14.prod.outlook.com (10.171.166.16) X-MS-Office365-Filtering-Correlation-Id: 1994f67d-e96f-40bc-74c5-08d450feb6c4 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:CY4PR14MB1654; X-Microsoft-Exchange-Diagnostics: 1;CY4PR14MB1654;3:SX5GpEy7s2ZXXJR2Y01ej0+MXc6iRm05U6lzMquNgkqxTG1kmbSZLJckqz6eqG6q3sgnCP/xxls7tPNqHPgUa8me4l26Rea9IvPXV/D5T5kfXnHc593YgZP+sGEC4/NX3Ojvix9TqE1JNVXsXZfGpas2pwyp02WjlEBfd1018qZgLoKkml++Vaq2PaYwp1OIBtWa6/+iuP7qyw5aZjOJunagdA08cGpGZYXuVtHDLCVm4Fbuo9NuthWnwVkAp8jc0Tp6SZz6CK48HYtw/7DvAA==;25:1OIMmYsH2X6pKb/ZNc++xx/G5Ien1T2JbkWSoNru227KFCbLNl+gPfj2MODGhOdnZPbwGK3YLsvNE5D/xuP3ANtAqBOQ1STR6sZfrSKsj5t/L1i4b7EUOl7lkk14yOPypnc7enNhnWaI/2DFww0/A+rI1c+QUwMLvA76NCJ+HZIvezuZGf2AB9ItfqSGY9AUSqM2+R2JGNgiR596QsadheV7KCuKzNXZzo5lFMkCWG5FwO1i95EJFbBT1nK/VX1aZWNQVf8yV7v8o1rQnBIY+UP6kbnOc6NvkfwfUAxjUD13jOlTVJaQXFDX+Y790tLkMp56EZctS3yfHMoObm+NLAmUw4/liiHb1WDiwvOy+TUfnf6PpIfUzjE51mttyq17BCwVsI2QyhjOjPvjMu9++gSr2WvZjYBf4rqEPIwq72xu4cRxuBWAC2fYD5d2PYU8Gmj3j7JukgAfcBdXtUmMvQ== X-Microsoft-Exchange-Diagnostics: 1;CY4PR14MB1654;31:oz0htKm4PIPAMfFqK7GKILc7VCK9ovYyWvNdJECMA/bBq/qPHIGeDwQjSNBmBS4ctfdCFU+CwysvPG6XxA4QJ+b8a8cosl8DJOo7WAcY2tsuJex5yGM4KiMFJi3YAbtj99FYctFD+0xoPkL+thEb4vcLlc0O5GARGV5HgIy2IALbcDuZaxpY8p6VRinsm1fw352EDDwk2qW+LAAU1ek4z7lrlLQSnMpZGje4PpyJPAcXvHdEKcEaMmrTM07oWNOlY7A3pmfmp+DVEhdq+dSNdA==;20:UXi9hCFECR99GdjNfcI/IwBJPF8X+39Vtzs9GpQ/HCIJCfZERuuzIKCvjZu67vIXuW+rSN7HASfJJujeAI9Ax+nPytl0acm9KfILcRvw4zZcy/OUlDcw4nuPntoiV+1wyLPjTR6BQg/WSfBTYvpiTyUef/RdW9et6QigrgkUpOBweY6qbxqih/hpSoMCcT7qJTK/dYwbwWpHgpMv4U/wgRiLNZpacNWsiqghzt8HdmMFGtziuO6jE5hFrN+e1mbt2n07P05VH0IoNcUDWb/dE6BzbTXo3xqtr0G7akTna+wBoV58G0+chhZhIo95PdgGg9dzPGTAj4lmyA43Ly/0nwgsJBrAQUpBGaGLptHnFTgYulU/dxNdArqlcszZDZDirB7UjvVJE5nj/j53a1J8/16kbORAFYx5GHV13TyA+V33MBtQkB3nh8a1GjQAG3GBvmfj7KOx/u+si7AJX6l4kNXK/fuLV4AMlxEAHQtT/OCGIBF6Rc3QC+d2r+P4Z+t5 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6041248)(20161123564025)(20161123560025)(20161123555025)(20161123562025)(20161123558025)(6072148);SRVR:CY4PR14MB1654;BCL:0;PCL:0;RULEID:;SRVR:CY4PR14MB1654; X-Microsoft-Exchange-Diagnostics: 1;CY4PR14MB1654;4:4hpRLzeYKgcVCSZnzH11GZ1Ay/OMJDx1lfqkSk57a8jBgZbYgPCka782gveNEDKPQuXSRi17mEudILA4fIEfVNjbBTVUzVgJepLORjKtLjY6xC/7nY1VV+xlMSttVCpirITxu+wcBGoVfZ2gVAuOsLVcbvRNqkDNzCNSK4GV8XlYvQp2A3jmSLmahT4OOleyn4PCDUHkuASEGQgCaP3B9rl517b2Qrvu1i0wgvp8Z7oeXoo7OqlTcTb/7wmC48PIDfGo5w72xsEOOuuVmP6iSFMecPvQx6s6uTYbB9m5I4SLIVzee2qdthqGtrpvGgK5ZrgVXPHr0f3BDXkHA9+UjpOogEM1WkRJCF26y+5x4Ic6ebAA+Vs/+SoY4JGbn8X44QsV9thRyhPnmtDbKU+aMvP9y4whtu8ufUt82Fpps4TN/ZVa4MA688db0BCBXE7BhEoglULkKqYAKPFvWEjKhHy9iiNkF8YrOOp2No1wdrcZUtVJrwLNgOfUYCbtgCQj7thE8H1USfirzEHzvr6N7pw0Yyc9ttiPt/E7sfm2INdIC+9wj41QDqU7CC/mjCpqBcK8MW2RjFLqYvJK0zzO/v4qa7Tn8grCPyK3GK2TLhY= X-Forefront-PRVS: 02135EB356 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(979002)(6049001)(6009001)(7916002)(39450400003)(39410400002)(39830400002)(54534003)(24454002)(189002)(199003)(6486002)(53546003)(305945005)(25786008)(8676002)(81156014)(81166006)(75432002)(77096006)(54906002)(106356001)(53936002)(5660300001)(5890100001)(2950100002)(3846002)(50226002)(6666003)(6916009)(110136004)(6116002)(90366009)(92566002)(21480400002)(38730400002)(229853002)(4326007)(88552002)(66066001)(97736004)(105586002)(6246003)(101416001)(2906002)(82746002)(84326002)(568964002)(42882006)(50986999)(189998001)(86362001)(7736002)(83716003)(68736007)(42186005)(33656002)(76176999)(41533002)(104396002)(72826003)(969003)(989001)(999001)(1009001)(1019001);DIR:OUT;SFP:1102;SCL:1;SRVR:CY4PR14MB1654;H:[10.20.179.37];FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY4PR14MB1654;23:4J44ut0tA/yWdLG6AMm4393lwAJFBlcfcc87VxOf9?= =?us-ascii?Q?D1eK404H5Ac12zmSjzGgKFr7pSrR40wnApyPnUejAtJbWKzaEyXR2YpM5VMS?= =?us-ascii?Q?HH2hOp6w7iFtzHpJJySnG3RdR8nRZLCQ1hPgZf7ROAeafjEXvSZ6XTVV7foY?= =?us-ascii?Q?GDkA1kI6JaK54M3kMJjjIla7WKu19HUmLtF0WyfaX1eTCiftmWHEL74h1ASZ?= =?us-ascii?Q?CEuobryblaT9NRw6bj5nCmF7OHR9LiWRRVctZPK5Y9oZUK5863WaxgXMppiI?= =?us-ascii?Q?sg1iBk5Ryaoq/nT89n/wZMU0dcuTs3tbDCUw407rF3P7ZkCXIX5KDTQiFpVa?= =?us-ascii?Q?Yy6CpxITQevwJetNNGI1P8gG9HbRXGn+ToZfYL4D9edwHJsPcQDZLGIJfE6e?= =?us-ascii?Q?yQzrTXy9v9cSEqvGu72sBBWamMlDs5BaNoYh6iLQoCD9J/872XWBV9MVnOsV?= =?us-ascii?Q?U4DZGPD7FXDPBsUuWKltzvCqgJ/wDCns+R4a9xhCRNrYxUQ0QBPDjXKD8q25?= =?us-ascii?Q?jYxdYfFPiq5mtUAbRbEC4zsfcaGV0OcwrX//iAi8M9JEtBovr9a9QJcWuB+2?= =?us-ascii?Q?itmMMULBKGuIwP5TAHAMTfd9rnxOoHlbJpB6XVvkF9tGCaqOORGpJ5QDriJZ?= =?us-ascii?Q?lMAZD7Op7eO2DObrN5lOkzk1YvbKuUmLDp9eUdiUWToUf7j9K91e6SRHdVN7?= =?us-ascii?Q?k/iOumD0B2LVBVDcEcmemDaSZ0iWqr1t9PqPPlsUsoJL5X7OXjIZLRmkRTXv?= =?us-ascii?Q?kIDICDwRYWjpP3XB44AcBxicUMCmMBmQMEUv1Z897s8tX46qp5iBf2iT+QzH?= =?us-ascii?Q?Xew5FNW2/eWtDDYJeFhWDIZgxqoMc56x54SIJ/zSegAVeoyXvcXbI1qr3hxH?= =?us-ascii?Q?+rYhJmRvQ3wQHY6qUVKOcoSLXVbB0dWAeGXoTE0BaJEXXxrs7ure/EVLWDMc?= =?us-ascii?Q?ycVKWTNWmeMRlg16E0BSRyYx0FmkN3O13g4QdcCwyiCBQluV39DHNckrCJjP?= =?us-ascii?Q?FyMRWmeMKPf7+RojEfHyEDk20bczd11jxukKH8uPPOBnqwj0H7wNZj6AK/ZD?= =?us-ascii?Q?WNxc9VYOhhZ8Nfvvk0MaGFxrO/eXDcOdwpLJ7jX2bqZrSRc72TfJJv955Sr9?= =?us-ascii?Q?/XV1q7zKfF8zoVmfvsjjKEcWctyAKlwaLtvZivxlByGOKp9BCc69RS0Cl94D?= =?us-ascii?Q?m73BLu8++8nbMr8C7YawXJEwXye+yUkVBU/Bd8IGd0gZmXUIS27wzYtsZN38?= =?us-ascii?Q?hKLIdrxwDa3QV6mARzTdhUguBV3Oro1XnrIjdNuPbHczH59v3ydrFg97s7fb?= =?us-ascii?Q?EczuSGJ47s+NXIXeTPRISXvKwj3LEIc9jkac+sYDMOvvKua6fSXW5mMSyW13?= =?us-ascii?Q?eOFkDiv4OSaLi8mm6S2XS80DayXqMrWXkrr2zaSIqG8h1ujY9EJkuwO+y7PH?= =?us-ascii?Q?657abBPxToMozm3b/X72rjlD1lLo6Fne1FOSTuD/Iu9RZGUaDt1oI6MfNPr6?= =?us-ascii?Q?4BOsJLixUreBj7I1JVAQnJJMzKUYoKY6MUqs9PxO8S6HVHzpCpbyCsFVSBCs?= =?us-ascii?Q?seOZc/1fjxgHEAULw=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY4PR14MB1654;6:Ku6qIvp8G+2Nmd0TRDlzXp46ElFqd7+GUcdCHXTUaqtdMKfcr9ZdAXKnRz/Tba/09/L1wIabkqKcwO300DckAvoS7ArzW5ai13bfRc+mmRBCJdAXsf61McSki3/Qyr1ABeY6KmAYe06M1r7YYs0R0zz2YOQoWSYhLwL6zv22s2er9SDY+ks7J8lwVAKa/RWU/8sYJ19aiSZoqb54sCh+jRYBpWVXcOpn48lTVqX+aU9AvoQL4ugAPq/D9H0yyTkCRzQ1rPRayyIHcZ1cqaUp0dCZS7b8SGbi5bIogYtxG7DkCkmRl++14v4riRILlQII6e4WzGrrqxH+5oPaDfzeImLOShSnAoS8/Qwzzu9wR1M911BZrc3U40yQUpSVMQ5qRDajkwYyVk11wqwWXDxCSg==;5:szNxqzwIDxSlEGcJ3kD4MVMhwTFSYVLOf3Y3Mv7qB9hlehhwzRxPEgcuyH77lCBeAjUFHtJ/CY3UDpYYAOnSmvpoqwjrF2cg4yiGN2fDD/xc/vkUVB5twUi0xcX8YIAyRHV2JJjuH+dizxRcRMcpxA==;24:4uBOhLlXyT6rvqNTzb8VtdimcjzuDYO0/lIr9CQC+d3ZS6Tp08stuwnff2EuPsAmSLz9DoN33ae/HZ5C0lYDGNSRK7HJMBRwsvulm06K36U= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CY4PR14MB1654;7:zyshfHUUiRnSdHwwBqHH1T5Qns2JeSTv/UleTrynYbhQ9G9Qf3KSY+UA9ALURI7IfzkJcSDPlJmsWRooeaxHlI0rkVy/TD7/Dd7RK+3WEr4k9eO6KEBCUgPAiMMcU8XFh0kYRHwkTao045d/aFs+a1/5XZMxhvAmuVoqZ5mnY0TLtMw+wcQAZnWZOaxE0hkuOM12hKT/Ecw6Cymxa9bxFq8ujiuIAlXYjkOe3LVRMevChrELx/454l1CyI4y4McGudtEOHuy6M9CStK+uMCZHWHgWCurN/c/XN0CLjULDLZNaqBSK9f0evfCZ/Y8c2xcsjLNf+9zHKIBfCnuaSW2v/FyCR6YOhv49+MD0JF5PKa83b8fsQSDrEhUtOGtKnMISuowh5Y9q6/Axz9LwqYTLPPNWdZgI1WjEaBBTQE4aeKZE9jvIttpI+DGSaGY9DvTwYZjL6kcN5KXWbClMASUJouWfByr7vmiB5SUc6o9GNlu9xWruLKAs4S9sdm+7W94bTUpZRaNr3AaT8OZGbgUng== X-OriginatorOrg: cs.rutgers.edu X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Feb 2017 15:17:07.1044 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR14MB1654 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --=_MailMate_250D46D4-7E4E-424F-A7BB-743748908B10_= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable On 9 Feb 2017, at 3:15, Naoya Horiguchi wrote: > On Sun, Feb 05, 2017 at 11:12:46AM -0500, Zi Yan wrote: >> From: Naoya Horiguchi >> >> This patch adds thp migration's core code, including conversions >> between a PMD entry and a swap entry, setting PMD migration entry, >> removing PMD migration entry, and waiting on PMD migration entries. >> >> This patch makes it possible to support thp migration. >> If you fail to allocate a destination page as a thp, you just split >> the source thp as we do now, and then enter the normal page migration.= >> If you succeed to allocate destination thp, you enter thp migration. >> Subsequent patches actually enable thp migration for each caller of >> page migration by allowing its get_new_page() callback to >> allocate thps. >> >> ChangeLog v1 -> v2: >> - support pte-mapped thp, doubly-mapped thp >> >> Signed-off-by: Naoya Horiguchi >> >> ChangeLog v2 -> v3: >> - use page_vma_mapped_walk() >> >> Signed-off-by: Zi Yan >> --- >> arch/x86/include/asm/pgtable_64.h | 2 + >> include/linux/swapops.h | 70 +++++++++++++++++- >> mm/huge_memory.c | 151 +++++++++++++++++++++++++++++= +++++---- >> mm/migrate.c | 29 +++++++- >> mm/page_vma_mapped.c | 13 +++- >> mm/pgtable-generic.c | 3 +- >> mm/rmap.c | 14 +++- >> 7 files changed, 259 insertions(+), 23 deletions(-) >> > ... >> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >> index 6893c47428b6..fd54bbdc16cf 100644 >> --- a/mm/huge_memory.c >> +++ b/mm/huge_memory.c >> @@ -1613,20 +1613,51 @@ int __zap_huge_pmd_locked(struct mmu_gather *t= lb, struct vm_area_struct *vma, >> atomic_long_dec(&tlb->mm->nr_ptes); >> tlb_remove_page_size(tlb, pmd_page(orig_pmd), HPAGE_PMD_SIZE); >> } else { >> - struct page *page =3D pmd_page(orig_pmd); >> - page_remove_rmap(page, true); >> - VM_BUG_ON_PAGE(page_mapcount(page) < 0, page); >> - VM_BUG_ON_PAGE(!PageHead(page), page); >> - if (PageAnon(page)) { >> - pgtable_t pgtable; >> - pgtable =3D pgtable_trans_huge_withdraw(tlb->mm, pmd); >> - pte_free(tlb->mm, pgtable); >> - atomic_long_dec(&tlb->mm->nr_ptes); >> - add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); >> + struct page *page; >> + int migration =3D 0; >> + >> + if (!is_pmd_migration_entry(orig_pmd)) { >> + page =3D pmd_page(orig_pmd); >> + VM_BUG_ON_PAGE(page_mapcount(page) < 0, page); >> + VM_BUG_ON_PAGE(!PageHead(page), page); >> + page_remove_rmap(page, true); > >> + if (PageAnon(page)) { >> + pgtable_t pgtable; >> + >> + pgtable =3D pgtable_trans_huge_withdraw(tlb->mm, >> + pmd); >> + pte_free(tlb->mm, pgtable); >> + atomic_long_dec(&tlb->mm->nr_ptes); >> + add_mm_counter(tlb->mm, MM_ANONPAGES, >> + -HPAGE_PMD_NR); >> + } else { >> + if (arch_needs_pgtable_deposit()) >> + zap_deposited_table(tlb->mm, pmd); >> + add_mm_counter(tlb->mm, MM_FILEPAGES, >> + -HPAGE_PMD_NR); >> + } > > This block is exactly equal to the one in else block below, > So you can factor out into some function. Of course, I will do that. > >> } else { >> - if (arch_needs_pgtable_deposit()) >> - zap_deposited_table(tlb->mm, pmd); >> - add_mm_counter(tlb->mm, MM_FILEPAGES, -HPAGE_PMD_NR); >> + swp_entry_t entry; >> + >> + entry =3D pmd_to_swp_entry(orig_pmd); >> + page =3D pfn_to_page(swp_offset(entry)); > >> + if (PageAnon(page)) { >> + pgtable_t pgtable; >> + >> + pgtable =3D pgtable_trans_huge_withdraw(tlb->mm, >> + pmd); >> + pte_free(tlb->mm, pgtable); >> + atomic_long_dec(&tlb->mm->nr_ptes); >> + add_mm_counter(tlb->mm, MM_ANONPAGES, >> + -HPAGE_PMD_NR); >> + } else { >> + if (arch_needs_pgtable_deposit()) >> + zap_deposited_table(tlb->mm, pmd); >> + add_mm_counter(tlb->mm, MM_FILEPAGES, >> + -HPAGE_PMD_NR); >> + } > >> + free_swap_and_cache(entry); /* waring in failure? */ >> + migration =3D 1; >> } >> tlb_remove_page_size(tlb, page, HPAGE_PMD_SIZE); >> } >> @@ -2634,3 +2665,97 @@ static int __init split_huge_pages_debugfs(void= ) >> } >> late_initcall(split_huge_pages_debugfs); >> #endif >> + >> +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION >> +void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw, >> + struct page *page) >> +{ >> + struct vm_area_struct *vma =3D pvmw->vma; >> + struct mm_struct *mm =3D vma->vm_mm; >> + unsigned long address =3D pvmw->address; >> + pmd_t pmdval; >> + swp_entry_t entry; >> + >> + if (pvmw->pmd && !pvmw->pte) { >> + pmd_t pmdswp; >> + >> + mmu_notifier_invalidate_range_start(mm, address, >> + address + HPAGE_PMD_SIZE); > > Don't you have to put mmu_notifier_invalidate_range_* outside this if b= lock? I think I need to add mmu_notifier_invalidate_page() in else block. Because Kirill's page_vma_mapped_walk() iterates each PMD or PTE. In set_pmd_migration_etnry(), if the page is PMD-mapped, it will be calle= d once with PMD, then mmu_notifier_invalidate_range_* can be used. On the other = hand, if the page is PTE-mapped, the function will be called 1~512 times depend= ing on how many PTEs are present. mmu_notifier_invalidate_range_* is not suit= able. mmu_notifier_invalidate_page() on the corresponding subpage should work. -- Best Regards Yan Zi --=_MailMate_250D46D4-7E4E-424F-A7BB-743748908B10_= Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Comment: GPGTools - https://gpgtools.org iQEcBAEBCgAGBQJYnIftAAoJEEGLLxGcTqbMWiQH/AvqJQhxcHKZkh3FW8nDAH9M 9HzFEn3Q5Up5NrVIY1J1rq0fTAil1MCNvftGr2Yk4FKa8Rp91roIvbFDYSyFJMmr kR51f7ykcvyty3FlngtUF9fDSup9RzMFXII/z9m/HcSBmeRAMumINAnBdqQwO6Sc GNDJpoZcIXI4m+TjO2yMgQpSYbl1dxKlpFNsdMCfSVE8Vv7eT7PGH5W7wDc288zc p7i/XlEuakShtYh3k2EnjX93JRrd5rWz26cqnRde5qAOqlngpHKlF4V3ZyJjV3KH hgDm6mrYgNFCkBFR0GsOjicZ40L36AWk2Ckm18h0lBlRwXdwY7LpDK5ee6IIkLI= =EbXh -----END PGP SIGNATURE----- --=_MailMate_250D46D4-7E4E-424F-A7BB-743748908B10_=--