]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: extract same logic of creating device symlink
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 2 Jun 2021 16:07:45 +0000 (01:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 4 Jun 2021 06:51:39 +0000 (15:51 +0900)
This also limits the number of trial.

src/udev/udev-node.c

index b4f2a896686c5ff1bf57a2db1fa5ea053803432e..b9471397148f5ae043101303e82eb1ea4a32f7e4 100644 (file)
 #include "udev-node.h"
 #include "user-util.h"
 
+#define CREATE_LINK_MAX_RETRIES 128
 #define LINK_UPDATE_MAX_RETRIES 128
 #define TOUCH_FILE_MAX_RETRIES  128
 #define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
 
+static int create_symlink(const char *target, const char *slink) {
+        int r;
+
+        assert(target);
+        assert(slink);
+
+        for (unsigned i = 0; i < CREATE_LINK_MAX_RETRIES; i++) {
+                r = mkdir_parents_label(slink, 0755);
+                if (r == -ENOENT)
+                        continue;
+                if (r < 0)
+                        return r;
+
+                mac_selinux_create_file_prepare(slink, S_IFLNK);
+                if (symlink(target, slink) < 0)
+                        r = -errno;
+                else
+                        r = 0;
+                mac_selinux_create_file_clear();
+                if (r != -ENOENT)
+                        return r;
+        }
+
+        return r;
+}
+
 static int node_symlink(sd_device *dev, const char *node, const char *slink) {
         _cleanup_free_ char *slink_dirname = NULL, *target = NULL;
         const char *id, *slink_tmp;
@@ -71,47 +98,35 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
                 }
         } else {
                 log_device_debug(dev, "Creating symlink '%s' to '%s'", slink, target);
-                do {
-                        r = mkdir_parents_label(slink, 0755);
-                        if (!IN_SET(r, 0, -ENOENT))
-                                break;
-                        mac_selinux_create_file_prepare(slink, S_IFLNK);
-                        if (symlink(target, slink) < 0)
-                                r = -errno;
-                        mac_selinux_create_file_clear();
-                } while (r == -ENOENT);
-                if (r == 0)
+
+                r = create_symlink(target, slink);
+                if (r >= 0)
                         return 0;
-                if (r < 0)
-                        log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink);
+
+                log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink);
         }
 
         log_device_debug(dev, "Atomically replace '%s'", slink);
+
         r = device_get_device_id(dev, &id);
         if (r < 0)
                 return log_device_error_errno(dev, r, "Failed to get device id: %m");
         slink_tmp = strjoina(slink, ".tmp-", id);
+
         (void) unlink(slink_tmp);
-        do {
-                r = mkdir_parents_label(slink_tmp, 0755);
-                if (!IN_SET(r, 0, -ENOENT))
-                        break;
-                mac_selinux_create_file_prepare(slink_tmp, S_IFLNK);
-                if (symlink(target, slink_tmp) < 0)
-                        r = -errno;
-                mac_selinux_create_file_clear();
-        } while (r == -ENOENT);
+
+        r = create_symlink(target, slink_tmp);
         if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target);
+                return log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target);
 
         if (rename(slink_tmp, slink) < 0) {
                 r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink);
                 (void) unlink(slink_tmp);
-        } else
-                /* Tell caller that we replaced already existing symlink. */
-                r = 1;
+                return r;
+        }
 
-        return r;
+        /* Tell caller that we replaced already existing symlink. */
+        return 1;
 }
 
 static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir, char **ret) {