---
daemon/btrfs.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++
daemon/daemon.h | 1 +
daemon/fs-min-size.c | 34 ++++++++++++++++++++++++-
generator/actions.ml | 6 ++++-
4 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index ddb029d..652a17e 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -2190,3 +2190,74 @@ do_btrfs_replace (const char *srcdev, const char *targetdev,
return 0;
}
+
+/* btrfs command add a new command
+ * inspect-internal min-dev-size <path>
+ * since v4.2
+ * We could check whether 'btrfs' supports
+ * 'min-dev-size' command by checking the output of
+ * 'btrfs --help' command.
+ */
+static int
+test_btrfs_min_dev_size (void)
+{
+ CLEANUP_FREE char *err = NULL, *out = NULL;
+ static int result = -1;
+ const char *cmd_pattern = "btrfs inspect-internal min-dev-size";
+ int r;
+
+ if (result != -1)
+ return result;
+
+ r = commandr (&out, &err, str_btrfs, "--help", NULL);
+
+ if (r == -1) {
+ reply_with_error ("btrfs: %s", err);
+ return -1;
+ }
+
+ if (strstr (out, cmd_pattern) == NULL)
+ result = 0;
+ else
+ result = 1;
+
+ return result;
+}
+
+int64_t
+btrfs_minimum_size (const char *path)
+{
+ CLEANUP_FREE char *err = NULL, *out = NULL;
+ int64_t ret = 0;
+ int r;
+ int min_size_supported = test_btrfs_min_dev_size ();
+
+ if (min_size_supported == -1)
+ return -1;
+ else if (min_size_supported == 0)
+ NOT_SUPPORTED (-1, "'btrfs inspect-internal min-dev-size' \
+ needs btrfs-progs >= 4.2");
+
+ r = command (&out, &err, str_btrfs, "inspect-internal",
+ "min-dev-size", sysroot_path (path), NULL);
+
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ return -1;
+ }
+
+#if __WORDSIZE == 64
+#define XSTRTOD64 xstrtol
+#else
+#define XSTRTOD64 xstrtoll
+#endif
+
+ if (XSTRTOD64 (out, NULL, 10, &ret, NULL) != LONGINT_OK) {
+ reply_with_error ("cannot parse minimum size");
+ return -1;
+ }
+
+#undef XSTRTOD64
+
+ return ret;
+}
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 8bcc9bd..4a969dd 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -280,6 +280,7 @@ extern char *btrfs_get_label (const char *device);
extern int btrfs_set_label (const char *device, const char *label);
extern int btrfs_set_uuid (const char *device, const char *uuid);
extern int btrfs_set_uuid_random (const char *device);
+extern int64_t btrfs_minimum_size (const char *path);
/*-- in ntfs.c --*/
extern char *ntfs_get_label (const char *device);
diff --git a/daemon/fs-min-size.c b/daemon/fs-min-size.c
index 4f93f8c..ca71c4d 100644
--- a/daemon/fs-min-size.c
+++ b/daemon/fs-min-size.c
@@ -25,12 +25,37 @@
#include "daemon.h"
#include "actions.h"
+static char*
+get_mount_point (const char *device)
+{
+ CLEANUP_FREE_STRING_LIST char **mountpoints = do_mountpoints();
+ size_t i;
+ char *path;
+
+ if (mountpoints == NULL) {
+ reply_with_error ("cannot get mountpoints");
+ return NULL;
+ }
+
+ for (i = 0; mountpoints[i] != NULL; i += 2) {
+ if (STREQ (mountpoints[i], device)) {
+ path = strdup (mountpoints[i + 1]);
+ if (path == NULL)
+ reply_with_perror ("strdup");
+ return path;
+ }
+ }
+
+ reply_with_error ("device not mounted: %s", device);
+ return NULL;
+}
+
int64_t
do_vfs_minimum_size (const mountable_t *mountable)
{
int64_t r;
- /* How we set the label depends on the filesystem type. */
+ /* How we get minimum size depends on the filesystem type. */
CLEANUP_FREE char *vfs_type = do_vfs_type (mountable);
if (vfs_type == NULL)
return -1;
@@ -41,6 +66,13 @@ do_vfs_minimum_size (const mountable_t *mountable)
else if (STREQ (vfs_type, "ntfs"))
r = ntfs_minimum_size (mountable->device);
+ else if (STREQ (vfs_type, "btrfs")) {
+ CLEANUP_FREE char *path = get_mount_point (mountable->device);
+ if (path == NULL)
+ return -1;
+ r = btrfs_minimum_size (path);
+ }
+
else
NOT_SUPPORTED (-1, "don't know how to get minimum size of '%s'
filesystems",
vfs_type);
diff --git a/generator/actions.ml b/generator/actions.ml
index 62176ab..8832410 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12761,6 +12761,10 @@ To read the UUID on a filesystem, call
C<guestfs_vfs_uuid>." };
InitPartition, IfAvailable "ntfsprogs", TestRun(
[["mkfs"; "ntfs"; "/dev/sda1"; "";
"NOARG"; ""; ""; "NOARG"];
["vfs_minimum_size"; "/dev/sda1"]]), [];
+ InitPartition, Always, TestRun (
+ [["mkfs"; "btrfs"; "/dev/sda1"; "";
"NOARG"; ""; ""; "NOARG"];
+ ["mount"; "/dev/sda1"; "/"];
+ ["vfs_minimum_size"; "/dev/sda1"]]), [];
];
shortdesc = "get minimum filesystem size";
longdesc = "\
@@ -12770,7 +12774,7 @@ This is the minimum possible size for filesystem shrinking.
If getting minimum size of specified filesystem is not supported,
this will fail and set errno as ENOTSUP.
-See also L<ntfsresize(8)>, L<resize2fs(8)>." };
+See also L<ntfsresize(8)>, L<resize2fs(8)>, L<btrfs(8)>." };
]
--
1.8.3.1