--- x/kernel/cgroup/cgroup.c +++ y/kernel/cgroup/cgroup.c @@ -3995,7 +3995,7 @@ static int cgroup_cpu_pressure_show(stru static ssize_t pressure_write(struct kernfs_open_file *of, char *buf, size_t nbytes, enum psi_res res) { - struct cgroup_file_ctx *ctx = of->priv; + struct cgroup_file_ctx *ctx; struct psi_trigger *new; struct cgroup *cgrp; struct psi_group *psi; @@ -4004,14 +4004,18 @@ static ssize_t pressure_write(struct ker if (!cgrp) return -ENODEV; - cgroup_get(cgrp); - cgroup_kn_unlock(of->kn); - + ctx = of->priv; + if (!ctx) { + cgroup_kn_unlock(of->kn); + return -ENODEV; + } /* Allow only one trigger per file descriptor */ if (ctx->psi.trigger) { - cgroup_put(cgrp); + cgroup_kn_unlock(of->kn); return -EBUSY; } + cgroup_get(cgrp); + cgroup_kn_unlock(of->kn); psi = cgroup_psi(cgrp); new = psi_trigger_create(psi, buf, res, of->file, of); @@ -4019,9 +4023,27 @@ static ssize_t pressure_write(struct ker cgroup_put(cgrp); return PTR_ERR(new); } + cgroup_put(cgrp); + cgrp = cgroup_kn_lock_live(of->kn, false); + if (!cgrp) { + psi_trigger_destroy(new); + return -ENODEV; + } + ctx = of->priv; + if (!ctx) { + cgroup_kn_unlock(of->kn); + psi_trigger_destroy(new); + return -ENODEV; + } + /* Allow only one trigger per file descriptor */ + if (ctx->psi.trigger) { + cgroup_kn_unlock(of->kn); + psi_trigger_destroy(new); + return -EBUSY; + } smp_store_release(&ctx->psi.trigger, new); - cgroup_put(cgrp); + cgroup_kn_unlock(of->kn); return nbytes; }