From 1aa8d4d49981959340118dfb7ebd94be56232b21 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sat, 1 Jul 2023 12:07:26 +0200 Subject: [PATCH] Imported Upstream version 12.2 --- .version | 2 +- HISTORY | 14 ++ Makefile.in | 61 ++++--- aclocal.m4 | 46 +++--- cmdline/elem.h | 7 + cmdline/io.c | 4 +- cmdline/io.h | 4 +- cmdline/mingw.c | 34 ++-- cmdline/portable.h | 2 +- cmdline/scan.c | 353 +++++++++++++++++++++++++++-------------- cmdline/snapraid.c | 7 + cmdline/state.c | 8 +- cmdline/state.h | 1 + cmdline/support.c | 14 ++ cmdline/support.h | 6 + cmdline/unix.c | 2 +- config.h.in | 4 + configure | 255 +++++++++++++++++++++-------- configure.ac | 56 ++++--- raid/raid.h | 2 +- tommyds/tommyhashdyn.h | 2 +- 21 files changed, 611 insertions(+), 273 deletions(-) diff --git a/.version b/.version index 37b64da..5b585d9 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -11.6 \ No newline at end of file +12.2 \ No newline at end of file diff --git a/HISTORY b/HISTORY index 8d11aed..aea2e9c 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,20 @@ SnapRAID HISTORY ================ +12.2 2022/08 +============ + * Fix build issue with GLIBC 2.36 + +12.1 2022/01 +============ + * Reduce stack usage to work in environments with limited stack size, like MUSL. + * Increase the default disk cache from 8 MiB to 16 MiB. + +12.0 2021/12 +============ + * Parallel disk scanning. It's always enabled but it doesn't cover the -m option + that still process disks sequentially. + 11.6 2021/10 ============ * The 'fix' and 'check' command with the -e option now process the whole diff --git a/Makefile.in b/Makefile.in index 9524fd5..6fbf6de 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -153,7 +153,7 @@ am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = -am__depfiles_maybe = +am__maybe_remake_depfiles = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) @@ -205,8 +205,8 @@ man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) HEADERS = $(noinst_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)config.h.in +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -555,8 +555,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -809,7 +809,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -852,7 +855,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -867,6 +870,10 @@ dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @@ -878,7 +885,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -896,7 +903,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -906,9 +913,11 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) @@ -1097,20 +1106,20 @@ uninstall-man: uninstall-man1 check-local clean clean-binPROGRAMS clean-checkPROGRAMS \ clean-cscope clean-generic clean-local cscope cscopelist-am \ ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \ - dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \ - distclean distclean-compile distclean-generic distclean-hdr \ - distclean-tags distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-binPROGRAMS install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-man1 install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - maintainer-clean-local mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-binPROGRAMS uninstall-man \ - uninstall-man1 + dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \ + distcheck distclean distclean-compile distclean-generic \ + distclean-hdr distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-man1 install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic maintainer-clean-local mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-man uninstall-man1 .PRECIOUS: Makefile diff --git a/aclocal.m4 b/aclocal.m4 index 09c00d5..b092b74 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.16.2 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.]) # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.15' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.15], [], +m4_if([$1], [1.16.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.15])dnl +[AM_AUTOMAKE_VERSION([1.16.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -143,7 +143,7 @@ fi])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -230,8 +230,8 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. @@ -298,7 +298,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -340,7 +340,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -361,7 +361,7 @@ if test x"${install_sh+set}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -382,7 +382,7 @@ AC_SUBST([am__leading_dot])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -421,7 +421,7 @@ fi # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -450,7 +450,7 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -497,7 +497,7 @@ AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -516,7 +516,7 @@ AC_DEFUN([AM_RUN_LOG], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -597,7 +597,7 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -657,7 +657,7 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -685,7 +685,7 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -704,7 +704,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/cmdline/elem.h b/cmdline/elem.h index a780432..0048153 100644 --- a/cmdline/elem.h +++ b/cmdline/elem.h @@ -369,6 +369,13 @@ struct snapraid_disk { */ thread_mutex_t fs_mutex; int fs_mutex_enabled; /*< If the lock has to be used. */ + + /** + * Mutex for protecting the scan process. + * + * It's used during the scan process to protect the stampset to identity copy of files + */ + thread_mutex_t stamp_mutex; #endif /** diff --git a/cmdline/io.c b/cmdline/io.c index d315304..3cc77ac 100644 --- a/cmdline/io.c +++ b/cmdline/io.c @@ -879,9 +879,9 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state, #if HAVE_THREAD if (io_cache == 0) { - /* default is 8 MiB of cache */ + /* default is 16 MiB of cache */ /* this seems to be a good tradeoff between speed and memory usage */ - io->io_max = 8 * 1024 * 1024 / state->block_size; + io->io_max = 16 * 1024 * 1024 / state->block_size; if (io->io_max < IO_MIN) io->io_max = IO_MIN; if (io->io_max > IO_MAX) diff --git a/cmdline/io.h b/cmdline/io.h index f0153dc..685ac97 100644 --- a/cmdline/io.h +++ b/cmdline/io.h @@ -35,8 +35,8 @@ * 4 - 452 MB/s, CPU 54%, speed 118% * 8 - 487 MB/s, CPU 60%, speed 128% * 16 - 505 MB/s, CPU 63%, speed 132% - * 32 - 520 MB/s, CPU 64%, speed 136% - * 64 - 524 MB/s, CPU 65%, speed 137% + * 32 - 520 MB/s, CPU 64%, speed 136% [SnapRAID <= 12.0] + * 64 - 524 MB/s, CPU 65%, speed 137% [SnapRAID > 12.0] * 128 - 525 MB/s, CPU 66%, speed 138% */ #define IO_MIN 3 /* required by writers, readers can work also with 2 */ diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 705278c..2a0069f 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -31,14 +31,26 @@ int exit_sync_needed = 2; /* Add missing Windows declaration */ /* For SetThreadExecutionState */ +#ifndef WIN32_ES_SYSTEM_REQUIRED #define WIN32_ES_SYSTEM_REQUIRED 0x00000001L +#endif +#ifndef WIN32_ES_DISPLAY_REQUIRED #define WIN32_ES_DISPLAY_REQUIRED 0x00000002L +#endif +#ifndef WIN32_ES_USER_PRESENT #define WIN32_ES_USER_PRESENT 0x00000004L +#endif +#ifndef WIN32_ES_AWAYMODE_REQUIRED #define WIN32_ES_AWAYMODE_REQUIRED 0x00000040L +#endif +#ifndef WIN32_ES_CONTINUOUS #define WIN32_ES_CONTINUOUS 0x80000000L +#endif /* File Index */ +#ifndef FILE_INVALID_FILE_ID #define FILE_INVALID_FILE_ID ((ULONGLONG)-1LL) +#endif /** * Direct access to RtlGenRandom(). @@ -475,7 +487,7 @@ static void windows_attr2stat(DWORD FileAttributes, DWORD ReparseTag, struct win */ static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ATTRIBUTE_TAG_INFO* tag, struct windows_stat* st) { - uint64_t mtime; + int64_t mtime; windows_attr2stat(info->dwFileAttributes, tag->ReparseTag, st); @@ -518,7 +530,7 @@ static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ * "that includes 128-bit file identifiers. If GetFileInformationByHandle returns" * "FILE_INVALID_FILE_ID, the identifier may only be described in 128 bit form." */ - if (st->st_ino == FILE_INVALID_FILE_ID) { + if (st->st_ino == (uint64_t)FILE_INVALID_FILE_ID) { log_fatal("Invalid inode number! Is this ReFS?\n"); errno = EINVAL; return -1; @@ -532,7 +544,7 @@ static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ */ static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ID_BOTH_DIR_INFO* stream, struct windows_stat* st) { - uint64_t mtime; + int64_t mtime; /* The FILE_ID_BOTH_DIR_INFO doesn't have the ReparseTag information */ /* we could use instead FILE_ID_EXTD_DIR_INFO, but it's available only */ @@ -563,7 +575,7 @@ static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FIL st->st_sync = 0; /* in ReFS the IDs are 128 bit, and the 64 bit interface may fail */ - if (st->st_ino == FILE_INVALID_FILE_ID) { + if (st->st_ino == (uint64_t)FILE_INVALID_FILE_ID) { log_fatal("Invalid inode number! Is this ReFS?\n"); errno = EINVAL; return -1; @@ -577,7 +589,7 @@ static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FIL */ static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_stat* st) { - uint64_t mtime; + int64_t mtime; windows_attr2stat(info->dwFileAttributes, info->dwReserved0, st); @@ -789,7 +801,7 @@ static BOOL GetFilePhysicalOffset(HANDLE h, uint64_t* physical) BOOL ret; DWORD n; - /* in Wine FSCTL_GET_RETRIVIAL_POINTERS is not supported */ + /* in Wine FSCTL_GET_RETRIEVAL_POINTERS is not supported */ if (is_wine) { *physical = FILEPHY_UNREPORTED_OFFSET; return TRUE; @@ -1039,7 +1051,7 @@ int windows_futimens(int fd, struct windows_timespec tv[2]) { HANDLE h; FILETIME ft; - uint64_t mtime; + int64_t mtime; if (fd == -1) { errno = EBADF; @@ -1061,7 +1073,7 @@ int windows_futimens(int fd, struct windows_timespec tv[2]) mtime = tv[0].tv_sec; mtime *= 10000000; mtime += tv[0].tv_nsec / 100; - mtime += 116444736000000000; + mtime += 116444736000000000LL; ft.dwHighDateTime = mtime >> 32; ft.dwLowDateTime = mtime; @@ -1079,7 +1091,7 @@ int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], i wchar_t conv_buf[CONV_MAX]; HANDLE h; FILETIME ft; - uint64_t mtime; + int64_t mtime; DWORD wflags; /* @@ -1119,7 +1131,7 @@ int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], i mtime = tv[0].tv_sec; mtime *= 10000000; mtime += tv[0].tv_nsec / 100; - mtime += 116444736000000000; + mtime += 116444736000000000LL; ft.dwHighDateTime = mtime >> 32; ft.dwLowDateTime = mtime; @@ -1556,7 +1568,7 @@ int windows_link(const char* existing, const char* file) } /** - * In Windows 10 allow creation of symblink by not privileged user. + * In Windows 10 allow creation of symlink by not privileged user. * * See: Symlinks in Windows 10! * https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/#cQG7cx48oGH86lkI.97 diff --git a/cmdline/portable.h b/cmdline/portable.h index 4d5b89b..3227a7b 100644 --- a/cmdline/portable.h +++ b/cmdline/portable.h @@ -362,7 +362,7 @@ int devuuid(uint64_t device, char* uuid, size_t size); #define FILEPHY_REAL_OFFSET 3 /** - * Get the physcal address of the specified file. + * Get the physical address of the specified file. * This is expected to be just a hint and not necessarily correct or unique. * Return 0 on success. */ diff --git a/cmdline/scan.c b/cmdline/scan.c index f879cd3..70e3f16 100644 --- a/cmdline/scan.c +++ b/cmdline/scan.c @@ -25,6 +25,17 @@ struct snapraid_scan { struct snapraid_state* state; /**< State used. */ struct snapraid_disk* disk; /**< Disk used. */ + thread_id_t thread; /**< Thread used for scanning the disk */ + + int is_diff; /**< If it's a diff command or a scanning */ + int need_write; /**< If a state write is required */ + +#if HAVE_THREAD + /** + * Mutex for protecting the disk stampset table + */ + thread_mutex_t mutex; +#endif /** * Counters of changes. @@ -45,16 +56,69 @@ struct snapraid_scan { tommy_node node; }; +static struct snapraid_scan* scan_alloc(struct snapraid_state* state, struct snapraid_disk* disk, int is_diff) +{ + struct snapraid_scan* scan; + + scan = malloc_nofail(sizeof(struct snapraid_scan)); + scan->state = state; + scan->disk = disk; + scan->count_equal = 0; + scan->count_move = 0; + scan->count_copy = 0; + scan->count_restore = 0; + scan->count_change = 0; + scan->count_remove = 0; + scan->count_insert = 0; + tommy_list_init(&scan->file_insert_list); + tommy_list_init(&scan->link_insert_list); + tommy_list_init(&scan->dir_insert_list); + scan->is_diff = is_diff; + scan->need_write = 0; + +#if HAVE_THREAD + thread_mutex_init(&disk->stamp_mutex); +#endif + + return scan; +} + +static void scan_free(struct snapraid_scan* scan) +{ +#if HAVE_THREAD + thread_mutex_destroy(&scan->disk->stamp_mutex); +#endif + + free(scan); +} + +static void stamp_lock(struct snapraid_disk* disk) +{ +#if HAVE_THREAD + thread_mutex_lock(&disk->stamp_mutex); +#else + (void)disk; +#endif +} + +static void stamp_unlock(struct snapraid_disk* disk) +{ +#if HAVE_THREAD + thread_mutex_unlock(&disk->stamp_mutex); +#else + (void)disk; +#endif +} + /** * Remove the specified link from the data set. */ static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* slink) { - struct snapraid_state* state = scan->state; struct snapraid_disk* disk = scan->disk; /* state changed */ - state->need_write = 1; + scan->need_write = 1; /* remove the file from the link containers */ tommy_hashdyn_remove_existing(&disk->linkset, &slink->nodeset); @@ -69,11 +133,10 @@ static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* s */ static void scan_link_insert(struct snapraid_scan* scan, struct snapraid_link* slink) { - struct snapraid_state* state = scan->state; struct snapraid_disk* disk = scan->disk; /* state changed */ - state->need_write = 1; + scan->need_write = 1; /* insert the link in the link containers */ tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); @@ -116,13 +179,13 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, /* it's an update */ /* we have to save the linkto/type */ - state->need_write = 1; + scan->need_write = 1; ++scan->count_change; log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); if (is_diff) { - printf("update %s\n", fmt_term(disk, slink->sub, esc_buffer)); + msg_info("update %s\n", fmt_term(disk, slink->sub, esc_buffer)); } /* update it */ @@ -139,7 +202,7 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); if (is_diff) { - printf("add %s\n", fmt_term(disk, sub, esc_buffer)); + msg_info("add %s\n", fmt_term(disk, sub, esc_buffer)); } /* and continue to insert it */ @@ -166,7 +229,7 @@ static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* block_off_t parity_pos; /* state changed */ - state->need_write = 1; + scan->need_write = 1; /* allocate the blocks of the file */ parity_pos = disk->first_free_block; @@ -267,7 +330,7 @@ static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_fil tommy_list_remove_existing(&disk->filelist, &file->nodelist); /* state changed */ - state->need_write = 1; + scan->need_write = 1; /* here we are supposed to adjust the ::first_free_block position */ /* with the parity position we are deleting */ @@ -563,8 +626,11 @@ static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* f /* insert the file in the containers */ if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + + stamp_lock(disk); tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + stamp_unlock(disk); /* delayed allocation of the parity */ scan_file_delayed_allocate(scan, file); @@ -583,7 +649,10 @@ static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* f if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); + + stamp_lock(disk); tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); + stamp_unlock(disk); /* deallocate the file from the parity */ scan_file_deallocate(scan, file); @@ -706,7 +775,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, file->mtime_nsec = STAT_NSEC(st); /* we have to save the new mtime */ - state->need_write = 1; + scan->need_write = 1; } if (strcmp(file->sub, sub) != 0) { @@ -715,7 +784,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, log_tag("scan:move:%s:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(sub, esc_buffer_alt)); if (is_diff) { - printf("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt)); + msg_info("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt)); } /* remove from the name set */ @@ -728,7 +797,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); /* we have to save the new name */ - state->need_write = 1; + scan->need_write = 1; } else { /* otherwise it's equal */ ++scan->count_equal; @@ -864,7 +933,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, file->mtime_nsec = STAT_NSEC(st); /* we have to save the new mtime */ - state->need_write = 1; + scan->need_write = 1; } /* if when processing the disk we used the past inodes values */ @@ -878,7 +947,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); if (is_diff) { - printf("restore %s\n", fmt_term(disk, sub, esc_buffer)); + msg_info("restore %s\n", fmt_term(disk, sub, esc_buffer)); } /* remove from the inode set */ @@ -891,7 +960,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); /* we have to save the new inode */ - state->need_write = 1; + scan->need_write = 1; } else { /* otherwise it's the case of not persistent inode, where doesn't */ /* matter if the inode is different or equal, because they have no */ @@ -976,12 +1045,14 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct snapraid_disk* other_disk = i->data; struct snapraid_file* other_file; + stamp_lock(other_disk); /* if the nanosecond part of the time stamp is valid, search */ /* for name and stamp, otherwise for path and stamp */ if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); else other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash); + stamp_unlock(other_disk); /* if found, and it's a fully hashed file */ if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { @@ -993,7 +1064,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc_tag(other_file->sub, esc_buffer), disk->name, esc_tag(file->sub, esc_buffer_alt)); if (is_diff) { - printf("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt)); + msg_info("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt)); } /* mark it as reported */ @@ -1017,14 +1088,14 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, ); if (is_diff) { - printf("update %s\n", fmt_term(disk, sub, esc_buffer)); + msg_info("update %s\n", fmt_term(disk, sub, esc_buffer)); } } else { ++scan->count_insert; log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); if (is_diff) { - printf("add %s\n", fmt_term(disk, sub, esc_buffer)); + msg_info("add %s\n", fmt_term(disk, sub, esc_buffer)); } } } @@ -1038,11 +1109,10 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, */ static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir* dir) { - struct snapraid_state* state = scan->state; struct snapraid_disk* disk = scan->disk; /* state changed */ - state->need_write = 1; + scan->need_write = 1; /* remove the file from the dir containers */ tommy_hashdyn_remove_existing(&disk->dirset, &dir->nodeset); @@ -1057,11 +1127,10 @@ static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir */ static void scan_emptydir_insert(struct snapraid_scan* scan, struct snapraid_dir* dir) { - struct snapraid_state* state = scan->state; struct snapraid_disk* disk = scan->disk; /* state changed */ - state->need_write = 1; + scan->need_write = 1; /* insert the dir in the dir containers */ tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); @@ -1172,7 +1241,7 @@ struct stat* dstat(const char* file, struct stat* st) * Process a directory. * Return != 0 if at least one file or link is processed. */ -static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub) +static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* path_next, char* sub_next, char* tmp) { struct snapraid_state* state = scan->state; struct snapraid_disk* disk = scan->disk; @@ -1180,25 +1249,28 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch DIR* d; tommy_list list; tommy_node* node; + size_t path_len; + size_t sub_len; + + path_len = strlen(path_next); + sub_len = strlen(sub_next); tommy_list_init(&list); - d = opendir(dir); + d = opendir(path_next); if (!d) { /* LCOV_EXCL_START */ - log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); + log_fatal("Error opening directory '%s'. %s.\n", path_next, strerror(errno)); if (level == 0) log_fatal("If this is the disk mount point, remember to create it manually\n"); else - log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub); + log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub_next); exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } /* read the full directory */ while (1) { - char path_next[PATH_MAX]; - char sub_next[PATH_MAX]; struct dirent_sorted* entry; const char* name; struct dirent* dd; @@ -1215,8 +1287,11 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch dd = readdir(d); if (dd == 0 && errno != 0) { /* LCOV_EXCL_START */ - log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); - log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub); + /* restore removing additions */ + path_next[path_len] = 0; + sub_next[sub_len] = 0; + log_fatal("Error reading directory '%s'. %s.\n", path_next, strerror(errno)); + log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub_next); exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } @@ -1229,8 +1304,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) continue; - pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + pathcatl(path_next, path_len, PATH_MAX, name); /* check for not supported file names */ if (name[0] == 0) { @@ -1276,7 +1350,9 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch if (closedir(d) != 0) { /* LCOV_EXCL_START */ - log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); + /* restore removing additions */ + path_next[path_len] = 0; + log_fatal("Error closing directory '%s'. %s.\n", path_next, strerror(errno)); exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } @@ -1299,9 +1375,6 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch /* process the sorted dir entries */ node = list; while (node != 0) { - char path_next[PATH_MAX]; - char sub_next[PATH_MAX]; - char out[PATH_MAX]; struct snapraid_filter* reason = 0; struct dirent_sorted* dd = node->data; const char* name = dd->d_name; @@ -1311,8 +1384,8 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch struct stat st_buf; #endif - pathprint(path_next, sizeof(path_next), "%s%s", dir, name); - pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + pathcatl(path_next, path_len, PATH_MAX, name); + pathcatl(sub_next, sub_len, PATH_MAX, name); /* start with an unknown type */ type = -1; @@ -1383,14 +1456,13 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET); processed = 1; } else { - msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX)); } } else if (type == 1) { /* LNK */ if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { - char subnew[PATH_MAX]; int ret; - ret = readlink(path_next, subnew, sizeof(subnew)); + ret = readlink(path_next, tmp, PATH_MAX); if (ret >= PATH_MAX) { /* LCOV_EXCL_START */ log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next); @@ -1407,13 +1479,13 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next); /* readlink doesn't put the final 0 */ - subnew[ret] = 0; + tmp[ret] = 0; /* process as a symbolic link */ - scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK); + scan_link(scan, is_diff, sub_next, tmp, FILE_IS_SYMLINK); processed = 1; } else { - msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX)); } } else if (type == 2) { /* DIR */ if (filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) { @@ -1429,13 +1501,12 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch } else #endif { - char sub_dir[PATH_MAX]; - /* recurse */ - pathslash(path_next, sizeof(path_next)); - pathcpy(sub_dir, sizeof(sub_dir), sub_next); - pathslash(sub_dir, sizeof(sub_dir)); - if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) { + pathslash(path_next, PATH_MAX); + pathslash(sub_next, PATH_MAX); + if (scan_sub(scan, level + 1, is_diff, path_next, sub_next, tmp) == 0) { + /* restore removing additions */ + pathcatl(sub_next, sub_len, PATH_MAX, name); /* scan the directory as empty dir */ scan_emptydir(scan, sub_next); } @@ -1443,7 +1514,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch processed = 1; } } else { - msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX)); } } else { if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { @@ -1453,7 +1524,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next); } else { - msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX)); } } @@ -1467,6 +1538,80 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch return processed; } +/** + * Process a directory. + * Return != 0 if at least one file or link is processed. + */ +static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub) +{ + /* working buffers used by scan_sub() */ + char path_next[PATH_MAX]; + char sub_next[PATH_MAX]; + char tmp[PATH_MAX]; + + pathcpy(path_next, sizeof(path_next), dir); + pathcpy(sub_next, sizeof(sub_next), sub); + + return scan_sub(scan, level, is_diff, path_next, sub_next, tmp); +} + +static void* scan_disk(void* arg) +{ + struct snapraid_scan* scan = arg; + struct snapraid_disk* disk = scan->disk; + int ret; + int has_persistent_inodes; + int has_syncronized_hardlinks; + uint64_t start; + + /* check if the disk supports persistent inodes */ + ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (!has_persistent_inodes) { + disk->has_volatile_inodes = 1; + } + if (!has_syncronized_hardlinks) { + disk->has_volatile_hardlinks = 1; + } + + /* if inodes or UUID are not persistent/changed/unsupported */ + if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) { + /* remove all the inodes from the inode collection */ + /* if they are not persistent, all of them could be changed now */ + /* and we don't want to find false matching ones */ + /* see scan_file() for more details */ + tommy_node* node = disk->filelist; + while (node) { + struct snapraid_file* file = node->data; + + node = node->next; + + /* remove from the inode set */ + tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + + /* clear the inode */ + file->inode = 0; + + /* mark as missing inode */ + file_flag_set(file, FILE_IS_WITHOUT_INODE); + } + } + + start = tick_ms(); + + scan_dir(scan, 0, scan->is_diff, disk->dir, ""); + + if (!scan->is_diff) + msg_progress("Scanned %s in %" PRIu64 " seconds\n", disk->name, (tick_ms() - start) / 1000); + + return 0; +} + static int state_diffscan(struct snapraid_state* state, int is_diff) { tommy_node* i; @@ -1482,76 +1627,44 @@ static int state_diffscan(struct snapraid_state* state, int is_diff) if (is_diff) msg_progress("Comparing...\n"); + else + msg_progress("Scanning...\n"); - /* first scan all the directory and find new and deleted files */ + /* allocate all the scan data */ for (i = state->disklist; i != 0; i = i->next) { struct snapraid_disk* disk = i->data; struct snapraid_scan* scan; - tommy_node* node; - int ret; - int has_persistent_inodes; - int has_syncronized_hardlinks; - scan = malloc_nofail(sizeof(struct snapraid_scan)); - scan->state = state; - scan->disk = disk; - scan->count_equal = 0; - scan->count_move = 0; - scan->count_copy = 0; - scan->count_restore = 0; - scan->count_change = 0; - scan->count_remove = 0; - scan->count_insert = 0; - tommy_list_init(&scan->file_insert_list); - tommy_list_init(&scan->link_insert_list); - tommy_list_init(&scan->dir_insert_list); + scan = scan_alloc(state, disk, is_diff); tommy_list_insert_tail(&scanlist, &scan->node, scan); - - if (!is_diff) - msg_progress("Scanning disk %s...\n", disk->name); - - /* check if the disk supports persistent inodes */ - ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - if (!has_persistent_inodes) { - disk->has_volatile_inodes = 1; - } - if (!has_syncronized_hardlinks) { - disk->has_volatile_hardlinks = 1; - } - - /* if inodes or UUID are not persistent/changed/unsupported */ - if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) { - /* remove all the inodes from the inode collection */ - /* if they are not persistent, all of them could be changed now */ - /* and we don't want to find false matching ones */ - /* see scan_file() for more details */ - node = disk->filelist; - while (node) { - struct snapraid_file* file = node->data; - - node = node->next; - - /* remove from the inode set */ - tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); - - /* clear the inode */ - file->inode = 0; - - /* mark as missing inode */ - file_flag_set(file, FILE_IS_WITHOUT_INODE); - } - } - - scan_dir(scan, 0, is_diff, disk->dir, ""); } + /* first scan all the directory and find new and deleted files */ + for (i = scanlist; i != 0; i = i->next) { + struct snapraid_scan* scan = i->data; +#if HAVE_THREAD + if (state->opt.skip_multi_scan) + scan_disk(scan); + else + thread_create(&scan->thread, scan_disk, scan); +#else + scan_disk(scan); +#endif + } + +#if HAVE_THREAD + /* wait for all threads to terminate */ + for (i = scanlist; i != 0; i = i->next) { + struct snapraid_scan* scan = i->data; + void* retval; + + /* wait for thread termination */ + if (!state->opt.skip_multi_scan) + thread_join(scan->thread, &retval); + } +#endif + /* we split the search in two phases because to detect files */ /* moved from one disk to another we have to start deletion */ /* only when all disks have all the new files found */ @@ -1580,7 +1693,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff) log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); if (is_diff) { - printf("remove %s\n", fmt_term(disk, file->sub, esc_buffer)); + msg_info("remove %s\n", fmt_term(disk, file->sub, esc_buffer)); } scan_file_remove(scan, file); @@ -1601,7 +1714,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff) log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); if (is_diff) { - printf("remove %s\n", fmt_term(disk, slink->sub, esc_buffer)); + msg_info("remove %s\n", fmt_term(disk, slink->sub, esc_buffer)); } scan_link_remove(scan, slink); @@ -1707,6 +1820,14 @@ static int state_diffscan(struct snapraid_state* state, int is_diff) } } + /* propagate the state change (after all the scan operations are called) */ + for (i = scanlist; i != 0; i = i->next) { + struct snapraid_scan* scan = i->data; + if (scan->need_write) { + state->need_write = 1; + } + } + /* check for disks where all the previously existing files where removed */ if (!state->opt.force_empty) { int all_missing = 0; @@ -1896,7 +2017,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff) } log_flush(); - tommy_list_foreach(&scanlist, (tommy_foreach_func*)free); + tommy_list_foreach(&scanlist, (tommy_foreach_func*)scan_free); /* check the file-system on all disks */ state_fscheck(state, "after scan"); diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index 3665666..55a943e 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -307,6 +307,7 @@ void config(char* conf, size_t conf_size, const char* argv0) #define OPT_TEST_SKIP_CONTENT_WRITE 302 #define OPT_TEST_SKIP_SPACE_HOLDER 303 #define OPT_TEST_FORMAT 304 +#define OPT_TEST_SKIP_MULTI_SCAN 305 #if HAVE_GETOPT_LONG struct option long_options[] = { @@ -475,6 +476,9 @@ struct option long_options[] = { /* Set the output format */ { "test-fmt", 1, 0, OPT_TEST_FORMAT }, + /* Skip thread in disk scan */ + { "test-skip-multi-scan", 0, 0, OPT_TEST_SKIP_MULTI_SCAN }, + { 0, 0, 0, 0 } }; #endif @@ -929,6 +933,9 @@ int main(int argc, char* argv[]) /* LCOV_EXCL_STOP */ } break; + case OPT_TEST_SKIP_MULTI_SCAN : + opt.skip_multi_scan = 1; + break; default : /* LCOV_EXCL_START */ log_fatal("Unknown option '%c'\n", (char)c); diff --git a/cmdline/state.c b/cmdline/state.c index 336a70c..e8333a0 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -37,10 +37,6 @@ * writing to disk, but you'll need to access multiple times the same data, * being potentially slower. * - * For upcoming SnapRAID version it's planned to add a mutex protection - * at the file-system structure, slowing down multiple data access, - * so we disable it. - * * Multi thread for verify is instead always generally faster, * so we enable it if possible. */ @@ -3904,6 +3900,8 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc) tommy_node* i; int fail; + msg_progress("Verifying...\n"); + /* start all reading threads */ i = tommy_list_head(&state->contentlist); while (i) { @@ -3912,8 +3910,6 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc) char tmp[PATH_MAX]; STREAM* f; - msg_progress("Verifying %s...\n", content->content); - pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); f = sopen_read(tmp); if (f == 0) { diff --git a/cmdline/state.h b/cmdline/state.h index e91e0cf..d9e30bd 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -119,6 +119,7 @@ struct snapraid_option { int auto_conf; /**< Allow to run without configuration file. */ int force_stats; /**< Force stats print during process. */ uint64_t parity_limit_size; /**< Test limit for parity files. */ + int skip_multi_scan; /**< Don't use threads in scan. */ }; struct snapraid_state { diff --git a/cmdline/support.c b/cmdline/support.c index 5343df2..0ac4260 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -663,6 +663,20 @@ void pathcat(char* dst, size_t size, const char* src) memcpy(dst + dst_len, src, src_len + 1); } +void pathcatl(char* dst, size_t dst_len, size_t size, const char* src) +{ + size_t src_len = strlen(src); + + if (dst_len + src_len + 1 > size) { + /* LCOV_EXCL_START */ + log_fatal("Path too long '%s%s'\n", dst, src); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + memcpy(dst + dst_len, src, src_len + 1); +} + void pathcatc(char* dst, size_t size, char c) { size_t dst_len = strlen(dst); diff --git a/cmdline/support.h b/cmdline/support.h index 090f45d..0a2ec4e 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -265,6 +265,12 @@ void pathcpy(char* dst, size_t size, const char* src); */ void pathcat(char* dst, size_t size, const char* src); +/** + * Concatenate a path limiting the size knowing the length. + * Abort if too long. + */ +void pathcatl(char* dst, size_t dst_len, size_t size, const char* src); + /** * Concatenate a path limiting the size. * Abort if too long. diff --git a/cmdline/unix.c b/cmdline/unix.c index 1594898..ce17cf2 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -474,7 +474,7 @@ static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) #endif /** - * Get the UUID using liblkid. + * Get the UUID using libblkid. * It uses a cache to work without root permission, resulting in UUID * not necessarily recent. * We could call blkid_probe_all() to refresh the UUID, but it would diff --git a/config.h.in b/config.h.in index de1555e..2d2d65b 100644 --- a/config.h.in +++ b/config.h.in @@ -33,6 +33,10 @@ /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME +/* Define to 1 if you have the declaration of `statfs', and to 0 if you don't. + */ +#undef HAVE_DECL_STATFS + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H diff --git a/configure b/configure index db599aa..12baf82 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for snapraid 11.6. +# Generated by GNU Autoconf 2.69 for snapraid 12.2. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='snapraid' PACKAGE_TARNAME='snapraid' -PACKAGE_VERSION='11.6' -PACKAGE_STRING='snapraid 11.6' +PACKAGE_VERSION='12.2' +PACKAGE_STRING='snapraid 12.2' PACKAGE_BUGREPORT='' PACKAGE_URL='http://www.snapraid.it' @@ -1304,7 +1304,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures snapraid 11.6 to adapt to many kinds of systems. +\`configure' configures snapraid 12.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1374,7 +1374,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of snapraid 11.6:";; + short | recursive ) echo "Configuration of snapraid 12.2:";; esac cat <<\_ACEOF @@ -1496,7 +1496,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -snapraid configure 11.6 +snapraid configure 12.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2098,11 +2098,57 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by snapraid $as_me 11.6, which was +It was created by snapraid $as_me 12.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2450,7 +2496,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -am__api_version='1.15' +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2965,7 +3011,7 @@ fi # Define the identity of the package. PACKAGE='snapraid' - VERSION='11.6' + VERSION='12.2' cat >>confdefs.h <<_ACEOF @@ -2995,8 +3041,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The @@ -3047,7 +3093,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -5170,7 +5216,7 @@ fi done -for ac_header in sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h sys/sysmacros.h sys/mkdev.h +for ac_header in sys/file.h sys/ioctl.h sys/sysmacros.h sys/mkdev.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -5636,54 +5682,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -fi - -ac_fn_c_check_member "$LINENO" "struct statfs" "f_type" "ac_cv_member_struct_statfs_f_type" " -#if HAVE_SYS_PARAM_H -#include -#endif -#if HAVE_SYS_MOUNT_H -#include -#endif -#if HAVE_SYS_VFS_H -#include -#endif -#if HAVE_SYS_STATFS_H -#include -#endif - -" -if test "x$ac_cv_member_struct_statfs_f_type" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_STRUCT_STATFS_F_TYPE 1 -_ACEOF - - -fi - -ac_fn_c_check_member "$LINENO" "struct statfs" "f_fstypename" "ac_cv_member_struct_statfs_f_fstypename" " -#if HAVE_SYS_PARAM_H -#include -#endif -#if HAVE_SYS_MOUNT_H -#include -#endif -#if HAVE_SYS_VFS_H -#include -#endif -#if HAVE_SYS_STATFS_H -#include -#endif - -" -if test "x$ac_cv_member_struct_statfs_f_fstypename" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1 -_ACEOF - - fi @@ -5759,7 +5757,7 @@ _ACEOF fi done -for ac_func in fstatat flock statfs +for ac_func in fstatat flock do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -5944,6 +5942,119 @@ if test "$ac_res" != no; then : fi +for ac_header in sys/vfs.h sys/statfs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_decl "$LINENO" "statfs" "ac_cv_have_decl_statfs" " +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif + +" +if test "x$ac_cv_have_decl_statfs" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STATFS $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + + for ac_header in sys/param.h sys/mount.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +fi + +for ac_func in statfs +do : + ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs" +if test "x$ac_cv_func_statfs" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STATFS 1 +_ACEOF + +fi +done + + +ac_fn_c_check_member "$LINENO" "struct statfs" "f_type" "ac_cv_member_struct_statfs_f_type" " +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif + +" +if test "x$ac_cv_member_struct_statfs_f_type" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_TYPE 1 +_ACEOF + + +fi + + +ac_fn_c_check_member "$LINENO" "struct statfs" "f_fstypename" "ac_cv_member_struct_statfs_f_fstypename" " +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif + +" +if test "x$ac_cv_member_struct_statfs_f_fstypename" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1 +_ACEOF + + +fi + + # Check whether --with-blkid was given. if test "${with_blkid+set}" = set; then : @@ -6333,6 +6444,22 @@ fi rm -f conftest* + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wno-zero-length-bounds" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wno-zero-length-bounds... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wno-zero-length-bounds conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wno-zero-length-bounds" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + # Check whether --enable-asm was given. if test "${enable_asm+set}" = set; then : enableval=$enable_asm; @@ -7339,7 +7466,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by snapraid $as_me 11.6, which was +This file was extended by snapraid $as_me 12.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7402,7 +7529,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -snapraid config.status 11.6 +snapraid config.status 12.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 713a4cd..f32e842 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h]) AC_CHECK_HEADERS([unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h]) AC_CHECK_HEADERS([pthread.h math.h]) -AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h sys/sysmacros.h sys/mkdev.h]) +AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/sysmacros.h sys/mkdev.h]) AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h mach/mach_time.h execinfo.h]) dnl Checks for typedefs, structures, and compiler characteristics. @@ -65,6 +65,38 @@ AC_CHECK_MEMBERS([struct stat.st_nlink, struct stat.st_mtim.tv_nsec, struct stat #include #endif ]]) + +dnl Checks for library functions. +AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul]) +AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction]) +AC_CHECK_FUNCS([ftruncate fallocate access]) +AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range]) +AC_CHECK_FUNCS([getc_unlocked ferror_unlocked fnmatch]) +AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat]) +AC_CHECK_FUNCS([fstatat flock]) +AC_CHECK_FUNCS([mach_absolute_time]) +AC_CHECK_FUNCS([backtrace backtrace_symbols]) +AC_SEARCH_LIBS([clock_gettime], [rt]) +AC_CHECK_FUNCS([clock_gettime]) +AC_CHECK_CC_OPT([-pthread], CFLAGS="$CFLAGS -pthread", CFLAGS="$CFLAGS -D_REENTRANT") +AC_CHECK_FUNCS([pthread_create]) +AC_SEARCH_LIBS([exp], [m]) + +dnl Checks for statfs for linux avoiding to include sys/mount.h that is required only in darwin +dnl In glibc since 7eae6a91e9b1670330c9f15730082c91c0b1d570, milestone 2.36, sys/mount.h defines fsconfig_command which conflicts with linux/mount.h +AC_CHECK_HEADERS([sys/vfs.h sys/statfs.h]) +AC_CHECK_DECLS([statfs], [], [ + AC_CHECK_HEADERS([sys/param.h sys/mount.h]) + ], [[ +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif +]]) +AC_CHECK_FUNCS([statfs]) + AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[ #if HAVE_SYS_PARAM_H #include @@ -79,6 +111,7 @@ AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[ #include #endif ]]) + AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[ #if HAVE_SYS_PARAM_H #include @@ -94,22 +127,6 @@ AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[ #endif ]]) -dnl Checks for library functions. -AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul]) -AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction]) -AC_CHECK_FUNCS([ftruncate fallocate access]) -AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range]) -AC_CHECK_FUNCS([getc_unlocked ferror_unlocked fnmatch]) -AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat]) -AC_CHECK_FUNCS([fstatat flock statfs]) -AC_CHECK_FUNCS([mach_absolute_time]) -AC_CHECK_FUNCS([backtrace backtrace_symbols]) -AC_SEARCH_LIBS([clock_gettime], [rt]) -AC_CHECK_FUNCS([clock_gettime]) -AC_CHECK_CC_OPT([-pthread], CFLAGS="$CFLAGS -pthread", CFLAGS="$CFLAGS -D_REENTRANT") -AC_CHECK_FUNCS([pthread_create]) -AC_SEARCH_LIBS([exp], [m]) - dnl Checks for libblkid AC_ARG_WITH([blkid], AS_HELP_STRING([--without-blkid], [Ignore presence of blkid and disable it])) @@ -135,6 +152,9 @@ AC_CHECK_CC_OPT([-Wextra], CFLAGS="$CFLAGS -Wextra", []) AC_CHECK_CC_OPT([-Wuninitialized], CFLAGS="$CFLAGS -Wuninitialized", []) AC_CHECK_CC_OPT([-Wshadow], CFLAGS="$CFLAGS -Wshadow", []) +dnl Disable warning about zero-length-bounds raised by gcc 10 on linux kernel header on the fm_extents field +AC_CHECK_CC_OPT([-Wno-zero-length-bounds], CFLAGS="$CFLAGS -Wno-zero-length-bounds", []) + dnl Checks for asm AC_ARG_ENABLE([asm], AS_HELP_STRING([--disable-asm], [Disable inline assembly])) @@ -179,7 +199,7 @@ dnl Checks for AS supporting the SSE4.2 instructions. AC_MSG_CHECKING([for sse42]) asmsse42=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) unsigned f(unsigned crc, unsigned char b) { asm volatile("crc32b %1, %0" : "+r" (crc) : "rm" (b)); diff --git a/raid/raid.h b/raid/raid.h index aeeb39f..352643b 100644 --- a/raid/raid.h +++ b/raid/raid.h @@ -192,7 +192,7 @@ int raid_check(int nr, int *ir, int nd, int np, size_t size, void **v); * This function identifies the failed data and parity blocks using the * available redundancy. * - * It uses a brute force method, and then the call can be expansive. + * It uses a brute force method, and then the call can be expensive. * The expected execution time is proportional at the binomial coefficient * @np + @nd choose @np - 1, usually written as: * diff --git a/tommyds/tommyhashdyn.h b/tommyds/tommyhashdyn.h index 0ea042f..5a8c125 100644 --- a/tommyds/tommyhashdyn.h +++ b/tommyds/tommyhashdyn.h @@ -35,7 +35,7 @@ * All the elements are reallocated in a single resize operation done inside * tommy_hashdyn_insert() or tommy_hashdyn_remove(). * - * Note that the resize operation takes approximatively 100 [ms] with 1 million of elements, + * Note that the resize operation takes approximately 100 [ms] with 1 million of elements, * and 1 [second] with 10 millions. This could be a problem in real-time applications. * * The resize also fragment the heap, as it involves allocating a double-sized table, copy elements,