From 71ae04c40081d11cc412d731d59c4a25e6bc5f07 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 14 Mar 2018 12:22:27 +0100 Subject: [PATCH] core/umount: use libmount to enumerate /proc/swaps 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 | 50 +++++++++++++++++++----------------------- src/test/test-umount.c | 2 +- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/core/umount.c b/src/core/umount.c index 6dc88ca7bbd..0323bdbd808 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -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; diff --git a/src/test/test-umount.c b/src/test/test-umount.c index e1d56291acb..770d1a73c86 100644 --- a/src/test/test-umount.c +++ b/src/test/test-umount.c @@ -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); -- 2.47.3