d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering/***
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering This file is part of systemd.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering Copyright 2014 Lennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering systemd is free software; you can redistribute it and/or modify it
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering under the terms of the GNU Lesser General Public License as published by
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering (at your option) any later version.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering systemd is distributed in the hope that it will be useful, but
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering Lesser General Public License for more details.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering You should have received a copy of the GNU Lesser General Public License
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering***/
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering#include <fcntl.h>
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering#include "btrfs-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fileio.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "log.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "parse-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "string-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "util.h"
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poetteringint main(int argc, char *argv[]) {
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering BtrfsQuotaInfo quota;
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering int r, fd;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (fd < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering log_error_errno(errno, "Failed to open root directory: %m");
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering else {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering char ts[FORMAT_TIMESTAMP_MAX], bs[FORMAT_BYTES_MAX];
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering BtrfsSubvolInfo info;
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_get_info_fd(fd, 0, &info);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (r < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering log_error_errno(r, "Failed to get subvolume info: %m");
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering else {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering log_info("otime: %s", format_timestamp(ts, sizeof(ts), info.otime));
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering log_info("read-only (search): %s", yes_no(info.read_only));
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering }
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_qgroup_get_quota_fd(fd, 0, &quota);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (r < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering log_error_errno(r, "Failed to get quota info: %m");
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering else {
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering log_info("referenced: %s", strna(format_bytes(bs, sizeof(bs), quota.referenced)));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering log_info("exclusive: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive)));
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering log_info("referenced_max: %s", strna(format_bytes(bs, sizeof(bs), quota.referenced_max)));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering log_info("exclusive_max: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive_max)));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering r = btrfs_subvol_get_read_only_fd(fd);
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering if (r < 0)
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering log_error_errno(r, "Failed to get read only flag: %m");
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering else
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering log_info("read-only (ioctl): %s", yes_no(r));
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering safe_close(fd);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering }
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering r = btrfs_subvol_make("/xxxtest");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
4c1fc3e404d648c70bd2f50ac50aeac6ece8872eDaniel Mack r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to write file: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
e9bc1871b974fa9e33d9c1a45e249e6d1c8bc562Lennart Poettering r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", 0);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to make snapshot: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
e9bc1871b974fa9e33d9c1a45e249e6d1c8bc562Lennart Poettering r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", BTRFS_SNAPSHOT_READ_ONLY);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to make snapshot: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxtest", BTRFS_REMOVE_QUOTA);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to remove subvolume: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxtest2", BTRFS_REMOVE_QUOTA);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to remove subvolume: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxtest3", BTRFS_REMOVE_QUOTA);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to remove subvolume: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
e9bc1871b974fa9e33d9c1a45e249e6d1c8bc562Lennart Poettering r = btrfs_subvol_snapshot("/etc", "/etc2", BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to make snapshot: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/etc2", BTRFS_REMOVE_QUOTA);
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering if (r < 0)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering log_error_errno(r, "Failed to remove subvolume: %m");
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering r = btrfs_subvol_make("/xxxrectest");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering r = btrfs_subvol_make("/xxxrectest/xxxrectest2");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering r = btrfs_subvol_make("/xxxrectest/xxxrectest3");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering r = btrfs_subvol_make("/xxxrectest/xxxrectest3/sub");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (mkdir("/xxxrectest/dir", 0755) < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(errno, "Failed to make directory: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (mkdir("/xxxrectest/dir/xxxrectest4/dir", 0755) < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(errno, "Failed to make directory: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4/dir/xxxrectest5");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (mkdir("/xxxrectest/mnt", 0755) < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(errno, "Failed to make directory: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering r = btrfs_subvol_snapshot("/xxxrectest", "/xxxrectest2", BTRFS_SNAPSHOT_RECURSIVE);
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering if (r < 0)
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering log_error_errno(r, "Failed to snapshot subvolume: %m");
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxrectest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (r < 0)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering log_error_errno(r, "Failed to recursively remove subvolume: %m");
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxrectest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering if (r < 0)
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering log_error_errno(r, "Failed to recursively remove subvolume: %m");
f70a17f8d47ec8a62fa3b9b0bbe40fa107088540Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_make("/xxxquotatest");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_auto_qgroup("/xxxquotatest", 0, true);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to set up auto qgroup: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_make("/xxxquotatest/beneath");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to make subvolume: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_auto_qgroup("/xxxquotatest/beneath", 0, false);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to set up auto qgroup: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_qgroup_set_limit("/xxxquotatest/beneath", 0, 4ULL * 1024 * 1024 * 1024);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to set up quota limit: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_set_subtree_quota_limit("/xxxquotatest", 0, 5ULL * 1024 * 1024 * 1024);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to set up quota limit: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_snapshot("/xxxquotatest", "/xxxquotatest2", BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to setup snapshot: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_qgroup_get_quota("/xxxquotatest2/beneath", 0, &quota);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to query quota: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering assert_se(quota.referenced_max == 4ULL * 1024 * 1024 * 1024);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_get_subtree_quota("/xxxquotatest2", 0, &quota);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed to query quota: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering assert_se(quota.referenced_max == 5ULL * 1024 * 1024 * 1024);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxquotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed remove subvolume: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering r = btrfs_subvol_remove("/xxxquotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering if (r < 0)
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering log_error_errno(r, "Failed remove subvolume: %m");
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering return 0;
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering}