On Sun, Nov 23, 2014 at 08:33:41PM -0800, Chris Leech wrote: > This adds auto detection for iSCSI and some FCoE drivers and treats > mounts to file-systems on those devices as remote-fs. > > Signed-off-by: Chris Leech <cle...@redhat.com> No need for this.
I now pushed patches 1-4 with some small changes here and there. Since libmount is not optional, I removed if from the version string. This patch I didn't push: this seems like something that would be better done through udev rules, by setting some tags. Then systemd could simply check for the presence of a tag on the device without having any special knowledge about iscsi and firends. Zbyszek > --- > src/core/mount.c | 168 > +++++++++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 158 insertions(+), 10 deletions(-) > > diff --git a/src/core/mount.c b/src/core/mount.c > index 513dcec..52a4ba7 100644 > --- a/src/core/mount.c > +++ b/src/core/mount.c > @@ -26,6 +26,7 @@ > #include <signal.h> > #include <libmount.h> > #include <sys/inotify.h> > +#include <libudev.h> > > #include "manager.h" > #include "unit.h" > @@ -44,6 +45,7 @@ > #include "bus-errors.h" > #include "exit-status.h" > #include "def.h" > +#include "udev-util.h" > > static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = { > [MOUNT_DEAD] = UNIT_INACTIVE, > @@ -64,20 +66,166 @@ static const UnitActiveState > state_translation_table[_MOUNT_STATE_MAX] = { > static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void > *userdata); > static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t > revents, void *userdata); > > -static bool mount_needs_network(const char *options, const char *fstype) { > +static bool scsi_host_is(struct udev_device *host, const char *type) { > + _cleanup_free_ char *path; > + struct stat st; > + > + assert(host); > + assert(type); > + > + /* a <type>_host device created by the scsi transport class > + * should exists for all the transport types looked for */ > + > + if (asprintf(&path, "%s/%s_host", udev_device_get_syspath(host), > type) < 0) { > + log_oom(); > + return false; > + } > + return stat(path, &st) == 0 && S_ISDIR(st.st_mode); > +} > + > +static bool scsi_host_is_network(struct udev_device *block) { > + struct udev_device *host = NULL; > + struct udev *udev; > + > + assert(block); > + udev = udev_device_get_udev(block); > + > + host = udev_device_get_parent_with_subsystem_devtype(block, "scsi", > "scsi_host"); > + if (!host) > + return false; > + > + /* iSCSI */ > + if (scsi_host_is(host, "iscsi")) > + return true; > + > + /* FCoE appears as an FC host with a parent FCoE Ctlr device > + * This will at least detect the software fcoe module and bnx2fc on > kernels >= 3.5 */ > + if (scsi_host_is(host, "fc")) { > + _cleanup_free_ char *fc_host_path = NULL; > + _cleanup_udev_device_unref_ struct udev_device *fc_host = > NULL; > + struct udev_device *fcoe_ctlr = NULL; > + > + if (asprintf(&fc_host_path, "%s/fc_host/%s", > udev_device_get_syspath(host), udev_device_get_sysname(host)) < 0) { > + log_oom(); > + return false; > + }; > + fc_host = udev_device_new_from_syspath(udev, fc_host_path); > + fcoe_ctlr = > udev_device_get_parent_with_subsystem_devtype(fc_host, "fcoe", "fcoe_ctlr"); > + if (fcoe_ctlr) > + return true; > + } > + > + return false; > +} > + > +static int dot_filter(const struct dirent *d) { > + if (streq(".", d->d_name) || streq("..", d->d_name)) > + return 0; > + return 1; > +} > + > +static inline bool is_partition(struct udev_device *block) { > + const char *devtype; > + > + devtype = udev_device_get_devtype(block); > + if (streq(devtype, "partition")) { > + return true; > + } > + return false; > +} > + > +static bool block_needs_network(struct udev_device *block) { > + struct udev_device *parent = NULL; > + _cleanup_free_ char *slaves_path = NULL; > + _cleanup_free_ struct dirent **slaves = NULL; > + struct udev *udev; > + int n, i; > + bool rc = false; > + > + assert(block); > + udev = udev_device_get_udev(block); > + > + if (scsi_host_is_network(block)) > + return true; > + > + /* if this is a partition, check the parent device */ > + > + if (is_partition(block)) { > + parent = udev_device_get_parent(block); > + if (parent && block_needs_network(parent)) > + return true; > + } > + > + /* if this block device has "slaves" check them as well > + * this handles DM maps including LVM and multipath */ > + > + if (asprintf(&slaves_path, "%s/slaves", > udev_device_get_syspath(block)) < 0) { > + log_oom(); > + return false; > + } > + > + n = scandir(slaves_path, &slaves, dot_filter, alphasort); > + for (i = 0; i < n; i++) { > + _cleanup_udev_device_unref_ struct udev_device *slave = NULL; > + _cleanup_free_ char *newpath = NULL; > + _cleanup_free_ char *rp = NULL; > + > + if (asprintf(&newpath, "%s/%s", slaves_path, > slaves[i]->d_name) < 0) { > + log_oom(); > + goto free_the_slaves; > + } > + rp = realpath(newpath, NULL); > + if (!rp) { > + log_oom(); > + goto free_the_slaves; > + } > + slave = udev_device_new_from_syspath(udev, rp); > + if (slave && block_needs_network(slave)) { > + rc = true; > + goto free_the_slaves; > + } > + } > + > +free_the_slaves: > + for (i = 0; i < n; i++) > + free(slaves[i]); > + return rc; > +} > + > +static bool block_transport_is_network(struct udev *udev, const char *what) { > + _cleanup_udev_device_unref_ struct udev_device *block = NULL; > + struct stat st; > + > + assert(udev); > + assert(what); > + > + if ((stat(what, &st) != 0) || (!S_ISBLK(st.st_mode))) > + return false; > + > + block = udev_device_new_from_devnum(udev, 'b', st.st_rdev); > + if (!block) > + return false; > + > + return block_needs_network(block); > +} > + > +static bool mount_needs_network(Manager *m, const char *what, const char > *options, const char *fstype) { > if (mount_test_option(options, "_netdev")) > return true; > > if (fstype && fstype_is_network(fstype)) > return true; > > + if (what && block_transport_is_network(m->udev, what)) > + return true; > + > return false; > } > > -static bool mount_is_network(MountParameters *p) { > +static bool mount_is_network(Mount *m, MountParameters *p) { > assert(p); > > - return mount_needs_network(p->options, p->fstype); > + return mount_needs_network(m->meta.manager, p->what, p->options, > p->fstype); > } > > static bool mount_is_bind(MountParameters *p) { > @@ -104,10 +252,10 @@ static bool mount_is_auto(MountParameters *p) { > return !mount_test_option(p->options, "noauto"); > } > > -static bool needs_quota(MountParameters *p) { > +static bool needs_quota(Mount *m, MountParameters *p) { > assert(p); > > - if (mount_is_network(p)) > + if (mount_is_network(m, p)) > return false; > > if (mount_is_bind(p)) > @@ -263,7 +411,7 @@ static int mount_add_mount_links(Mount *m) { > pm = get_mount_parameters_fragment(m); > if (pm && pm->what && > path_is_absolute(pm->what) && > - !mount_is_network(pm)) { > + !mount_is_network(m, pm)) { > > r = unit_require_mounts_for(UNIT(m), pm->what); > if (r < 0) > @@ -342,7 +490,7 @@ static int mount_add_quota_links(Mount *m) { > if (!p) > return 0; > > - if (!needs_quota(p)) > + if (!needs_quota(m, p)) > return 0; > > r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, > UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true); > @@ -390,7 +538,7 @@ static int mount_add_default_dependencies(Mount *m) { > path_equal(m->where, "/usr")) > return 0; > > - if (mount_is_network(p)) { > + if (mount_is_network(m, p)) { > after = SPECIAL_REMOTE_FS_PRE_TARGET; > after2 = SPECIAL_NETWORK_TARGET; > online = SPECIAL_NETWORK_ONLINE_TARGET; > @@ -1408,7 +1556,7 @@ static int mount_add_one( > if (m->running_as == SYSTEMD_SYSTEM) { > const char* target; > > - target = mount_needs_network(options, fstype) ? > SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; > + target = mount_needs_network(m, what, options, > fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; > r = unit_add_dependency_by_name(u, UNIT_BEFORE, > target, NULL, true); > if (r < 0) > goto fail; > @@ -1436,7 +1584,7 @@ static int mount_add_one( > if (m->running_as == SYSTEMD_SYSTEM) { > const char* target; > > - target = mount_needs_network(options, fstype) ? > SPECIAL_REMOTE_FS_TARGET : NULL; > + target = mount_needs_network(m, what, options, > fstype) ? SPECIAL_REMOTE_FS_TARGET : NULL; > /* _netdev option may have shown up late, or on a > * remount. Add remote-fs dependencies, even though > * local-fs ones may already be there */ > -- > 1.9.3 > > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel