@@ -631,22 +631,16 @@ static int cgfsng_get_memory_slabinfo_fd(struct cgroup_ops *ops, const char *cgr
631631 return openat (h -> fd , path , O_RDONLY | O_CLOEXEC | O_NOFOLLOW );
632632}
633633
634- static bool cgfsng_can_use_swap (struct cgroup_ops * ops , const char * cgroup )
634+ static bool cgfsng_can_use_memory_feature (struct cgroup_ops * ops ,
635+ struct hierarchy * h , const char * cgroup , const char * file )
635636{
636637 __do_free char * cgroup_rel = NULL , * junk_value = NULL ;
637- const char * file ;
638- struct hierarchy * h ;
639638 bool ret ;
640639
641- h = ops -> get_hierarchy (ops , "memory" );
642- if (!h )
643- return false;
644-
645640 cgroup_rel = must_make_path_relative (cgroup , NULL );
646- file = is_unified_hierarchy (h ) ? "memory.swap.current" : "memory.memsw.usage_in_bytes" ;
647641
648642 /* For v2, we need to look at the lower levels of the hierarchy because
649- * no 'memory.swap .current' file exists at the root. We must search
643+ * no 'memory.<feature> .current' file exists at the root. We must search
650644 * upwards in the hierarchy in case memory accounting is disabled via
651645 * cgroup.subtree_control for the given cgroup itself.
652646 */
@@ -663,7 +657,7 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
663657 __do_closedir DIR * dir = NULL ;
664658 struct dirent * dent ;
665659
666- fd = dup (h -> fd );
660+ fd = openat_safe (h -> fd , "." );
667661 if (fd < 0 )
668662 return false;
669663
@@ -684,7 +678,7 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
684678 if (dent -> d_type == DT_DIR ) {
685679 __do_free char * path ;
686680
687- path = must_make_path_relative (dent -> d_name , "memory.swap.current" , NULL );
681+ path = must_make_path_relative (dent -> d_name , file , NULL );
688682
689683 if (!faccessat (h -> fd , path , F_OK , 0 )) {
690684 /* We found it. Exit. */
@@ -704,6 +698,32 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
704698 return ret ;
705699}
706700
701+ static bool cgfsng_can_use_swap (struct cgroup_ops * ops , const char * cgroup )
702+ {
703+ struct hierarchy * h ;
704+
705+ h = ops -> get_hierarchy (ops , "memory" );
706+ if (!h )
707+ return false;
708+
709+ return cgfsng_can_use_memory_feature (ops , h , cgroup , is_unified_hierarchy (h ) ? "memory.swap.current" : "memory.memsw.usage_in_bytes" );
710+ }
711+
712+ static bool cgfsng_can_use_zswap (struct cgroup_ops * ops , const char * cgroup )
713+ {
714+ struct hierarchy * h ;
715+
716+ h = ops -> get_hierarchy (ops , "memory" );
717+ if (!h )
718+ return false;
719+
720+ /* zswap is only available in cgroupv2 */
721+ if (!is_unified_hierarchy (h ))
722+ return false;
723+
724+ return cgfsng_can_use_memory_feature (ops , h , cgroup , "memory.zswap.current" );
725+ }
726+
707727static int cgfsng_get_memory_stats (struct cgroup_ops * ops , const char * cgroup ,
708728 char * * value )
709729{
@@ -1110,6 +1130,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
11101130 cgfsng_ops -> get_memory_swap_current = cgfsng_get_memory_swap_current ;
11111131 cgfsng_ops -> get_memory_slabinfo_fd = cgfsng_get_memory_slabinfo_fd ;
11121132 cgfsng_ops -> can_use_swap = cgfsng_can_use_swap ;
1133+ cgfsng_ops -> can_use_zswap = cgfsng_can_use_zswap ;
11131134
11141135 /* cpuset */
11151136 cgfsng_ops -> get_cpuset_cpus = cgfsng_get_cpuset_cpus ;
0 commit comments