summaryrefslogtreecommitdiff
path: root/src/shared/machine-pool.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-03-03 00:13:12 +0100
committerLennart Poettering <lennart@poettering.net>2015-03-03 00:13:12 +0100
commit26166c88e0b47b83972f32b5057ecbffe06bf904 (patch)
treeafff66bbc1b717d9202c16ff1c1b131fa307c272 /src/shared/machine-pool.c
parenta68188812290cb9ec9f3f8a17b65e64549a4fd65 (diff)
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%).
Diffstat (limited to 'src/shared/machine-pool.c')
-rw-r--r--src/shared/machine-pool.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index b74252dbc8..3eafb9443a 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;
+}