From patchwork Tue Jul 2 15:58:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vlastimil Babka X-Patchwork-Id: 13719961 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 3C4AEC30658 for ; Tue, 2 Jul 2024 15:58:12 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 949D66B008A; Tue, 2 Jul 2024 11:58:11 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 908D86B008C; Tue, 2 Jul 2024 11:58:11 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 799CE6B0095; Tue, 2 Jul 2024 11:58:11 -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 5BE6A6B008A for ; Tue, 2 Jul 2024 11:58:11 -0400 (EDT) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 5FBCEA20FA for ; Tue, 2 Jul 2024 15:58:10 +0000 (UTC) X-FDA: 82295269140.06.B8A3C97 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) by imf04.hostedemail.com (Postfix) with ESMTP id 1DA0140014 for ; Tue, 2 Jul 2024 15:58:07 +0000 (UTC) Authentication-Results: imf04.hostedemail.com; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=1x1+B5V6; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b=vr79WnWh; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=V3TCk0Rl; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b=WiGNbOPw; spf=pass (imf04.hostedemail.com: domain of vbabka@suse.cz designates 195.135.223.130 as permitted sender) smtp.mailfrom=vbabka@suse.cz; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1719935866; 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:references:dkim-signature; bh=ZUXJa6qZ1Z85tU8NRRhDqffNTAJHYAKpnrU2JbYigmg=; b=SN/LQ+n0FJahXeW13FAar//VDQR91gyHGIE9j7gAcsWmr9/Zs3v3SgciGKqxBZTv+FIz+o fxBZgA6R/XtWT/v3Xa9si810N0AG/lqeCQQBs/8TSgPdbKi9IgYHMMUY8yJDGNNMIbNVva TeagmdXg9qkxRH4xv4w53ONn5RScIyU= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1719935866; a=rsa-sha256; cv=none; b=DMs85ojOR5OW4a8NcdWvdJyfW2eVw/wHt4+Vd6aeh4e1yDsjt8uoyO+TaOp4eVo7yZdQsg cP0/9mjaguCKmKufgKzTxz7brHOIJK2rYzmb8WYqhaXajZfbZvwjKMHyFTqUGa2oHEyw+z tHDt871yX6Yz4BV70CxHKr/IItajtEE= ARC-Authentication-Results: i=1; imf04.hostedemail.com; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=1x1+B5V6; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b=vr79WnWh; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=V3TCk0Rl; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b=WiGNbOPw; spf=pass (imf04.hostedemail.com: domain of vbabka@suse.cz designates 195.135.223.130 as permitted sender) smtp.mailfrom=vbabka@suse.cz; dmarc=none Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 00B2D21AE7; Tue, 2 Jul 2024 15:58:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1719935886; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=ZUXJa6qZ1Z85tU8NRRhDqffNTAJHYAKpnrU2JbYigmg=; b=1x1+B5V6VO16gcDXPWruRSuHy3ASUQ6OSGNwuHaQw9msV3aqKnchPiCWPrX2nCX2CuFE75 Dr2XDPshXdKkFZJZcw6v1lLoQblUazWtL2ZvXZscf9MipEteKJ5mb4vCiaG/aYG23CQTIz W/4gHll3tNhH1mpUELQr2wB7k0bY2vs= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1719935886; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=ZUXJa6qZ1Z85tU8NRRhDqffNTAJHYAKpnrU2JbYigmg=; b=vr79WnWh0OSe6gXYBRvDNQRwvXU8g6rMVkZ0jLdrYUtZvrY7laWbG58dOYscFWzoyzqpVd repYS55oqSmRzMAg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1719935885; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=ZUXJa6qZ1Z85tU8NRRhDqffNTAJHYAKpnrU2JbYigmg=; b=V3TCk0RlMSZAidW1rWOKh+fkjzUw7oFfX43T0DbAZnER/9hIC303LYKs4LW7f1GQa1VqPV 6A02cVf+RaQ7rO1CI+1z6mI6zIBsb9MQDzlG/B0qpbAH3rZp/njh2w2tQ0/EvwtE0/kbSF Krw8tjEWELO8q2WWU+55yZTjPvxzwBg= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1719935885; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=ZUXJa6qZ1Z85tU8NRRhDqffNTAJHYAKpnrU2JbYigmg=; b=WiGNbOPwwF9Jv0WQ7/9zyFt/L3g2WIE+q1uxP8+CVW4+J/xWVCSqyhzOEKi1/sWfS/LNdn eS3/uG3wB+dU68BA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id DDD0613A9A; Tue, 2 Jul 2024 15:58:04 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id G7rNNYwjhGZSMQAAD6G6ig (envelope-from ); Tue, 02 Jul 2024 15:58:04 +0000 From: Vlastimil Babka To: linux-mm@kvack.org, David Rientjes , Christoph Lameter Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com>, Roman Gushchin , Kees Cook , Alice Ryhl , Boqun Feng , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, Vlastimil Babka Subject: [PATCH] mm, slab: extend kmalloc() alignment for non power-of-two sizes Date: Tue, 2 Jul 2024 17:58:01 +0200 Message-ID: <20240702155800.166503-2-vbabka@suse.cz> X-Mailer: git-send-email 2.45.2 MIME-Version: 1.0 X-Rspamd-Action: no action X-Rspamd-Queue-Id: 1DA0140014 X-Stat-Signature: zwuf99rismct641ujxuss9x61aaomyqb X-Rspamd-Server: rspam09 X-Rspam-User: X-HE-Tag: 1719935887-122542 X-HE-Meta: U2FsdGVkX18Phioeumekk2pwz6yLPS3qen8803jpBEtoJa5rlruKbcQwOS5NcNQ1YKxW5EPOPT1vuV0E6N+52QEavR3XefqcgN8JXrYXJumSApnhngMeTe/d9rJ8+4klP3qnYdHRJiqlDZIzEP2AvoP3oHNhgFJRjae76bdW47/IYaexFEmgP+Tnd1gElgu6OQ+jbMJpxE9+2U38/1TchBSmIh93xkJ4I5MrTuUplVRA9tZDRNrjrsS1EtbgZzLELomOQ9KwpJEjZzic0cbZgqHkRFKwn9ZlR/+Df9ueUhj4szgeKZurmtV7H4UcT3MoGrGvkZZTED9M1tpmEoCt5w21Ejz9DDJaqCJQ9/+V1L9azIlpkc45h9cIk0VxuM2Ir2XUe9lLDUEL1sgUNG8i62JI4qfdKc9cnnoE7YNlXsOTt7TCPMAhZT2rqOwBMVJTLUjKuMjWiCeN4N1kUiulYAo67lnxHrYBkzRfrRpRnvyYPB2WnpdGwFZJtp1y81eo+ctIXkM35H5Zh/i4iyrklRvk/0CnFtIMuF7LI4bBA0/gokwGzlRKuDDHScuMCXpqLO93X6JgvA2QuPfO7+9q/1qsqqJ6AryKRihJxgu76nC1e2oJ0BU2UR2/i/V0AFZtdhUy1EbrQUIzMl43ga09kYI8xuIIVshWMUSTcImzn8Wmj7zqAvCS4e+OURvn2qLswHQD8UIBZJdogLSN9R3euqDKLY2ku4pOWVEe3XiMQ5esXK2ReUdbhLBI1hLgDHnvciGpfJdLy0ViOAIecB2AHMdOEKy3qauQhyJRjV6IfQxig8Ui4RKrs/jRARvvZX3UE7wB+QljlEscrI7NAc7zRNXFoCSs3KN7OcAvaQbeXhtSjQybmFtyI8s+xVJG5ut4rlTtHlpf0GF/OIJw3saryc+7ZTclU0/YmOPhx1sFoA8uV67cH+ajG92iuR0g2HPqMFN7nyFZDg9MdHJ8IIw c2h5yXyn 9iMA6HpACGZat/FWeM2qXyTDrdo+21T9tdilsPDKWgI6qjC+Pf0Q4Tr47HbW8ZV3jTt58QSmX+0NtThoCC7+0ZpIlI4PTtey4oOOp7P6mVFDB/Q/YvYoxTj10FtXgSSpFYdyTkepP7TjsL/CclX6eutzHYIKhkP0WZq6veCBCr89a8lZ3Z7ZRuvYbJtvOnq21x2OGzNU5UdvBzKFbw8b7vZSRsnDUj4gsCCScIVOdzyQay6zHIzYxSdbe1zuav+e9Di852B5WRcGRcQ6ZR+t2rrvkEqsImWpEqOTnWNSEUPQQdxQb+dPbrnG2n5jwPmKTHwYjV0tCZftMzBGzR5pQ6nKeDEmhj2sxgxaCpl43zAVjkXcTO6evewIngg== 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: Slab allocators have been guaranteeing natural alignment for power-of-two sizes since commit 59bb47985c1d ("mm, sl[aou]b: guarantee natural alignment for kmalloc(power-of-two)"), while any other sizes are aligned only to ARCH_KMALLOC_MINALIGN bytes. Rust's allocator API specifies size and alignment per allocation, which have to satisfy the following rules, per Alice Ryhl [1]: 1. The alignment is a power of two. 2. The size is non-zero. 3. When you round up the size to the next multiple of the alignment, then it must not overflow the signed type isize / ssize_t. In order to map this to kmalloc()'s guarantees, some requested allocation sizes have to be enlarged to the next power-of-two size [2]. For example, an allocation of size 96 and alignment of 32 will be enlarged to an allocation of size 128, because the existing kmalloc-96 bucket doesn't guarantee alignent above ARCH_KMALLOC_MINALIGN. Without slab debugging active, the layout of the kmalloc-96 slabs however naturally aligns the objects to 32 bytes, so extending the size to 128 bytes is wasteful. To improve the situation we can extend the kmalloc() alignment guarantees in a way that 1) doesn't change the current slab layout (and thus does not increase internal fragmentation) when slab debugging is not active 2) reduces waste in the Rust allocator use case 3) is a superset of the current guarantee for power-of-two sizes. The extended guarantee is that alignment is at least the largest power-of-two divisor of the requested size. For power-of-two sizes the largest divisor is the size itself, but let's keep this case documented separately for clarity. For current kmalloc size buckets, it means kmalloc-96 will guarantee alignment of 32 bytes and kmalloc-196 will guarantee 64 bytes. This covers the rules 1 and 2 above of Rust's API as long as the size is a multiple of the alignment. The Rust layer should now only need to round up the size to the next multiple if it isn't, while enforcing the rule 3. Implementation-wise, this changes the alignment calculation in create_boot_cache(). While at it also do the calulation only for caches with the SLAB_KMALLOC flag, because the function is also used to create the initial kmem_cache and kmem_cache_node caches, where no alignment guarantee is necessary. Link: https://lore.kernel.org/all/CAH5fLggjrbdUuT-H-5vbQfMazjRDpp2%2Bk3%3DYhPyS17ezEqxwcw@mail.gmail.com/ [1] Link: https://lore.kernel.org/all/CAH5fLghsZRemYUwVvhk77o6y1foqnCeDzW4WZv6ScEWna2+_jw@mail.gmail.com/ [2] Signed-off-by: Vlastimil Babka Acked-by: Roman Gushchin Reviewed-by: Boqun Feng --- Documentation/core-api/memory-allocation.rst | 6 ++++-- include/linux/slab.h | 3 ++- mm/slab_common.c | 9 +++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Documentation/core-api/memory-allocation.rst b/Documentation/core-api/memory-allocation.rst index 1c58d883b273..8b84eb4bdae7 100644 --- a/Documentation/core-api/memory-allocation.rst +++ b/Documentation/core-api/memory-allocation.rst @@ -144,8 +144,10 @@ configuration, but it is a good practice to use `kmalloc` for objects smaller than page size. The address of a chunk allocated with `kmalloc` is aligned to at least -ARCH_KMALLOC_MINALIGN bytes. For sizes which are a power of two, the -alignment is also guaranteed to be at least the respective size. +ARCH_KMALLOC_MINALIGN bytes. For sizes which are a power of two, the +alignment is also guaranteed to be at least the respective size. For other +sizes, the alignment is guaranteed to be at least the largest power-of-two +divisor of the size. Chunks allocated with kmalloc() can be resized with krealloc(). Similarly to kmalloc_array(): a helper for resizing arrays is provided in the form of diff --git a/include/linux/slab.h b/include/linux/slab.h index ed6bee5ec2b6..640cea6e6323 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -604,7 +604,8 @@ void *__kmalloc_large_node_noprof(size_t size, gfp_t flags, int node) * * The allocated object address is aligned to at least ARCH_KMALLOC_MINALIGN * bytes. For @size of power of two bytes, the alignment is also guaranteed - * to be at least to the size. + * to be at least to the size. For other sizes, the alignment is guaranteed to + * be at least the largest power-of-two divisor of @size. * * The @flags argument may be one of the GFP flags defined at * include/linux/gfp_types.h and described at diff --git a/mm/slab_common.c b/mm/slab_common.c index 1560a1546bb1..7272ef7bc55f 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -617,11 +617,12 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, s->size = s->object_size = size; /* - * For power of two sizes, guarantee natural alignment for kmalloc - * caches, regardless of SL*B debugging options. + * kmalloc caches guarantee alignment of at least the largest + * power-of-two divisor of the size. For power-of-two sizes, + * it is the size itself. */ - if (is_power_of_2(size)) - align = max(align, size); + if (flags & SLAB_KMALLOC) + align = max(align, 1U << (ffs(size) - 1)); s->align = calculate_alignment(flags, align, size); #ifdef CONFIG_HARDENED_USERCOPY