Skip to content

Use libmount more#12218

Merged
poettering merged 4 commits intosystemd:masterfrom
keszybz:use-libmount-more
Apr 30, 2019
Merged

Use libmount more#12218
poettering merged 4 commits intosystemd:masterfrom
keszybz:use-libmount-more

Conversation

@keszybz
Copy link
Member

@keszybz keszybz commented Apr 4, 2019

This might be a solution for #12018, once util-linux/util-linux#780 is resolved.

@evverx
Copy link
Contributor

evverx commented Apr 4, 2019

This pull request introduces 2 alerts when merging 90b4063 into 949082a - view on LGTM.com

new alerts:

  • 1 for Missing header guard
  • 1 for Comparison result is always the same

Comment posted by LGTM.com

@keszybz keszybz force-pushed the use-libmount-more branch from 90b4063 to 3f52e8b Compare April 4, 2019 13:13
@keszybz
Copy link
Member Author

keszybz commented Apr 4, 2019

Force-pushed to fix the two issues pointed out by LGTM.

@keszybz
Copy link
Member Author

keszybz commented Apr 5, 2019

You're right about the unescaping. I remember this was discussed when the current code was being merged, but for some reason the unescaping was left in, even though it shouldn't. Did maybe libmount behave differently in the past? Anyway, I added a patch to remove the unescaping in all places it was done, and adjusted the new patches to not do it. PTAL.

@keszybz keszybz force-pushed the use-libmount-more branch from 3f52e8b to d6e8280 Compare April 5, 2019 09:13
@@ -11,7 +11,6 @@
#include "dbus-mount.h"
#include "dbus-unit.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this commit should probably be added to v242 still?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the first three (refactoring, test, and cunescape removal)? I can submit separate PR.

iter = mnt_new_iter(MNT_ITER_FORWARD);
if (!table || !iter)
return log_oom();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still logs at non-debug level

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is different, it was logging at non-debug level before, I just kept the behaviour.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but please. let's fix this when touching that

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you were right, and I added logging here, but then removed it in one of the later commits. I now fixed this during the rebase to have return -ENOMEM.

