[Libguestfs] [PATCHv4 2/2] Include resize2fs_P into vfs_minimum_size.

Maxim Perevedentsev
Tue, 20 Oct 2015 15:45:56 -0000

---
 daemon/daemon.h      |  1 +
 daemon/ext2.c        | 62 +++++++++++++++++++++++++++++++++++++++++++++-------
 daemon/fs-min-size.c |  3 +++
 generator/actions.ml | 20 ++++-------------
 src/MAX_PROC_NR      |  2 +-
 5 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/daemon/daemon.h b/daemon/daemon.h
index 3b0266d..8bcc9bd 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -224,6 +224,7 @@ extern int sync_disks (void);
 #define EXT2_LABEL_MAX 16
 extern int fstype_is_extfs (const char *fstype);
 extern int ext_set_uuid_random (const char *device);
+extern int64_t ext_minimum_size (const char *device);

 /*-- in blkid.c --*/
 extern char *get_blkid_tag (const char *device, const char *tag);
diff --git a/daemon/ext2.c b/daemon/ext2.c
index 0cd6a66..01f934b 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -29,6 +29,7 @@
 #include "daemon.h"
 #include "c-ctype.h"
 #include "actions.h"
+#include "xstrtol.h"

 #define MAX_ARGS 128

@@ -279,15 +280,41 @@ do_resize2fs_M (const char *device)
   return 0;
 }

+static long
+get_block_size (const char *device)
+{
+  CLEANUP_FREE_STRING_LIST char **params = NULL;
+  const char *block_pattern = "Block size";
+  size_t i;
+  long block_size;
+
+  params = do_tune2fs_l (device);
+  if (params == NULL)
+    return -1;
+
+  for (i = 0; params[i] != NULL; i += 2) {
+    if (STREQ (params[i], block_pattern)) {
+      if (xstrtol (params[i + 1], NULL, 10, &block_size, NULL) !=
LONGINT_OK) {
+        reply_with_error ("cannot parse block size");
+        return -1;
+      }
+      return block_size;
+    }
+  }
+
+  reply_with_error ("missing 'Block size' in tune2fs_l
output");
+  return -1;
+}
+
 int64_t
-do_resize2fs_P (const char *device)
+ext_minimum_size (const char *device)
 {
   CLEANUP_FREE char *err = NULL, *out = NULL;
   CLEANUP_FREE_STRING_LIST char **lines = NULL;
   int r;
   size_t i;
-  char *p;
   int64_t ret;
+  long block_size;
   const char *pattern = "Estimated minimum size of the filesystem: ";

   r = command (&out, &err, str_resize2fs, "-P", device,
NULL);
@@ -300,17 +327,36 @@ do_resize2fs_P (const char *device)
   if (lines == NULL)
     return -1;

-  for (i = 0; lines[i] != NULL; ++i) {
-    if (verbose)
-      fprintf (stderr, "resize2fs_P: lines[%zu] =
\"%s\"\n", i, lines[i]);
+#if __WORDSIZE == 64
+#define XSTRTOD64 xstrtol
+#else
+#define XSTRTOD64 xstrtoll
+#endif

-    if ((p = strstr (lines[i], pattern))) {
-      if (sscanf (p + strlen(pattern), "%" SCNd64, &ret) != 1)
+  for (i = 0; lines[i] != NULL; ++i) {
+    if (STRPREFIX (lines[i], pattern)) {
+      if (XSTRTOD64 (lines[i] + strlen (pattern),
+                     NULL, 20, &ret, NULL) != LONGINT_OK) {
+        reply_with_error ("cannot parse minimum size");
+        return -1;
+      }
+      if ((block_size = get_block_size (device)) == -1)
+        return -1;
+      if (verbose) {
+        fprintf (stderr, "Minimum size in blocks: %" SCNd64 \
+                         "\nBlock count: %ld\n", ret, block_size);
+      }
+      if (INT64_MAX / block_size < ret) {
+        reply_with_error ("filesystem size too big: overflow");
         return -1;
-      return ret;
+      }
+      return ret * block_size;
     }
   }

+#undef XSTRTOD64
+
+  reply_with_error ("minimum size not found. Check output
format:\n%s", out);
   return -1;
 }

diff --git a/daemon/fs-min-size.c b/daemon/fs-min-size.c
index 652eb0e..4f93f8c 100644
--- a/daemon/fs-min-size.c
+++ b/daemon/fs-min-size.c
@@ -35,6 +35,9 @@ do_vfs_minimum_size (const mountable_t *mountable)
   if (vfs_type == NULL)
     return -1;

+  else if (fstype_is_extfs (vfs_type))
+    r = ext_minimum_size (mountable->device);
+
   else if (STREQ (vfs_type, "ntfs"))
     r = ntfs_minimum_size (mountable->device);

diff --git a/generator/actions.ml b/generator/actions.ml
index e0459c0..10acb7c 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12752,24 +12752,12 @@ Only some filesystem types support setting UUIDs.
 To read the UUID on a filesystem, call C<guestfs_vfs_uuid>." };

   { defaults with
-    name = "resize2fs_P"; added = (1, 31, 17);
-    style = RInt64 "sizeinblocks", [Device "device"], [];
-    proc_nr = Some 457;
-    tests = [
-      InitBasicFS, Always, TestRun (
-        [["resize2fs_P"; "/dev/sda1"]]), [];
-    ];
-    shortdesc = "get minimum filesystem size in blocks";
-    longdesc = "\
-Get the estimated minimum filesystem size of an ext2/3/4 filesystem in blocks.
-
-See also L<resize2fs(8)>." };
-
-  { defaults with
     name = "vfs_minimum_size"; added = (1, 31, 18);
     style = RInt64 "sizeinbytes", [Mountable "mountable"],
[];
-    proc_nr = Some 458;
+    proc_nr = Some 457;
     tests = [
+      InitBasicFS, Always, TestRun (
+        [["vfs_minimum_size"; "/dev/sda1"]]), [];
       InitPartition, IfAvailable "ntfsprogs", TestRun(
         [["mkfs"; "ntfs"; "/dev/sda1";
""; "NOARG"; ""; ""; "NOARG"];
          ["vfs_minimum_size"; "/dev/sda1"]]), [];
@@ -12782,7 +12770,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)>." };
+See also L<ntfsresize(8)>, L<resize2fs(8)>." };

 ]

diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index c92ddb6..de2a00c 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-458
+457
--
1.8.3.1