2013-12-29 18:27:10 +01:00
/*
* net / core / netclassid_cgroup . c Classid Cgroupfs Handling
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*
* Authors : Thomas Graf < tgraf @ suug . ch >
*/
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/cgroup.h>
# include <linux/fdtable.h>
# include <net/cls_cgroup.h>
# include <net/sock.h>
static inline struct cgroup_cls_state * css_cls_state ( struct cgroup_subsys_state * css )
{
return css ? container_of ( css , struct cgroup_cls_state , css ) : NULL ;
}
struct cgroup_cls_state * task_cls_state ( struct task_struct * p )
{
2015-07-22 12:23:20 +03:00
return css_cls_state ( task_css_check ( p , net_cls_cgrp_id ,
rcu_read_lock_bh_held ( ) ) ) ;
2013-12-29 18:27:10 +01:00
}
EXPORT_SYMBOL_GPL ( task_cls_state ) ;
static struct cgroup_subsys_state *
cgrp_css_alloc ( struct cgroup_subsys_state * parent_css )
{
struct cgroup_cls_state * cs ;
cs = kzalloc ( sizeof ( * cs ) , GFP_KERNEL ) ;
if ( ! cs )
return ERR_PTR ( - ENOMEM ) ;
return & cs - > css ;
}
static int cgrp_css_online ( struct cgroup_subsys_state * css )
{
struct cgroup_cls_state * cs = css_cls_state ( css ) ;
2014-05-16 13:22:48 -04:00
struct cgroup_cls_state * parent = css_cls_state ( css - > parent ) ;
2013-12-29 18:27:10 +01:00
if ( parent )
cs - > classid = parent - > classid ;
return 0 ;
}
static void cgrp_css_free ( struct cgroup_subsys_state * css )
{
kfree ( css_cls_state ( css ) ) ;
}
2015-11-20 12:31:39 -08:00
static int update_classid_sock ( const void * v , struct file * file , unsigned n )
2013-12-29 18:27:10 +01:00
{
int err ;
struct socket * sock = sock_from_file ( file , & err ) ;
if ( sock )
2015-12-07 17:38:52 -05:00
sock_cgroup_set_classid ( & sock - > sk - > sk_cgrp_data ,
( unsigned long ) v ) ;
2013-12-29 18:27:10 +01:00
return 0 ;
}
2015-11-20 12:31:39 -08:00
static void update_classid ( struct cgroup_subsys_state * css , void * v )
2013-12-29 18:27:10 +01:00
{
2015-11-20 12:31:39 -08:00
struct css_task_iter it ;
2013-12-29 18:27:10 +01:00
struct task_struct * p ;
2015-11-20 12:31:39 -08:00
css_task_iter_start ( css , & it ) ;
while ( ( p = css_task_iter_next ( & it ) ) ) {
2013-12-29 18:27:10 +01:00
task_lock ( p ) ;
2015-11-20 12:31:39 -08:00
iterate_fd ( p - > files , 0 , update_classid_sock , v ) ;
2013-12-29 18:27:10 +01:00
task_unlock ( p ) ;
}
2015-11-20 12:31:39 -08:00
css_task_iter_end ( & it ) ;
}
static void cgrp_attach ( struct cgroup_subsys_state * css ,
struct cgroup_taskset * tset )
{
update_classid ( css ,
( void * ) ( unsigned long ) css_cls_state ( css ) - > classid ) ;
2013-12-29 18:27:10 +01:00
}
static u64 read_classid ( struct cgroup_subsys_state * css , struct cftype * cft )
{
return css_cls_state ( css ) - > classid ;
}
static int write_classid ( struct cgroup_subsys_state * css , struct cftype * cft ,
u64 value )
{
2015-11-20 12:31:39 -08:00
struct cgroup_cls_state * cs = css_cls_state ( css ) ;
cs - > classid = ( u32 ) value ;
2013-12-29 18:27:10 +01:00
2015-11-20 12:31:39 -08:00
update_classid ( css , ( void * ) ( unsigned long ) cs - > classid ) ;
2013-12-29 18:27:10 +01:00
return 0 ;
}
static struct cftype ss_files [ ] = {
{
. name = " classid " ,
. read_u64 = read_classid ,
. write_u64 = write_classid ,
} ,
{ } /* terminate */
} ;
2014-02-08 10:36:58 -05:00
struct cgroup_subsys net_cls_cgrp_subsys = {
2013-12-29 18:27:10 +01:00
. css_alloc = cgrp_css_alloc ,
. css_online = cgrp_css_online ,
. css_free = cgrp_css_free ,
. attach = cgrp_attach ,
2014-07-15 11:05:09 -04:00
. legacy_cftypes = ss_files ,
2013-12-29 18:27:10 +01:00
} ;