Skip to content

Commit d0c4c5a

Browse files
xiaochenshengregkh
authored andcommitted
x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak
commit fd8d9db upstream. Willem reported growing of kernfs_node_cache entries in slabtop when repeatedly creating and removing resctrl subdirectories as well as when repeatedly mounting and unmounting the resctrl filesystem. On resource group (control as well as monitoring) creation via a mkdir an extra kernfs_node reference is obtained to ensure that the rdtgroup structure remains accessible for the rdtgroup_kn_unlock() calls where it is removed on deletion. The kernfs_node reference count is dropped by kernfs_put() in rdtgroup_kn_unlock(). With the above explaining the need for one kernfs_get()/kernfs_put() pair in resctrl there are more places where a kernfs_node reference is obtained without a corresponding release. The excessive amount of reference count on kernfs nodes will never be dropped to 0 and the kernfs nodes will never be freed in the call paths of rmdir and umount. It leads to reference count leak and kernfs_node_cache memory leak. Remove the superfluous kernfs_get() calls and expand the existing comments surrounding the remaining kernfs_get()/kernfs_put() pair that remains in use. Superfluous kernfs_get() calls are removed from two areas: (1) In call paths of mount and mkdir, when kernfs nodes for "info", "mon_groups" and "mon_data" directories and sub-directories are created, the reference count of newly created kernfs node is set to 1. But after kernfs_create_dir() returns, superfluous kernfs_get() are called to take an additional reference. (2) kernfs_get() calls in rmdir call paths. Fixes: 17eafd0 ("x86/intel_rdt: Split resource group removal in two") Fixes: 4af4a88 ("x86/intel_rdt/cqm: Add mount,umount support") Fixes: f3cbeac ("x86/intel_rdt/cqm: Add rmdir support") Fixes: d89b737 ("x86/intel_rdt/cqm: Add mon_data") Fixes: c7d9aac ("x86/intel_rdt/cqm: Add mkdir support for RDT monitoring") Fixes: 5dc1d5c ("x86/intel_rdt: Simplify info and base file lists") Fixes: 60cf5e1 ("x86/intel_rdt: Add mkdir to resctrl file system") Fixes: 4e978d0 ("x86/intel_rdt: Add "info" files to resctrl file system") Reported-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Xiaochen Shen <xiaochen.shen@intel.com> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Tested-by: Willem de Bruijn <willemb@google.com> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1604085053-31639-1-git-send-email-xiaochen.shen@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e799c00 commit d0c4c5a

1 file changed

Lines changed: 2 additions & 33 deletions

File tree

arch/x86/kernel/cpu/resctrl/rdtgroup.c

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,6 @@ static int rdtgroup_mkdir_info_resdir(struct rdt_resource *r, char *name,
16181618
if (IS_ERR(kn_subdir))
16191619
return PTR_ERR(kn_subdir);
16201620

1621-
kernfs_get(kn_subdir);
16221621
ret = rdtgroup_kn_set_ugid(kn_subdir);
16231622
if (ret)
16241623
return ret;
@@ -1641,7 +1640,6 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
16411640
kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL);
16421641
if (IS_ERR(kn_info))
16431642
return PTR_ERR(kn_info);
1644-
kernfs_get(kn_info);
16451643

16461644
ret = rdtgroup_add_files(kn_info, RF_TOP_INFO);
16471645
if (ret)
@@ -1662,12 +1660,6 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
16621660
goto out_destroy;
16631661
}
16641662

1665-
/*
1666-
* This extra ref will be put in kernfs_remove() and guarantees
1667-
* that @rdtgrp->kn is always accessible.
1668-
*/
1669-
kernfs_get(kn_info);
1670-
16711663
ret = rdtgroup_kn_set_ugid(kn_info);
16721664
if (ret)
16731665
goto out_destroy;
@@ -1696,12 +1688,6 @@ mongroup_create_dir(struct kernfs_node *parent_kn, struct rdtgroup *prgrp,
16961688
if (dest_kn)
16971689
*dest_kn = kn;
16981690

1699-
/*
1700-
* This extra ref will be put in kernfs_remove() and guarantees
1701-
* that @rdtgrp->kn is always accessible.
1702-
*/
1703-
kernfs_get(kn);
1704-
17051691
ret = rdtgroup_kn_set_ugid(kn);
17061692
if (ret)
17071693
goto out_destroy;
@@ -1988,13 +1974,11 @@ static int rdt_get_tree(struct fs_context *fc)
19881974
&kn_mongrp);
19891975
if (ret < 0)
19901976
goto out_info;
1991-
kernfs_get(kn_mongrp);
19921977

19931978
ret = mkdir_mondata_all(rdtgroup_default.kn,
19941979
&rdtgroup_default, &kn_mondata);
19951980
if (ret < 0)
19961981
goto out_mongrp;
1997-
kernfs_get(kn_mondata);
19981982
rdtgroup_default.mon.mon_data_kn = kn_mondata;
19991983
}
20001984

@@ -2365,11 +2349,6 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
23652349
if (IS_ERR(kn))
23662350
return PTR_ERR(kn);
23672351

2368-
/*
2369-
* This extra ref will be put in kernfs_remove() and guarantees
2370-
* that kn is always accessible.
2371-
*/
2372-
kernfs_get(kn);
23732352
ret = rdtgroup_kn_set_ugid(kn);
23742353
if (ret)
23752354
goto out_destroy;
@@ -2705,8 +2684,8 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
27052684
/*
27062685
* kernfs_remove() will drop the reference count on "kn" which
27072686
* will free it. But we still need it to stick around for the
2708-
* rdtgroup_kn_unlock(kn} call below. Take one extra reference
2709-
* here, which will be dropped inside rdtgroup_kn_unlock().
2687+
* rdtgroup_kn_unlock(kn) call. Take one extra reference here,
2688+
* which will be dropped inside rdtgroup_kn_unlock().
27102689
*/
27112690
kernfs_get(kn);
27122691

@@ -2921,11 +2900,6 @@ static int rdtgroup_rmdir_mon(struct kernfs_node *kn, struct rdtgroup *rdtgrp,
29212900
WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list));
29222901
list_del(&rdtgrp->mon.crdtgrp_list);
29232902

2924-
/*
2925-
* one extra hold on this, will drop when we kfree(rdtgrp)
2926-
* in rdtgroup_kn_unlock()
2927-
*/
2928-
kernfs_get(kn);
29292903
kernfs_remove(rdtgrp->kn);
29302904

29312905
return 0;
@@ -2937,11 +2911,6 @@ static int rdtgroup_ctrl_remove(struct kernfs_node *kn,
29372911
rdtgrp->flags = RDT_DELETED;
29382912
list_del(&rdtgrp->rdtgroup_list);
29392913

2940-
/*
2941-
* one extra hold on this, will drop when we kfree(rdtgrp)
2942-
* in rdtgroup_kn_unlock()
2943-
*/
2944-
kernfs_get(kn);
29452914
kernfs_remove(rdtgrp->kn);
29462915
return 0;
29472916
}

0 commit comments

Comments
 (0)