]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/umount: use libmount to enumerate /proc/swaps 8452/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 14 Mar 2018 11:22:27 +0000 (12:22 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 16 Mar 2018 09:12:50 +0000 (10:12 +0100)
example.swaps with "(deleted)" does not cause bogus entries in the list now,
but a memleak in libmount instead. The memleaks is not very important since
this code is run just once.
Reported as https://github.com/karelzak/util-linux/issues/596.

$ build/test-umount
...
/* test_swap_list("/proc/swaps") */
path=/var/tmp/swap o= f=0x0 try-ro=no dev=0:0
path=/dev/dm-2 o= f=0x0 try-ro=no dev=0:0
/* test_swap_list("/home/zbyszek/src/systemd/test/test-umount/example.swaps") */
path=/some/swapfile o= f=0x0 try-ro=no dev=0:0
path=/dev/dm-2 o= f=0x0 try-ro=no dev=0:0
==26912==
==26912== HEAP SUMMARY:
==26912==     in use at exit: 16 bytes in 1 blocks
==26912==   total heap usage: 1,546 allocs, 1,545 frees, 149,008 bytes allocated
==26912==
==26912== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==26912==    at 0x4C31C15: realloc (vg_replace_malloc.c:785)
==26912==    by 0x55C5D8C: _IO_vfscanf (in /usr/lib64/libc-2.26.so)
==26912==    by 0x55D8AEC: vsscanf (in /usr/lib64/libc-2.26.so)
==26912==    by 0x55D25C3: sscanf (in /usr/lib64/libc-2.26.so)
==26912==    by 0x53236D0: mnt_table_parse_stream (in /usr/lib64/libmount.so.1.1.0)
==26912==    by 0x53249B6: mnt_table_parse_file (in /usr/lib64/libmount.so.1.1.0)
==26912==    by 0x10D157: swap_list_get (umount.c:194)
==26912==    by 0x10B06E: test_swap_list (test-umount.c:34)
==26912==    by 0x10B24B: main (test-umount.c:56)
==26912==
==26912== LEAK SUMMARY:
==26912==    definitely lost: 16 bytes in 1 blocks
==26912==    indirectly lost: 0 bytes in 0 blocks
==26912==      possibly lost: 0 bytes in 0 blocks
==26912==    still reachable: 0 bytes in 0 blocks
==26912==         suppressed: 0 bytes in 0 blocks

src/core/umount.c
src/test/test-umount.c

index 6dc88ca7bbddb1b80a8940bc7146cb686614d1c3..0323bdbd808abc57747566a424d9f8c188c32c22 100644 (file)
@@ -180,43 +180,39 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
 }
 
 int swap_list_get(const char *swaps, MountPoint **head) {
-        _cleanup_fclose_ FILE *proc_swaps = NULL;
-        unsigned int i;
+        _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
+        _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
         int r;
 
         assert(head);
 
-        proc_swaps = fopen(swaps ?: "/proc/swaps", "re");
-        if (!proc_swaps)
-                return (errno == ENOENT) ? 0 : -errno;
+        t = mnt_new_table();
+        i = mnt_new_iter(MNT_ITER_FORWARD);
+        if (!t || !i)
+                return log_oom();
 
-        (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
+        r = mnt_table_parse_swaps(t, swaps);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse %s: %m", swaps);
+
+        for (;;) {
+                struct libmnt_fs *fs;
 
-        for (i = 2;; i++) {
                 MountPoint *swap;
-                _cleanup_free_ char *dev = NULL, *d = NULL;
-                int k;
-
-                k = fscanf(proc_swaps,
-                           "%ms " /* device/file */
-                           "%*s " /* type of swap */
-                           "%*s " /* swap size */
-                           "%*s " /* used */
-                           "%*s\n", /* priority */
-                           &dev);
-
-                if (k != 1) {
-                        if (k == EOF)
-                                break;
-
-                        log_warning("Failed to parse /proc/swaps:%u.", i);
-                        continue;
-                }
+                const char *source;
+                _cleanup_free_ char *d = NULL;
+
+                r = mnt_table_next_fs(t, i, &fs);
+                if (r == 1)
+                        break;
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get next entry from %s: %m", swaps);
 
-                if (endswith(dev, " (deleted)"))
+                source = mnt_fs_get_source(fs);
+                if (!source)
                         continue;
 
-                r = cunescape(dev, UNESCAPE_RELAX, &d);
+                r = cunescape(source, UNESCAPE_RELAX, &d);
                 if (r < 0)
                         return r;
 
index e1d56291acbbf40073156767cd3bb2237104a95f..770d1a73c8677af8bb127ff391e8759dca3f79be 100644 (file)
@@ -28,7 +28,7 @@ static void test_swap_list(const char *fname) {
         _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
         MountPoint *m;
 
-        log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/self/mountinfo");
+        log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/swaps");
 
         LIST_HEAD_INIT(mp_list_head);
         assert_se(swap_list_get(fname, &mp_list_head) >= 0);