Add a new column to pool stats, which will tell us class' zs_can_compact()
number, so it will be easier to analyze zsmalloc fragmentation.

At the moment, we have only numbers of FULL and ALMOST_EMPTY classes, but
they don't tell us how badly the class is fragmented internally.

The new /sys/kernel/debug/zsmalloc/zramX/classes output look as follows:

 class  size almost_full almost_empty obj_allocated   obj_used pages_used 
pages_per_zspage compact
[..]
    12   224           0            2           146          5          8       
         4       4
    13   240           0            0             0          0          0       
         1       0
    14   256           1           13          1840       1672        115       
         1      10
    15   272           0            0             0          0          0       
         1       0
[..]
    49   816           0            3           745        735        149       
         1       2
    51   848           3            4           361        306         76       
         4       8
    52   864          12           14           378        268         81       
         3      21
    54   896           1           12           117         57         26       
         2      12
    57   944           0            0             0          0          0       
         3       0
[..]
 Total                26          131         12709      10994       1071       
               134

For example, from this particular output we can easily conclude that class-896
is heavily fragmented -- it occupies 26 pages, 12 can be freed by compaction.

Signed-off-by: Sergey Senozhatsky <[email protected]>
---
 mm/zsmalloc.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 43e4cbc..046d364 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -494,6 +494,8 @@ static void __exit zs_stat_exit(void)
        debugfs_remove_recursive(zs_stat_root);
 }
 
+static unsigned long zs_can_compact(struct size_class *class);
+
 static int zs_stats_size_show(struct seq_file *s, void *v)
 {
        int i;
@@ -501,14 +503,15 @@ static int zs_stats_size_show(struct seq_file *s, void *v)
        struct size_class *class;
        int objs_per_zspage;
        unsigned long class_almost_full, class_almost_empty;
-       unsigned long obj_allocated, obj_used, pages_used;
+       unsigned long obj_allocated, obj_used, pages_used, compact;
        unsigned long total_class_almost_full = 0, total_class_almost_empty = 0;
        unsigned long total_objs = 0, total_used_objs = 0, total_pages = 0;
+       unsigned long total_compact = 0;
 
-       seq_printf(s, " %5s %5s %11s %12s %13s %10s %10s %16s\n",
+       seq_printf(s, " %5s %5s %11s %12s %13s %10s %10s %16s %7s\n",
                        "class", "size", "almost_full", "almost_empty",
                        "obj_allocated", "obj_used", "pages_used",
-                       "pages_per_zspage");
+                       "pages_per_zspage", "compact");
 
        for (i = 0; i < zs_size_classes; i++) {
                class = pool->size_class[i];
@@ -521,6 +524,7 @@ static int zs_stats_size_show(struct seq_file *s, void *v)
                class_almost_empty = zs_stat_get(class, CLASS_ALMOST_EMPTY);
                obj_allocated = zs_stat_get(class, OBJ_ALLOCATED);
                obj_used = zs_stat_get(class, OBJ_USED);
+               compact = zs_can_compact(class);
                spin_unlock(&class->lock);
 
                objs_per_zspage = get_maxobj_per_zspage(class->size,
@@ -528,23 +532,25 @@ static int zs_stats_size_show(struct seq_file *s, void *v)
                pages_used = obj_allocated / objs_per_zspage *
                                class->pages_per_zspage;
 
-               seq_printf(s, " %5u %5u %11lu %12lu %13lu %10lu %10lu %16d\n",
+               seq_printf(s, " %5u %5u %11lu %12lu %13lu"
+                               " %10lu %10lu %16d %7lu\n",
                        i, class->size, class_almost_full, class_almost_empty,
                        obj_allocated, obj_used, pages_used,
-                       class->pages_per_zspage);
+                       class->pages_per_zspage, compact);
 
                total_class_almost_full += class_almost_full;
                total_class_almost_empty += class_almost_empty;
                total_objs += obj_allocated;
                total_used_objs += obj_used;
                total_pages += pages_used;
+               total_compact += compact;
        }
 
        seq_puts(s, "\n");
-       seq_printf(s, " %5s %5s %11lu %12lu %13lu %10lu %10lu\n",
+       seq_printf(s, " %5s %5s %11lu %12lu %13lu %10lu %10lu %16s %7lu\n",
                        "Total", "", total_class_almost_full,
                        total_class_almost_empty, total_objs,
-                       total_used_objs, total_pages);
+                       total_used_objs, total_pages, "", total_compact);
 
        return 0;
 }
-- 
2.7.1

Reply via email to