aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2012-07-20 06:39:25 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-22 15:44:01 -0400
commit406a3c638ce8b17d9704052c07955490f732c2b8 (patch)
treedb759dfccc6c09196773d0cc1ec260a7a4e9db07 /net
parent0690899b4d4501b3505be069b9a687e68ccbe15b (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/core/netprio_cgroup.c53
-rw-r--r--net/core/sock.c6
-rw-r--r--net/socket.c5
3 files changed, 58 insertions, 6 deletions
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index b2e9caa1ad1..63d15e8f80e 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -25,6 +25,8 @@
25#include <net/sock.h> 25#include <net/sock.h>
26#include <net/netprio_cgroup.h> 26#include <net/netprio_cgroup.h>
27 27
28#include <linux/fdtable.h>
29
28#define PRIOIDX_SZ 128 30#define PRIOIDX_SZ 128
29 31
30static unsigned long prioidx_map[PRIOIDX_SZ]; 32static unsigned long prioidx_map[PRIOIDX_SZ];
@@ -272,6 +274,56 @@ out_free_devname:
272 return ret; 274 return ret;
273} 275}
274 276
277void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
278{
279 struct task_struct *p;
280 char *tmp = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
281
282 if (!tmp) {
283 pr_warn("Unable to attach cgrp due to alloc failure!\n");
284 return;
285 }
286
287 cgroup_taskset_for_each(p, cgrp, tset) {
288 unsigned int fd;
289 struct fdtable *fdt;
290 struct files_struct *files;
291
292 task_lock(p);
293 files = p->files;
294 if (!files) {
295 task_unlock(p);
296 continue;
297 }
298
299 rcu_read_lock();
300 fdt = files_fdtable(files);
301 for (fd = 0; fd < fdt->max_fds; fd++) {
302 char *path;
303 struct file *file;
304 struct socket *sock;
305 unsigned long s;
306 int rv, err = 0;
307
308 file = fcheck_files(files, fd);
309 if (!file)
310 continue;
311
312 path = d_path(&file->f_path, tmp, PAGE_SIZE);
313 rv = sscanf(path, "socket:[%lu]", &s);
314 if (rv <= 0)
315 continue;
316
317 sock = sock_from_file(file, &err);
318 if (!err)
319 sock_update_netprioidx(sock->sk, p);
320 }
321 rcu_read_unlock();
322 task_unlock(p);
323 }
324 kfree(tmp);
325}
326
275static struct cftype ss_files[] = { 327static struct cftype ss_files[] = {
276 { 328 {
277 .name = "prioidx", 329 .name = "prioidx",
@@ -289,6 +341,7 @@ struct cgroup_subsys net_prio_subsys = {
289 .name = "net_prio", 341 .name = "net_prio",
290 .create = cgrp_create, 342 .create = cgrp_create,
291 .destroy = cgrp_destroy, 343 .destroy = cgrp_destroy,
344 .attach = net_prio_attach,
292#ifdef CONFIG_NETPRIO_CGROUP 345#ifdef CONFIG_NETPRIO_CGROUP
293 .subsys_id = net_prio_subsys_id, 346 .subsys_id = net_prio_subsys_id,
294#endif 347#endif
diff --git a/net/core/sock.c b/net/core/sock.c
index 24039ac1242..2676a88f533 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1180,12 +1180,12 @@ void sock_update_classid(struct sock *sk)
1180} 1180}
1181EXPORT_SYMBOL(sock_update_classid); 1181EXPORT_SYMBOL(sock_update_classid);
1182 1182
1183void sock_update_netprioidx(struct sock *sk) 1183void sock_update_netprioidx(struct sock *sk, struct task_struct *task)
1184{ 1184{
1185 if (in_interrupt()) 1185 if (in_interrupt())
1186 return; 1186 return;
1187 1187
1188 sk->sk_cgrp_prioidx = task_netprioidx(current); 1188 sk->sk_cgrp_prioidx = task_netprioidx(task);
1189} 1189}
1190EXPORT_SYMBOL_GPL(sock_update_netprioidx); 1190EXPORT_SYMBOL_GPL(sock_update_netprioidx);
1191#endif 1191#endif
@@ -1215,7 +1215,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
1215 atomic_set(&sk->sk_wmem_alloc, 1); 1215 atomic_set(&sk->sk_wmem_alloc, 1);
1216 1216
1217 sock_update_classid(sk); 1217 sock_update_classid(sk);
1218 sock_update_netprioidx(sk); 1218 sock_update_netprioidx(sk, current);
1219 } 1219 }
1220 1220
1221 return sk; 1221 return sk;
diff --git a/net/socket.c b/net/socket.c
index 0452dca4cd2..dfe5b66c97e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -398,7 +398,7 @@ int sock_map_fd(struct socket *sock, int flags)
398} 398}
399EXPORT_SYMBOL(sock_map_fd); 399EXPORT_SYMBOL(sock_map_fd);
400 400
401static struct socket *sock_from_file(struct file *file, int *err) 401struct socket *sock_from_file(struct file *file, int *err)
402{ 402{
403 if (file->f_op == &socket_file_ops) 403 if (file->f_op == &socket_file_ops)
404 return file->private_data; /* set in sock_map_fd */ 404 return file->private_data; /* set in sock_map_fd */
@@ -406,6 +406,7 @@ static struct socket *sock_from_file(struct file *file, int *err)
406 *err = -ENOTSOCK; 406 *err = -ENOTSOCK;
407 return NULL; 407 return NULL;
408} 408}
409EXPORT_SYMBOL(sock_from_file);
409 410
410/** 411/**
411 * sockfd_lookup - Go from a file number to its socket slot 412 * sockfd_lookup - Go from a file number to its socket slot
@@ -554,8 +555,6 @@ static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
554 555
555 sock_update_classid(sock->sk); 556 sock_update_classid(sock->sk);
556 557
557 sock_update_netprioidx(sock->sk);
558
559 si->sock = sock; 558 si->sock = sock;
560 si->scm = NULL; 559 si->scm = NULL;
561 si->msg = msg; 560 si->msg = msg;