Hi Tejun, Today's linux-next merge of the cgroup tree got a conflict in: include/linux/cgroup.h kernel/cgroup.c between commit: bd1060a1d671 ("sock, cgroup: add sock->sk_cgroup") from the net-next tree and commit: f176ae3a5df6 ("cgroup: introduce cgroup namespaces") from the cgroup tree. I fixed it up (see below) and can carry the fix as necessary (no action is required). -- Cheers, Stephen Rothwell sfr@xxxxxxxxxxxxxxxx diff --cc include/linux/cgroup.h index 322a28482745,6d0992f3543d..000000000000 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@@ -577,45 -569,47 +569,88 @@@ static inline int cgroup_init(void) { r #endif /* !CONFIG_CGROUPS */ +/* + * sock->sk_cgrp_data handling. For more info, see sock_cgroup_data + * definition in cgroup-defs.h. + */ +#ifdef CONFIG_SOCK_CGROUP_DATA + +#if defined(CONFIG_CGROUP_NET_PRIO) || defined(CONFIG_CGROUP_NET_CLASSID) +extern spinlock_t cgroup_sk_update_lock; +#endif + +void cgroup_sk_alloc_disable(void); +void cgroup_sk_alloc(struct sock_cgroup_data *skcd); +void cgroup_sk_free(struct sock_cgroup_data *skcd); + +static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd) +{ +#if defined(CONFIG_CGROUP_NET_PRIO) || defined(CONFIG_CGROUP_NET_CLASSID) + unsigned long v; + + /* + * @skcd->val is 64bit but the following is safe on 32bit too as we + * just need the lower ulong to be written and read atomically. + */ + v = READ_ONCE(skcd->val); + + if (v & 1) + return &cgrp_dfl_root.cgrp; + + return (struct cgroup *)(unsigned long)v ?: &cgrp_dfl_root.cgrp; +#else + return (struct cgroup *)(unsigned long)skcd->val; +#endif +} + +#else /* CONFIG_CGROUP_DATA */ + +static inline void cgroup_sk_alloc(struct sock_cgroup_data *skcd) {} +static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {} + +#endif /* CONFIG_CGROUP_DATA */ + + struct cgroup_namespace { + atomic_t count; + struct ns_common ns; + struct user_namespace *user_ns; + struct css_set *root_cset; + }; + + extern struct cgroup_namespace init_cgroup_ns; + + #ifdef CONFIG_CGROUPS + + void free_cgroup_ns(struct cgroup_namespace *ns); + + struct cgroup_namespace * + copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns, + struct cgroup_namespace *old_ns); + + char *cgroup_path(struct cgroup *cgrp, char *buf, size_t buflen); + + #else /* !CONFIG_CGROUPS */ + + static inline void free_cgroup_ns(struct cgroup_namespace *ns) { } + static inline struct cgroup_namespace * + copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns, + struct cgroup_namespace *old_ns) + { + return old_ns; + } + + #endif /* !CONFIG_CGROUPS */ + + static inline void get_cgroup_ns(struct cgroup_namespace *ns) + { + if (ns) + atomic_inc(&ns->count); + } + + static inline void put_cgroup_ns(struct cgroup_namespace *ns) + { + if (ns && atomic_dec_and_test(&ns->count)) + free_cgroup_ns(ns); + } + #endif /* _LINUX_CGROUP_H */ diff --cc kernel/cgroup.c index fe95970b1f79,7eb1d9de2afa..000000000000 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@@ -57,8 -57,11 +57,12 @@@ #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */ #include <linux/kthread.h> #include <linux/delay.h> + #include <linux/proc_ns.h> + #include <linux/nsproxy.h> + #include <linux/proc_ns.h> + #include <linux/atomic.h> +#include <net/sock.h> /* * pidlists linger the following amount before being destroyed. The goal @@@ -5839,59 -5900,134 +5901,187 @@@ struct cgroup *cgroup_get_from_path(con } EXPORT_SYMBOL_GPL(cgroup_get_from_path); +/* + * sock->sk_cgrp_data handling. For more info, see sock_cgroup_data + * definition in cgroup-defs.h. + */ +#ifdef CONFIG_SOCK_CGROUP_DATA + +#if defined(CONFIG_CGROUP_NET_PRIO) || defined(CONFIG_CGROUP_NET_CLASSID) + +DEFINE_SPINLOCK(cgroup_sk_update_lock); +static bool cgroup_sk_alloc_disabled __read_mostly; + +void cgroup_sk_alloc_disable(void) +{ + if (cgroup_sk_alloc_disabled) + return; + pr_info("cgroup: disabling cgroup2 socket matching due to net_prio or net_cls activation\n"); + cgroup_sk_alloc_disabled = true; +} + +#else + +#define cgroup_sk_alloc_disabled false + +#endif + +void cgroup_sk_alloc(struct sock_cgroup_data *skcd) +{ + if (cgroup_sk_alloc_disabled) + return; + + rcu_read_lock(); + + while (true) { + struct css_set *cset; + + cset = task_css_set(current); + if (likely(cgroup_tryget(cset->dfl_cgrp))) { + skcd->val = (unsigned long)cset->dfl_cgrp; + break; + } + cpu_relax(); + } + + rcu_read_unlock(); +} + +void cgroup_sk_free(struct sock_cgroup_data *skcd) +{ + cgroup_put(sock_cgroup_ptr(skcd)); +} + +#endif /* CONFIG_SOCK_CGROUP_DATA */ + + /* cgroup namespaces */ + + static struct cgroup_namespace *alloc_cgroup_ns(void) + { + struct cgroup_namespace *new_ns; + int ret; + + new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL); + if (!new_ns) + return ERR_PTR(-ENOMEM); + ret = ns_alloc_inum(&new_ns->ns); + if (ret) { + kfree(new_ns); + return ERR_PTR(ret); + } + atomic_set(&new_ns->count, 1); + new_ns->ns.ops = &cgroupns_operations; + return new_ns; + } + + void free_cgroup_ns(struct cgroup_namespace *ns) + { + put_css_set(ns->root_cset); + put_user_ns(ns->user_ns); + ns_free_inum(&ns->ns); + kfree(ns); + } + EXPORT_SYMBOL(free_cgroup_ns); + + struct cgroup_namespace * + copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns, + struct cgroup_namespace *old_ns) + { + struct cgroup_namespace *new_ns = NULL; + struct css_set *cset = NULL; + int err; + + BUG_ON(!old_ns); + + if (!(flags & CLONE_NEWCGROUP)) { + get_cgroup_ns(old_ns); + return old_ns; + } + + /* Allow only sysadmin to create cgroup namespace. */ + err = -EPERM; + if (!ns_capable(user_ns, CAP_SYS_ADMIN)) + goto err_out; + + cset = task_css_set(current); + get_css_set(cset); + + err = -ENOMEM; + new_ns = alloc_cgroup_ns(); + if (!new_ns) + goto err_out; + + new_ns->user_ns = get_user_ns(user_ns); + new_ns->root_cset = cset; + + return new_ns; + + err_out: + if (cset) + put_css_set(cset); + kfree(new_ns); + return ERR_PTR(err); + } + + static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns) + { + return container_of(ns, struct cgroup_namespace, ns); + } + + static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns) + { + struct cgroup_namespace *cgroup_ns = to_cg_ns(ns); + + if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) || + !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN)) + return -EPERM; + + /* Don't need to do anything if we are attaching to our own cgroupns. */ + if (cgroup_ns == nsproxy->cgroup_ns) + return 0; + + get_cgroup_ns(cgroup_ns); + put_cgroup_ns(nsproxy->cgroup_ns); + nsproxy->cgroup_ns = cgroup_ns; + + return 0; + } + + static struct ns_common *cgroupns_get(struct task_struct *task) + { + struct cgroup_namespace *ns = NULL; + struct nsproxy *nsproxy; + + task_lock(task); + nsproxy = task->nsproxy; + if (nsproxy) { + ns = nsproxy->cgroup_ns; + get_cgroup_ns(ns); + } + task_unlock(task); + + return ns ? &ns->ns : NULL; + } + + static void cgroupns_put(struct ns_common *ns) + { + put_cgroup_ns(to_cg_ns(ns)); + } + + const struct proc_ns_operations cgroupns_operations = { + .name = "cgroup", + .type = CLONE_NEWCGROUP, + .get = cgroupns_get, + .put = cgroupns_put, + .install = cgroupns_install, + }; + + static __init int cgroup_namespaces_init(void) + { + return 0; + } + subsys_initcall(cgroup_namespaces_init); + #ifdef CONFIG_CGROUP_DEBUG static struct cgroup_subsys_state * debug_css_alloc(struct cgroup_subsys_state *parent_css) -- To unsubscribe from this list: send the line "unsubscribe linux-next" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html