mm/hugetlb: fix sysfs group leak in hugetlb_unregister_node()
authorMiaohe Lin <linmiaohe@huawei.com>
Tue, 16 Aug 2022 13:05:52 +0000 (21:05 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 12 Sep 2022 03:25:55 +0000 (20:25 -0700)
The sysfs group per_node_hstate_attr_group and hstate_demote_attr_group
when h->demote_order != 0 are created in hugetlb_register_node().  But
these sysfs groups are not removed when unregister the node, thus sysfs
group is leaked.  Using sysfs_remove_group() to fix this issue.

Link: https://lkml.kernel.org/r/20220816130553.31406-6-linmiaohe@huawei.com
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
Reviewed-by: Fengwei Yin <fengwei.yin@intel.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Muchun Song <songmuchun@bytedance.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/hugetlb.c

index 8d52827..648d9f5 100644 (file)
@@ -3850,12 +3850,18 @@ static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent,
        }
 
        if (h->demote_order) {
-               if (sysfs_create_group(hstate_kobjs[hi],
-                                       &hstate_demote_attr_group))
+               retval = sysfs_create_group(hstate_kobjs[hi],
+                                           &hstate_demote_attr_group);
+               if (retval) {
                        pr_warn("HugeTLB unable to create demote interfaces for %s\n", h->name);
+                       sysfs_remove_group(hstate_kobjs[hi], hstate_attr_group);
+                       kobject_put(hstate_kobjs[hi]);
+                       hstate_kobjs[hi] = NULL;
+                       return retval;
+               }
        }
 
-       return retval;
+       return 0;
 }
 
 static void __init hugetlb_sysfs_init(void)
@@ -3941,10 +3947,15 @@ static void hugetlb_unregister_node(struct node *node)
 
        for_each_hstate(h) {
                int idx = hstate_index(h);
-               if (nhs->hstate_kobjs[idx]) {
-                       kobject_put(nhs->hstate_kobjs[idx]);
-                       nhs->hstate_kobjs[idx] = NULL;
-               }
+               struct kobject *hstate_kobj = nhs->hstate_kobjs[idx];
+
+               if (!hstate_kobj)
+                       continue;
+               if (h->demote_order)
+                       sysfs_remove_group(hstate_kobj, &hstate_demote_attr_group);
+               sysfs_remove_group(hstate_kobj, &per_node_hstate_attr_group);
+               kobject_put(hstate_kobj);
+               nhs->hstate_kobjs[idx] = NULL;
        }
 
        kobject_put(nhs->hugepages_kobj);