Skip to content

Commit

Permalink
net: netprio_cgroup: rework update socket logic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
John Fastabend authored and David S. Miller committed Jul 22, 2012
1 parent 0690899 commit 406a3c6
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/linux/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ extern int sock_recvmsg(struct socket *sock, struct msghdr *msg,
size_t size, int flags);
extern int sock_map_fd(struct socket *sock, int flags);
extern struct socket *sockfd_lookup(int fd, int *err);
extern struct socket *sock_from_file(struct file *file, int *err);
#define sockfd_put(sock) fput(sock->file)
extern int net_ratelimit(void);

Expand Down
4 changes: 2 additions & 2 deletions include/net/netprio_cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct cgroup_netprio_state {
extern int net_prio_subsys_id;
#endif

extern void sock_update_netprioidx(struct sock *sk);
extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task);

#if IS_BUILTIN(CONFIG_NETPRIO_CGROUP)

Expand Down Expand Up @@ -82,7 +82,7 @@ static inline u32 task_netprioidx(struct task_struct *p)
#endif /* CONFIG_NETPRIO_CGROUP */

#else
#define sock_update_netprioidx(sk)
#define sock_update_netprioidx(sk, task)
#endif

#endif /* _NET_CLS_CGROUP_H */
53 changes: 53 additions & 0 deletions net/core/netprio_cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -272,6 +274,56 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft,
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",
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions net/core/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,15 @@ int sock_map_fd(struct socket *sock, int flags)
}
EXPORT_SYMBOL(sock_map_fd);

static struct socket *sock_from_file(struct file *file, int *err)
struct socket *sock_from_file(struct file *file, int *err)
{
if (file->f_op == &socket_file_ops)
return file->private_data; /* set in sock_map_fd */

*err = -ENOTSOCK;
return NULL;
}
EXPORT_SYMBOL(sock_from_file);

/**
* sockfd_lookup - Go from a file number to its socket slot
Expand Down Expand Up @@ -554,8 +555,6 @@ static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,

sock_update_classid(sock->sk);

sock_update_netprioidx(sock->sk);

si->sock = sock;
si->scm = NULL;
si->msg = msg;
Expand Down

0 comments on commit 406a3c6

Please sign in to comment.