hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8OIQR
----------------------------------------------------------------------
Filescgroup is used to control fd in cgroup v1 as cgroup controller, which will not be merged to mainline. It is better to control fd with misc, which provides the resource limiting and tracking mechanism for the scalar resources and already be merged, so add MISC_CG_RES_FD resource to control fd. Filescgroup will be abandoned in the future.
Signed-off-by: Chen Ridong chenridong@huawei.com --- fs/Makefile | 1 + fs/filescontrol.c | 34 ++++++++++++++ fs/misc-fd.c | 92 +++++++++++++++++++++++++++++++++++++ include/linux/fdtable.h | 1 + include/linux/misc-fd.h | 23 ++++++++++ include/linux/misc_cgroup.h | 2 + kernel/cgroup/misc.c | 2 + 7 files changed, 155 insertions(+) create mode 100644 fs/misc-fd.c create mode 100644 include/linux/misc-fd.h
diff --git a/fs/Makefile b/fs/Makefile index c4e433f8c46e..a66fa139c207 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_DIRTY_PAGES) += dirty_pages.o obj-$(CONFIG_FHANDLE) += fhandle.o obj-$(CONFIG_CGROUP_FILES) += filescontrol.o obj-$(CONFIG_CGROUP_FILES) += files-cgroup.o +obj-$(CONFIG_CGROUP_FILES) += misc-fd.o obj-y += iomap/
obj-y += quota/ diff --git a/fs/filescontrol.c b/fs/filescontrol.c index 35fb2fe9c2d0..eb9f67fca68b 100644 --- a/fs/filescontrol.c +++ b/fs/filescontrol.c @@ -8,6 +8,14 @@ #include <linux/fdtable.h> #include <linux/filescontrol.h> #include <linux/files-cgroup.h> +#include <linux/misc-fd.h> + +struct static_key_false misc_fd_enable_key; + +static inline bool file_cg_misc_enabled(void) +{ + return static_branch_likely(&misc_fd_enable_key); +}
u64 file_cg_count_fds(struct files_struct *files) { @@ -23,32 +31,58 @@ u64 file_cg_count_fds(struct files_struct *files)
int files_cg_alloc_fd(struct files_struct *files, u64 n) { + if (file_cg_misc_enabled()) + return misc_fd_alloc_fd(files, n); + return files_cgroup_alloc_fd(files, n); }
void files_cg_unalloc_fd(struct files_struct *files, u64 n) { + if (file_cg_misc_enabled()) + return misc_fd_unalloc_fd(files, n); + return files_cgroup_unalloc_fd(files, n); }
void files_cg_assign(struct files_struct *files) { + if (file_cg_misc_enabled()) + return misc_fd_assign(files); + return files_cgroup_assign(files); }
void files_cg_remove(struct files_struct *files) { + if (file_cg_misc_enabled()) + return misc_fd_remove(files); + return files_cgroup_remove(files); }
int files_cg_dup_fds(struct files_struct *newf) { + if (file_cg_misc_enabled()) + return misc_fd_dup_fds(newf); + return files_cgroup_dup_fds(newf); }
void files_cg_put_fd(struct files_struct *files, unsigned int fd) { + if (file_cg_misc_enabled()) + return misc_fd_put_fd(files, fd); + return files_cgroup_put_fd(files, fd); }
+static int __init enable_misc_fd(char *s) +{ + static_branch_enable(&misc_fd_enable_key); + pr_info("file_cg enable misc to control fd\n"); + + return 1; +} +__setup("file_cg=misc", enable_misc_fd);
diff --git a/fs/misc-fd.c b/fs/misc-fd.c new file mode 100644 index 000000000000..b72dcd4852db --- /dev/null +++ b/fs/misc-fd.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause +/* + * Copyright (c) 2024-2024, Huawei Tech. Co., Ltd. + * + * Author: Ridong Chen chenridong@huawei.com + */ + +#include <linux/misc_cgroup.h> +#include <linux/fdtable.h> +#include <linux/filescontrol.h> +#include <linux/misc-fd.h> + +static bool is_init; + +bool is_misc_fd_init(void) +{ + return is_init; +} + +void misc_fd_init(void) +{ + misc_cg_set_capacity(MISC_CG_RES_FD, U64_MAX); + is_init = true; +} + +/* + * If first time to alloc,it has to init capacity + */ +int misc_fd_alloc_fd(struct files_struct *files, u64 n) +{ + if (!is_misc_fd_init()) + misc_fd_init(); + if (files != &init_files) + return misc_cg_try_charge(MISC_CG_RES_FD, files->misc_cg, n); + return 0; +} + +void misc_fd_unalloc_fd(struct files_struct *files, u64 n) +{ + if (files != &init_files) + return misc_cg_uncharge(MISC_CG_RES_FD, files->misc_cg, n); +} + +void misc_fd_assign(struct files_struct *files) +{ + struct cgroup_subsys_state *css; + + if (files == NULL || files == &init_files) + return; + + css = task_get_css(current, misc_cgrp_id); + files->misc_cg = (css ? container_of(css, struct misc_cg, css) : NULL); +} + +void misc_fd_remove(struct files_struct *files) +{ + struct task_struct *tsk = current; + + if (files == &init_files) + return; + + task_lock(tsk); + spin_lock(&files->file_lock); + if (files->misc_cg != NULL) + css_put(&files->misc_cg->css); + spin_unlock(&files->file_lock); + task_unlock(tsk); +} + +int misc_fd_dup_fds(struct files_struct *newf) +{ + int err; + + if (newf == &init_files) + return 0; + + spin_lock(&newf->file_lock); + err = misc_fd_alloc_fd(newf, file_cg_count_fds(newf)); + spin_unlock(&newf->file_lock); + return err; +} + +void misc_fd_put_fd(struct files_struct *files, unsigned int fd) +{ + struct fdtable *fdt = files_fdtable(files); + + if (files == &init_files) + return; + + if (test_bit(fd, fdt->open_fds)) + return misc_fd_unalloc_fd(files, 1); +} diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 22b8b03fef6d..07f4940206b1 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -66,6 +66,7 @@ struct files_struct { unsigned long full_fds_bits_init[1]; struct file __rcu * fd_array[NR_OPEN_DEFAULT]; struct files_cgroup *files_cgroup; + struct misc_cg *misc_cg; };
struct file_operations; diff --git a/include/linux/misc-fd.h b/include/linux/misc-fd.h new file mode 100644 index 000000000000..92c238fe8d3b --- /dev/null +++ b/include/linux/misc-fd.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ +/* + * Copyright (c) 2024-2024, Huawei Tech. Co., Ltd. + * + * Author: Ridong Chen chenridong@huawei.com + */ + +#ifndef __FD_MISC_H_ +#define __FD_MISC_H_ + +#include <linux/fdtable.h> +extern struct files_struct init_files; + +extern int misc_fd_alloc_fd(struct files_struct *files, u64 n); +extern void misc_fd_unalloc_fd(struct files_struct *files, u64 n); + +extern void misc_fd_assign(struct files_struct *files); +extern void misc_fd_remove(struct files_struct *files); + +extern int misc_fd_dup_fds(struct files_struct *newf); +extern void misc_fd_put_fd(struct files_struct *files, unsigned int fd); + +#endif diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h index e799b1f8d05b..c859a1ed583f 100644 --- a/include/linux/misc_cgroup.h +++ b/include/linux/misc_cgroup.h @@ -18,6 +18,8 @@ enum misc_res_type { /* AMD SEV-ES ASIDs resource */ MISC_CG_RES_SEV_ES, #endif + /* fd for file control */ + MISC_CG_RES_FD, MISC_CG_RES_TYPES };
diff --git a/kernel/cgroup/misc.c b/kernel/cgroup/misc.c index 79a3717a5803..366a12b85f03 100644 --- a/kernel/cgroup/misc.c +++ b/kernel/cgroup/misc.c @@ -24,6 +24,8 @@ static const char *const misc_res_name[] = { /* AMD SEV-ES ASIDs resource */ "sev_es", #endif + /* fd for file control */ + "fd", };
/* Root misc cgroup */