net: netprio_cgroup: rework update socket logic
Instead of updating the sk_cgrp_prioidx struct field on every send this only updates the field when a task is moved via cgroup infrastructure. This allows sockets that may be used by a kernel worker thread to be managed. For example in the iscsi case today a user can put iscsid in a netprio cgroup and control traffic will be sent with the correct sk_cgrp_prioidx value set but as soon as data is sent the kernel worker thread isssues a send and sk_cgrp_prioidx is updated with the kernel worker threads value which is the default case. It seems more correct to only update the field when the user explicitly sets it via control group infrastructure. This allows the users to manage sockets that may be used with other threads. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
0690899b4d
commit
406a3c638c
@@ -25,6 +25,8 @@
|
||||
#include <net/sock.h>
|
||||
#include <net/netprio_cgroup.h>
|
||||
|
||||
#include <linux/fdtable.h>
|
||||
|
||||
#define PRIOIDX_SZ 128
|
||||
|
||||
static unsigned long prioidx_map[PRIOIDX_SZ];
|
||||
@@ -272,6 +274,56 @@ out_free_devname:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
|
||||
{
|
||||
struct task_struct *p;
|
||||
char *tmp = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
|
||||
|
||||
if (!tmp) {
|
||||
pr_warn("Unable to attach cgrp due to alloc failure!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cgroup_taskset_for_each(p, cgrp, tset) {
|
||||
unsigned int fd;
|
||||
struct fdtable *fdt;
|
||||
struct files_struct *files;
|
||||
|
||||
task_lock(p);
|
||||
files = p->files;
|
||||
if (!files) {
|
||||
task_unlock(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
fdt = files_fdtable(files);
|
||||
for (fd = 0; fd < fdt->max_fds; fd++) {
|
||||
char *path;
|
||||
struct file *file;
|
||||
struct socket *sock;
|
||||
unsigned long s;
|
||||
int rv, err = 0;
|
||||
|
||||
file = fcheck_files(files, fd);
|
||||
if (!file)
|
||||
continue;
|
||||
|
||||
path = d_path(&file->f_path, tmp, PAGE_SIZE);
|
||||
rv = sscanf(path, "socket:[%lu]", &s);
|
||||
if (rv <= 0)
|
||||
continue;
|
||||
|
||||
sock = sock_from_file(file, &err);
|
||||
if (!err)
|
||||
sock_update_netprioidx(sock->sk, p);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
task_unlock(p);
|
||||
}
|
||||
kfree(tmp);
|
||||
}
|
||||
|
||||
static struct cftype ss_files[] = {
|
||||
{
|
||||
.name = "prioidx",
|
||||
@@ -289,6 +341,7 @@ struct cgroup_subsys net_prio_subsys = {
|
||||
.name = "net_prio",
|
||||
.create = cgrp_create,
|
||||
.destroy = cgrp_destroy,
|
||||
.attach = net_prio_attach,
|
||||
#ifdef CONFIG_NETPRIO_CGROUP
|
||||
.subsys_id = net_prio_subsys_id,
|
||||
#endif
|
||||
|
@@ -1180,12 +1180,12 @@ void sock_update_classid(struct sock *sk)
|
||||
}
|
||||
EXPORT_SYMBOL(sock_update_classid);
|
||||
|
||||
void sock_update_netprioidx(struct sock *sk)
|
||||
void sock_update_netprioidx(struct sock *sk, struct task_struct *task)
|
||||
{
|
||||
if (in_interrupt())
|
||||
return;
|
||||
|
||||
sk->sk_cgrp_prioidx = task_netprioidx(current);
|
||||
sk->sk_cgrp_prioidx = task_netprioidx(task);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_update_netprioidx);
|
||||
#endif
|
||||
@@ -1215,7 +1215,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
|
||||
atomic_set(&sk->sk_wmem_alloc, 1);
|
||||
|
||||
sock_update_classid(sk);
|
||||
sock_update_netprioidx(sk);
|
||||
sock_update_netprioidx(sk, current);
|
||||
}
|
||||
|
||||
return sk;
|
||||
|
Reference in New Issue
Block a user