Received: by 10.223.185.116 with SMTP id b49csp837320wrg; Wed, 21 Feb 2018 07:43:16 -0800 (PST) X-Google-Smtp-Source: AH8x227I3PwIzC4ux36VT6jOTuWXoPmUei4wFzKDFVHYfFo7/JT01HTMcXrWRPVut/ylCdvKmem4 X-Received: by 10.98.214.218 with SMTP id a87mr3740714pfl.146.1519227795987; Wed, 21 Feb 2018 07:43:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519227795; cv=none; d=google.com; s=arc-20160816; b=Ce1BaXCAs0/ma92ZqEb768Y5ck5QwyVoyfC1QHI37VwCEyOhztYV6I28OTyUvTKAxa FCAjvjoSuwueSz6wc0VZj2nZtT3SHyQ8T1hZuQGvEh+r6AbrqVGgy1mrP5O7Jm1Q7X5O jgDoF6/ChakZYevKsr48wdRwGBahHbtlN8fFtIYIHsKupQ8GPMjjFOauRtz/tG/u+jkU 2UF7ifEPuzvcSN9FwGuEKHwM+f9wnIYp0QJT+oJo7nEybeQcLKOXgIXKqcetuXCUnhwQ X9HYz24QQu/40VrLSCOgfxSu6qaOC7PgANaXFwke+EIAlRfJ34VdDwSXsNztPHQyKKRF aJgg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=h4WVFCMwpEwBRjec25LNyqRTOY63os/e1vFx0cw/Wzo=; b=VGYPuZuSONSnZvtXzeVF7TNTIigSf3hoXfxQ5t5MyYF0mEAvsnMZekSzG5Cv4KxBlO G+EpET5UuNndozdrUr1q43UeMe2aePEhBtRqHJZh2pY+tWb05gAdbXqUStsEbZ9ywk2s Uy5/pwhjPdFIX3xMynXZxnzxDmiN727CKqi4CAjGD2zNdxuBbHa5EklFYmHf1YxGdJjU 4d/0tFuIPGR5bU618vnY1A2Fru9Xzs7quDg15o74BU64va490iLfquXAfkVqgLfmDvvF hDaP4CD2Z6r2qL4RF/diPMq5oole8z0DVWww4R9XwWcDFKBRw8kiW+J+/kLIRSo3sjnZ eU1Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@infradead.org header.s=bombadil.20170209 header.b=jMIiTcbV; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j7si188497pgp.293.2018.02.21.07.43.00; Wed, 21 Feb 2018 07:43:15 -0800 (PST) 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; dkim=fail header.i=@infradead.org header.s=bombadil.20170209 header.b=jMIiTcbV; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S938270AbeBUPmT (ORCPT + 99 others); Wed, 21 Feb 2018 10:42:19 -0500 Received: from bombadil.infradead.org ([198.137.202.133]:40002 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937089AbeBUPmR (ORCPT ); Wed, 21 Feb 2018 10:42:17 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=In-Reply-To:Content-Type:MIME-Version :References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=h4WVFCMwpEwBRjec25LNyqRTOY63os/e1vFx0cw/Wzo=; b=jMIiTcbVKU8YIynX9iscazYDb /enKd9TFSG5kZwjHF/LmBT4+IfTgKkU5BUmGUM9z04uXsaPqHRSZkCmAJH2mUxSN+ODg7F5h5Eho6 +WEGAyCEcpGrq7K7AVBGvJJquzQ3zXFrOIDB/NO5vEXRHhBmnTeMVTZQbUpWISlqwWr78GfxO9BXQ GiMkX5scjj9CSnajg4wpoQQWjlqK6bU1Djazs3KApzGGMUEib3yWmcej3Vexo6T9K2rEtbK/km8rF UMbMCe/zJTujScCSBzKghLQlZoFWaOP2e7zsSwYIkXgLg4DpG+JEJchfjaopD/GsjNExjJc3h+g/T Y43iyAVew==; Received: from willy by bombadil.infradead.org with local (Exim 4.89 #1 (Red Hat Linux)) id 1eoWX9-0000rC-8C; Wed, 21 Feb 2018 15:42:15 +0000 Date: Wed, 21 Feb 2018 07:42:14 -0800 From: Matthew Wilcox To: Konstantin Khlebnikov Cc: Dave Hansen , linux-kernel@vger.kernel.org, Christoph Hellwig , linux-mm@kvack.org, Andy Lutomirski , Andrew Morton , "Kirill A. Shutemov" Subject: Use higher-order pages in vmalloc Message-ID: <20180221154214.GA4167@bombadil.infradead.org> References: <151670492223.658225.4605377710524021456.stgit@buzz> <151670493255.658225.2881484505285363395.stgit@buzz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <151670493255.658225.2881484505285363395.stgit@buzz> User-Agent: Mutt/1.9.2 (2017-12-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Jan 23, 2018 at 01:55:32PM +0300, Konstantin Khlebnikov wrote: > Virtually mapped stack have two bonuses: it eats order-0 pages and > adds guard page at the end. But it slightly slower if system have > plenty free high-order pages. > > This patch adds option to use virtually bapped stack as fallback for > atomic allocation of traditional high-order page. This prompted me to write a patch I've been meaning to do for a while, allocating large pages if they're available to satisfy vmalloc. I thought it would save on touching multiple struct pages, but it turns out that the checking code we currently have in the free_pages path requires you to have initialised all of the tail pages (maybe we can make that code conditional ...) It does save the buddy allocator the trouble of breaking down higher-order pages into order-0 pages, only to allocate them again immediately. (um, i seem to have broken the patch while cleaning it up for submission. since it probably won't be accepted anyway, I'm not going to try to debug it) diff --git a/kernel/fork.c b/kernel/fork.c index be8aa5b98666..2bc01071b6ae 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -319,12 +319,12 @@ static void account_kernel_stack(struct task_struct *tsk, int account) if (vm) { int i; - BUG_ON(vm->nr_pages != THREAD_SIZE / PAGE_SIZE); - - for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++) { - mod_zone_page_state(page_zone(vm->pages[i]), + for (i = 0; i < vm->nr_pages; i++) { + struct page *page = vm->pages[i]; + unsigned int size = PAGE_SIZE << compound_order(page); + mod_zone_page_state(page_zone(page), NR_KERNEL_STACK_KB, - PAGE_SIZE / 1024 * account); + size / 1024 * account); } /* All stack pages belong to the same memcg. */ diff --git a/mm/vmalloc.c b/mm/vmalloc.c index b728c98f49cd..4bfc29b21bc1 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -134,6 +134,7 @@ static void vunmap_page_range(unsigned long addr, unsigned long end) static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, pgprot_t prot, struct page **pages, int *nr) { + unsigned int i; pte_t *pte; /* @@ -151,9 +152,13 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, return -EBUSY; if (WARN_ON(!page)) return -ENOMEM; - set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); + for (i = 0; i < (1UL << compound_order(page)); i++) { + set_pte_at(&init_mm, addr, pte++, + mk_pte(page + i, prot)); + addr += PAGE_SIZE; + } (*nr)++; - } while (pte++, addr += PAGE_SIZE, addr != end); + } while (addr != end); return 0; } @@ -1530,14 +1535,14 @@ static void __vunmap(const void *addr, int deallocate_pages) debug_check_no_obj_freed(addr, get_vm_area_size(area)); if (deallocate_pages) { - int i; + unsigned int i; for (i = 0; i < area->nr_pages; i++) { struct page *page = area->pages[i]; BUG_ON(!page); __ClearPageVmalloc(page); - __free_pages(page, 0); + __free_pages(page, compound_order(page)); } kvfree(area->pages); @@ -1696,11 +1701,20 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, for (i = 0; i < area->nr_pages; i++) { struct page *page; - - if (node == NUMA_NO_NODE) - page = alloc_page(alloc_mask); - else - page = alloc_pages_node(node, alloc_mask, 0); + unsigned int j = ilog2(area->nr_pages - i) + 1; + + do { + j--; + if (node == NUMA_NO_NODE) + page = alloc_pages(alloc_mask, j); + else + page = alloc_pages_node(node, alloc_mask, j); + } while (!page && j); + + if (j) { + area->nr_pages -= (1UL << j) - 1; + prep_compound_page(page, j); + } if (unlikely(!page)) { /* Successfully allocated i pages, free them in __vunmap() */ @@ -1719,8 +1733,8 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, fail: warn_alloc(gfp_mask, NULL, - "vmalloc: allocation failure, allocated %ld of %ld bytes", - (area->nr_pages*PAGE_SIZE), area->size); + "vmalloc: allocation failure, allocated %ld of %ld bytes", + (nr_pages * PAGE_SIZE), get_vm_area_size(area)); vfree(area->addr); return NULL; }