]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
ramctl: add support for zram-control
authorKarel Zak <kzak@redhat.com>
Wed, 11 May 2016 10:43:40 +0000 (12:43 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 11 May 2016 10:43:40 +0000 (12:43 +0200)
Based on patch from Timofey Titovets.

Addresses: https://github.com/karelzak/util-linux/issues/318
Reported-by: Timofey Titovets <nefelim4ag@gmail.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/zramctl.c

index 29041eb729a5a122f44c515a8a942ddf56efc5f9..1713805561dc5719033a492827d7eb7a2b5d7d42 100644 (file)
@@ -36,6 +36,7 @@
 #include "ismounted.h"
 #include "strv.h"
 #include "path.h"
+#include "pathnames.h"
 
 /*#define CONFIG_ZRAM_DEBUG*/
 
@@ -112,7 +113,9 @@ struct zram {
        struct sysfs_cxt sysfs;
        char    **mm_stat;
 
-       unsigned int mm_stat_probed : 1;
+       unsigned int mm_stat_probed : 1,
+                    control_probed : 1,
+                    has_control : 1;   /* has /sys/class/zram-control/ */
 };
 
 #define ZRAM_EMPTY     { .devname = { '\0' }, .sysfs = UL_SYSFSCXT_EMPTY }
@@ -171,6 +174,17 @@ static void zram_set_devname(struct zram *z, const char *devname, size_t n)
        zram_reset_stat(z);
 }
 
+static int zram_get_devnum(struct zram *z)
+{
+       int n;
+
+       assert(z);
+
+       if (sscanf(z->devname, "/dev/zram%d", &n) == 1)
+               return n;
+       return -EINVAL;
+}
+
 static struct zram *new_zram(const char *devname)
 {
        struct zram *z = xcalloc(1, sizeof(struct zram));
@@ -261,6 +275,50 @@ static int zram_used(struct zram *z)
        return 0;
 }
 
+static int zram_has_control(struct zram *z)
+{
+       if (!z->control_probed) {
+               z->has_control = access(_PATH_SYS_CLASS "/zram-control/", F_OK) == 0 ? 1 : 0;
+               z->control_probed = 1;
+               DBG(fprintf(stderr, "zram-control: %s", z->has_control ? "yes" : "no"));
+       }
+
+       return z->has_control;
+}
+
+static int zram_control_add(struct zram *z)
+{
+       int n;
+
+       if (!zram_has_control(z))
+               return -ENOSYS;
+
+       n = path_read_s32(_PATH_SYS_CLASS "/zram-control/hot_add");
+       if (n < 0)
+               return n;
+
+       DBG(fprintf(stderr, "hot-add: %d", n));
+       zram_set_devname(z, NULL, n);
+       return 0;
+}
+
+static int zram_control_remove(struct zram *z)
+{
+       char str[sizeof stringify_value(INT_MAX)];
+       int n;
+
+       if (!zram_has_control(z))
+               return -ENOSYS;
+
+       n = zram_get_devnum(z);
+       if (n < 0)
+               return n;
+
+       DBG(fprintf(stderr, "hot-remove: %d", n));
+       snprintf(str, sizeof(str), "%d", n);
+       return path_write_str(str, _PATH_SYS_CLASS "/zram-control/hot_remove");
+}
+
 static struct zram *find_free_zram(void)
 {
        struct zram *z = new_zram(NULL);
@@ -270,7 +328,7 @@ static struct zram *find_free_zram(void)
        for (i = 0; isfree == 0; i++) {
                DBG(fprintf(stderr, "find free: checking zram%zu", i));
                zram_set_devname(z, NULL, i);
-               if (!zram_exist(z))
+               if (!zram_exist(z) && zram_control_add(z) != 0)
                        break;
                isfree = !zram_used(z);
        }
@@ -281,7 +339,6 @@ static struct zram *find_free_zram(void)
        return z;
 }
 
-
 static char *get_mm_stat(struct zram *z, size_t idx, int bytes)
 {
        struct sysfs_cxt *sysfs;
@@ -630,6 +687,7 @@ int main(int argc, char **argv)
                                warn(_("%s: failed to reset"), zram->devname);
                                rc = 1;
                        }
+                       zram_control_remove(zram);
                        free_zram(zram);
                        optind++;
                }