	__acquires(&cgroup_mutex) __acquires(&cgroup_threadgroup_rwsem)
{
	int ret;
	struct cgroup *dst_cgrp = NULL;
	struct css_set *cset;
	struct super_block *sb;
	struct file *f;

	if (kargs->flags & CLONE_INTO_CGROUP)
		mutex_lock(&cgroup_mutex);

	cgroup_threadgroup_change_begin(current);

	spin_lock_irq(&css_set_lock);
	cset = task_css_set(current);
	get_css_set(cset);
	spin_unlock_irq(&css_set_lock);

	if (!(kargs->flags & CLONE_INTO_CGROUP)) {
		kargs->cset = cset;
		return 0;
	}

	f = fget_raw(kargs->cgroup);
	if (!f) {
		ret = -EBADF;
		goto err;
	}
	sb = f->f_path.dentry->d_sb;

	dst_cgrp = cgroup_get_from_file(f);
	if (IS_ERR(dst_cgrp)) {
		ret = PTR_ERR(dst_cgrp);
		dst_cgrp = NULL;
		goto err;
	}

	if (cgroup_is_dead(dst_cgrp)) {
		ret = -ENODEV;
		goto err;
	}

	/*
	 * Verify that we the target cgroup is writable for us. This is
	 * usually done by the vfs layer but since we're not going through
	 * the vfs layer here we need to do it "manually".
	 */
	ret = cgroup_may_write(dst_cgrp, sb);
	if (ret)
		goto err;

	ret = cgroup_attach_permissions(cset->dfl_cgrp, dst_cgrp, sb,
					!(kargs->flags & CLONE_THREAD),
					current->nsproxy->cgroup_ns);
	if (ret)
		goto err;

	kargs->cset = find_css_set(cset, dst_cgrp);
	if (!kargs->cset) {
		ret = -ENOMEM;
		goto err;
	}

	put_css_set(cset);
	fput(f);
	kargs->cgrp = dst_cgrp;
	return ret;

err:
	cgroup_threadgroup_change_end(current);
	mutex_unlock(&cgroup_mutex);
	if (f)
		fput(f);
	if (dst_cgrp)
		cgroup_put(dst_cgrp);
	put_css_set(cset);
	if (kargs->cset)
		put_css_set(kargs->cset);
	return ret;
}
	__acquires(&cgroup_mutex) __acquires(&cgroup_threadgroup_rwsem)
{
	int ret;
	struct cgroup *dst_cgrp = NULL;
	struct css_set *cset;
	struct super_block *sb;
	struct file *f;

	if (kargs->flags & CLONE_INTO_CGROUP)
		mutex_lock(&cgroup_mutex);

	cgroup_threadgroup_change_begin(current);

	spin_lock_irq(&css_set_lock);
	cset = task_css_set(current);
	get_css_set(cset);
	spin_unlock_irq(&css_set_lock);

	if (!(kargs->flags & CLONE_INTO_CGROUP)) {
		kargs->cset = cset;
		return 0;
	}

	f = fget_raw(kargs->cgroup);
	if (!f) {
		ret = -EBADF;
		goto err;
	}
	sb = f->f_path.dentry->d_sb;

	dst_cgrp = cgroup_get_from_file(f);
	if (IS_ERR(dst_cgrp)) {
		ret = PTR_ERR(dst_cgrp);
		dst_cgrp = NULL;
		goto err;
	}

	if (cgroup_is_dead(dst_cgrp)) {
		ret = -ENODEV;
		goto err;
	}

	 
	ret = cgroup_may_write(dst_cgrp, sb);
	if (ret)
		goto err;

	ret = cgroup_attach_permissions(cset->dfl_cgrp, dst_cgrp, sb,
					!(kargs->flags & CLONE_THREAD),
					current->nsproxy->cgroup_ns);
	if (ret)
		goto err;

	kargs->cset = find_css_set(cset, dst_cgrp);
	if (!kargs->cset) {
		ret = -ENOMEM;
		goto err;
	}

	put_css_set(cset);
	fput(f);
	kargs->cgrp = dst_cgrp;
	return ret;

err:
	cgroup_threadgroup_change_end(current);
	mutex_unlock(&cgroup_mutex);
	if (f)
		fput(f);
	if (dst_cgrp)
		cgroup_put(dst_cgrp);
	put_css_set(cset);
	if (kargs->cset)
		put_css_set(kargs->cset);
	return ret;
}