From: sashiko-bot@kernel.org
To: "Huang Shijie" <huangsj@hygon.cn>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH 3/3] mm: split the file's i_mmap tree for NUMA
Date: Mon, 13 Apr 2026 07:25:57 +0000 [thread overview]
Message-ID: <20260413072557.B2BFEC116C6@smtp.kernel.org> (raw)
In-Reply-To: <20260413062042.804-4-huangsj@hygon.cn>
Sashiko AI review found 6 potential issue(s):
- [Critical] Type confusion and kernel panic in `vma_interval_tree_foreach()` macro.
- [High] Memory leak of LSM security blob on `init_mapping_i_mmap()` failure.
- [High] Hardcoded `GFP_KERNEL` ignores caller's allocation constraints, causing deadlocks.
- [High] Massive memory bloat and allocation overhead per inode.
- [High] NULL pointer dereference in `first_vma()` for uninitialized `i_mmap`.
- [Medium] Integer truncation in `mapping_mapped()` leading to logic errors.
--
commit 8f800a00de85443e08da55055eb7cfb4938865a5
Author: Huang Shijie <huangsj@hygon.cn>
Subject: mm: split the file's i_mmap tree for NUMA
This commit splits the i_mmap tree into multiple NUMA-node-specific
trees to reduce lock contention during VMA operations. It introduces
a vma_count field and rewrites vma_interval_tree_foreach to iterate
over the new structure.
> diff --git a/fs/inode.c b/fs/inode.c
> index cc12b68e021b2..3067cb2558da0 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
[ ... ]
> +#ifdef CONFIG_NUMA
> +static void free_mapping_i_mmap(struct address_space *mapping)
[ ... ]
> +static int init_mapping_i_mmap(struct address_space *mapping)
> +{
> + struct rb_root_cached *root;
> + int i;
> +
> + /* The extra one is used as terminator in vma_interval_tree_foreach() */
> + mapping->i_mmap = kzalloc(sizeof(root) * (nr_node_ids + 1), GFP_KERNEL);
Does hardcoding GFP_KERNEL here ignore the caller's allocation constraints?
inode_init_always_gfp() is passed a gfp_t mask because it can be called in
restricted contexts where blocking is not permitted, such as with GFP_NOFS
or GFP_ATOMIC. Could using GFP_KERNEL unconditionally cause filesystem
recursion or deadlocks under memory pressure?
> + if (!mapping->i_mmap)
> + return -ENOMEM;
> +
> + for (i = 0; i < nr_node_ids; i++) {
> + root = kzalloc_node(sizeof(*root), GFP_KERNEL, i);
Will allocating these arrays and root nodes for every single inode cause
significant memory bloat?
Since this applies to all inodes, including those that are never
memory-mapped like directories, pipes, or sockets, does this negate the
performance and scalability benefits of the optimized inode_cachep slab
cache?
[ ... ]
> @@ -307,6 +357,9 @@ int inode_init_always_gfp(struct super_block *sb, struct inode *inode, gfp_t gfp
> if (unlikely(security_inode_alloc(inode, gfp)))
> return -ENOMEM;
>
> + if (init_mapping_i_mmap(mapping))
> + return -ENOMEM;
> +
Does returning -ENOMEM here leak the LSM security blob?
If init_mapping_i_mmap() fails, the function returns directly without
calling security_inode_free(inode) to clean up the allocation made just
above it.
[ ... ]
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 9fe59b8cc2e4e..9f337a56389d8 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
[ ... ]
> @@ -547,6 +552,27 @@ static inline void i_mmap_assert_write_locked(struct address_space *mapping)
> lockdep_assert_held_write(&mapping->i_mmap_rwsem);
> }
>
> +#ifdef CONFIG_NUMA
> +static inline int mapping_mapped(const struct address_space *mapping)
> +{
> + return READ_ONCE(mapping->vma_count);
> +}
Can this truncate the unsigned long vma_count?
The vma_count field is defined as an unsigned long, but this function
returns an int. On 64-bit systems, if the count reaches a multiple of 2^32,
could it be implicitly cast to 0 and cause core MM routines to mistakenly
treat the file as unmapped?
[ ... ]
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 4c775e5ed50cc..eda527424e225 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
[ ... ]
> @@ -4045,9 +4050,36 @@ struct vm_area_struct *vma_interval_tree_iter_next(struct vm_area_struct *node,
> unsigned long start, unsigned long last);
>
> /* Please use get_i_mmap_root() to get the @root */
> +#ifdef CONFIG_NUMA
> +/* Find the first valid VMA in the sibling trees */
> +static inline struct vm_area_struct *first_vma(struct rb_root_cached ***__r,
> + unsigned long start, unsigned long last)
> +{
> + struct vm_area_struct *vma = NULL;
> + struct rb_root_cached **tree = *__r;
> +
> + while (*tree) {
Can this dereference a NULL pointer if mapping->i_mmap is uninitialized?
Address spaces initialized via address_space_init_once() (like
swapper_spaces) will have i_mmap set to NULL. If a caller iterates without
checking mapping_mapped() first, could get_i_mmap_root() return NULL,
assigning NULL to tree and causing a panic here?
> + vma = vma_interval_tree_iter_first(*tree++, start, last);
> + if (vma)
> + break;
> + }
> +
> + /* Save for the next loop */
> + *__r = tree;
> + return vma;
> +}
> +
> +/* @_tmp is referenced to avoid unused variable warning. */
> +#define vma_interval_tree_foreach(vma, root, start, last) \
> + for (struct rb_root_cached **_r = (void *)(root), \
Is it safe to use a (void *) cast here?
If an unmodified caller (e.g. an external driver) passes &mapping->i_mmap
instead of using get_i_mmap_root(), the cast suppresses type checking. Since
mapping->i_mmap is now a pointer to an array, evaluating it as an
rb_root_cached node pointer could lead to a fatal out-of-bounds dereference.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260413062042.804-1-huangsj@hygon.cn?part=3
next prev parent reply other threads:[~2026-04-13 7:25 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-13 6:20 [PATCH 0/3] mm: split the file's i_mmap tree for NUMA Huang Shijie
2026-04-13 6:20 ` [PATCH 1/3] mm: use mapping_mapped to simplify the code Huang Shijie
2026-04-13 6:20 ` [PATCH 2/3] mm: use get_i_mmap_root to access the file's i_mmap Huang Shijie
2026-04-13 6:44 ` sashiko-bot
2026-04-13 6:55 ` Huang Shijie
2026-04-13 6:20 ` [PATCH 3/3] mm: split the file's i_mmap tree for NUMA Huang Shijie
2026-04-13 7:25 ` sashiko-bot [this message]
2026-04-13 15:33 ` [PATCH 0/3] " Mateusz Guzik
2026-04-14 9:11 ` Huang Shijie
2026-04-16 10:29 ` Mateusz Guzik
2026-04-16 11:48 ` Huang Shijie
2026-04-17 6:59 ` Huang Shijie
2026-04-20 2:10 ` Huang Shijie
2026-04-20 13:48 ` Pedro Falcato
2026-04-21 3:06 ` Huang Shijie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260413072557.B2BFEC116C6@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=huangsj@hygon.cn \
--cc=linux-perf-users@vger.kernel.org \
--cc=sashiko@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox