On Thu 15-12-22 09:33:54, Mathieu Desnoyers wrote: > On 2022-12-15 02:51, Michal Hocko wrote: [...] > > Btw. looking at the code again it seems rather pointless to duplicate > > the policy just to throw it away anyway. A slightly bigger diff but this > > looks more reasonable to me. What do you think? I can also send it as a > > clean up on top of your fix. > > I think it would be best if this comes as a cleanup on top of my fix. The > diff is larger than the minimal change needed to fix the leak in stable > branches. > > Your approach looks fine, except for the vma_policy(vma) -> old change > already spotted by Aneesh. This shouldn't have any real effect on the functionality. Anyway, here is a follow up cleanup: --- >From f3fdb6f65fa3977aab13378b8e299b168719577c Mon Sep 17 00:00:00 2001 From: Michal Hocko <mhocko@xxxxxxxx> Date: Thu, 15 Dec 2022 15:41:27 +0100 Subject: [PATCH] mm/mempolicy: do not duplicate policy if it is not applicable for set_mempolicy_home_node set_mempolicy_home_node tries to duplicate a memory policy before checking it whether it is applicable for the operation. There is no real reason for doing that and it might actually be a pointless memory allocation and deallocation exercise for MPOL_INTERLEAVE. Not a big problem but we can do better. Simply check the policy before acting on it. Signed-off-by: Michal Hocko <mhocko@xxxxxxxx> --- mm/mempolicy.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 02c8a712282f..becf41e10076 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1489,7 +1489,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; - struct mempolicy *new; + struct mempolicy *new, *old; unsigned long vmstart; unsigned long vmend; unsigned long end; @@ -1521,31 +1521,27 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le return 0; mmap_write_lock(mm); for_each_vma_range(vmi, vma, end) { - vmstart = max(start, vma->vm_start); - vmend = min(end, vma->vm_end); - new = mpol_dup(vma_policy(vma)); - if (IS_ERR(new)) { - err = PTR_ERR(new); - break; - } - /* - * Only update home node if there is an existing vma policy - */ - if (!new) - continue; - /* * If any vma in the range got policy other than MPOL_BIND * or MPOL_PREFERRED_MANY we return error. We don't reset * the home node for vmas we already updated before. */ - if (new->mode != MPOL_BIND && new->mode != MPOL_PREFERRED_MANY) { - mpol_put(new); + old = vma_policy(vma); + if (!old) + continue; + if (old->mode != MPOL_BIND && old->mode != MPOL_PREFERRED_MANY) { err = -EOPNOTSUPP; break; } + new = mpol_dup(old); + if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } new->home_node = home_node; + vmstart = max(start, vma->vm_start); + vmend = min(end, vma->vm_end); err = mbind_range(mm, vmstart, vmend, new); mpol_put(new); if (err) -- 2.30.2 -- Michal Hocko SUSE Labs