diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-05-19 13:50:36 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-05-19 13:50:36 +0200 |
commit | fcd8b266edf0df2b85079fcf7b099cd4028740e6 (patch) | |
tree | 2a3c036e86caf6c72382811edf16ded720ee9192 | |
parent | 2005219f83130a8d5948b070b132f5dc21400a5f (diff) |
mount: don't claim a device is gone from /proc/self/mountinfo before it is gone from *all* lines
Devices might be referenced by multiple mount points in
/proc/self/mountinfo, hence we should consider them unmounted only after
they disappeared from all lines, not just from one.
http://lists.freedesktop.org/archives/systemd-devel/2015-May/032026.html
-rw-r--r-- | src/core/mount.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/src/core/mount.c b/src/core/mount.c index 8ef3d1755d..c1a9ea5fa0 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1628,7 +1628,10 @@ fail: } static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + _cleanup_set_free_ Set *around = NULL, *gone = NULL; Manager *m = userdata; + const char *what; + Iterator i; Unit *u; int r; @@ -1695,6 +1698,8 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, if (!mount->is_mounted) { + /* A mount point is gone */ + mount->from_proc_self_mountinfo = false; switch (mount->state) { @@ -1710,13 +1715,17 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, break; } - if (mount->parameters_proc_self_mountinfo.what) - (void) device_found_node(m, mount->parameters_proc_self_mountinfo.what, false, DEVICE_FOUND_MOUNT, true); + /* Remember that this device might just have disappeared */ + if (mount->parameters_proc_self_mountinfo.what) { + if (set_ensure_allocated(&gone, &string_hash_ops) < 0 || + set_put(gone, mount->parameters_proc_self_mountinfo.what) < 0) + log_oom(); /* we don't care too much about OOM here... */ + } } else if (mount->just_mounted || mount->just_changed) { - /* New or changed mount entry */ + /* A mount point was added or changed */ switch (mount->state) { @@ -1741,12 +1750,27 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, mount_set_state(mount, mount->state); break; } + + if (mount->parameters_proc_self_mountinfo.what) { + + if (set_ensure_allocated(&around, &string_hash_ops) < 0 || + set_put(around, mount->parameters_proc_self_mountinfo.what) < 0) + log_oom(); + } } /* Reset the flags for later calls */ mount->is_mounted = mount->just_mounted = mount->just_changed = false; } + SET_FOREACH(what, gone, i) { + if (set_contains(around, what)) + continue; + + /* Let the device units know that the device is no longer mounted */ + (void) device_found_node(m, what, false, DEVICE_FOUND_MOUNT, true); + } + return 0; } |