mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
cgroup: start switching to fs_context
Unfortunately, cgroup is tangled into kernfs infrastructure. To avoid converting all kernfs-based filesystems at once, we need to untangle the remount part of things, instead of having it go through kernfs_sop_remount_fs(). Fortunately, it's not hard to do. This commit just gets cgroup/cgroup1 to use fs_context to deliver options on mount and remount paths. Parsing those is going to be done in the next commits; for now we do pretty much what legacy case does. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
935c6912b1
commit
90129625d9
@ -7,6 +7,7 @@
|
|||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/refcount.h>
|
#include <linux/refcount.h>
|
||||||
|
#include <linux/fs_context.h>
|
||||||
|
|
||||||
#define TRACE_CGROUP_PATH_LEN 1024
|
#define TRACE_CGROUP_PATH_LEN 1024
|
||||||
extern spinlock_t trace_cgroup_path_lock;
|
extern spinlock_t trace_cgroup_path_lock;
|
||||||
@ -36,6 +37,18 @@ extern void __init enable_debug_cgroup(void);
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cgroup filesystem superblock creation/mount context.
|
||||||
|
*/
|
||||||
|
struct cgroup_fs_context {
|
||||||
|
char *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct cgroup_fs_context *cgroup_fc2context(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
return fc->fs_private;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A cgroup can be associated with multiple css_sets as different tasks may
|
* A cgroup can be associated with multiple css_sets as different tasks may
|
||||||
* belong to different cgroups on different hierarchies. In the other
|
* belong to different cgroups on different hierarchies. In the other
|
||||||
@ -255,5 +268,6 @@ void cgroup1_check_for_release(struct cgroup *cgrp);
|
|||||||
struct dentry *cgroup1_mount(struct file_system_type *fs_type, int flags,
|
struct dentry *cgroup1_mount(struct file_system_type *fs_type, int flags,
|
||||||
void *data, unsigned long magic,
|
void *data, unsigned long magic,
|
||||||
struct cgroup_namespace *ns);
|
struct cgroup_namespace *ns);
|
||||||
|
int cgroup1_reconfigure(struct fs_context *ctx);
|
||||||
|
|
||||||
#endif /* __CGROUP_INTERNAL_H */
|
#endif /* __CGROUP_INTERNAL_H */
|
||||||
|
@ -1046,17 +1046,19 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cgroup1_remount(struct kernfs_root *kf_root, int *flags, char *data)
|
int cgroup1_reconfigure(struct fs_context *fc)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
|
||||||
|
struct kernfs_root *kf_root = kernfs_root_from_sb(fc->root->d_sb);
|
||||||
struct cgroup_root *root = cgroup_root_from_kf(kf_root);
|
struct cgroup_root *root = cgroup_root_from_kf(kf_root);
|
||||||
|
int ret = 0;
|
||||||
struct cgroup_sb_opts opts;
|
struct cgroup_sb_opts opts;
|
||||||
u16 added_mask, removed_mask;
|
u16 added_mask, removed_mask;
|
||||||
|
|
||||||
cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp);
|
cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp);
|
||||||
|
|
||||||
/* See what subsystems are wanted */
|
/* See what subsystems are wanted */
|
||||||
ret = parse_cgroupfs_options(data, &opts);
|
ret = parse_cgroupfs_options(ctx->data, &opts);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
@ -1106,7 +1108,6 @@ static int cgroup1_remount(struct kernfs_root *kf_root, int *flags, char *data)
|
|||||||
struct kernfs_syscall_ops cgroup1_kf_syscall_ops = {
|
struct kernfs_syscall_ops cgroup1_kf_syscall_ops = {
|
||||||
.rename = cgroup1_rename,
|
.rename = cgroup1_rename,
|
||||||
.show_options = cgroup1_show_options,
|
.show_options = cgroup1_show_options,
|
||||||
.remount_fs = cgroup1_remount,
|
|
||||||
.mkdir = cgroup_mkdir,
|
.mkdir = cgroup_mkdir,
|
||||||
.rmdir = cgroup_rmdir,
|
.rmdir = cgroup_rmdir,
|
||||||
.show_path = cgroup_show_path,
|
.show_path = cgroup_show_path,
|
||||||
|
@ -1811,12 +1811,13 @@ static int cgroup_show_options(struct seq_file *seq, struct kernfs_root *kf_root
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data)
|
static int cgroup_reconfigure(struct fs_context *fc)
|
||||||
{
|
{
|
||||||
|
struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
|
||||||
unsigned int root_flags;
|
unsigned int root_flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = parse_cgroup_root_flags(data, &root_flags);
|
ret = parse_cgroup_root_flags(ctx->data, &root_flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -2067,21 +2068,98 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
|
|||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
/*
|
||||||
int flags, const char *unused_dev_name,
|
* Destroy a cgroup filesystem context.
|
||||||
void *data)
|
*/
|
||||||
|
static void cgroup_fs_context_free(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
|
||||||
|
|
||||||
|
kfree(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cgroup_parse_monolithic(struct fs_context *fc, void *data)
|
||||||
|
{
|
||||||
|
struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
|
||||||
|
|
||||||
|
ctx->data = data;
|
||||||
|
if (ctx->data)
|
||||||
|
security_sb_eat_lsm_opts(ctx->data, &fc->security);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cgroup_get_tree(struct fs_context *fc)
|
||||||
{
|
{
|
||||||
struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
|
struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
|
||||||
struct dentry *dentry;
|
struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
|
||||||
|
unsigned int root_flags;
|
||||||
|
struct dentry *root;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
get_cgroup_ns(ns);
|
/* Check if the caller has permission to mount. */
|
||||||
|
if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
ret = parse_cgroup_root_flags(ctx->data, &root_flags);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
cgrp_dfl_visible = true;
|
||||||
|
cgroup_get_live(&cgrp_dfl_root.cgrp);
|
||||||
|
|
||||||
|
root = cgroup_do_mount(&cgroup2_fs_type, fc->sb_flags, &cgrp_dfl_root,
|
||||||
|
CGROUP2_SUPER_MAGIC, ns);
|
||||||
|
if (IS_ERR(root))
|
||||||
|
return PTR_ERR(root);
|
||||||
|
|
||||||
|
apply_cgroup_root_flags(root_flags);
|
||||||
|
fc->root = root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cgroup1_get_tree(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
|
||||||
|
struct cgroup_fs_context *ctx = cgroup_fc2context(fc);
|
||||||
|
struct dentry *root;
|
||||||
|
|
||||||
/* Check if the caller has permission to mount. */
|
/* Check if the caller has permission to mount. */
|
||||||
if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) {
|
if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
|
||||||
put_cgroup_ns(ns);
|
return -EPERM;
|
||||||
return ERR_PTR(-EPERM);
|
|
||||||
}
|
root = cgroup1_mount(&cgroup_fs_type, fc->sb_flags, ctx->data,
|
||||||
|
CGROUP_SUPER_MAGIC, ns);
|
||||||
|
if (IS_ERR(root))
|
||||||
|
return PTR_ERR(root);
|
||||||
|
|
||||||
|
fc->root = root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fs_context_operations cgroup_fs_context_ops = {
|
||||||
|
.free = cgroup_fs_context_free,
|
||||||
|
.parse_monolithic = cgroup_parse_monolithic,
|
||||||
|
.get_tree = cgroup_get_tree,
|
||||||
|
.reconfigure = cgroup_reconfigure,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct fs_context_operations cgroup1_fs_context_ops = {
|
||||||
|
.free = cgroup_fs_context_free,
|
||||||
|
.parse_monolithic = cgroup_parse_monolithic,
|
||||||
|
.get_tree = cgroup1_get_tree,
|
||||||
|
.reconfigure = cgroup1_reconfigure,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise the cgroup filesystem creation/reconfiguration context.
|
||||||
|
*/
|
||||||
|
static int cgroup_init_fs_context(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
struct cgroup_fs_context *ctx;
|
||||||
|
|
||||||
|
ctx = kzalloc(sizeof(struct cgroup_fs_context), GFP_KERNEL);
|
||||||
|
if (!ctx)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first time anyone tries to mount a cgroup, enable the list
|
* The first time anyone tries to mount a cgroup, enable the list
|
||||||
@ -2090,29 +2168,12 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|||||||
if (!use_task_css_set_links)
|
if (!use_task_css_set_links)
|
||||||
cgroup_enable_task_cg_lists();
|
cgroup_enable_task_cg_lists();
|
||||||
|
|
||||||
if (fs_type == &cgroup2_fs_type) {
|
fc->fs_private = ctx;
|
||||||
unsigned int root_flags;
|
if (fc->fs_type == &cgroup2_fs_type)
|
||||||
|
fc->ops = &cgroup_fs_context_ops;
|
||||||
ret = parse_cgroup_root_flags(data, &root_flags);
|
else
|
||||||
if (ret) {
|
fc->ops = &cgroup1_fs_context_ops;
|
||||||
put_cgroup_ns(ns);
|
return 0;
|
||||||
return ERR_PTR(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
cgrp_dfl_visible = true;
|
|
||||||
cgroup_get_live(&cgrp_dfl_root.cgrp);
|
|
||||||
|
|
||||||
dentry = cgroup_do_mount(&cgroup2_fs_type, flags, &cgrp_dfl_root,
|
|
||||||
CGROUP2_SUPER_MAGIC, ns);
|
|
||||||
if (!IS_ERR(dentry))
|
|
||||||
apply_cgroup_root_flags(root_flags);
|
|
||||||
} else {
|
|
||||||
dentry = cgroup1_mount(&cgroup_fs_type, flags, data,
|
|
||||||
CGROUP_SUPER_MAGIC, ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
put_cgroup_ns(ns);
|
|
||||||
return dentry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgroup_kill_sb(struct super_block *sb)
|
static void cgroup_kill_sb(struct super_block *sb)
|
||||||
@ -2136,14 +2197,14 @@ static void cgroup_kill_sb(struct super_block *sb)
|
|||||||
|
|
||||||
struct file_system_type cgroup_fs_type = {
|
struct file_system_type cgroup_fs_type = {
|
||||||
.name = "cgroup",
|
.name = "cgroup",
|
||||||
.mount = cgroup_mount,
|
.init_fs_context = cgroup_init_fs_context,
|
||||||
.kill_sb = cgroup_kill_sb,
|
.kill_sb = cgroup_kill_sb,
|
||||||
.fs_flags = FS_USERNS_MOUNT,
|
.fs_flags = FS_USERNS_MOUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct file_system_type cgroup2_fs_type = {
|
static struct file_system_type cgroup2_fs_type = {
|
||||||
.name = "cgroup2",
|
.name = "cgroup2",
|
||||||
.mount = cgroup_mount,
|
.init_fs_context = cgroup_init_fs_context,
|
||||||
.kill_sb = cgroup_kill_sb,
|
.kill_sb = cgroup_kill_sb,
|
||||||
.fs_flags = FS_USERNS_MOUNT,
|
.fs_flags = FS_USERNS_MOUNT,
|
||||||
};
|
};
|
||||||
@ -5268,7 +5329,6 @@ int cgroup_rmdir(struct kernfs_node *kn)
|
|||||||
|
|
||||||
static struct kernfs_syscall_ops cgroup_kf_syscall_ops = {
|
static struct kernfs_syscall_ops cgroup_kf_syscall_ops = {
|
||||||
.show_options = cgroup_show_options,
|
.show_options = cgroup_show_options,
|
||||||
.remount_fs = cgroup_remount,
|
|
||||||
.mkdir = cgroup_mkdir,
|
.mkdir = cgroup_mkdir,
|
||||||
.rmdir = cgroup_rmdir,
|
.rmdir = cgroup_rmdir,
|
||||||
.show_path = cgroup_show_path,
|
.show_path = cgroup_show_path,
|
||||||
|
Loading…
Reference in New Issue
Block a user