Package: coreutils;
Reported by: Giuseppe Scrivano <gscrivan <at> redhat.com>
Date: Sun, 25 Jan 2015 03:06:02 UTC
Severity: normal
Tags: patch
Done: Assaf Gordon <assafgordon <at> gmail.com>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Giuseppe Scrivano <gscrivan <at> redhat.com> To: Pádraig Brady <P <at> draigbrady.com> Cc: Bernhard Voelker <mail <at> bernhard-voelker.de>, Eric Blake <eblake <at> redhat.com>, 19681 <at> debbugs.gnu.org, Paul Eggert <eggert <at> cs.ucla.edu> Subject: bug#19681: [PATCH] sync: use syncfs(2) if any argument is specified Date: Tue, 27 Jan 2015 11:48:44 +0100
Pádraig Brady <P <at> draigbrady.com> writes: > thanks! > Pádraig. Thanks for the review, I've amended the changes you suggested: From b2babc9838b52892e2cdc46bc4590fa852daa0eb Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano <gscrivan <at> redhat.com> Date: Sun, 25 Jan 2015 01:33:45 +0100 Subject: [PATCH] sync: add support for fsync(2), fdatasync(2) and syncfs(2) * AUTHORS: Add myself to sync's authors. * NEWS: Mention the new feature. * m4/jm-macros.m4 (coreutils_MACROS): Check for syncfs. * man/sync.x: Add references to syncfs, fsync and fdatasync. * doc/coreutils.texi (sync invocation): Document the new feature. * src/sync.c: Include "quote.h". (AUTHORS): Include myself. (MODE_FILE, MODE_DATA, MODE_FILE_SYSTEM, MODE_SYNC): New enum values. (long_options): Define. (sync_arg): New function. (usage): Describe that arguments are now accepted. (main): Add arguments parsing and add support for fsync(2), fdatasync(2) and syncfs(2). --- AUTHORS | 2 +- NEWS | 3 + doc/coreutils.texi | 20 ++++++- m4/jm-macros.m4 | 1 + man/sync.x | 2 +- src/sync.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 170 insertions(+), 15 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0296830..64c11d7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -83,7 +83,7 @@ stat: Michael Meskes stdbuf: Pádraig Brady stty: David MacKenzie sum: Kayvan Aghaiepour, David MacKenzie -sync: Jim Meyering +sync: Jim Meyering, Giuseppe Scrivano tac: Jay Lepreau, David MacKenzie tail: Paul Rubin, David MacKenzie, Ian Lance Taylor, Jim Meyering tee: Mike Parker, Richard M. Stallman, David MacKenzie diff --git a/NEWS b/NEWS index e0a2893..3d4190b 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,9 @@ GNU coreutils NEWS -*- outline -*- split accepts a new --separator option to select a record separator character other than the default newline character. + sync no longer ignores arguments and it uses fsync(2), fdatasync(2) + and syncfs(2) synchronization in addition to sync(2). + ** Changes in behavior df no longer suppresses separate exports of the same remote device, as diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 5a3c31a..a1e664b 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -12053,8 +12053,24 @@ crashes, data may be lost or the file system corrupted as a result. The @command{sync} command ensures everything in memory is written to disk. -Any arguments are ignored, except for a lone @option{--help} or -@option{--version} (@pxref{Common options}). +If any argument is specified then only the specified files will be +synchronized. It uses internally the syscall fsync(2) on each of them. + +If at least one file is specified, it is possible to change the +synchronization policy with the following options. Also see +@ref{Common options}. + +@table @samp +@item --data +@opindex --data +Do not synchronize the file metadata unless it is required to maintain +data integrity. It uses the syscall fdatasync(2). + +@item --file-system +@opindex --file-system +Synchronize all the I/O waiting for the file systems that contain the file. +It uses the syscall syncfs(2). +@end table @exitstatus diff --git a/m4/jm-macros.m4 b/m4/jm-macros.m4 index 58fdd97..79f124b 100644 --- a/m4/jm-macros.m4 +++ b/m4/jm-macros.m4 @@ -89,6 +89,7 @@ AC_DEFUN([coreutils_MACROS], sethostname siginterrupt sync + syncfs sysctl sysinfo tcgetpgrp diff --git a/man/sync.x b/man/sync.x index 7947bb7..6ced07e 100644 --- a/man/sync.x +++ b/man/sync.x @@ -3,4 +3,4 @@ sync \- flush file system buffers [DESCRIPTION] .\" Add any additional description here [SEE ALSO] -sync(2) +fdatasync(2), fsync(2), sync(2), syncfs(2) diff --git a/src/sync.c b/src/sync.c index e9f4d7e..6c4d571 100644 --- a/src/sync.c +++ b/src/sync.c @@ -23,12 +23,31 @@ #include "system.h" #include "error.h" -#include "long-options.h" +#include "quote.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "sync" -#define AUTHORS proper_name ("Jim Meyering") +#define AUTHORS \ + proper_name ("Jim Meyering"), \ + proper_name ("Giuseppe Scrivano") + +enum +{ + MODE_FILE, + MODE_DATA, + MODE_FILE_SYSTEM, + MODE_SYNC +}; + +static struct option const long_options[] = +{ + {"data", no_argument, NULL, MODE_DATA}, + {"file-system", no_argument, NULL, MODE_FILE_SYSTEM}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +}; void usage (int status) @@ -37,11 +56,21 @@ usage (int status) emit_try_help (); else { - printf (_("Usage: %s [OPTION]\n"), program_name); + printf (_("Usage: %s [OPTION] [PATH]...\n"), program_name); fputs (_("\ Force changed blocks to disk, update the super block.\n\ \n\ +If one or more file paths are specified, sync only them,\n\ +use --data and --file-system to change the default behavior\n\ +\n\ "), stdout); + + fputs (_("\ + --file-system sync the file systems that contain the path\n\ + --data flush the metadata only if needed later for\n\ + data retrieval to be correctly handled\n\ +"), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); emit_ancillary_info (PROGRAM_NAME); @@ -49,9 +78,61 @@ Force changed blocks to disk, update the super block.\n\ exit (status); } +static bool +sync_arg (int mode, char *file) +{ + int ret = -1; + int fd = open (file, O_RDONLY); + if (fd < 0) + { + error (0, errno, _("cannot open %s for reading"), quote (file)); + return false; + } + + switch (mode) + { + case MODE_FILE: + ret = fsync (fd); + break; + + case MODE_DATA: + ret = fdatasync (fd); + break; + +#if HAVE_SYNCFS + case MODE_FILE_SYSTEM: + ret = syncfs (fd); + break; +#endif + + default: + error (EXIT_FAILURE, errno, _("invalid mode specified")); + break; + } + + if (ret < 0) + { + error (0, errno, _("syncing error")); + return false; + } + + if (close (fd) < 0) + { + error (0, errno, _("failed to close %s"), quote (file)); + return false; + } + + return true; +} + int main (int argc, char **argv) { + bool args_specified; + int c, ret; + bool arg_data = false, arg_file_system = false; + int mode; + initialize_main (&argc, &argv); set_program_name (argv[0]); setlocale (LC_ALL, ""); @@ -60,14 +141,68 @@ main (int argc, char **argv) atexit (close_stdout); - parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version, - usage, AUTHORS, (char const *) NULL); - if (getopt_long (argc, argv, "", NULL, NULL) != -1) - usage (EXIT_FAILURE); + while ((c = getopt_long (argc, argv, "", long_options, NULL)) + != -1) + { + switch (c) + { + case MODE_DATA: + arg_data = true; + break; + + case MODE_FILE_SYSTEM: + arg_file_system = true; + break; + + case_GETOPT_HELP_CHAR; + + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + + default: + usage (EXIT_FAILURE); + } + } + + args_specified = optind < argc; + + if (arg_data && arg_file_system) + { + error (EXIT_FAILURE, errno, + _("cannot specify both --data and --file-system")); + } + + if (!args_specified && arg_data) + error (EXIT_FAILURE, errno, _("--data needs at least one argument")); + + if (arg_data) + mode = MODE_DATA; + else if (! arg_file_system) + { + mode = args_specified ? MODE_FILE : MODE_SYNC; + } + else + { + /* On systems where syncfs is not available, or if no args are specified, + fallback to sync. */ + if (HAVE_SYNCFS && args_specified) + mode = MODE_FILE_SYSTEM; + else + { + mode = MODE_SYNC; + } + } - if (optind < argc) - error (0, 0, _("ignoring all arguments")); + if (mode == MODE_SYNC) + { + sync (); + return EXIT_SUCCESS; + } - sync (); - return EXIT_SUCCESS; + ret = EXIT_SUCCESS; + for (; optind < argc; optind++) + { + if (! sync_arg (mode, argv[optind])) + ret = EXIT_FAILURE; + } + return ret; } -- 2.1.0
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.