From patchwork Wed Jul 17 22:24:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 13735867 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id A029DC3DA5D for ; Wed, 17 Jul 2024 22:25:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2427B6B00A8; Wed, 17 Jul 2024 18:25:34 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 1F2A66B00B6; Wed, 17 Jul 2024 18:25:34 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0932D6B00B8; Wed, 17 Jul 2024 18:25:34 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id DEC606B00B6 for ; Wed, 17 Jul 2024 18:25:33 -0400 (EDT) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 5E9D780CA2 for ; Wed, 17 Jul 2024 22:25:33 +0000 (UTC) X-FDA: 82350677346.18.146BA86 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by imf13.hostedemail.com (Postfix) with ESMTP id 23F0720028 for ; Wed, 17 Jul 2024 22:25:30 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=mMdu6Px9; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf13.hostedemail.com: domain of dakr@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=dakr@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1721255086; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=+tmN+7huRBZwtjtCb2iu946Hq1PJVgyuDl+Alo90jZA=; b=PoYfVC7xDvBVAgDfX6UkM2ISJx7p/twSnmJG3h90XA4m15LobE0q9RvO9zY7eB8bJsH/6f vXidAWdEb1QT6v4rpn9Mo56fiK6+VfUwDXG4qLqLMxD+1U62ygPjlsCfL3a9NUQaLCc335 pXkpvjGHSc2Su/5rfenUSlMGorJp7IU= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1721255086; a=rsa-sha256; cv=none; b=w37z4oR+mt7KXXlnu59gbb1P7i3KiPJvv0A00DUTVlwlxHqF0zyT9lxQbb8qmWxJFBJB4I gMqafjkHWJqqY5loDiXC2L+dsgWF9yIZqcsoiwghae5QjR/QqsWOihTtM5MZkX8g6wPN6Y Jjl8ITbYNTqM1X61H9mlaj9j7CxLpR4= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=mMdu6Px9; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf13.hostedemail.com: domain of dakr@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=dakr@kernel.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id C14AACE1874; Wed, 17 Jul 2024 22:25:26 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CDF41C2BD10; Wed, 17 Jul 2024 22:25:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1721255126; bh=tXaAq6dQU0DYi9kqEOhCwnRJo8WINgtfsOO12DLQp/M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mMdu6Px9696h6a8IIIg+uuDYZ+vEQr1pGnPPwtF0lQLYRAYhTXlLJOoW0DYmJJvvN moaMm+DS2g/0CQ2kGqQ2NXanXuFNoEzPrdI76Xm71x/mBW14OxbdVJFcps8FNwPSCU zLovJ+77wkGbLSB7G+Myp51+g3b5DsDmngzwo2kIy8hI3xZlGlx7G3sac3A0yGz64x r+DvvOm6Jk/Q0azeEiCwfBil5E84SuVBqFI9/cVeDjvYBMCkqajYnzUH5GpqoHHNVX tIo7fYDQzBPnaE/KYK6mSQAvA8yqYx0pGFcsHg8U/xSFIvrrGTPBZpA6Qp4OsmB0qR RECBeGKGKEi5Q== From: Danilo Krummrich To: cl@linux.com, penberg@kernel.org, rientjes@google.com, iamjoonsoo.kim@lge.com, akpm@linux-foundation.org, vbabka@suse.cz, roman.gushchin@linux.dev, 42.hyeyoo@gmail.com, urezki@gmail.com, hch@infradead.org, kees@kernel.org, ojeda@kernel.org, wedsonaf@gmail.com, mhocko@kernel.org, mpe@ellerman.id.au, chandan.babu@oracle.com, christian.koenig@amd.com Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH 1/2] mm: vmalloc: implement vrealloc() Date: Thu, 18 Jul 2024 00:24:01 +0200 Message-ID: <20240717222427.2211-2-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240717222427.2211-1-dakr@kernel.org> References: <20240717222427.2211-1-dakr@kernel.org> MIME-Version: 1.0 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 23F0720028 X-Stat-Signature: 5ixo5e53jzp3mjm88bo7jzz63fy7ypd3 X-Rspam-User: X-HE-Tag: 1721255130-561150 X-HE-Meta: U2FsdGVkX193hHMp/v5axF9CiAU/ZLIFIML5AWlDoWA/eskeiW308wutZwH76T37ce3+p8CUZKXOaSdrIfrsxxkiLpj0V7mCRqM09bNa+wSFX4Hr7xSjLAMoH5Kne3PuARV6ykFzjD6nMZs4FrZQBDfQtMJhsS3m2RQEep2TcwJibimPETnIS0+MMseMZw+zvMIDz36rzRIBNtxOjByYr/4sPY7K+TmpUJ6UoF+ROJfuhxDfrJlBg5+FjIg0Trd1mJ098X2L4cL47aGaUzYC++/txNzYQgyHzN3OCmvscqDdqai6mKEAdIWDorXyn3E7N9PqRWASateXP3BLAHXA4edpPrVeisJKODetrWuT6vcgCAPVU0m57MSP8GeKhqZxnboqQLFvqLGFxVyP+3LW6Dr9LbAaSTY/HmVG85DI/Il5lYZG5Zk3r6YbQn4XNpufUBFhxZtU0yLrov+VdjFWx1R3U/KcAvVMbi0aL3JqMnKVWmNUHpRazDYsW3bEjJZIpBfKdMb8vhZYjpm8tIFvwDFB0Pv2qFTfQzONlUhsm8cTKGoG5wUh6V+jRRvMtxBVAHNvVRz8X6xb9+FRwN1qkI9g7Awt0dEpKrS3tu46dHgF/Ad0UJ3Rnpno+0YgKkXea1B09gMtFNAZLaDHM5miefW/mVBrkyLGbNCarcn/FsnQ1twhdZ4SuIvsCI6mTELhC+IGxOR+HkYtq9zuIAdzdYsaDKMnQfxnh/PTLrifgZO9nLU2YdGrYfUxbk812KcHYrrz6fcLRhffT6DJkABHMhggzYXu1nXWDVHhVZzlX3373eGorYb+dPf1y3Pibvr/zJnzpVmSVz2u4BRd1hUchYn78NTrRYc65rBa+2kjMtwp/nARzAnyHyw3yr+3H0Nj/bmd4ItmI0tSqaFL7jTpljAxBywEIhkF7TlbaH9Z2Ybu1S+/OxqITIuonX5ewh3FcIX72hmb9zvIzaR+vkx O6FCqdb0 uR1fcKoIOyDYT0o2mlOBZtPhiHlSMH5EEDwNgH9z2BeSexXANqwhJCepkeh3j96qStK1j+hNlPHwY38Yd71vRmMz7Uo/fTKRVKuI/N5rbCa9Gn7b+DX55uf2QcFgilYv+G9/XgBPvDULS4ZvVoEr5ntndEBhlx63eyx19B+RZEXF2EFAN/cDEwUtvNvp2OQ+mKEjwKaZ91rOx65m00KhIse2+2ha8LDcTGvC434XfR4pgEBgIocdHzArqTxFhvAA7ncOOBartauLhWHJB+H96ms19JQdWnHEt5TeBe9EwsCTnLKOwR8bI0JIoFA== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Implement vrealloc() analogous to krealloc(). Currently, krealloc() requires the caller to pass the size of the previous memory allocation, which, instead, should be self-contained. We attempt to fix this in a subsequent patch which, in order to do so, requires vrealloc(). Besides that, we need realloc() functions for kernel allocators in Rust too. With `Vec` or `KVec` respectively, potentially growing (and shrinking) data structures are rather common. Signed-off-by: Danilo Krummrich --- include/linux/vmalloc.h | 4 +++ mm/vmalloc.c | 58 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index e4a631ec430b..9ff0a8e5c323 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -189,6 +189,10 @@ extern void *__vcalloc_noprof(size_t n, size_t size, gfp_t flags) __alloc_size(1 extern void *vcalloc_noprof(size_t n, size_t size) __alloc_size(1, 2); #define vcalloc(...) alloc_hooks(vcalloc_noprof(__VA_ARGS__)) +extern void * __must_check vrealloc_noprof(const void *p, size_t size, + gfp_t flags) __realloc_size(2); +#define vrealloc(...) alloc_hooks(vrealloc_noprof(__VA_ARGS__)) + extern void vfree(const void *addr); extern void vfree_atomic(const void *addr); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index e34ea860153f..4ec949ac9d9d 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -4036,6 +4036,64 @@ void *vzalloc_node_noprof(unsigned long size, int node) } EXPORT_SYMBOL(vzalloc_node_noprof); +/** + * vrealloc - reallocate virtually contiguous memory; contents remain unchanged + * @p: object to reallocate memory for + * @size: the size to reallocate + * @flags: the flags for the page level allocator + * + * The contents of the object pointed to are preserved up to the lesser of the + * new and old size (__GFP_ZERO flag is effectively ignored). + * + * If @p is %NULL, vrealloc() behaves exactly like vmalloc(). If @size is 0 and + * @p is not a %NULL pointer, the object pointed to is freed. + * + * Return: pointer to the allocated memory; %NULL if @size is zero or in case of + * failure + */ +void *vrealloc_noprof(const void *p, size_t size, gfp_t flags) +{ + size_t old_size = 0; + void *n; + + if (!size) { + vfree(p); + return NULL; + } + + if (p) { + struct vm_struct *vm; + + vm = find_vm_area(p); + if (unlikely(!vm)) { + WARN(1, "Trying to vrealloc() nonexistent vm area (%p)\n", p); + return NULL; + } + + old_size = get_vm_area_size(vm); + } + + if (size <= old_size) { + /* TODO: Can we optimize and shrink the allocation? What would + * be a good metric for when to shrink the vm_area? + */ + return (void *)p; + } + + /* TODO: Can we optimize and extend the existing allocation if we have + * enough contiguous space left in the virtual address space? + */ + n = __vmalloc_noprof(size, flags); + + if (p) { + memcpy(n, p, old_size); + vfree(p); + } + + return n; +} +EXPORT_SYMBOL(vrealloc_noprof); + #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32) #define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL) #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA) From patchwork Wed Jul 17 22:24:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 13735868 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53087C3DA60 for ; Wed, 17 Jul 2024 22:25:38 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id C07BB6B00B8; Wed, 17 Jul 2024 18:25:37 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id BB8446B00B9; Wed, 17 Jul 2024 18:25:37 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A31716B00BA; Wed, 17 Jul 2024 18:25:37 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 7FFA56B00B8 for ; Wed, 17 Jul 2024 18:25:37 -0400 (EDT) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 2CEC5C17A8 for ; Wed, 17 Jul 2024 22:25:37 +0000 (UTC) X-FDA: 82350677514.24.BC97C90 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf30.hostedemail.com (Postfix) with ESMTP id 7F93C80003 for ; Wed, 17 Jul 2024 22:25:35 +0000 (UTC) Authentication-Results: imf30.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=TU1wOqp3; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf30.hostedemail.com: domain of dakr@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=dakr@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1721255105; a=rsa-sha256; cv=none; b=GFgWuZ1mrZVN+KGa6IMKszu7nCk4+VuMk8eW7xWkcgjsLpgpSxxwj4wuI4dO6VydZLQIY0 uv7w8A8NDNFz2f6R+OLwCKD8JiDfpAkzmD3rRkGXWOCQgDu0RXWginc9BEYWbs55z4FZXc 9xbvr7w3434oP8dQZzL1mRnm+yd1CLE= ARC-Authentication-Results: i=1; imf30.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=TU1wOqp3; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf30.hostedemail.com: domain of dakr@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=dakr@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1721255105; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=YSmLNUydjiArX5AG2B5sL3zRwb+f8Q83M/dxoFKB+mI=; b=ZxsQcYLlvuVs/bA7JnzXpSSvQCEQHuNc+YJXx0jbAb+Z3xkq0PxOBpuBHsSroZgz6y/rT0 +GoWwYmqmL6peWrhd1oqdYM67k0B4Q/xjitSZ3NpNBSct42YAk3Gq6v77r1biVTp48Wqsw 9EhAo/cwcsHmuCo45OIPoWXhI3uDMu8= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 9A58361759; Wed, 17 Jul 2024 22:25:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 26296C2BD10; Wed, 17 Jul 2024 22:25:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1721255134; bh=q6Wwch18E7w/rj6z/NtXtCgXxoq1cCuw2p/00HKzoug=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TU1wOqp3HqZeeURDJIDlL2o2KRjuK80l5lZxxJkdvvG3NwNrd7Bfoff7B0aGFzSUO E2PYgrbgVop0vwAH1xUIZSzOwQUQXuJcOkQ2e0qnGu880I6GQa2q0JK21PlRuHiMYA bOnJfK6tIytukZMFLd9eemS8pkTxH/B11b1tVA4VFj1q0VCg26IbJaXve/ZF+5gN/J 8px0llDgAw7BQZa83S470IIiY4NJcGbTxJeTnDT8EqpKn0I7kxwUJZLihx5V5/z9ld ydzMi1RLJgJKO3gEZ4pE3ZbtysErMUiU0/ixJ7WnRr5VLOtJ1pXmrqn5bzaafI3LCe jlP/5Uc8Ghevg== From: Danilo Krummrich To: cl@linux.com, penberg@kernel.org, rientjes@google.com, iamjoonsoo.kim@lge.com, akpm@linux-foundation.org, vbabka@suse.cz, roman.gushchin@linux.dev, 42.hyeyoo@gmail.com, urezki@gmail.com, hch@infradead.org, kees@kernel.org, ojeda@kernel.org, wedsonaf@gmail.com, mhocko@kernel.org, mpe@ellerman.id.au, chandan.babu@oracle.com, christian.koenig@amd.com Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH 2/2] mm: kvmalloc: align kvrealloc() with krealloc() Date: Thu, 18 Jul 2024 00:24:02 +0200 Message-ID: <20240717222427.2211-3-dakr@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240717222427.2211-1-dakr@kernel.org> References: <20240717222427.2211-1-dakr@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 7F93C80003 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: uirefe9chox448i3urdw16pmfosy494m X-HE-Tag: 1721255135-45026 X-HE-Meta: U2FsdGVkX1/Da0yN3udAnTOF3XuDYzATuzRfUaskK/ocKVRgl5p0v0TjwjAE5PT3jV2FlwAhiBReX/6nlc4AYReSe3I82EYO/qShg+nitclTDQtI9wA5BSb64UzC5CrpArXyN7eYzx/5ox7QiD7KFgq5bmyoA+WbTi3ANT01l+J8k2V5NeKqckxTuXlVB7M/ClmIfBU2z3IKIgwOxUEBTzRzAHZ2juyZXOS+WcGh+X6i2wB9UH4AzOd5aKe/KqOst0QIshFYVIftQJkW2UcU+Zmt0galrXIV4Th0xZq2BiRqXOi7HSVvLpXNfSMuufEvjg29BgSEcdPm3b6jo186MNnnWr+DT7Sff760hsiIdyxNg/laOqDX9V4qpJvE0KOCo0m6MYXVda1B2qmNtCZNy+AD0zBSlO+d1edv/xJQs25f//G2jz7T5ogWwaOtAogNqJb+f3uOAOaRt9EIYRS3YmKTCSA0gJTC1/Jh3jKGZUlVcnLIOhE9srL9QzXiwj9DF3Ebn2ZVdV4dEJS0FbrNqDukgAlF34cdCM53/Z2rVMn/c1/WMNXsq2H7KQ9b45QnnNtGsIj0AX98e1kKN7HwPhwtkxM29UPaTDKcNw4D4I0ovRcG3onaaWYPI7Fbv03IS894P2t8OgIq6tkzWpnaaLVHE5/WleM8D0/q1R7Vi2zERUYXztNH2tgv8ITUmA3gEkrJ6VcU/PRoogVhejPhUOFJllC69qKfP2LsIn1Ht3DRrLX7nXdAOFOXK1tTmvEFM3XHPiSSdFORG27DtmBssUzEM1FkF3Quu6ZqU8q8eHUnlxsRCWsUNq1IRH7q9ime575l2cFEec2RfZaKVSD1z4Do0eNPJ5T5MM3X/iZ/1B/HOnXvlW7YniFIChV3vCV25Lvchp+Nh5reosy1GNZ/1vVeqHL/2gas/IqbHJh1IX5UuKPz1BKaV/49TE/2iuh73bXr2V/hDwNB5Y9YxF0 FuonpnQz RQzLSro2lwMgZfbD6SJstk7oa69p26t93S9KQfJwUto9C9YWZzr5tWqY+MXjuMCT5XZUCq0MgYoTOuWCib96I3Q1ntRJF56S+iZrhwNk4/splLU8y8q+8D1SEGVJTxBqlDhqIxuTHe7MSWqVfHxUhT9z51bv1ynA8gbZn2iSSamTil1DRgwcnvQFDQ2twQD1TKNNHTn2TjNlS2mCS7Hawff37YwqKD4B6wxEKe+2gJAfurp2NUExXJMP//L9t0ZEIvTorMzQDjMtM6AvextRr6bwkIQOtvI0QLYSBW7k/nKS89tw9o5l4eKRe5g== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Besides the obvious (and desired) difference between krealloc() and kvrealloc(), there is some inconsistency in their function signatures and behavior: - krealloc() frees the memory when the requested size is zero, whereas kvrealloc() simply returns a pointer to the existing allocation. - krealloc() behaves like kmalloc() if a NULL pointer is passed, whereas kvrealloc() does not accept a NULL pointer at all and, if passed, would fault instead. - krealloc() is self-contained, whereas kvrealloc() relies on the caller to provide the size of the previous allocation. Inconsistent behavior throughout allocation APIs is error prone, hence make kvrealloc() behave like krealloc(), which seems superior in all mentioned aspects. Besides that, implementing kvrealloc() by making use of krealloc() and vrealloc() provides oppertunities to grow (and shrink) allocations more efficiently. For instance, vrealloc() could be optimized to extend the existing allocation if there is enough contiguous space left in the virtual address space at the end of the existing allocation. Signed-off-by: Danilo Krummrich --- arch/powerpc/platforms/pseries/papr-vpd.c | 5 +- drivers/gpu/drm/drm_exec.c | 3 +- fs/xfs/xfs_log_recover.c | 2 +- include/linux/slab.h | 3 +- kernel/resource.c | 3 +- lib/fortify_kunit.c | 3 +- mm/util.c | 72 ++++++++++++++++------- 7 files changed, 56 insertions(+), 35 deletions(-) diff --git a/arch/powerpc/platforms/pseries/papr-vpd.c b/arch/powerpc/platforms/pseries/papr-vpd.c index c29e85db5f35..1574176e3ffc 100644 --- a/arch/powerpc/platforms/pseries/papr-vpd.c +++ b/arch/powerpc/platforms/pseries/papr-vpd.c @@ -156,10 +156,7 @@ static int vpd_blob_extend(struct vpd_blob *blob, const char *data, size_t len) const char *old_ptr = blob->data; char *new_ptr; - new_ptr = old_ptr ? - kvrealloc(old_ptr, old_len, new_len, GFP_KERNEL_ACCOUNT) : - kvmalloc(len, GFP_KERNEL_ACCOUNT); - + new_ptr = kvrealloc(old_ptr, new_len, GFP_KERNEL_ACCOUNT); if (!new_ptr) return -ENOMEM; diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c index 2da094bdf8a4..18e366cc4993 100644 --- a/drivers/gpu/drm/drm_exec.c +++ b/drivers/gpu/drm/drm_exec.c @@ -145,8 +145,7 @@ static int drm_exec_obj_locked(struct drm_exec *exec, size_t size = exec->max_objects * sizeof(void *); void *tmp; - tmp = kvrealloc(exec->objects, size, size + PAGE_SIZE, - GFP_KERNEL); + tmp = kvrealloc(exec->objects, size + PAGE_SIZE, GFP_KERNEL); if (!tmp) return -ENOMEM; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 4fe627991e86..bbe5ecb2345b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2132,7 +2132,7 @@ xlog_recover_add_to_cont_trans( old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; old_len = item->ri_buf[item->ri_cnt-1].i_len; - ptr = kvrealloc(old_ptr, old_len, len + old_len, GFP_KERNEL); + ptr = kvrealloc(old_ptr, len + old_len, GFP_KERNEL); if (!ptr) return -ENOMEM; memcpy(&ptr[old_len], dp, len); diff --git a/include/linux/slab.h b/include/linux/slab.h index 7247e217e21b..41ede46d3bd2 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -808,8 +808,7 @@ kvmalloc_array_node_noprof(size_t n, size_t size, gfp_t flags, int node) #define kvcalloc_node(...) alloc_hooks(kvcalloc_node_noprof(__VA_ARGS__)) #define kvcalloc(...) alloc_hooks(kvcalloc_noprof(__VA_ARGS__)) -extern void *kvrealloc_noprof(const void *p, size_t oldsize, size_t newsize, gfp_t flags) - __realloc_size(3); +extern void *kvrealloc_noprof(const void *p, size_t size, gfp_t flags) __realloc_size(2); #define kvrealloc(...) alloc_hooks(kvrealloc_noprof(__VA_ARGS__)) extern void kvfree(const void *addr); diff --git a/kernel/resource.c b/kernel/resource.c index fcbca39dbc45..46e064c8dce2 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -458,8 +458,7 @@ int walk_system_ram_res_rev(u64 start, u64 end, void *arg, /* re-alloc */ struct resource *rams_new; - rams_new = kvrealloc(rams, rams_size * sizeof(struct resource), - (rams_size + 16) * sizeof(struct resource), + rams_new = kvrealloc(rams, (rams_size + 16) * sizeof(struct resource), GFP_KERNEL); if (!rams_new) goto out; diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c index 27ea8bf0252c..acbdc7855100 100644 --- a/lib/fortify_kunit.c +++ b/lib/fortify_kunit.c @@ -308,8 +308,7 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(vmalloc) orig = kvmalloc(prev_size, gfp); \ KUNIT_EXPECT_TRUE(test, orig != NULL); \ checker(((expected_pages) * PAGE_SIZE) * 2, \ - kvrealloc(orig, prev_size, \ - ((alloc_pages) * PAGE_SIZE) * 2, gfp), \ + kvrealloc(orig, ((alloc_pages) * PAGE_SIZE) * 2, gfp), \ kvfree(p)); \ } while (0) DEFINE_ALLOC_SIZE_TEST_PAIR(kvmalloc) diff --git a/mm/util.c b/mm/util.c index 983baf2bd675..6a4eb9c1d9b7 100644 --- a/mm/util.c +++ b/mm/util.c @@ -598,6 +598,21 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, } EXPORT_SYMBOL(vm_mmap); +static gfp_t to_kmalloc_flags(gfp_t flags, size_t size) +{ + if (size > PAGE_SIZE) { + flags |= __GFP_NOWARN; + + if (!(flags & __GFP_RETRY_MAYFAIL)) + flags |= __GFP_NORETRY; + + /* nofail semantic is implemented by the vmalloc fallback */ + flags &= ~__GFP_NOFAIL; + } + + return flags; +} + /** * kvmalloc_node - attempt to allocate physically contiguous memory, but upon * failure, fall back to non-contiguous (vmalloc) allocation. @@ -616,7 +631,6 @@ EXPORT_SYMBOL(vm_mmap); */ void *kvmalloc_node_noprof(size_t size, gfp_t flags, int node) { - gfp_t kmalloc_flags = flags; void *ret; /* @@ -626,17 +640,7 @@ void *kvmalloc_node_noprof(size_t size, gfp_t flags, int node) * However make sure that larger requests are not too disruptive - no * OOM killer and no allocation failure warnings as we have a fallback. */ - if (size > PAGE_SIZE) { - kmalloc_flags |= __GFP_NOWARN; - - if (!(kmalloc_flags & __GFP_RETRY_MAYFAIL)) - kmalloc_flags |= __GFP_NORETRY; - - /* nofail semantic is implemented by the vmalloc fallback */ - kmalloc_flags &= ~__GFP_NOFAIL; - } - - ret = kmalloc_node_noprof(size, kmalloc_flags, node); + ret = kmalloc_node_noprof(size, to_kmalloc_flags(flags, size), node); /* * It doesn't really make sense to fallback to vmalloc for sub page @@ -704,18 +708,42 @@ void kvfree_sensitive(const void *addr, size_t len) } EXPORT_SYMBOL(kvfree_sensitive); -void *kvrealloc_noprof(const void *p, size_t oldsize, size_t newsize, gfp_t flags) +/** + * kvrealloc - reallocate memory; contents remain unchanged + * @p: object to reallocate memory for + * @size: the size to reallocate + * @flags: the flags for the page level allocator + * + * The contents of the object pointed to are preserved up to the lesser of the + * new and old size (__GFP_ZERO flag is effectively ignored). + * + * If @p is %NULL, kvrealloc() behaves exactly like kvmalloc(). If @size is 0 + * and @p is not a %NULL pointer, the object pointed to is freed. + * + * Return: pointer to the allocated memory or %NULL in case of error + */ +void *kvrealloc_noprof(const void *p, size_t size, gfp_t flags) { - void *newp; + void *n; + + if (is_vmalloc_addr(p)) + return vrealloc_noprof(p, size, flags); + + n = krealloc_noprof(p, size, to_kmalloc_flags(flags, size)); + if (!n) { + /* We failed to krealloc(), fall back to kvmalloc(). */ + n = kvmalloc_noprof(size, flags); + if (!n) + return NULL; + + if (p) { + /* We already know that `p` is not a vmalloc address. */ + memcpy(n, p, ksize(p)); + kfree(p); + } + } - if (oldsize >= newsize) - return (void *)p; - newp = kvmalloc_noprof(newsize, flags); - if (!newp) - return NULL; - memcpy(newp, p, oldsize); - kvfree(p); - return newp; + return n; } EXPORT_SYMBOL(kvrealloc_noprof);