> +static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts) > +{ > + struct cgroupfs_root *root; > + > + if (!opts->subsys_bits) > + return ERR_PTR(-EINVAL); > + > + root = kzalloc(sizeof(*root), GFP_KERNEL); > + if (!root) > + return ERR_PTR(-ENOMEM); > + > + init_cgroup_root(root); > + root->subsys_bits = opts->subsys_bits; > + root->flags = opts->flags; > + if (opts->release_agent) > + strcpy(root->release_agent_path, opts->release_agent); > + if (opts->name) > + strcpy(root->name, opts->name); > + opts->created_root = true; > + return root; > +} > + > static int cgroup_set_super(struct super_block *sb, void *data) > { > int ret; > - struct cgroupfs_root *root = data; > + struct cgroup_sb_opts *opts = data; > + struct cgroupfs_root *root; > > + root = cgroup_root_from_opts(opts); > + if (IS_ERR(root)) > + return PTR_ERR(root); > ret = set_anon_super(sb, NULL); > - if (ret) > + if (ret) { > + kfree(root); > return ret; > + } > > sb->s_fs_info = root; > root->sb = sb; > @@ -1039,44 +1091,23 @@ static int cgroup_get_sb(struct file_system_type *fs_type, > struct cgroup_sb_opts opts; > int ret = 0; > struct super_block *sb; > - struct cgroupfs_root *root; > - struct list_head tmp_cg_links; > > /* First find the desired set of subsystems */ > ret = parse_cgroupfs_options(data, &opts); > - if (ret) { > - kfree(opts.release_agent); > - return ret; > - } > - > - root = kzalloc(sizeof(*root), GFP_KERNEL); > - if (!root) { > - kfree(opts.release_agent); > - return -ENOMEM; > - } > - > - init_cgroup_root(root); > - root->subsys_bits = opts.subsys_bits; > - root->flags = opts.flags; > - if (opts.release_agent) { > - strcpy(root->release_agent_path, opts.release_agent); > - kfree(opts.release_agent); > - } > + if (ret) > + goto out_err; > > - sb = sget(fs_type, cgroup_test_super, cgroup_set_super, root); > + sb = sget(fs_type, cgroup_test_super, cgroup_set_super, &opts); > cgroup_set_super() is called with spinlock held, so we can't do kmalloc(GFP_KERNEL). sget(...) { spin_lock(&sb_lock); ... err = set(s, data); if (err) { spin_unlock(&sb_lock); ... } > if (IS_ERR(sb)) { > - kfree(root); > - return PTR_ERR(sb); > + ret = PTR_ERR(sb); > + goto out_err; > } > > - if (sb->s_fs_info != root) { > - /* Reusing an existing superblock */ > - BUG_ON(sb->s_root == NULL); > - kfree(root); > - root = NULL; > - } else { > + if (opts.created_root) { > /* New superblock */ > + struct cgroupfs_root *root = sb->s_fs_info; > + struct list_head tmp_cg_links; > struct cgroup *root_cgrp = &root->top_cgroup; > struct inode *inode; > int i; > @@ -1109,7 +1140,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type, > if (ret == -EBUSY) { > mutex_unlock(&cgroup_mutex); > mutex_unlock(&inode->i_mutex); > - goto free_cg_links; > + free_cg_links(&tmp_cg_links); > + goto drop_new_super; > } > > /* EBUSY should be the only error here */ > @@ -1146,12 +1178,17 @@ static int cgroup_get_sb(struct file_system_type *fs_type, > } > > simple_set_mnt(mnt, sb); > + kfree(opts.release_agent); > + kfree(opts.name); > return 0; > > - free_cg_links: > - free_cg_links(&tmp_cg_links); > drop_new_super: > deactivate_locked_super(sb); > + > + out_err: > + kfree(opts.release_agent); > + kfree(opts.name); > + > return ret; > } _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers