From f7128f0f8f4430af8a6d47ea897d98eb4cf0d46f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 26 Oct 2018 23:24:58 -0400 Subject: [PATCH] cgroup: Convert cgroup_idr to XArray Signed-off-by: Matthew Wilcox --- include/linux/cgroup-defs.h | 4 ++-- kernel/cgroup/cgroup.c | 33 ++++++++++++++------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 430e219e3aba..341d062905be 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -355,7 +355,7 @@ struct cgroup { unsigned long flags; /* "unsigned long" so bitops work */ /* - * idr allocated in-hierarchy ID. + * In-hierarchy ID. * * ID 0 is not used, the ID of the root cgroup is always 1, and a * new cgroup will be assigned with a smallest available ID. @@ -521,7 +521,7 @@ struct cgroup_root { unsigned int flags; /* IDs for cgroups in this hierarchy */ - struct idr cgroup_idr; + struct xarray cgroup_ids; /* The path to use for release notifications. */ char release_agent_path[PATH_MAX]; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 753afbca549f..bc9c8fd63d8d 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -90,7 +90,7 @@ char trace_cgroup_path[TRACE_CGROUP_PATH_LEN]; bool cgroup_debug __read_mostly; /* - * Protects cgroup_idr and css_idr so that IDs can be released without + * Protects css_idr so that IDs can be released without * grabbing cgroup_mutex. */ static DEFINE_SPINLOCK(cgroup_idr_lock); @@ -1309,10 +1309,7 @@ static void cgroup_exit_root_id(struct cgroup_root *root) void cgroup_free_root(struct cgroup_root *root) { - if (root) { - idr_destroy(&root->cgroup_idr); - kfree(root); - } + kfree(root); } static void cgroup_destroy_root(struct cgroup_root *root) @@ -1976,7 +1973,7 @@ void init_cgroup_root(struct cgroup_fs_context *ctx) atomic_set(&root->nr_cgrps, 1); cgrp->root = root; init_cgroup_housekeeping(cgrp); - idr_init(&root->cgroup_idr); + xa_init_flags(&root->cgroup_ids, XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_BH); root->flags = ctx->flags; if (ctx->release_agent) @@ -1997,10 +1994,10 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) lockdep_assert_held(&cgroup_mutex); - ret = cgroup_idr_alloc(&root->cgroup_idr, root_cgrp, 1, 2, GFP_KERNEL); + ret = xa_insert_bh(&root->cgroup_ids, 1, root_cgrp, GFP_KERNEL); if (ret < 0) goto out; - root_cgrp->id = ret; + root_cgrp->id = 1; root_cgrp->ancestor_ids[0] = ret; ret = percpu_ref_init(&root_cgrp->self.refcnt, css_release, @@ -5036,7 +5033,7 @@ static void css_release_work_fn(struct work_struct *work) tcgrp->nr_dying_descendants--; spin_unlock_irq(&css_set_lock); - cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); + xa_erase_bh(&cgrp->root->cgroup_ids, cgrp->id); cgrp->id = -1; /* @@ -5226,12 +5223,10 @@ static struct cgroup *cgroup_create(struct cgroup *parent) goto out_cancel_ref; } - /* - * Temporarily set the pointer to NULL, so idr_find() won't return - * a half-baked cgroup. - */ - cgrp->id = cgroup_idr_alloc(&root->cgroup_idr, NULL, 2, 0, GFP_KERNEL); - if (cgrp->id < 0) { + /* Use a NULL pointer, so we won't find a half-baked cgroup. */ + ret = xa_alloc_bh(&root->cgroup_ids, &cgrp->id, NULL, xa_limit_32b, + GFP_KERNEL); + if (ret < 0) { ret = -ENOMEM; goto out_stat_exit; } @@ -5244,7 +5239,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent) ret = psi_cgroup_alloc(cgrp); if (ret) - goto out_idr_free; + goto out_xa_free; ret = cgroup_bpf_inherit(cgrp); if (ret) @@ -5293,7 +5288,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent) * @cgrp is now fully operational. If something fails after this * point, it'll be released via the normal destruction path. */ - cgroup_idr_replace(&root->cgroup_idr, cgrp, cgrp->id); + xa_store_bh(&root->cgroup_ids, cgrp->id, cgrp, 0); /* * On the default hierarchy, a child doesn't automatically inherit @@ -5308,8 +5303,8 @@ static struct cgroup *cgroup_create(struct cgroup *parent) out_psi_free: psi_cgroup_free(cgrp); -out_idr_free: - cgroup_idr_remove(&root->cgroup_idr, cgrp->id); +out_xa_free: + xa_erase_bh(&root->cgroup_ids, cgrp->id); out_stat_exit: if (cgroup_on_dfl(parent)) cgroup_rstat_exit(cgrp); -- 2.50.1