[Libguestfs] [PATCH 5/5] New API: Bind the tune2fs command.

Richard W.M. Jones
Wed, 09 Nov 2011 18:23:43 -0000

Previously we bound the 'tune2fs -l' command so that we could list out
the tunables of an ext2/3/4 filesystem.  Also commands like
set_e2label and set_e2uuid used tune2fs.

This commit binds many of the tunables that can be set using tune2fs.

The coverage is not complete, but we can add more later because this
uses optional parameters so the call is extensible without breaking
ABI.  The current change gives us enough for using libguestfs within
OpenStack.
---
 daemon/ext2.c                  |  192 ++++++++++++++++++++++++++++++++++++++++
 generator/generator_actions.ml |   84 +++++++++++++++++
 src/MAX_PROC_NR                |    2 +-
 3 files changed, 277 insertions(+), 1 deletions(-)

diff --git a/daemon/ext2.c b/daemon/ext2.c
index f7889da..9bc3581 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -498,3 +498,195 @@ do_mke2fs_JU (const char *fstype, int blocksize, const
char *device,
   free (err);
   return 0;
 }
+
+/* Takes optional arguments, consult optargs_bitmask. */
+int
+do_tune2fs (const char *device, /* only required parameter */
+            int force,
+            int maxmountcount,
+            int mountcount,
+            const char *errorbehavior,
+            int64_t group,
+            int intervalbetweenchecksdays,
+            int intervalbetweenchecksweeks,
+            int intervalbetweenchecksmonths,
+            int reservedblockspercentage,
+            const char *lastmounteddirectory,
+            int64_t reservedblockscount,
+            int64_t user)
+{
+  const size_t max_args = 64;
+  const char *argv[max_args];
+  size_t i = 0;
+  int r;
+  char *err;
+  char prog[] = "tune2fs";
+  char maxmountcount_s[64];
+  char mountcount_s[64];
+  char group_s[64];
+  char intervalbetweenchecks_s[64];
+  char reservedblockspercentage_s[64];
+  char reservedblockscount_s[64];
+  char user_s[64];
+  size_t ibc_count = 0;
+
+  if (e2prog (prog) == -1)
+    return -1;
+
+  argv[i++] = prog;
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_FORCE_BITMASK) {
+    if (force)
+      argv[i++] = "-f";
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_MAXMOUNTCOUNT_BITMASK) {
+    if (maxmountcount < 0) {
+      reply_with_error ("maxmountcount cannot be negative");
+      return -1;
+    }
+    argv[i++] = "-c";
+    snprintf (maxmountcount_s, sizeof maxmountcount_s, "%d",
maxmountcount);
+    argv[i++] = maxmountcount_s;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_MOUNTCOUNT_BITMASK) {
+    if (mountcount < 0) {
+      reply_with_error ("mountcount cannot be negative");
+      return -1;
+    }
+    argv[i++] = "-C";
+    snprintf (mountcount_s, sizeof mountcount_s, "%d", mountcount);
+    argv[i++] = mountcount_s;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_ERRORBEHAVIOR_BITMASK) {
+    if (STRNEQ (errorbehavior, "continue") &&
+        STRNEQ (errorbehavior, "remount-ro") &&
+        STRNEQ (errorbehavior, "panic")) {
+      reply_with_error ("invalid errorbehavior parameter: %s",
errorbehavior);
+      return -1;
+    }
+    argv[i++] = "-e";
+    argv[i++] = errorbehavior;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_GROUP_BITMASK) {
+    if (group < 0) {
+      reply_with_error ("group cannot be negative");
+      return -1;
+    }
+    argv[i++] = "-g";
+    snprintf (group_s, sizeof group_s, "%" PRIi64, group);
+    argv[i++] = group_s;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_INTERVALBETWEENCHECKSDAYS_BITMASK)
{
+    if (intervalbetweenchecksdays < 0) {
+      reply_with_error ("intervalbetweenchecksdays cannot be
negative");
+      return -1;
+    }
+    argv[i++] = "-i";
+    if (intervalbetweenchecksdays > 0) {
+      snprintf (intervalbetweenchecks_s, sizeof intervalbetweenchecks_s,
+                "%dd", intervalbetweenchecksdays);
+      argv[i++] = intervalbetweenchecks_s;
+    }
+    else
+      argv[i++] = "0";
+
+    ibc_count++;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_INTERVALBETWEENCHECKSWEEKS_BITMASK)
{
+    if (intervalbetweenchecksweeks < 0) {
+      reply_with_error ("intervalbetweenchecksweeks cannot be
negative");
+      return -1;
+    }
+    argv[i++] = "-i";
+    if (intervalbetweenchecksweeks > 0) {
+      snprintf (intervalbetweenchecks_s, sizeof intervalbetweenchecks_s,
+                "%dw", intervalbetweenchecksweeks);
+      argv[i++] = intervalbetweenchecks_s;
+    }
+    else
+      argv[i++] = "0";
+
+    ibc_count++;
+  }
+
+  if (optargs_bitmask &
GUESTFS_TUNE2FS_INTERVALBETWEENCHECKSMONTHS_BITMASK) {
+    if (intervalbetweenchecksmonths < 0) {
+      reply_with_error ("intervalbetweenchecksmonths cannot be
negative");
+      return -1;
+    }
+    argv[i++] = "-i";
+    if (intervalbetweenchecksmonths > 0) {
+      snprintf (intervalbetweenchecks_s, sizeof intervalbetweenchecks_s,
+                "%dm", intervalbetweenchecksmonths);
+      argv[i++] = intervalbetweenchecks_s;
+    }
+    else
+      argv[i++] = "0";
+
+    ibc_count++;
+  }
+
+  if (ibc_count > 1) {
+    reply_with_error ("intervalbetweendays/weeks/months: only one of these
optional parameters can be specified");
+    return -1;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSPERCENTAGE_BITMASK) {
+    if (reservedblockspercentage < 0) {
+      reply_with_error ("reservedblockspercentage cannot be
negative");
+      return -1;
+    }
+    argv[i++] = "-m";
+    snprintf (reservedblockspercentage_s, sizeof reservedblockspercentage_s,
+              "%d", reservedblockspercentage);
+    argv[i++] = reservedblockspercentage_s;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_LASTMOUNTEDDIRECTORY_BITMASK) {
+    argv[i++] = "-M";
+    argv[i++] = lastmounteddirectory;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSCOUNT_BITMASK) {
+    if (reservedblockscount < 0) {
+      reply_with_error ("reservedblockscount cannot be negative");
+      return -1;
+    }
+    argv[i++] = "-r";
+    snprintf (reservedblockscount_s, sizeof reservedblockscount_s,
+              "%" PRIi64, reservedblockscount);
+    argv[i++] = reservedblockscount_s;
+  }
+
+  if (optargs_bitmask & GUESTFS_TUNE2FS_USER_BITMASK) {
+    if (user < 0) {
+      reply_with_error ("user cannot be negative");
+      return -1;
+    }
+    argv[i++] = "-u";
+    snprintf (user_s, sizeof user_s, "%" PRIi64, user);
+    argv[i++] = user_s;
+  }
+
+  argv[i++] = device;
+  argv[i++] = NULL;
+
+  if (i > max_args)
+    abort ();
+
+  r = commandv (NULL, &err, argv);
+  if (r == -1) {
+    reply_with_error ("%s: %s: %s", prog, device, err);
+    free (err);
+    return -1;
+  }
+
+  free (err);
+  return 0;
+}
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index d3fa3e0..1b2c36b 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -6332,6 +6332,90 @@ is for copying blocks within existing files.  See
C<guestfs_cp>,
 C<guestfs_cp_a> and C<guestfs_mv> for general file copying and
 moving functions.");

+  ("tune2fs", (RErr, [Device "device"], [Bool
"force"; Int "maxmountcount"; Int "mountcount";
String "errorbehavior"; Int64 "group"; Int
"intervalbetweenchecksdays"; Int
"intervalbetweenchecksweeks"; Int
"intervalbetweenchecksmonths"; Int
"reservedblockspercentage"; String "lastmounteddirectory";
Int64 "reservedblockscount"; Int64 "user"]), 298, [],
+   [InitBasicFS, Always, TestRun (
+     [["tune2fs"; "/dev/sda1"; "false";
"0"; ""; "NOARG"; ""; "0";
""; ""; ""; "NOARG"; "";
""]])],
+   "adjust ext2/ext3/ext4 filesystem parameters",
+   "\
+This call allows you to adjust various filesystem parameters of
+an ext2/ext3/ext4 filesystem called C<device>.
+
+The optional parameters are:
+
+=over 4
+
+=item C<force>
+
+Force tune2fs to complete the operation even in the face of errors.
+This is the same as the tune2fs C<-f> option.
+
+=item C<maxmountcount>
+
+Set the number of mounts after which the filesystem is checked
+by L<e2fsck(8)>.  If this is C<0> then the number of mounts is
+disregarded.  This is the same as the tune2fs C<-c> option.
+
+=item C<mountcount>
+
+Set the number of times the filesystem has been mounted.
+This is the same as the tune2fs C<-C> option.
+
+=item C<errorbehavior>
+
+Change the behavior of the kernel code when errors are detected.
+Possible values currently are: C<continue>, C<remount-ro>,
C<panic>.
+In practice these options don't really make any difference,
+particularly for write errors.
+
+This is the same as the tune2fs C<-e> option.
+
+=item C<group>
+
+Set the group which can use reserved filesystem blocks.
+This is the same as the tune2fs C<-g> option except that it
+can only be specified as a number.
+
+=item C<intervalbetweenchecksdays>
+
+=item C<intervalbetweenchecksweeks>
+
+=item C<intervalbetweenchecksmonths>
+
+Adjust the maximal time between two filesystem checks
+(in days, weeks or months respectively).  Only a maximum of
+one of these optional parameters may be passed to the call.
+If the option is passed as C<0> then time-dependent checking
+is disabled.
+
+This is the same as the tune2fs C<-i> option.
+
+=item C<reservedblockspercentage>
+
+Set the percentage of the filesystem which may only be allocated
+by privileged processes.
+This is the same as the tune2fs C<-m> option.
+
+=item C<lastmounteddirectory>
+
+Set the last mounted directory.
+This is the same as the tune2fs C<-M> option.
+
+=item C<reservedblockscount>
+Set the number of reserved filesystem blocks.
+This is the same as the tune2fs C<-r> option.
+
+=item C<user>
+
+Set the user who can use the reserved filesystem blocks.
+This is the same as the tune2fs C<-u> option except that it
+can only be specified as a number.
+
+=back
+
+To get the current values of filesystem parameters, see
+C<guestfs_tune2fs_l>.  For precise details of how tune2fs
+works, see the L<tune2fs(8)> man page.");
+
 ]

 let all_functions = non_daemon_functions @ daemon_functions
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 95de1ee..a1f7f63 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-297
+298
--
1.7.6