continue;
if (!set_contains(done, path)) {
r = set_put_strdup(todo, path);
if (r < 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to handle EEXIST gracefully, as before

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_put_strdup return 0 if the entry exists.

for (;;) {
_cleanup_free_ char *path = NULL, *where = NULL, *dev = NULL;
int r;
r = mnt_table_parse_mtab(table, NULL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should add a helper for this to libmount-util:

int mnt_table_proc_self_mount_info(struct libmnt_table **ret);

which allocates the table and opens it in one go. and maybe even go one step further and also allocate an iter at the same time and return that. After all we currently always do these three steps separately, always the same way

@keszybz keszybz added the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Apr 5, 2019
@keszybz keszybz force-pushed the use-libmount-more branch from d6e8280 to 92f1194 Compare April 5, 2019 13:11
@keszybz
Copy link
Member Author

keszybz commented Apr 5, 2019

Force pushed with a bugfix (wrong return value on error), and the suggested change to add a helper function. I also added one more commit to relax the test case which fails in CI.

@keszybz keszybz added ci-fails/needs-rework 🔥 Please rework this, the CI noticed an issue with the PR and removed reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks labels Apr 5, 2019
@keszybz keszybz force-pushed the use-libmount-more branch from 92f1194 to a3eddfd Compare April 8, 2019 14:57
@keszybz keszybz removed the ci-fails/needs-rework 🔥 Please rework this, the CI noticed an issue with the PR label Apr 8, 2019
@keszybz
Copy link
Member Author

keszybz commented Apr 8, 2019

I think the CI failure is again caused by old libmount version. I hope it'll pass now.

DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);

static inline int libmount_parse(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, static inline? I think this should just be a regular function, it's complicated enough to warrant that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was explained in the commit message that adds the function. I'll repush for the other things, and then I'll try to make the explanation clearer.


if (source)
/* Older libmount seems to require this. */
assert(path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert(!source || path)?


assert_se(mnt_table_next_fs(table, iter, &fs) == 0);
r = mnt_table_next_fs(table, iter, &fs);
if (r < 0 && may_fail) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a comment here maybe, that says "we allow this to fail in some tests, see below", or so?

@keszybz keszybz force-pushed the use-libmount-more branch from a3eddfd to ab57b19 Compare April 8, 2019 21:13
@keszybz keszybz force-pushed the use-libmount-more branch from ab57b19 to 79d8329 Compare April 8, 2019 21:17
@keszybz
Copy link
Member Author

keszybz commented Apr 8, 2019

Updated:

  • the test is updated to reflect the changes in libmount that were merged upstream in the meantime
  • things are skipped more consistently in tests, and the requested comment has been added
  • the log_oom() thing pointed out in review is fixed
  • assert() is updated as requested

@keszybz keszybz force-pushed the use-libmount-more branch from 79d8329 to 8cab8c6 Compare April 9, 2019 07:09
@keszybz
Copy link
Member Author

keszybz commented Apr 10, 2019

bionic-i386 fails in two places: test/TEST-29-UDEV-ID_RENAMING test/TEST-30-ONCLOCKCHANGE.
TEST-29 fails with "systemd-testsuite login: Failed to wait for daemon to reply: Connection timed out", might be just a timeout.
TEST-30 is known flakey.
I'll force push to fix the errors pointed out by @mrc0mmand.

@keszybz keszybz force-pushed the use-libmount-more branch from 8cab8c6 to 75b9abc Compare April 10, 2019 12:08
@mrc0mmand
Copy link
Member

mrc0mmand commented Apr 10, 2019

The Travis CI integration is having an aneurysm, so I triggered it manually: https://travis-ci.org/systemd/systemd/builds/517648222

rewind(proc_self_mountinfo);

r = mnt_table_parse_stream(table, proc_self_mountinfo, "/proc/self/mountinfo");
r = libmount_parse("/proc/self/mountinfo", proc_self_mountinfo, &table, &iter);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, so i wonder about the two uses in bind_remount_recursive_with_mountinfo() and umount_recursive(). We use this when setting up a namespace environment for a service. i.e. we operate on a different root than the real one. libmount is unlikely to understand that though and will merge data from /run/mount/utab into what is read here, but that's data about host mounts, not about mounts in the little namespaced environment we are setting up. Hence, we should somehow massage libmount into not loading utab meta info here if we want to use it in an entirely generic function like these two that should make no assumptions on the context they are called in.

@karelzak can you comment on this maybe? is there a way we can use the libmount mnt_table_xyz API without it reading utab for such namespaced environments?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karelzak can you comment on this maybe? is there a way we can use the libmount mnt_table_xyz API without it reading utab for such namespaced environments?

Only mnt_table_parse_mtab() reads utab userspace junk.

So, all you need is to use mnt_table_parse_file(), mnt_new_table_from_file() or mnt_table_parse_stream() with "/proc/self/mountinfo" as path to the table.

And for libmount_monitor API -- the utab is enabled only if explicitly requested by mnt_monitor_enable_userspace().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. So it seems only umount_recursive() needs changing. bind_remount_recursive_with_mountinfo() already uses mnt_table_parse_stream(). I pushed one more commit to do this.

keszybz added 4 commits April 23, 2019 23:29
It seems better to use just a single parsing algorithm for /proc/self/mountinfo.

Also, unify the naming of variables in all places that use mnt_table_next_fs().
It makes it easier to compare the different call sites.
Same motivation as in other places: let's use a single logic to parse this.

Use path_equal() to compare the path.

A bug in error handling is fixed: if we failed after the GREEDY_REALLOC but
before the line that sets the last item to NULL, we would jump to
_cleanup_strv_free_ with the strv unterminated. Let's use GREEDY_REALLOC0
to avoid the issue.
This wraps a few common steps. It is defined as inline function instead of in a
.c file to avoid having a .c file. With a .c file, we would have three choices:
- either link it into libshared, but then then libshared would have to be
  linked to libmount.
- or compile the .c file into each target separately. This has the disdvantage
  that configuration of every target has to be updated and stuff will be compiled
  multiple times anyway, which is not too different from keeping this in the
  header file.
- or create a new convenience library just for this. This also has the disadvantage
  that the every target would have to be updated, and a separate library for a
  10 line function seems overkill.

By keeping everything in a header file, we compile this a few times, but
otherwise it's the least painful option. The compiler can optimize most of the
function away, because it knows if 'source' is set or not.
@keszybz keszybz force-pushed the use-libmount-more branch from 75b9abc to 2f2d81d Compare April 23, 2019 21:55
@poettering poettering merged commit adb7b78 into systemd:master Apr 30, 2019
@keszybz keszybz deleted the use-libmount-more branch May 3, 2019 08:23
edevolder pushed a commit to edevolder/systemd that referenced this pull request Jun 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

6 participants