[systemd-commits] 3 commits - TODO man/systemd.netdev.xml src/import src/machine src/shared

Lennart Poettering lennart at kemper.freedesktop.org
Mon Mar 2 15:21:52 PST 2015


 TODO                        |   12 +++----
 man/systemd.netdev.xml      |    2 -
 src/import/import-dkr.c     |    5 ++
 src/import/import-job.c     |   13 +++++++
 src/import/import-job.h     |    3 +
 src/import/import-raw.c     |    5 ++
 src/import/import-tar.c     |    5 ++
 src/machine/machined-dbus.c |    8 ++--
 src/shared/btrfs-util.c     |   17 +++++++--
 src/shared/btrfs-util.h     |    4 +-
 src/shared/machine-pool.c   |   75 ++++++++++++++++++++++++++++++++++++++++++++
 src/shared/machine-pool.h   |    1 
 12 files changed, 134 insertions(+), 16 deletions(-)

New commits:
commit 7d417f0f357c59cc1846aa832161e69a2328f699
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 3 00:20:23 2015 +0100

    update TODO

diff --git a/TODO b/TODO
index e8e4800..60efaaf 100644
--- a/TODO
+++ b/TODO
@@ -34,6 +34,12 @@ External:
 
 Features:
 
+* create a btrfs qgroup for /var/lib/machines, and add all container
+  subvolumes we create to it.
+
+* nspawn: add --overlay= to support overlay file systems, similar to
+  --tmpfs= and --bind=.
+
 * When logging about multiple units (stopping BoundTo units, conflicts, etc.),
   log both units as UNIT=, so that journalctl -u triggers on both.
 
@@ -65,10 +71,6 @@ Features:
 * Introduce $LISTEN_NAMES to complement $LISTEN_FDS, containing a
   colon separated list of identifiers for the fds passed.
 
-* networkd: implement BindCarrier= logic to .network units that binds
-  application of the file to the carrier sense on another interface,
-  in order to implement uplink/downlink logic.
-
 * when the fstab-generator runs in the initrd, it should create a /dev/null mask for systemd-fsck-root.service, to avoid that the the root fs is fsck'ed twice.
 
 * maybe introduce WantsMountsFor=? Usecase:
@@ -132,8 +134,6 @@ Features:
 
 * "machinectl commit" that takes a writable snapshot of a tree, invokes a shell in it, and marks it read-only after use
 
-* add transparent btrfs pool in a loopback file in /var if btrfs operations (such as systemd-import pull-dkr) are used and /var is not a btrfs file system
-
 * systemd-nspawn -x should support ephemeral instances of gpt images
 
 * hostnamectl: show root image uuid

commit 26166c88e0b47b83972f32b5057ecbffe06bf904
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 3 00:13:12 2015 +0100

    importd: automatically grow /var/lib/machines/ loopback filesystem during downloads
    
    If /var/lib/machines is mounted as btrfs loopback file system in
    /var/lib/machines.raw with this change we automatically grow the file
    system as it fills up. After each 10M we write to it during imports, we
    check the free disk space, and if the fill level grows beyond 66% we
    increase the size of the file system to 3x the fill level (thus lowering
    it to 33%).

diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c
index fb72f6c..2d4e9b3 100644
--- a/src/import/import-dkr.c
+++ b/src/import/import-dkr.c
@@ -28,6 +28,7 @@
 #include "btrfs-util.h"
 #include "utf8.h"
 #include "mkdir.h"
+#include "path-util.h"
 #include "import-util.h"
 #include "curl-util.h"
 #include "aufs-util.h"
