Received: by 2002:ab2:3350:0:b0:1f4:6588:b3a7 with SMTP id o16csp834451lqe; Sun, 7 Apr 2024 06:13:46 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXl6OIMvoDqSr6HHydy8T9HOVULMSAkJ46DgUJlKHexBM3QYF9MNktB1855v3oru3x82KRm8IJgpDpEVR07UJ6LcaruYI/p6XS4ijqkNQ== X-Google-Smtp-Source: AGHT+IHMpARSL3ewG1dPJZCgFYHf9rtiWsTbWmp9/ynLRdhHcrg34FI8SHPfhZpYE6DrK7b9hvTc X-Received: by 2002:a50:9f4b:0:b0:56d:ed86:c6f4 with SMTP id b69-20020a509f4b000000b0056ded86c6f4mr5181572edf.11.1712495626042; Sun, 07 Apr 2024 06:13:46 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1712495626; cv=pass; d=google.com; s=arc-20160816; b=th3APUWgfuvX155cmqi8hhOqmk28LSRwAzpq9H36qfR/NikV2DBV/zr326+q1v5NkY dyWezUydbCkE3iW85ZYh+EEcmHYPn9upvybjcfdwlTILbsfA6iTTYBtYhkc/7TpzeF6S 6g1HMGW7Wu6GO3FPKws5Ja7ZjXasVkyO1PkPr9s2ZiPaTKWFgsYuHzu1p7fKblWya4sg XtBClltnIZ5RZ9uZSXrUFUdVxTMS7B8ylbsNzQ572DuBi9CXqIn8YbwC0d8bayIX0JYs YZP2tO5iVxNJjGkPmH/h0zLiZDZR9WyQQvkvv+neDpbnVMGwKiIiHZIOo0CGaqk8trIj PQlw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=+Z1sNexvcfsuU49xW1KJHXwKoxZNEqa6JavsGGMquZ0=; fh=inFsbniLgByi1PvLyextVSu1v80SuS19K1zpiR/HfaU=; b=vI/PjXMcxcNM2RXjHo0oZeFeA/d9BSDFMb0tYYtybYOAktF5aS83gjWJScj8+Fvh+6 ZO1RKwrs3BEu+ZlHWg5GieTzJ0uA06RK69qSGyWqCsoZkIyvKS386OAsbXWazHgbX8tK ZxeCKBCBTyqzn5scwJAak6d+udnd1jvY1Y2yulJyRoY8O7RN8+zal7UeUH+vtDoXjwJX eD5FA6HEZXt1hcFwXB1PiSxuxNvtxagAqSkLirupKAMbfw+rmlX3k+H+Xoj8u9F0plm8 P6Hsb1w9dnu5HB1nhkpCeJLbMl9GDzSK70YRoSZozvS9VxL2bu+/h59CT36l2rOQhPjY X8cw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=huawei.com dmarc=pass fromdomain=huawei.com); spf=pass (google.com: domain of linux-kernel+bounces-134404-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-134404-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Return-Path: Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id n13-20020a05640205cd00b0056dfa65446fsi2712791edx.362.2024.04.07.06.13.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Apr 2024 06:13:46 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-134404-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=huawei.com dmarc=pass fromdomain=huawei.com); spf=pass (google.com: domain of linux-kernel+bounces-134404-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-134404-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 994661F21724 for ; Sun, 7 Apr 2024 13:13:45 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4CAA538DE8; Sun, 7 Apr 2024 13:11:19 +0000 (UTC) Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9F9E3839D; Sun, 7 Apr 2024 13:11:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712495478; cv=none; b=EJ9kgJww2rc+kMIVggfcmPrRtSU+oVuGnMPcYgTQYP0pYZ+6NcJ4cNj3/94i6v5QJDdTWBLqFRr4RqRFEF5FH88PTMnGLjg2zY9RLGn1LWsMLz+2jvmF+KJDYsWhwTc2S8sDJxyvrkeVU+clyhT64Wvs25pK3evumCu2poqAS/4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712495478; c=relaxed/simple; bh=WCE8RXU0X7aMBPY//3QOWVCfbjWVSvTLXrqCWiLgSow=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DnEUoNbffHpbKQEAb1elQ9RWPwngzGb/b26QaLSMNVG4E1B24vvR09rZ0qX9hTFE0eK3/G0D5zT/fkQ4rKK1oeJVZEk/vGuA4hGjdeRgJTaQrkv3IRt71RyOkpFq3Pkdv6CQHiuPuKHVUELjdZusoIlHFNtwMu6dD2Wkmzd51bA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.17]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4VCCJR5XMdz1GCqF; Sun, 7 Apr 2024 21:10:31 +0800 (CST) Received: from dggpemm500005.china.huawei.com (unknown [7.185.36.74]) by mail.maildlp.com (Postfix) with ESMTPS id B1C0E1A0188; Sun, 7 Apr 2024 21:11:14 +0800 (CST) Received: from localhost.localdomain (10.69.192.56) by dggpemm500005.china.huawei.com (7.185.36.74) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.35; Sun, 7 Apr 2024 21:11:14 +0800 From: Yunsheng Lin To: , , CC: , , Yunsheng Lin , Andrew Morton , Subject: [PATCH net-next v1 07/12] mm: page_frag: reuse existing bit field of 'va' for pagecnt_bias Date: Sun, 7 Apr 2024 21:08:44 +0800 Message-ID: <20240407130850.19625-8-linyunsheng@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20240407130850.19625-1-linyunsheng@huawei.com> References: <20240407130850.19625-1-linyunsheng@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To dggpemm500005.china.huawei.com (7.185.36.74) As alignment of 'va' is always aligned with the order of the page allocated, we can reuse the LSB bits for the pagecount bias, and remove the orginal space needed by 'pagecnt_bias'. Also limit the 'fragsz' to be at least the size of 'usigned int' to match the limited pagecnt_bias. Signed-off-by: Yunsheng Lin --- include/linux/page_frag_cache.h | 20 +++++++---- mm/page_frag_cache.c | 63 +++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/include/linux/page_frag_cache.h b/include/linux/page_frag_cache.h index 40a7d6da9ef0..a97a1ac017d6 100644 --- a/include/linux/page_frag_cache.h +++ b/include/linux/page_frag_cache.h @@ -9,7 +9,18 @@ #define PAGE_FRAG_CACHE_MAX_ORDER get_order(PAGE_FRAG_CACHE_MAX_SIZE) struct page_frag_cache { - void *va; + union { + void *va; + /* we maintain a pagecount bias, so that we dont dirty cache + * line containing page->_refcount every time we allocate a + * fragment. As 'va' is always aligned with the order of the + * page allocated, we can reuse the LSB bits for the pagecount + * bias, and its bit width happens to be indicated by the + * 'size_mask' below. + */ + unsigned long pagecnt_bias; + + }; #if (PAGE_SIZE < PAGE_FRAG_CACHE_MAX_SIZE) __u16 offset; __u16 size_mask:15; @@ -18,10 +29,6 @@ struct page_frag_cache { __u32 offset:31; __u32 pfmemalloc:1; #endif - /* we maintain a pagecount bias, so that we dont dirty cache line - * containing page->_refcount every time we allocate a fragment. - */ - unsigned int pagecnt_bias; }; static inline void page_frag_cache_init(struct page_frag_cache *nc) @@ -56,7 +63,8 @@ static inline void *page_frag_alloc_va_align(struct page_frag_cache *nc, gfp_t gfp_mask, unsigned int align) { - WARN_ON_ONCE(!is_power_of_2(align) || align >= PAGE_SIZE); + WARN_ON_ONCE(!is_power_of_2(align) || align >= PAGE_SIZE || + fragsz < sizeof(unsigned int)); return __page_frag_alloc_va_align(nc, fragsz, gfp_mask, align); } diff --git a/mm/page_frag_cache.c b/mm/page_frag_cache.c index a02e57a439f0..ae1393d0619a 100644 --- a/mm/page_frag_cache.c +++ b/mm/page_frag_cache.c @@ -18,8 +18,8 @@ #include #include "internal.h" -static struct page *__page_frag_cache_refill(struct page_frag_cache *nc, - gfp_t gfp_mask) +static bool __page_frag_cache_refill(struct page_frag_cache *nc, + gfp_t gfp_mask) { struct page *page = NULL; gfp_t gfp = gfp_mask; @@ -35,9 +35,26 @@ static struct page *__page_frag_cache_refill(struct page_frag_cache *nc, if (unlikely(!page)) page = alloc_pages_node(NUMA_NO_NODE, gfp, 0); - nc->va = page ? page_address(page) : NULL; + if (unlikely(!page)) { + nc->va = NULL; + return false; + } + + nc->va = page_address(page); - return page; +#if (PAGE_SIZE < PAGE_FRAG_CACHE_MAX_SIZE) + VM_BUG_ON(nc->pagecnt_bias & nc->size_mask); + page_ref_add(page, nc->size_mask - 1); + nc->pagecnt_bias |= nc->size_mask; +#else + VM_BUG_ON(nc->pagecnt_bias & (PAGE_SIZE - 1)); + page_ref_add(page, PAGE_SIZE - 2); + nc->pagecnt_bias |= (PAGE_SIZE - 1); +#endif + + nc->pfmemalloc = page_is_pfmemalloc(page); + nc->offset = 0; + return true; } void page_frag_cache_drain(struct page_frag_cache *nc) @@ -67,38 +84,31 @@ EXPORT_SYMBOL(__page_frag_cache_drain); void *page_frag_alloc_va(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask) { - unsigned int size, offset; + unsigned long size_mask; + unsigned int offset; struct page *page; + void *va; if (unlikely(!nc->va)) { refill: - page = __page_frag_cache_refill(nc, gfp_mask); - if (!page) + if (!__page_frag_cache_refill(nc, gfp_mask)) return NULL; - - /* Even if we own the page, we do not use atomic_set(). - * This would break get_page_unless_zero() users. - */ - page_ref_add(page, PAGE_FRAG_CACHE_MAX_SIZE); - - /* reset page count bias and offset to start of new frag */ - nc->pfmemalloc = page_is_pfmemalloc(page); - nc->pagecnt_bias = PAGE_FRAG_CACHE_MAX_SIZE + 1; - nc->offset = 0; } #if (PAGE_SIZE < PAGE_FRAG_CACHE_MAX_SIZE) /* if size can vary use size else just use PAGE_SIZE */ - size = nc->size_mask + 1; + size_mask = nc->size_mask; #else - size = PAGE_SIZE; + size_mask = PAGE_SIZE - 1; #endif + va = (void *)((unsigned long)nc->va & ~size_mask); offset = nc->offset; - if (unlikely(offset + fragsz > size)) { - page = virt_to_page(nc->va); - if (!page_ref_sub_and_test(page, nc->pagecnt_bias)) + if (unlikely(offset + fragsz > (size_mask + 1))) { + page = virt_to_page(va); + + if (!page_ref_sub_and_test(page, nc->pagecnt_bias & size_mask)) goto refill; if (unlikely(nc->pfmemalloc)) { @@ -107,12 +117,11 @@ void *page_frag_alloc_va(struct page_frag_cache *nc, unsigned int fragsz, } /* OK, page count is 0, we can safely set it */ - set_page_count(page, PAGE_FRAG_CACHE_MAX_SIZE + 1); + set_page_count(page, size_mask); + nc->pagecnt_bias |= size_mask; - /* reset page count bias and offset to start of new frag */ - nc->pagecnt_bias = PAGE_FRAG_CACHE_MAX_SIZE + 1; offset = 0; - if (unlikely(fragsz > size)) { + if (unlikely(fragsz > (size_mask + 1))) { /* * The caller is trying to allocate a fragment * with fragsz > PAGE_SIZE but the cache isn't big @@ -129,7 +138,7 @@ void *page_frag_alloc_va(struct page_frag_cache *nc, unsigned int fragsz, nc->pagecnt_bias--; nc->offset = offset + fragsz; - return nc->va + offset; + return va + offset; } EXPORT_SYMBOL(page_frag_alloc_va); -- 2.33.0