@@ -580,12 +580,52 @@ static void apply_dir_rules(void)
580580
581581/*** Control groups ***/
582582
583- static char cg_path [256 ];
583+ struct cg_controller_desc {
584+ const char * name ;
585+ int optional ;
586+ };
587+
588+ typedef enum {
589+ CG_MEMORY = 0 ,
590+ CG_CPUACCT ,
591+ CG_CPUSET ,
592+ CG_NUM_CONTROLLERS ,
593+ } cg_controller ;
594+
595+ static const struct cg_controller_desc cg_controllers [CG_NUM_CONTROLLERS + 1 ] = {
596+ [CG_MEMORY ] = { "memory" , 0 },
597+ [CG_CPUACCT ] = { "cpuacct" , 0 },
598+ [CG_CPUSET ] = { "cpuset" , 1 },
599+ [CG_NUM_CONTROLLERS ] = { NULL , 0 },
600+ };
601+
602+ #define FOREACH_CG_CONTROLLER (_controller ) \
603+ for (cg_controller (_controller) = 0; \
604+ (_controller) < CG_NUM_CONTROLLERS; (_controller)++)
605+
606+ static const char * cg_controller_name (cg_controller c )
607+ {
608+ return cg_controllers [c ].name ;
609+ }
610+
611+ static const int cg_controller_optional (cg_controller c )
612+ {
613+ return cg_controllers [c ].optional ;
614+ }
615+
616+ static char cg_name [256 ];
584617
585618#define CG_BUFSIZE 1024
586619
620+ static void
621+ cg_makepath (char * buf , size_t len , cg_controller c , const char * attr )
622+ {
623+ const char * cg_root = CONFIG_ISOLATE_CGROUP_ROOT ;
624+ snprintf (buf , len , "%s/%s/%s/%s" , cg_root , cg_controller_name (c ), cg_name , attr );
625+ }
626+
587627static int
588- cg_read (char * attr , char * buf )
628+ cg_read (cg_controller controller , const char * attr , char * buf )
589629{
590630 int maybe = 0 ;
591631 if (attr [0 ] == '?' )
@@ -595,7 +635,7 @@ cg_read(char *attr, char *buf)
595635 }
596636
597637 char path [256 ];
598- snprintf (path , sizeof (path ), "%s/%s" , cg_path , attr );
638+ cg_makepath (path , sizeof (path ), controller , attr );
599639
600640 int fd = open (path , O_RDONLY );
601641 if (fd < 0 )
@@ -621,30 +661,47 @@ cg_read(char *attr, char *buf)
621661 return 1 ;
622662}
623663
624- static void __attribute__((format (printf ,2 , 3 )))
625- cg_write (char * attr , char * fmt , ...)
664+ static void __attribute__((format (printf ,3 , 4 )))
665+ cg_write (cg_controller controller , const char * attr , const char * fmt , ...)
626666{
667+ int maybe = 0 ;
668+ if (attr [0 ] == '?' )
669+ {
670+ attr ++ ;
671+ maybe = 1 ;
672+ }
673+
627674 va_list args ;
628675 va_start (args , fmt );
629676
630677 char buf [CG_BUFSIZE ];
631678 int n = vsnprintf (buf , sizeof (buf ), fmt , args );
632679 if (n >= CG_BUFSIZE )
633- die ("cg_writef : Value for attribute %s is too long" , attr );
680+ die ("cg_write : Value for attribute %s is too long" , attr );
634681
635682 if (verbose > 1 )
636683 msg ("CG: Write %s = %s" , attr , buf );
637684
638685 char path [256 ];
639- snprintf (path , sizeof (path ), "%s/%s" , cg_path , attr );
686+ cg_makepath (path , sizeof (path ), controller , attr );
640687
641688 int fd = open (path , O_WRONLY | O_TRUNC );
642689 if (fd < 0 )
643- die ("Cannot write %s: %m" , path );
690+ {
691+ if (maybe )
692+ return ;
693+ else
694+ die ("Cannot write %s: %m" , path );
695+ }
644696
645697 int written = write (fd , buf , n );
646698 if (written < 0 )
647- die ("Cannot set %s to %s: %m" , path , buf );
699+ {
700+ if (maybe )
701+ return ;
702+ else
703+ die ("Cannot set %s to %s: %m" , path , buf );
704+ }
648705 if (written != n )
649706 die ("Short write to %s (%d out of %d bytes)" , path , written , n );
650707
@@ -662,8 +719,8 @@ cg_init(void)
662719 if (!dir_exists (cg_root ))
663720 die ("Control group filesystem at %s not mounted" , cg_root );
664721
665- snprintf (cg_path , sizeof (cg_path ), "%s/ box-%d" , cg_root , box_id );
666- msg ("Using control group %s\n" , cg_path );
722+ snprintf (cg_name , sizeof (cg_name ), "box-%d" , box_id );
723+ msg ("Using control group %s\n" , cg_name );
667724}
668725
669726static void
@@ -674,22 +731,27 @@ cg_prepare(void)
674731
675732 struct stat st ;
676733 char buf [CG_BUFSIZE ];
734+ char path [256 ];
677735
678- if ( stat ( cg_path , & st ) >= 0 || errno != ENOENT )
736+ FOREACH_CG_CONTROLLER ( controller )
679737 {
680- msg ("Control group %s already exists, trying to empty it.\n" , cg_path );
681- if (rmdir (cg_path ) < 0 )
682- die ("Failed to reset control group %s: %m" , cg_path );
683- }
738+ cg_makepath (path , sizeof (path ), controller , "" );
739+ if (stat (path , & st ) >= 0 || errno != ENOENT )
740+ {
741+ msg ("Control group %s already exists, trying to empty it.\n" , path );
742+ if (rmdir (path ) < 0 )
743+ die ("Failed to reset control group %s: %m" , path );
744+ }
684745
685- if (mkdir (cg_path , 0777 ) < 0 )
686- die ("Failed to create control group %s: %m" , cg_path );
746+ if (mkdir (path , 0777 ) < 0 && !cg_controller_optional (controller ))
747+ die ("Failed to create control group %s: %m" , path );
748+ }
687749
688750 // If cpuset module is enabled, copy allowed cpus and memory nodes from parent group
689- if (cg_read ("?../ cpuset.cpus" , buf ))
690- cg_write ("cpuset.cpus" , "%s" , buf );
691- if (cg_read ("?../ cpuset.mems" , buf ))
692- cg_write ("cpuset.mems" , "%s" , buf );
751+ if (cg_read (CG_CPUSET , "? cpuset.cpus" , buf ))
752+ cg_write (CG_CPUSET , "cpuset.cpus" , "%s" , buf );
753+ if (cg_read (CG_CPUSET , "? cpuset.mems" , buf ))
754+ cg_write (CG_CPUSET , "cpuset.mems" , "%s" , buf );
693755}
694756
695757static void
@@ -698,22 +760,24 @@ cg_enter(void)
698760 if (!cg_enable )
699761 return ;
700762
701- msg ("Entering control group %s\n" , cg_path );
763+ msg ("Entering control group %s\n" , cg_name );
702764
703- struct stat st ;
704- if (stat (cg_path , & st ) < 0 )
705- die ("Control group %s does not exist: %m" , cg_path );
765+ FOREACH_CG_CONTROLLER (controller )
766+ {
767+ if (cg_controller_optional (controller ))
768+ cg_write (controller , "?tasks" , "%d\n" , (int ) getpid ());
769+ else
770+ cg_write (controller , "tasks" , "%d\n" , (int ) getpid ());
771+ }
706772
707773 if (cg_memory_limit )
708774 {
709- cg_write ("memory.limit_in_bytes" , "%lld\n" , (long long ) cg_memory_limit << 10 );
710- cg_write ("memory.memsw.limit_in_bytes" , "%lld\n" , (long long ) cg_memory_limit << 10 );
775+ cg_write (CG_MEMORY , "memory.limit_in_bytes" , "%lld\n" , (long long ) cg_memory_limit << 10 );
776+ cg_write (CG_MEMORY , "memory.memsw.limit_in_bytes" , "%lld\n" , (long long ) cg_memory_limit << 10 );
711777 }
712778
713779 if (cg_timing )
714- cg_write ("cpuacct.usage" , "0\n" );
715-
716- cg_write ("tasks" , "%d\n" , (int ) getpid ());
780+ cg_write (CG_CPUACCT , "cpuacct.usage" , "0\n" );
717781}
718782
719783static int
@@ -723,7 +787,7 @@ cg_get_run_time_ms(void)
723787 return 0 ;
724788
725789 char buf [CG_BUFSIZE ];
726- cg_read ("cpuacct.usage" , buf );
790+ cg_read (CG_CPUACCT , "cpuacct.usage" , buf );
727791 unsigned long long ns = atoll (buf );
728792 return ns / 1000000 ;
729793}
@@ -738,9 +802,9 @@ cg_stats(void)
738802
739803 // Memory usage statistics
740804 unsigned long long mem = 0 , memsw = 0 ;
741- if (cg_read ("?memory.max_usage_in_bytes" , buf ))
805+ if (cg_read (CG_MEMORY , "?memory.max_usage_in_bytes" , buf ))
742806 mem = atoll (buf );
743- if (cg_read ("?memory.memsw.max_usage_in_bytes" , buf ))
807+ if (cg_read (CG_MEMORY , "?memory.memsw.max_usage_in_bytes" , buf ))
744808 {
745809 memsw = atoll (buf );
746810 if (memsw > mem )
@@ -758,12 +822,24 @@ cg_remove(void)
758822 if (!cg_enable )
759823 return ;
760824
761- cg_read ("tasks" , buf );
762- if (buf [0 ])
763- die ("Some tasks left in control group %s, failed to remove it" , cg_path );
825+ FOREACH_CG_CONTROLLER (controller )
826+ {
827+ if (cg_controller_optional (controller )) {
828+ if (!cg_read (controller , "?tasks" , buf ))
829+ continue ;
830+ } else
831+ cg_read (controller , "tasks" , buf );
832+
833+ if (buf [0 ])
834+ die ("Some tasks left in controller %s of cgroup %s, failed to remove it" ,
835+ cg_controller_name (controller ), cg_name );
764836
765- if (rmdir (cg_path ) < 0 )
766- die ("Cannot remove control group %s: %m" , cg_path );
837+ char path [256 ];
838+ cg_makepath (path , sizeof (path ), controller , "" );
839+
840+ if (rmdir (path ) < 0 )
841+ die ("Cannot remove control group %s: %m" , path );
842+ }
767843}
768844
769845/*** Disk quotas ***/
0 commit comments