@@ -72,6 +73,7 @@ struct DkrImport {
 
         char *local;
         bool force_local;
+        bool grow_machine_directory;
 
         char *temp_path;
         char *final_path;
@@ -156,6 +158,8 @@ int dkr_import_new(
         if (!i->image_root)
                 return -ENOMEM;
 
+        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
+
         i->index_url = strdup(index_url);
         if (!i->index_url)
                 return -ENOMEM;
@@ -561,6 +565,7 @@ static int dkr_import_pull_layer(DkrImport *i) {
         i->layer_job->on_finished = dkr_import_job_on_finished;
         i->layer_job->on_open_disk = dkr_import_job_on_open_disk;
         i->layer_job->on_progress = dkr_import_job_on_progress;
+        i->layer_job->grow_machine_directory = i->grow_machine_directory;
 
         r = import_job_begin(i->layer_job);
         if (r < 0)
diff --git a/src/import/import-job.c b/src/import/import-job.c
index 8094865..980b639 100644
--- a/src/import/import-job.c
+++ b/src/import/import-job.c
@@ -22,8 +22,12 @@
 #include <sys/xattr.h>
 
 #include "strv.h"
+#include "machine-pool.h"
 #include "import-job.h"
 
+/* Grow the /var/lib/machines directory after each 10MiB written */
+#define IMPORT_GROW_INTERVAL_BYTES (UINT64_C(10) * UINT64_C(1024) * UINT64_C(1024))
+
 ImportJob* import_job_unref(ImportJob *j) {
         if (!j)
                 return NULL;
@@ -197,6 +201,11 @@ static int import_job_write_uncompressed(ImportJob *j, void *p, size_t sz) {
 
         if (j->disk_fd >= 0) {
 
+                if (j->grow_machine_directory && j->written_since_last_grow >= IMPORT_GROW_INTERVAL_BYTES) {
+                        j->written_since_last_grow = 0;
+                        grow_machine_directory();
+                }
+
                 if (j->allow_sparse)
                         n = sparse_write(j->disk_fd, p, sz, 64);
                 else
@@ -219,6 +228,7 @@ static int import_job_write_uncompressed(ImportJob *j, void *p, size_t sz) {
         }
 
         j->written_uncompressed += sz;
+        j->written_since_last_grow += sz;
 
         return 0;
 }
@@ -667,6 +677,9 @@ int import_job_begin(ImportJob *j) {
         if (j->state != IMPORT_JOB_INIT)
                 return -EBUSY;
 
+        if (j->grow_machine_directory)
+                grow_machine_directory();
+
         r = curl_glue_make(&j->curl, j->url, j);
         if (r < 0)
                 return r;
diff --git a/src/import/import-job.h b/src/import/import-job.h
index dcf89cb..2c01d72 100644
--- a/src/import/import-job.h
+++ b/src/import/import-job.h
@@ -107,6 +107,9 @@ struct ImportJob {
         gcry_md_hd_t checksum_context;
 
         char *checksum;
+
+        bool grow_machine_directory;
+        uint64_t written_since_last_grow;
 };
 
 int import_job_new(ImportJob **job, const char *url, CurlGlue *glue, void *userdata);
diff --git a/src/import/import-raw.c b/src/import/import-raw.c
index 8d99f10..89c064c 100644
--- a/src/import/import-raw.c
+++ b/src/import/import-raw.c
@@ -31,6 +31,7 @@
 #include "util.h"
 #include "macro.h"
 #include "mkdir.h"
+#include "path-util.h"
 #include "import-util.h"
 #include "curl-util.h"
 #include "qcow2-util.h"
@@ -61,6 +62,7 @@ struct RawImport {
 
         char *local;
         bool force_local;
+        bool grow_machine_directory;
 
         char *temp_path;
         char *final_path;
@@ -115,6 +117,8 @@ int raw_import_new(
         if (!i->image_root)
                 return -ENOMEM;
 
+        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
+
         if (event)
                 i->event = sd_event_ref(event);
         else {
@@ -480,6 +484,7 @@ int raw_import_pull(RawImport *i, const char *url, const char *local, bool force
         i->raw_job->on_open_disk = raw_import_job_on_open_disk;
         i->raw_job->on_progress = raw_import_job_on_progress;
         i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+        i->raw_job->grow_machine_directory = i->grow_machine_directory;
 
         r = import_find_old_etags(url, i->image_root, DT_REG, ".raw-", ".raw", &i->raw_job->old_etags);
         if (r < 0)
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 493252a..472e336 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -30,6 +30,7 @@
 #include "util.h"
 #include "macro.h"
 #include "mkdir.h"
+#include "path-util.h"
 #include "import-util.h"
 #include "curl-util.h"
 #include "import-job.h"
@@ -58,6 +59,7 @@ struct TarImport {
 
         char *local;
         bool force_local;
+        bool grow_machine_directory;
 
         pid_t tar_pid;
 
@@ -121,6 +123,8 @@ int tar_import_new(
         if (!i->image_root)
                 return -ENOMEM;
 
+        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
+
         if (event)
                 i->event = sd_event_ref(event);
         else {
@@ -376,6 +380,7 @@ int tar_import_pull(TarImport *i, const char *url, const char *local, bool force
         i->tar_job->on_open_disk = tar_import_job_on_open_disk;
         i->tar_job->on_progress = tar_import_job_on_progress;
         i->tar_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+        i->tar_job->grow_machine_directory = i->grow_machine_directory;
 
         r = import_find_old_etags(url, i->image_root, DT_DIR, ".tar-", NULL, &i->tar_job->old_etags);
         if (r < 0)
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 5ab40b0..adba812 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -805,14 +805,16 @@ static int method_set_pool_limit(sd_bus *bus, sd_bus_message *message, void *use
         if (r < 0)
                 return r;
 
-        r = btrfs_resize_loopback("/var/lib/machines", limit);
-        if (r < 0 && r != -ENODEV)
+        r = btrfs_resize_loopback("/var/lib/machines", limit, false);
+        if (r == -ENOTTY)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
+        if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
                 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
 
         r = btrfs_quota_limit("/var/lib/machines", limit);
         if (r == -ENOTTY)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
-        else if (r < 0)
+        if (r < 0)
                 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
 
         return sd_bus_reply_method_return(message, NULL);
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index 52fc5f4..256c5a6 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -705,7 +705,7 @@ int btrfs_quota_limit(const char *path, uint64_t referred_max) {
         return btrfs_quota_limit_fd(fd, referred_max);
 }
 
-int btrfs_resize_loopback_fd(int fd, uint64_t new_size) {
+int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
         struct btrfs_ioctl_vol_args args = {};
         _cleanup_free_ char *p = NULL, *loop = NULL, *backing = NULL;
         _cleanup_close_ int loop_fd = -1, backing_fd = -1;
@@ -726,6 +726,8 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size) {
         if (asprintf(&p, "/sys/dev/block/%u:%u/loop/backing_file", major(dev), minor(dev)) < 0)
                 return -ENOMEM;
         r = read_one_line_file(p, &backing);
+        if (r == -ENOENT)
+                return -ENODEV;
         if (r < 0)
                 return r;
         if (isempty(backing) || !path_is_absolute(backing))
@@ -743,6 +745,9 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size) {
         if (new_size == (uint64_t) st.st_size)
                 return 0;
 
+        if (grow_only && new_size < (uint64_t) st.st_size)
+                return -EINVAL;
+
         if (asprintf(&loop, "/dev/block/%u:%u", major(dev), minor(dev)) < 0)
                 return -ENOMEM;
         loop_fd = open(loop, O_RDWR|O_CLOEXEC|O_NOCTTY);
@@ -770,15 +775,19 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size) {
                         return -errno;
         }
 
-        return 0;
+        /* Make sure the free disk space is correctly updated for both file systems */
+        (void) fsync(fd);
+        (void) fsync(backing_fd);
+
+        return 1;
 }
 
-int btrfs_resize_loopback(const char *p, uint64_t new_size) {
+int btrfs_resize_loopback(const char *p, uint64_t new_size, bool grow_only) {
         _cleanup_close_ int fd = -1;
 
         fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
                 return -errno;
 
-        return btrfs_resize_loopback_fd(fd, new_size);
+        return btrfs_resize_loopback_fd(fd, new_size, grow_only);
 }
diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
index e654a3f..a2c246b 100644
--- a/src/shared/btrfs-util.h
+++ b/src/shared/btrfs-util.h
@@ -72,5 +72,5 @@ int btrfs_quota_enable(const char *path, bool b);
 int btrfs_quota_limit_fd(int fd, uint64_t referred_max);
 int btrfs_quota_limit(const char *path, uint64_t referred_max);
 
-int btrfs_resize_loopback_fd(int fd, uint64_t size);
-int btrfs_resize_loopback(const char *path, uint64_t size);
+int btrfs_resize_loopback_fd(int fd, uint64_t size, bool grow_only);
+int btrfs_resize_loopback(const char *path, uint64_t size, bool grow_only);
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index b74252d..3eafb94 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -169,6 +169,7 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) {
         _cleanup_free_ char* loopdev = NULL;
         char tmpdir[] = "/tmp/import-mount.XXXXXX", *mntdir = NULL;
         bool tmpdir_made = false, mntdir_made = false, mntdir_mounted = false;
+        char buf[FORMAT_BYTES_MAX];
         int r, nr = -1;
 
         /* btrfs cannot handle file systems < 16M, hence use this as minimum */
@@ -274,6 +275,10 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) {
                 goto fail;
         }
 
+        (void) syncfs(fd);
+
+        log_info("Set up /var/lib/machines as btrfs loopback file system of size %s mounted on /var/lib/machines.raw.", format_bytes(buf, sizeof(buf), size));
+
         (void) umount2(mntdir, MNT_DETACH);
         (void) rmdir(mntdir);
         (void) rmdir(tmpdir);
@@ -299,3 +304,73 @@ fail:
 
         return r;
 }
+
+static int sync_path(const char *p) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return -errno;
+
+        if (syncfs(fd) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int grow_machine_directory(void) {
+        char buf[FORMAT_BYTES_MAX];
+        struct statvfs a, b;
+        uint64_t old_size, new_size, max_add;
+        int r;
+
+        /* Ensure the disk space data is accurate */
+        sync_path("/var/lib/machines");
+        sync_path("/var/lib/machines.raw");
+
+        if (statvfs("/var/lib/machines.raw", &a) < 0)
+                return -errno;
+
+        if (statvfs("/var/lib/machines", &b) < 0)
+                return -errno;
+
+        /* Don't grow if not enough disk space is available on the host */
+        if (((uint64_t) a.f_bavail * (uint64_t) a.f_bsize) <= VAR_LIB_MACHINES_FREE_MIN)
+                return 0;
+
+        /* Don't grow if at least 1/3th of the fs is still free */
+        if (b.f_bavail > b.f_blocks / 3)
+                return 0;
+
+        /* Calculate how much we are willing to add at maximum */
+        max_add = ((uint64_t) a.f_bavail * (uint64_t) a.f_bsize) - VAR_LIB_MACHINES_FREE_MIN;
+
+        /* Calculate the old size */
+        old_size = (uint64_t) b.f_blocks * (uint64_t) b.f_bsize;
+
+        /* Calculate the new size as three times the size of what is used right now */
+        new_size = ((uint64_t) b.f_blocks - (uint64_t) b.f_bavail) * (uint64_t) b.f_bsize * 3;
+
+        /* Always, grow at least to the start size */
+        if (new_size < VAR_LIB_MACHINES_SIZE_START)
+                new_size = VAR_LIB_MACHINES_SIZE_START;
+
+        /* If the new size is smaller than the old size, don't grow */
+        if (new_size < old_size)
+                return 0;
+
+        /* Ensure we never add more than the maximum */
+        if (new_size > old_size + max_add)
+                new_size = old_size + max_add;
+
+        r = btrfs_resize_loopback("/var/lib/machines", new_size, true);
+        if (r <= 0)
+                return r;
+
+        r = btrfs_quota_limit("/var/lib/machines", new_size);
+        if (r < 0)
+                return r;
+
+        log_info("Grew /var/lib/machines btrfs loopback file system to %s.", format_bytes(buf, sizeof(buf), new_size));
+        return 1;
+}
diff --git a/src/shared/machine-pool.h b/src/shared/machine-pool.h
index 9c9849f..06c5d40 100644
--- a/src/shared/machine-pool.h
+++ b/src/shared/machine-pool.h
@@ -24,3 +24,4 @@
 #include "sd-bus.h"
 
 int setup_machine_directory(uint64_t size, sd_bus_error *error);
+int grow_machine_directory(void);

commit a68188812290cb9ec9f3f8a17b65e64549a4fd65
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Mar 3 00:11:51 2015 +0100

    man: fix typo

diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 4480e19..ef58887 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -108,7 +108,7 @@
           <entry>A bond device is an aggregation of all its slave devices. See <ulink url="https://www.kernel.org/doc/Documentation/networking/bonding.txt">Linux Ethernet Bonding Driver HOWTO</ulink> for details.Local configuration</entry></row>
 
           <row><entry><varname>bridge</varname></entry>
-          <entry>A bridge devcie is a software switch, each of its slave devices and the bridge itself are ports of the switch.</entry></row>
+          <entry>A bridge device is a software switch, each of its slave devices and the bridge itself are ports of the switch.</entry></row>
 
           <row><entry><varname>dummy</varname></entry>
           <entry>A dummy device drops all packets sent to it.</entry></row>



More information about the systemd-commits mailing list