summaryrefslogtreecommitdiff
path: root/src/shared/btrfs-util.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/btrfs-util.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/btrfs-util.c')
-rw-r--r--src/shared/btrfs-util.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index 52fc5f4a17..256c5a6995 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);
}