Received: by 2002:a5b:505:0:0:0:0:0 with SMTP id o5csp5433054ybp; Mon, 14 Oct 2019 22:39:40 -0700 (PDT) X-Google-Smtp-Source: APXvYqwbkIoc5uzivOEmgfqbVxzfpKrxL8hKR9LPsIcyq+CZzkCAzPVm5mvjoI//0RCprDQqIvd+ X-Received: by 2002:a50:c304:: with SMTP id a4mr31976867edb.303.1571117980619; Mon, 14 Oct 2019 22:39:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571117980; cv=none; d=google.com; s=arc-20160816; b=0S0Y+NensokHEqWQbFZ6M6p3jvj1fldV9fJ5U5XanJjxqaFillY2v7VDrEUfHaawS1 v+jXhzKIXuC0kcTZ1/e8ihqQ93wjdp+prfGuM1d8iMuhG1zeDciW3tUUXVxdWVk0oM3b 0LBFEOKmmSqAO4QifyjNuWD0elyDH/YIe9N1C2/1NSLos71a/DA/y0Q86Kt+kjeD3nSA iU5nb2hQJqSbWRFqbX9RsA1If91jG4dDVvHdr64sWcKVi8cTIag57osTa7YqX2R3LA6Z 6psE8FLt4uKRTXSLgivKKSkbrHkSoFhE3k0Im7vdh5fiakJhkLEPfiMb5ICDVP3zglCv nbcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=oPiw8R9lVX2s5VG1D89AQOnRTmAa+LUEnOvoCczfDe4=; b=cAhm0ARdEP09dPuLNbizajlDkfM8mo5s5bXyR2ghfr808defIIq9htIaewZ9aRPvrd xo3u56aab+/hGRgdabodXszQdI2+iChxLn8R6b2jcPm6uvgVlm9rpVw3hFtNfCyxYRC4 wqN9B6JFladAFcedeB/fgWgVtFvEHp71855JU9y4Khbhuo4t+Qz2TuZ1g6x9NfWAxswi 8qRiYUtHfJ03nNkXShmCezqbs750VpPO4Vqq6wSxZILcpQviCmJgPB0RMVCc3U7PvAwi uor2VD2sxPOjvxSw/rF7wlAobb1f6XtC2oCEQJ88vMBIxZKqH2G9d6Qz58/hfZ7S2665 QP6w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w19si12235422eju.407.2019.10.14.22.39.17; Mon, 14 Oct 2019 22:39:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728025AbfJODth (ORCPT + 99 others); Mon, 14 Oct 2019 23:49:37 -0400 Received: from out30-54.freemail.mail.aliyun.com ([115.124.30.54]:45072 "EHLO out30-54.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727092AbfJODtg (ORCPT ); Mon, 14 Oct 2019 23:49:36 -0400 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R341e4;CH=green;DM=||false|;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04426;MF=teawaterz@linux.alibaba.com;NM=1;PH=DS;RN=7;SR=0;TI=SMTPD_---0Tf5len0_1571111370; Received: from localhost(mailfrom:teawaterz@linux.alibaba.com fp:SMTPD_---0Tf5len0_1571111370) by smtp.aliyun-inc.com(127.0.0.1); Tue, 15 Oct 2019 11:49:33 +0800 From: Hui Zhu To: konrad.wilk@oracle.com, sjenning@redhat.com, ddstreet@ieee.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org Cc: Hui Zhu , Hui Zhu Subject: [PATCH 2/2] mm, zswap: Support THP Date: Tue, 15 Oct 2019 11:49:09 +0800 Message-Id: <1571111349-5041-2-git-send-email-teawater@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1571111349-5041-1-git-send-email-teawater@gmail.com> References: <1571111349-5041-1-git-send-email-teawater@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This commit let zswap treats THP as continuous normal pages in zswap_frontswap_store. It will store them to a lot of "zswap_entry". These "zswap_entry" will be inserted to "zswap_tree" together. Signed-off-by: Hui Zhu --- mm/zswap.c | 170 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 61 deletions(-) diff --git a/mm/zswap.c b/mm/zswap.c index 46a3223..36aa10d 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -316,11 +316,7 @@ static void zswap_rb_erase(struct rb_root *root, struct zswap_entry *entry) } } -/* - * Carries out the common pattern of freeing and entry's zpool allocation, - * freeing the entry itself, and decrementing the number of stored pages. - */ -static void zswap_free_entry(struct zswap_entry *entry) +static void zswap_free_entry_1(struct zswap_entry *entry) { if (!entry->length) atomic_dec(&zswap_same_filled_pages); @@ -329,6 +325,15 @@ static void zswap_free_entry(struct zswap_entry *entry) zswap_pool_put(entry->pool); } zswap_entry_cache_free(entry); +} + +/* + * Carries out the common pattern of freeing and entry's zpool allocation, + * freeing the entry itself, and decrementing the number of stored pages. + */ +static void zswap_free_entry(struct zswap_entry *entry) +{ + zswap_free_entry_1(entry); atomic_dec(&zswap_stored_pages); zswap_update_total_size(); } @@ -980,15 +985,11 @@ static void zswap_fill_page(void *ptr, unsigned long value) memset_l(page, value, PAGE_SIZE / sizeof(unsigned long)); } -/********************************* -* frontswap hooks -**********************************/ -/* attempts to compress and store an single page */ -static int zswap_frontswap_store(unsigned type, pgoff_t offset, - struct page *page) +static int zswap_frontswap_store_1(unsigned type, pgoff_t offset, + struct page *page, + struct zswap_entry **entry_pointer) { - struct zswap_tree *tree = zswap_trees[type]; - struct zswap_entry *entry, *dupentry; + struct zswap_entry *entry; struct crypto_comp *tfm; int ret; unsigned int hlen, dlen = PAGE_SIZE; @@ -998,36 +999,6 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset, struct zswap_header zhdr = { .swpentry = swp_entry(type, offset) }; gfp_t gfp; - /* THP isn't supported */ - if (PageTransHuge(page)) { - ret = -EINVAL; - goto reject; - } - - if (!zswap_enabled || !tree) { - ret = -ENODEV; - goto reject; - } - - /* reclaim space if needed */ - if (zswap_is_full()) { - zswap_pool_limit_hit++; - if (zswap_shrink()) { - zswap_reject_reclaim_fail++; - ret = -ENOMEM; - goto reject; - } - - /* A second zswap_is_full() check after - * zswap_shrink() to make sure it's now - * under the max_pool_percent - */ - if (zswap_is_full()) { - ret = -ENOMEM; - goto reject; - } - } - /* allocate entry */ entry = zswap_entry_cache_alloc(GFP_KERNEL); if (!entry) { @@ -1035,6 +1006,7 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset, ret = -ENOMEM; goto reject; } + *entry_pointer = entry; if (zswap_same_filled_pages_enabled) { src = kmap_atomic(page); @@ -1044,7 +1016,7 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset, entry->length = 0; entry->value = value; atomic_inc(&zswap_same_filled_pages); - goto insert_entry; + goto out; } kunmap_atomic(src); } @@ -1093,31 +1065,105 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset, entry->handle = handle; entry->length = dlen; -insert_entry: +out: + return 0; + +put_dstmem: + put_cpu_var(zswap_dstmem); + zswap_pool_put(entry->pool); +freepage: + zswap_entry_cache_free(entry); +reject: + return ret; +} + +/********************************* +* frontswap hooks +**********************************/ +/* attempts to compress and store an single page */ +static int zswap_frontswap_store(unsigned type, pgoff_t offset, + struct page *page) +{ + struct zswap_tree *tree = zswap_trees[type]; + struct zswap_entry **entries = NULL, *dupentry; + struct zswap_entry *single_entry[1]; + int ret; + int i, nr; + + if (!zswap_enabled || !tree) { + ret = -ENODEV; + goto reject; + } + + /* reclaim space if needed */ + if (zswap_is_full()) { + zswap_pool_limit_hit++; + if (zswap_shrink()) { + zswap_reject_reclaim_fail++; + ret = -ENOMEM; + goto reject; + } + + /* A second zswap_is_full() check after + * zswap_shrink() to make sure it's now + * under the max_pool_percent + */ + if (zswap_is_full()) { + ret = -ENOMEM; + goto reject; + } + } + + nr = hpage_nr_pages(page); + + if (unlikely(nr > 1)) { + entries = kvmalloc(sizeof(struct zswap_entry *) * nr, + GFP_KERNEL); + if (!entries) { + ret = -ENOMEM; + goto reject; + } + } else + entries = single_entry; + + for (i = 0; i < nr; i++) { + ret = zswap_frontswap_store_1(type, offset + i, page + i, + &entries[i]); + if (ret) + goto freepage; + } + /* map */ spin_lock(&tree->lock); - do { - ret = zswap_rb_insert(&tree->rbroot, entry, &dupentry); - if (ret == -EEXIST) { - zswap_duplicate_entry++; - /* remove from rbtree */ - zswap_rb_erase(&tree->rbroot, dupentry); - zswap_entry_put(tree, dupentry); - } - } while (ret == -EEXIST); + for (i = 0; i < nr; i++) { + do { + ret = zswap_rb_insert(&tree->rbroot, entries[i], + &dupentry); + if (ret == -EEXIST) { + zswap_duplicate_entry++; + /* remove from rbtree */ + zswap_rb_erase(&tree->rbroot, dupentry); + zswap_entry_put(tree, dupentry); + } + } while (ret == -EEXIST); + } spin_unlock(&tree->lock); /* update stats */ - atomic_inc(&zswap_stored_pages); + atomic_add(nr, &zswap_stored_pages); zswap_update_total_size(); - return 0; - -put_dstmem: - put_cpu_var(zswap_dstmem); - zswap_pool_put(entry->pool); + ret = 0; freepage: - zswap_entry_cache_free(entry); + if (unlikely(nr > 1)) { + if (ret) { + int j; + + for (j = 0; j < i; j++) + zswap_free_entry_1(entries[j]); + } + kvfree(entries); + } reject: return ret; } @@ -1136,6 +1182,8 @@ static int zswap_frontswap_load(unsigned type, pgoff_t offset, unsigned int dlen; int ret; + BUG_ON(PageTransHuge(page)); + /* find */ spin_lock(&tree->lock); entry = zswap_entry_find_get(&tree->rbroot, offset); -- 2.7.4