]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/automount.c
util-lib: split out IO related calls to io-util.[ch]
[thirdparty/systemd.git] / src / core / automount.c
index 342dd8f0a9736b197530ee4b6840146878389910..d362d6579d923fff0482a9f877814869fd6a18e6 100644 (file)
 ***/
 
 #include <errno.h>
-#include <limits.h>
-#include <sys/mount.h>
-#include <unistd.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <linux/auto_dev-ioctl.h>
+#include <linux/auto_fs4.h>
 #include <sys/epoll.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
-#include <linux/auto_fs4.h>
-#include <linux/auto_dev-ioctl.h>
+#include <unistd.h>
 
-#include "unit.h"
+#include "async.h"
 #include "automount.h"
-#include "mount.h"
-#include "unit-name.h"
-#include "special.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "dbus-automount.h"
+#include "fd-util.h"
+#include "formats-util.h"
+#include "io-util.h"
 #include "label.h"
 #include "mkdir.h"
+#include "mount.h"
 #include "path-util.h"
-#include "dbus-automount.h"
-#include "bus-util.h"
-#include "bus-error.h"
-#include "formats-util.h"
 #include "process-util.h"
-#include "async.h"
+#include "special.h"
+#include "string-util.h"
+#include "unit-name.h"
+#include "unit.h"
 
 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
@@ -127,13 +130,10 @@ static void automount_done(Unit *u) {
 
         unmount_autofs(a);
 
-        free(a->where);
-        a->where = NULL;
+        a->where = mfree(a->where);
 
-        set_free(a->tokens);
-        a->tokens = NULL;
-        set_free(a->expire_tokens);
-        a->expire_tokens = NULL;
+        a->tokens = set_free(a->tokens);
+        a->expire_tokens = set_free(a->expire_tokens);
 
         a->expire_event_source = sd_event_source_unref(a->expire_event_source);
 }
@@ -471,13 +471,20 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) {
         return r;
 }
 
+static int automount_start_expire(Automount *a);
+
 int automount_update_mount(Automount *a, MountState old_state, MountState state) {
+        int r;
+
         assert(a);
 
         switch (state) {
         case MOUNT_MOUNTED:
         case MOUNT_REMOUNTING:
                 automount_send_ready(a, a->tokens, 0);
+                r = automount_start_expire(a);
+                if (r < 0)
+                        log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
                 break;
          case MOUNT_DEAD:
          case MOUNT_UNMOUNTING:
@@ -490,6 +497,7 @@ int automount_update_mount(Automount *a, MountState old_state, MountState state)
          case MOUNT_FAILED:
                 if (old_state != state)
                         automount_send_ready(a, a->tokens, -ENODEV);
+                (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
                 break;
         default:
                 break;
@@ -633,8 +641,6 @@ static void *expire_thread(void *p) {
         return NULL;
 }
 
-static int automount_start_expire(Automount *a);
-
 static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
         Automount *a = AUTOMOUNT(userdata);
         _cleanup_(expire_data_freep) struct expire_data *data = NULL;
@@ -672,6 +678,9 @@ static int automount_start_expire(Automount *a) {
 
         assert(a);
 
+        if (a->timeout_idle_usec == 0)
+                return 0;
+
         timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC);
 
         if (a->expire_event_source) {
@@ -730,10 +739,6 @@ static void automount_enter_runnning(Automount *a) {
                 }
         }
 
-        r = automount_start_expire(a);
-        if (r < 0)
-                log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
-
         automount_set_state(a, AUTOMOUNT_RUNNING);
         return;
 
@@ -772,8 +777,9 @@ static int automount_stop(Unit *u) {
 
 static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
         Automount *a = AUTOMOUNT(u);
-        void *p;
         Iterator i;
+        void *p;
+        int r;
 
         assert(a);
         assert(f);
@@ -788,15 +794,9 @@ static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
         SET_FOREACH(p, a->expire_tokens, i)
                 unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
 
-        if (a->pipe_fd >= 0) {
-                int copy;
-
-                copy = fdset_put_dup(fds, a->pipe_fd);
-                if (copy < 0)
-                        return copy;
-
-                unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
-        }
+        r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd);
+        if (r < 0)
+                return r;
 
         return 0;
 }
@@ -904,6 +904,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         union autofs_v5_packet_union packet;
         Automount *a = AUTOMOUNT(userdata);
+        struct stat st;
         int r;
 
         assert(a);
@@ -963,6 +964,19 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
                         log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                         goto fail;
                 }
+
+                /* Before we do anything, let's see if somebody is playing games with us? */
+                if (lstat(a->where, &st) < 0) {
+                        log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
+                        goto fail;
+                }
+
+                if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
+                        log_unit_info(UNIT(a), "Automount point already unmounted?");
+                        automount_send_ready(a, a->expire_tokens, 0);
+                        break;
+                }
+
                 r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
                 if (r < 0) {
                         log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
@@ -1008,15 +1022,6 @@ static bool automount_supported(void) {
         return supported;
 }
 
-static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
-        [AUTOMOUNT_DEAD] = "dead",
-        [AUTOMOUNT_WAITING] = "waiting",
-        [AUTOMOUNT_RUNNING] = "running",
-        [AUTOMOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
-
 static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
         [AUTOMOUNT_SUCCESS] = "success",
         [AUTOMOUNT_FAILURE_RESOURCES] = "resources"
@@ -1056,7 +1061,6 @@ const UnitVTable automount_vtable = {
 
         .reset_failed = automount_reset_failed,
 
-        .bus_interface = "org.freedesktop.systemd1.Automount",
         .bus_vtable = bus_automount_vtable,
 
         .shutdown = automount_shutdown,