xfsrestore: use utimensat() to provide atime/mtime with ns resolution
PATCH v2 1/1 xfsrestore: use utimensat() to provide atime/mtime with ns resolution
xfsdump encodes and stores the full atime and mtime for each file with nanosecond resolution. xfsrestore uses utime() to set the times of each file that is restored. The latter supports resolution of 1 second, thus sub-second timestamp data is lost on restore.
Add the associated configure checks for and use utimensat() when available to restore timestamps with nanosecond resolution. Create a new helper to facilitate conditional support for utimensat().
---
v2:
- Use AC_TRY_LINK() instead of AC_TRY_COMPILE() to ensure utimensat() exists.
v1: http://oss.sgi.com/archives/xfs/2014-09/msg00025.html
configure.ac | 2 ++ include/builddefs.in | 1 + m4/Makefile | 1 + m4/package_libcdev.m4 | 16 ++++++++++++++++ restore/Makefile | 4 ++++ restore/content.c | 38 ++++++++++++++++++++++++++++++-------- 6 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 m4/package_libcdev.m4
configure.ac +2 -0
@@ -82,6 +82,8 @@ AC_PACKAGE_NEED_ATTRIBUTES_H AC_PACKAGE_NEED_ATTRIBUTES_MACROS AC_PACKAGE_NEED_ATTRGET_LIBATTR +AC_HAVE_UTIMENSAT + AC_MANUAL_FORMAT AC_CONFIG_FILES([include/builddefs])
include/builddefs.in +1 -0
@@ -69,6 +69,7 @@ ENABLE_SHARED = @enable_shared@ ENABLE_GETTEXT = @enable_gettext@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@ +HAVE_UTIMENSAT = @have_utimensat@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/Makefile +1 -0
@@ -16,6 +16,7 @@ LSRCFILES = \ manual_format.m4 \ package_attrdev.m4 \ package_globals.m4 \ + package_libcdev.m4 \ package_ncurses.m4 \ package_pthread.m4 \ package_utilies.m4 \
m4/package_libcdev.m4 new file +16 -0
@@ -0,0 +1,16 @@ +# +# Check if we have a utimensat libc call +# +AC_DEFUN([AC_HAVE_UTIMENSAT], + [ AC_MSG_CHECKING([for utimensat]) + AC_TRY_LINK([ +#define _ATFILE_SOURCE +#include <fcntl.h> +#include <sys/stat.h> + ], [ + utimensat(AT_FDCWD, 0, 0, AT_SYMLINK_NOFOLLOW); + ], have_utimensat=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + AC_SUBST(have_utimensat) + ])
restore/Makefile +4 -0
@@ -102,6 +102,10 @@ LTDEPENDENCIES = $(LIBRMT) LCFLAGS = -DRESTORE +ifeq ($(HAVE_UTIMENSAT),yes) +LCFLAGS += -DHAVE_UTIMENSAT +endif + default: depend $(LTCOMMAND) include $(BUILDRULES)
restore/content.c +30 -8
@@ -7418,6 +7418,34 @@ done:return 0 ; } +/* +* Set the access and modification times for a file. +*/ +static int +restore_file_amtime ( +const char *path, +struct bstat *bstatp) +{ +int rval; + +#ifdef HAVE_UTIMENSAT +struct timespec times[2 ]; + + times[0 ].tv_sec = bstatp->bs_atime.tv_sec; + times[0 ].tv_nsec = bstatp->bs_atime.tv_nsec; + times[1 ].tv_sec = bstatp->bs_mtime.tv_sec; + times[1 ].tv_nsec = bstatp->bs_mtime.tv_nsec; + rval =utimensat (AT_FDCWD , path, times,0 ); +#else +struct utimbuf utimbuf; + + utimbuf.actime = (time32_t )bstatp->bs_atime.tv_sec; + utimbuf.modtime = (time32_t )bstatp->bs_mtime.tv_sec; + rval =utime (path, &utimbuf); +#endif +return rval; +} +/* called to begin a regular file. if no path given, or if just toc, * don't actually write, just read. also get into that situation if * cannot prepare destination. fd == -1 signifies no write. *statp
@@ -7671,7 +7699,6 @@ restore_complete_reg(stream_context_t *strcxtp)bstat_t *bstatp = &strcxtp->sc_bstat;char *path = strcxtp->sc_path;intgen_t fd = strcxtp->sc_fd; -struct utimbuf utimbuf;intgen_t rval;// only applies to regular files
@@ -7688,9 +7715,7 @@ restore_complete_reg(stream_context_t *strcxtp)/* set the access and modification times */ - utimbuf.actime = (time32_t )bstatp->bs_atime.tv_sec; - utimbuf.modtime = (time32_t )bstatp->bs_mtime.tv_sec; - rval =utime ( path, &utimbuf ); + rval =restore_file_amtime (path, bstatp);if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set access and modification "
@@ -7770,7 +7795,6 @@ static bool_t restore_spec( filehdr_t *fhdrp, rv_t *rvp, char *path ) {bstat_t *bstatp = &fhdrp->fh_stat; -struct utimbuf utimbuf;char *printstr;intgen_t rval;
@@ -7913,9 +7937,7 @@ restore_spec( filehdr_t *fhdrp, rv_t *rvp, char *path )/* set the access and modification times */ - utimbuf.actime = (time32_t )bstatp->bs_atime.tv_sec; - utimbuf.modtime = (time32_t )bstatp->bs_mtime.tv_sec; - rval =utime ( path, &utimbuf ); + rval =restore_file_amtime (path, bstatp);if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set access and modification "
Signature · 6 lines
1.8.3.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 10 lines · Brian Foster
xfsdump encodes and stores the full atime and mtime for each file with nanosecond resolution. xfsrestore uses
utime()to set the times of each file that is restored. The latter supports resolution of 1 second, thus sub-second timestamp data is lost on restore.Add the associated configure checks for and use
utimensat()when available to restore timestamps with nanosecond resolution. Create a new helper to facilitate conditional support forutimensat().Signed-off-by Brian Foster <[email protected]>
Looks good to me,
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs