dd65c9
From d09c35c48005669c4c4663e3ba8a6f979432cead Mon Sep 17 00:00:00 2001
dd65c9
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
dd65c9
Date: Tue, 5 Sep 2017 11:30:33 +0200
dd65c9
Subject: [PATCH] cryptsetup-generator: use remote-cryptsetup.target when
dd65c9
 _netdev is present
dd65c9
dd65c9
This allows such devices to depend on the network. Their startup will
dd65c9
be delayed similarly to network mount units.
dd65c9
dd65c9
Fixes #4642.
dd65c9
dd65c9
Cherry-picked from: b001ad61e91b6499897f0c977045c7608c233bfa
dd65c9
Resolves: #1384014
dd65c9
---
dd65c9
 man/crypttab.xml                      | 13 +++++++++++++
dd65c9
 src/cryptsetup/cryptsetup-generator.c | 36 +++++++++++++++++++++++------------
dd65c9
 2 files changed, 37 insertions(+), 12 deletions(-)
dd65c9
dd65c9
diff --git a/man/crypttab.xml b/man/crypttab.xml
dd65c9
index 3e249ad23..7085a1623 100644
dd65c9
--- a/man/crypttab.xml
dd65c9
+++ b/man/crypttab.xml
dd65c9
@@ -189,6 +189,19 @@
dd65c9
         <option>size=</option>.</para></listitem>
dd65c9
       </varlistentry>
dd65c9
 
dd65c9
+      <varlistentry>
dd65c9
+        <term><option>_netdev</option></term>
dd65c9
+
dd65c9
+        <listitem><para>Marks this cryptsetup device as requiring network. It will be
dd65c9
+        started after the network is available, similarly to
dd65c9
+        <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
dd65c9
+        units marked with <option>_netdev</option>. The service unit to set up this device
dd65c9
+        will be ordered between <filename>remote-cryptsetup-pre.target</filename> and
dd65c9
+        <filename>remote-cryptsetup.target</filename>, instead of
dd65c9
+        <filename>cryptsetup-pre.target</filename> and
dd65c9
+        <filename>cryptsetup.target</filename>.</para></listitem>
dd65c9
+      </varlistentry>
dd65c9
+
dd65c9
       <varlistentry>
dd65c9
         <term><option>noauto</option></term>
dd65c9
 
dd65c9
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
dd65c9
index d191def5f..49dc8f14b 100644
dd65c9
--- a/src/cryptsetup/cryptsetup-generator.c
dd65c9
+++ b/src/cryptsetup/cryptsetup-generator.c
dd65c9
@@ -60,7 +60,7 @@ static int create_disk(
dd65c9
         _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL,
dd65c9
                 *filtered = NULL;
dd65c9
         _cleanup_fclose_ FILE *f = NULL;
dd65c9
-        bool noauto, nofail, tmp, swap;
dd65c9
+        bool noauto, nofail, tmp, swap, netdev;
dd65c9
         char *from;
dd65c9
         int r;
dd65c9
 
dd65c9
@@ -71,6 +71,7 @@ static int create_disk(
dd65c9
         nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
dd65c9
         tmp = fstab_test_option(options, "tmp\0");
dd65c9
         swap = fstab_test_option(options, "swap\0");
dd65c9
+        netdev = fstab_test_option(options, "_netdev\0");
dd65c9
 
dd65c9
         if (tmp && swap) {
dd65c9
                 log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
dd65c9
@@ -101,22 +102,24 @@ static int create_disk(
dd65c9
         if (!f)
dd65c9
                 return log_error_errno(errno, "Failed to create unit file %s: %m", p);
dd65c9
 
dd65c9
-        fputs(
dd65c9
+        fprintf(f,
dd65c9
                 "# Automatically generated by systemd-cryptsetup-generator\n\n"
dd65c9
                 "[Unit]\n"
dd65c9
-                "Description=Cryptography Setup for %I\n"
dd65c9
+                "Description=Cryptography Setup for %%I\n"
dd65c9
                 "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
dd65c9
                 "SourcePath=/etc/crypttab\n"
dd65c9
                 "DefaultDependencies=no\n"
dd65c9
                 "Conflicts=umount.target\n"
dd65c9
-                "BindsTo=dev-mapper-%i.device\n"
dd65c9
+                "BindsTo=dev-mapper-%%i.device\n"
dd65c9
                 "IgnoreOnIsolate=true\n"
dd65c9
-                "After=systemd-readahead-collect.service systemd-readahead-replay.service cryptsetup-pre.target\n",
dd65c9
-                f);
dd65c9
+                "After=systemd-readahead-collect.service systemd-readahead-replay.service\n"
dd65c9
+                "After=%s\n",
dd65c9
+                netdev ? "remote-cryptsetup-pre.target" : "cryptsetup-pre.target");
dd65c9
 
dd65c9
         if (!nofail)
dd65c9
                 fprintf(f,
dd65c9
-                        "Before=cryptsetup.target\n");
dd65c9
+                        "Before=%s\n",
dd65c9
+                        netdev ? "remote-cryptsetup.target" : "cryptsetup.target");
dd65c9
 
dd65c9
         if (password) {
dd65c9
                 if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random"))
dd65c9
@@ -196,16 +199,25 @@ static int create_disk(
dd65c9
                         return log_error_errno(errno, "Failed to create symlink %s: %m", to);
dd65c9
 
dd65c9
                 free(to);
dd65c9
-                if (!nofail)
dd65c9
-                        to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
dd65c9
-                else
dd65c9
-                        to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
dd65c9
+                if (!netdev) {
dd65c9
+                        if (!nofail)
dd65c9
+                                to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
dd65c9
+                        else
dd65c9
+                                to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
dd65c9
+                } else {
dd65c9
+                        if (!nofail)
dd65c9
+                                to = strjoin(arg_dest, "/remote-cryptsetup.target.requires/", n, NULL);
dd65c9
+                        else
dd65c9
+                                to = strjoin(arg_dest, "/remote-cryptsetup.target.wants/", n, NULL);
dd65c9
+                }
dd65c9
                 if (!to)
dd65c9
                         return log_oom();
dd65c9
 
dd65c9
                 mkdir_parents_label(to, 0755);
dd65c9
-                if (symlink(from, to) < 0)
dd65c9
+                if (symlink(from, to) < 0) {
dd65c9
+                        free(to);
dd65c9
                         return log_error_errno(errno, "Failed to create symlink %s: %m", to);
dd65c9
+                }
dd65c9
         }
dd65c9
 
dd65c9
         free(to);