@@ -636,20 +636,72 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
636
636
__do_free char * cgroup_rel = NULL , * junk_value = NULL ;
637
637
const char * file ;
638
638
struct hierarchy * h ;
639
+ bool ret ;
639
640
640
641
h = ops -> get_hierarchy (ops , "memory" );
641
642
if (!h )
642
643
return false;
643
644
644
645
cgroup_rel = must_make_path_relative (cgroup , NULL );
645
646
file = is_unified_hierarchy (h ) ? "memory.swap.current" : "memory.memsw.usage_in_bytes" ;
647
+
646
648
/* For v2, we need to look at the lower levels of the hierarchy because
647
649
* no 'memory.swap.current' file exists at the root. We must search
648
650
* upwards in the hierarchy in case memory accounting is disabled via
649
651
* cgroup.subtree_control for the given cgroup itself.
650
652
*/
651
- int ret = cgroup_walkup_to_root (ops -> cgroup2_root_fd , h -> fd , cgroup_rel , file , & junk_value );
652
- return ret == 0 ;
653
+ if (is_cgroup2_fd (h -> fd ) && strcmp (cgroup , "/" ) == 0 ) {
654
+ /*
655
+ * It looks like LXCFS sits in the root cgroup,
656
+ * which means that we have to find *some* cgroup
657
+ * down the tree and check a (file) presence in there.
658
+ *
659
+ * Note, that this only needed for cgroup2.
660
+ */
661
+
662
+ __do_close int fd = - EBADF ;
663
+ __do_closedir DIR * dir = NULL ;
664
+ struct dirent * dent ;
665
+
666
+ fd = dup (h -> fd );
667
+ if (fd < 0 )
668
+ return false;
669
+
670
+ dir = fdopendir (fd );
671
+ if (!dir ) {
672
+ lxcfs_error ("Failed to open memory cgroup hierarchy\n" );
673
+ return false;
674
+ }
675
+ /* Transfer ownership to fdopendir(). */
676
+ move_fd (fd );
677
+
678
+ ret = false;
679
+ while (((dent = readdir (dir )) != NULL )) {
680
+ if (strcmp (dent -> d_name , "." ) == 0 ||
681
+ strcmp (dent -> d_name , ".." ) == 0 )
682
+ continue ;
683
+
684
+ if (dent -> d_type == DT_DIR ) {
685
+ __do_free char * path ;
686
+
687
+ path = must_make_path_relative (dent -> d_name , "memory.swap.current" , NULL );
688
+
689
+ if (!faccessat (h -> fd , path , F_OK , 0 )) {
690
+ /* We found it. Exit. */
691
+ ret = true;
692
+ break ;
693
+ }
694
+ }
695
+ }
696
+ } else {
697
+ /*
698
+ * We can check a (file) presence on the current
699
+ * level and go up in the cgroup tree if needed.
700
+ */
701
+ ret = cgroup_walkup_to_root (ops -> cgroup2_root_fd , h -> fd , cgroup_rel , file , & junk_value ) == 0 ;
702
+ }
703
+
704
+ return ret ;
653
705
}
654
706
655
707
static int cgfsng_get_memory_stats (struct cgroup_ops * ops , const char * cgroup ,
0 commit comments