From f23f556f03f72b966c7a6cc8f4afa03a29d1ea5f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 6 Jan 2015 16:00:27 -0500 Subject: [PATCH] checkout: Add --fsync=false Some use cases for checkouts don't need to fsync during checkout. Installer programs for example will just do a global fsync at the end. In the future, the default "ostree admin" core could also be rearchitected to only do a transaction commit right before reboot, and do the fsync then. https://bugzilla.gnome.org/show_bug.cgi?id=742482 --- Makefile-ostree.am | 2 ++ src/libostree/ostree-repo-checkout.c | 39 ++++++++++++-------- src/ostree/ot-builtin-checkout.c | 22 ++++++++++++ src/ostree/ot-builtin-commit.c | 43 +++++++--------------- src/ostree/ot-tool-util.c | 53 ++++++++++++++++++++++++++++ src/ostree/ot-tool-util.h | 35 ++++++++++++++++++ 6 files changed, 149 insertions(+), 45 deletions(-) create mode 100644 src/ostree/ot-tool-util.c create mode 100644 src/ostree/ot-tool-util.h diff --git a/Makefile-ostree.am b/Makefile-ostree.am index dc7e83c7..b82932c7 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -47,6 +47,8 @@ ostree_SOURCES = src/ostree/main.c \ src/ostree/ot-dump.c \ src/ostree/ot-editor.c \ src/ostree/ot-editor.h \ + src/ostree/ot-tool-util.c \ + src/ostree/ot-tool-util.h \ $(NULL) # Admin subcommand diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index c31bd3d0..1340484c 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -64,13 +64,16 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)temp_out); - do - res = fsync (fd); - while (G_UNLIKELY (res == -1 && errno == EINTR)); - if (G_UNLIKELY (res == -1)) + if (!self->disable_fsync) { - gs_set_error_from_errno (error, errno); - goto out; + do + res = fsync (fd); + while (G_UNLIKELY (res == -1 && errno == EINTR)); + if (G_UNLIKELY (res == -1)) + { + gs_set_error_from_errno (error, errno); + goto out; + } } if (!g_output_stream_close (temp_out, cancellable, error)) @@ -100,7 +103,8 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, } static gboolean -write_regular_file_content (OstreeRepoCheckoutMode mode, +write_regular_file_content (OstreeRepo *self, + OstreeRepoCheckoutMode mode, GOutputStream *output, GFileInfo *file_info, GVariant *xattrs, @@ -150,10 +154,13 @@ write_regular_file_content (OstreeRepoCheckoutMode mode, } } - if (fsync (fd) == -1) + if (!self->disable_fsync) { - gs_set_error_from_errno (error, errno); + if (fsync (fd) == -1) + { + gs_set_error_from_errno (error, errno); goto out; + } } if (!g_output_stream_close (output, cancellable, error)) @@ -165,7 +172,8 @@ write_regular_file_content (OstreeRepoCheckoutMode mode, } static gboolean -checkout_file_from_input_at (OstreeRepoCheckoutMode mode, +checkout_file_from_input_at (OstreeRepo *self, + OstreeRepoCheckoutMode mode, GFileInfo *file_info, GVariant *xattrs, GInputStream *input, @@ -231,7 +239,7 @@ checkout_file_from_input_at (OstreeRepoCheckoutMode mode, temp_out = g_unix_output_stream_new (fd, TRUE); fd = -1; /* Transfer ownership */ - if (!write_regular_file_content (mode, temp_out, file_info, xattrs, input, + if (!write_regular_file_content (self, mode, temp_out, file_info, xattrs, input, cancellable, error)) goto out; } @@ -248,7 +256,8 @@ checkout_file_from_input_at (OstreeRepoCheckoutMode mode, * it into place. This implements union-like behavior. */ static gboolean -checkout_file_unioning_from_input_at (OstreeRepoCheckoutMode mode, +checkout_file_unioning_from_input_at (OstreeRepo *repo, + OstreeRepoCheckoutMode mode, GFileInfo *file_info, GVariant *xattrs, GInputStream *input, @@ -291,7 +300,7 @@ checkout_file_unioning_from_input_at (OstreeRepoCheckoutMode mode, cancellable, error)) goto out; - if (!write_regular_file_content (mode, temp_out, file_info, xattrs, input, + if (!write_regular_file_content (repo, mode, temp_out, file_info, xattrs, input, cancellable, error)) goto out; } @@ -498,7 +507,7 @@ checkout_one_file_at (OstreeRepo *repo, if (overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES) { - if (!checkout_file_unioning_from_input_at (mode, source_info, xattrs, input, + if (!checkout_file_unioning_from_input_at (repo, mode, source_info, xattrs, input, destination_dfd, destination_parent, destination_name, cancellable, error)) @@ -509,7 +518,7 @@ checkout_one_file_at (OstreeRepo *repo, } else { - if (!checkout_file_from_input_at (mode, source_info, xattrs, input, + if (!checkout_file_from_input_at (repo, mode, source_info, xattrs, input, destination_dfd, destination_parent, destination_name, cancellable, error)) diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index b3284ef8..b6d150ab 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -29,6 +29,7 @@ #include "ot-builtins.h" #include "ostree.h" #include "otutil.h" +#include "ot-tool-util.h" static gboolean opt_user_mode; static gboolean opt_allow_noent; @@ -36,6 +37,23 @@ static char *opt_subpath; static gboolean opt_union; static gboolean opt_from_stdin; static char *opt_from_file; +static gboolean opt_disable_fsync; + +static gboolean +parse_fsync_cb (const char *option_name, + const char *value, + gpointer data, + GError **error) +{ + gboolean val; + + if (!ot_parse_boolean (option_name, value, &val, error)) + return FALSE; + + opt_disable_fsync = !val; + + return TRUE; +} static GOptionEntry options[] = { { "user-mode", 'U', 0, G_OPTION_ARG_NONE, &opt_user_mode, "Do not change file ownership or initialize extended attributes", NULL }, @@ -44,6 +62,7 @@ static GOptionEntry options[] = { { "allow-noent", 0, 0, G_OPTION_ARG_NONE, &opt_allow_noent, "Do nothing if specified path does not exist", NULL }, { "from-stdin", 0, 0, G_OPTION_ARG_NONE, &opt_from_stdin, "Process many checkouts from standard input", NULL }, { "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" }, + { "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" }, { NULL } }; @@ -186,6 +205,9 @@ ostree_builtin_checkout (int argc, char **argv, GCancellable *cancellable, GErro if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) goto out; + if (opt_disable_fsync) + ostree_repo_set_disable_fsync (repo, TRUE); + if (argc < 2) { gchar *help = g_option_context_get_help (context, TRUE, NULL); diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 47c9b7c3..79ee77c3 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -27,6 +27,7 @@ #include "ot-editor.h" #include "ostree.h" #include "otutil.h" +#include "ot-tool-util.h" static char *opt_subject; static char *opt_body; @@ -49,38 +50,20 @@ static char *opt_gpg_homedir; static gboolean opt_generate_sizes; static gboolean opt_disable_fsync; -#define ARG_EQ(x, y) (g_ascii_strcasecmp(x, y) == 0) -/* create a function to parse the --fsync option, and current parse it the - * same as --disable-fsync. Allows us to add other things later, and not have - * a double negative. */ -static gboolean opt__fsync(const gchar *option_name, - const gchar *value, - gpointer data, - GError **error) +static gboolean +parse_fsync_cb (const char *option_name, + const char *value, + gpointer data, + GError **error) { - g_assert(g_str_equal(option_name, "--fsync")); + gboolean val; - if (0) {} - else if (ARG_EQ(value, "1")) - opt_disable_fsync = 0; - else if (ARG_EQ(value, "true")) - opt_disable_fsync = 0; - else if (ARG_EQ(value, "yes")) - opt_disable_fsync = 0; - else if (ARG_EQ(value, "0")) - opt_disable_fsync = 1; - else if (ARG_EQ(value, "false")) - opt_disable_fsync = 1; - else if (ARG_EQ(value, "none")) - opt_disable_fsync = 1; - else if (ARG_EQ(value, "no")) - opt_disable_fsync = 1; - else - /* do we want to complain here? */ - return 0; + if (!ot_parse_boolean (option_name, value, &val, error)) + return FALSE; + + opt_disable_fsync = !val; - - return 1; + return TRUE; } static GOptionEntry options[] = { @@ -104,7 +87,7 @@ static GOptionEntry options[] = { #endif { "generate-sizes", 0, 0, G_OPTION_ARG_NONE, &opt_generate_sizes, "Generate size information along with commit metadata", NULL }, { "disable-fsync", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL }, - { "fsync", 0, 0, G_OPTION_ARG_CALLBACK, opt__fsync, "Specify how to invoke fsync()", NULL }, + { "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" }, { NULL } }; diff --git a/src/ostree/ot-tool-util.c b/src/ostree/ot-tool-util.c new file mode 100644 index 00000000..fd4bbf92 --- /dev/null +++ b/src/ostree/ot-tool-util.c @@ -0,0 +1,53 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2015 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "ot-admin-functions.h" +#include "otutil.h" +#include "ostree.h" +#include "libgsystem.h" +#include "ot-tool-util.h" + +gboolean +ot_parse_boolean (const char *option_name, + const char *value, + gboolean *out_parsed, + GError **error) +{ +#define ARG_EQ(x, y) (g_ascii_strcasecmp(x, y) == 0) + if (ARG_EQ(value, "1") + || ARG_EQ(value, "true") + || ARG_EQ(value, "yes")) + *out_parsed = TRUE; + else if (ARG_EQ(value, "0") + || ARG_EQ(value, "false") + || ARG_EQ(value, "no") + || ARG_EQ(value, "none")) + *out_parsed = FALSE; + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Invalid boolean argument '%s'", value); + return FALSE; + } + + return TRUE; +} diff --git a/src/ostree/ot-tool-util.h b/src/ostree/ot-tool-util.h new file mode 100644 index 00000000..201190e7 --- /dev/null +++ b/src/ostree/ot-tool-util.h @@ -0,0 +1,35 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2015 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +gboolean +ot_parse_boolean (const char *option_name, + const char *value, + gboolean *out_parsed, + GError **error); + +G_END_DECLS +