Merge tag 'upstream/12.2'

Upstream version 12.2
This commit is contained in:
Mario Fetka 2023-07-01 12:07:26 +02:00
commit 73b05cde71
21 changed files with 611 additions and 273 deletions

View File

@ -1 +1 @@
11.6 12.2

14
HISTORY
View File

@ -1,6 +1,20 @@
SnapRAID HISTORY 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 11.6 2021/10
============ ============
* The 'fix' and 'check' command with the -e option now process the whole * The 'fix' and 'check' command with the -e option now process the whole

View File

@ -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@ # @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 # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -153,7 +153,7 @@ am__v_at_0 = @
am__v_at_1 = am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = depcomp =
am__depfiles_maybe = am__maybe_remake_depfiles =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@) AM_V_CC = $(am__v_CC_@AM_V@)
@ -205,8 +205,8 @@ man1dir = $(mandir)/man1
NROFF = nroff NROFF = nroff
MANS = $(man_MANS) MANS = $(man_MANS)
HEADERS = $(noinst_HEADERS) HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
$(LISP)config.h.in config.h.in
# Read a list of newline-separated strings from the standard input, # Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is # and print each of them once, without duplicates. Input order is
# *not* preserved. # *not* preserved.
@ -555,8 +555,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' $(SHELL) ./config.status'; \ echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \ $(SHELL) ./config.status;; \
*) \ *) \
echo ' 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__depfiles_maybe);; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
esac; esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(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 TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files -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) $(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)" test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@ -852,7 +855,7 @@ distdir: $(DISTFILES)
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)" || chmod -R a+r "$(distdir)"
dist-gzip: 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) $(am__post_remove_distdir)
dist-bzip2: 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 tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir) $(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 dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \ @echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2 "legacy program 'compress' is deprecated." >&2
@ -878,7 +885,7 @@ dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \ @echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2 "deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&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) $(am__post_remove_distdir)
dist-zip: distdir dist-zip: distdir
@ -896,7 +903,7 @@ dist dist-all:
distcheck: dist distcheck: dist
case '$(DIST_ARCHIVES)' in \ case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \ *.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*) \ *.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \ *.tar.lz*) \
@ -906,9 +913,11 @@ distcheck: dist
*.tar.Z*) \ *.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \ *.shar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \ *.zip*) \
unzip $(distdir).zip ;;\ unzip $(distdir).zip ;;\
*.tar.zst*) \
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac esac
chmod -R a-w $(distdir) chmod -R a-w $(distdir)
chmod u+w $(distdir) chmod u+w $(distdir)
@ -1097,20 +1106,20 @@ uninstall-man: uninstall-man1
check-local clean clean-binPROGRAMS clean-checkPROGRAMS \ check-local clean clean-binPROGRAMS clean-checkPROGRAMS \
clean-cscope clean-generic clean-local cscope cscopelist-am \ clean-cscope clean-generic clean-local cscope cscopelist-am \
ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \ ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \
dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \ dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \
distclean distclean-compile distclean-generic distclean-hdr \ distcheck distclean distclean-compile distclean-generic \
distclean-tags distcleancheck distdir distuninstallcheck dvi \ distclean-hdr distclean-tags distcleancheck distdir \
dvi-am html html-am info info-am install install-am \ distuninstallcheck dvi dvi-am html html-am info info-am \
install-binPROGRAMS install-data install-data-am install-dvi \ install install-am install-binPROGRAMS install-data \
install-dvi-am install-exec install-exec-am install-html \ install-data-am install-dvi install-dvi-am install-exec \
install-html-am install-info install-info-am install-man \ install-exec-am install-html install-html-am install-info \
install-man1 install-pdf install-pdf-am install-ps \ install-info-am install-man install-man1 install-pdf \
install-ps-am install-strip installcheck installcheck-am \ install-pdf-am install-ps install-ps-am install-strip \
installdirs maintainer-clean maintainer-clean-generic \ installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-local mostlyclean mostlyclean-compile \ maintainer-clean-generic maintainer-clean-local mostlyclean \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
uninstall-am uninstall-binPROGRAMS uninstall-man \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-man1 uninstall-man uninstall-man1
.PRECIOUS: Makefile .PRECIOUS: Makefile

46
aclocal.m4 vendored
View File

@ -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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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. 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'.])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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. # generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.) # (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION], 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 Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. 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 [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. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], 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_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -143,7 +143,7 @@ fi])])
# Do all the work for Automake. -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x # For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see: # dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
AC_SUBST([mkdir_p], ['$(MKDIR_P)']) AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target (and possibly the TAP driver). The # We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms. # system "awk" is bad on some platforms.
@ -298,7 +298,7 @@ END
Aborting the configuration process, to ensure you take notice of the issue. Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>. that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@ -340,7 +340,7 @@ for _am_header in $config_headers :; do
done done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -361,7 +361,7 @@ if test x"${install_sh+set}" != xset; then
fi fi
AC_SUBST([install_sh])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -421,7 +421,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -450,7 +450,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION], AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) [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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -497,7 +497,7 @@ AC_LANG_POP([C])])
# For backward compatibility. # For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -597,7 +597,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -657,7 +657,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -685,7 +685,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,

View File

@ -369,6 +369,13 @@ struct snapraid_disk {
*/ */
thread_mutex_t fs_mutex; thread_mutex_t fs_mutex;
int fs_mutex_enabled; /*< If the lock has to be used. */ 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 #endif
/** /**

View File

@ -879,9 +879,9 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state,
#if HAVE_THREAD #if HAVE_THREAD
if (io_cache == 0) { 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 */ /* 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) if (io->io_max < IO_MIN)
io->io_max = IO_MIN; io->io_max = IO_MIN;
if (io->io_max > IO_MAX) if (io->io_max > IO_MAX)

View File

@ -35,8 +35,8 @@
* 4 - 452 MB/s, CPU 54%, speed 118% * 4 - 452 MB/s, CPU 54%, speed 118%
* 8 - 487 MB/s, CPU 60%, speed 128% * 8 - 487 MB/s, CPU 60%, speed 128%
* 16 - 505 MB/s, CPU 63%, speed 132% * 16 - 505 MB/s, CPU 63%, speed 132%
* 32 - 520 MB/s, CPU 64%, speed 136% * 32 - 520 MB/s, CPU 64%, speed 136% [SnapRAID <= 12.0]
* 64 - 524 MB/s, CPU 65%, speed 137% * 64 - 524 MB/s, CPU 65%, speed 137% [SnapRAID > 12.0]
* 128 - 525 MB/s, CPU 66%, speed 138% * 128 - 525 MB/s, CPU 66%, speed 138%
*/ */
#define IO_MIN 3 /* required by writers, readers can work also with 2 */ #define IO_MIN 3 /* required by writers, readers can work also with 2 */

View File

@ -31,14 +31,26 @@ int exit_sync_needed = 2;
/* Add missing Windows declaration */ /* Add missing Windows declaration */
/* For SetThreadExecutionState */ /* For SetThreadExecutionState */
#ifndef WIN32_ES_SYSTEM_REQUIRED
#define WIN32_ES_SYSTEM_REQUIRED 0x00000001L #define WIN32_ES_SYSTEM_REQUIRED 0x00000001L
#endif
#ifndef WIN32_ES_DISPLAY_REQUIRED
#define WIN32_ES_DISPLAY_REQUIRED 0x00000002L #define WIN32_ES_DISPLAY_REQUIRED 0x00000002L
#endif
#ifndef WIN32_ES_USER_PRESENT
#define WIN32_ES_USER_PRESENT 0x00000004L #define WIN32_ES_USER_PRESENT 0x00000004L
#endif
#ifndef WIN32_ES_AWAYMODE_REQUIRED
#define WIN32_ES_AWAYMODE_REQUIRED 0x00000040L #define WIN32_ES_AWAYMODE_REQUIRED 0x00000040L
#endif
#ifndef WIN32_ES_CONTINUOUS
#define WIN32_ES_CONTINUOUS 0x80000000L #define WIN32_ES_CONTINUOUS 0x80000000L
#endif
/* File Index */ /* File Index */
#ifndef FILE_INVALID_FILE_ID
#define FILE_INVALID_FILE_ID ((ULONGLONG)-1LL) #define FILE_INVALID_FILE_ID ((ULONGLONG)-1LL)
#endif
/** /**
* Direct access to RtlGenRandom(). * 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) 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); 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" * "that includes 128-bit file identifiers. If GetFileInformationByHandle returns"
* "FILE_INVALID_FILE_ID, the identifier may only be described in 128 bit form." * "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"); log_fatal("Invalid inode number! Is this ReFS?\n");
errno = EINVAL; errno = EINVAL;
return -1; 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) 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 */ /* 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 */ /* 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; st->st_sync = 0;
/* in ReFS the IDs are 128 bit, and the 64 bit interface may fail */ /* 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"); log_fatal("Invalid inode number! Is this ReFS?\n");
errno = EINVAL; errno = EINVAL;
return -1; 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) 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); windows_attr2stat(info->dwFileAttributes, info->dwReserved0, st);
@ -789,7 +801,7 @@ static BOOL GetFilePhysicalOffset(HANDLE h, uint64_t* physical)
BOOL ret; BOOL ret;
DWORD n; DWORD n;
/* in Wine FSCTL_GET_RETRIVIAL_POINTERS is not supported */ /* in Wine FSCTL_GET_RETRIEVAL_POINTERS is not supported */
if (is_wine) { if (is_wine) {
*physical = FILEPHY_UNREPORTED_OFFSET; *physical = FILEPHY_UNREPORTED_OFFSET;
return TRUE; return TRUE;
@ -1039,7 +1051,7 @@ int windows_futimens(int fd, struct windows_timespec tv[2])
{ {
HANDLE h; HANDLE h;
FILETIME ft; FILETIME ft;
uint64_t mtime; int64_t mtime;
if (fd == -1) { if (fd == -1) {
errno = EBADF; errno = EBADF;
@ -1061,7 +1073,7 @@ int windows_futimens(int fd, struct windows_timespec tv[2])
mtime = tv[0].tv_sec; mtime = tv[0].tv_sec;
mtime *= 10000000; mtime *= 10000000;
mtime += tv[0].tv_nsec / 100; mtime += tv[0].tv_nsec / 100;
mtime += 116444736000000000; mtime += 116444736000000000LL;
ft.dwHighDateTime = mtime >> 32; ft.dwHighDateTime = mtime >> 32;
ft.dwLowDateTime = mtime; 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]; wchar_t conv_buf[CONV_MAX];
HANDLE h; HANDLE h;
FILETIME ft; FILETIME ft;
uint64_t mtime; int64_t mtime;
DWORD wflags; 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 = tv[0].tv_sec;
mtime *= 10000000; mtime *= 10000000;
mtime += tv[0].tv_nsec / 100; mtime += tv[0].tv_nsec / 100;
mtime += 116444736000000000; mtime += 116444736000000000LL;
ft.dwHighDateTime = mtime >> 32; ft.dwHighDateTime = mtime >> 32;
ft.dwLowDateTime = mtime; 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! * See: Symlinks in Windows 10!
* https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/#cQG7cx48oGH86lkI.97 * https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/#cQG7cx48oGH86lkI.97

View File

@ -362,7 +362,7 @@ int devuuid(uint64_t device, char* uuid, size_t size);
#define FILEPHY_REAL_OFFSET 3 #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. * This is expected to be just a hint and not necessarily correct or unique.
* Return 0 on success. * Return 0 on success.
*/ */

View File

@ -25,6 +25,17 @@
struct snapraid_scan { struct snapraid_scan {
struct snapraid_state* state; /**< State used. */ struct snapraid_state* state; /**< State used. */
struct snapraid_disk* disk; /**< Disk 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. * Counters of changes.
@ -45,16 +56,69 @@ struct snapraid_scan {
tommy_node node; 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. * Remove the specified link from the data set.
*/ */
static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* slink) 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; struct snapraid_disk* disk = scan->disk;
/* state changed */ /* state changed */
state->need_write = 1; scan->need_write = 1;
/* remove the file from the link containers */ /* remove the file from the link containers */
tommy_hashdyn_remove_existing(&disk->linkset, &slink->nodeset); 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) 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; struct snapraid_disk* disk = scan->disk;
/* state changed */ /* state changed */
state->need_write = 1; scan->need_write = 1;
/* insert the link in the link containers */ /* insert the link in the link containers */
tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); 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 */ /* it's an update */
/* we have to save the linkto/type */ /* we have to save the linkto/type */
state->need_write = 1; scan->need_write = 1;
++scan->count_change; ++scan->count_change;
log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
if (is_diff) { 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 */ /* 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)); log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
if (is_diff) { 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 */ /* 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; block_off_t parity_pos;
/* state changed */ /* state changed */
state->need_write = 1; scan->need_write = 1;
/* allocate the blocks of the file */ /* allocate the blocks of the file */
parity_pos = disk->first_free_block; 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); tommy_list_remove_existing(&disk->filelist, &file->nodelist);
/* state changed */ /* state changed */
state->need_write = 1; scan->need_write = 1;
/* here we are supposed to adjust the ::first_free_block position */ /* here we are supposed to adjust the ::first_free_block position */
/* with the parity position we are deleting */ /* 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 */ /* insert the file in the containers */
if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->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->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)); 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 */ /* delayed allocation of the parity */
scan_file_delayed_allocate(scan, file); 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)) if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
stamp_lock(disk);
tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
stamp_unlock(disk);
/* deallocate the file from the parity */ /* deallocate the file from the parity */
scan_file_deallocate(scan, file); 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); file->mtime_nsec = STAT_NSEC(st);
/* we have to save the new mtime */ /* we have to save the new mtime */
state->need_write = 1; scan->need_write = 1;
} }
if (strcmp(file->sub, sub) != 0) { 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)); 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) { 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 */ /* 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)); tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
/* we have to save the new name */ /* we have to save the new name */
state->need_write = 1; scan->need_write = 1;
} else { } else {
/* otherwise it's equal */ /* otherwise it's equal */
++scan->count_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); file->mtime_nsec = STAT_NSEC(st);
/* we have to save the new mtime */ /* 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 */ /* 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)); log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
if (is_diff) { 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 */ /* 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)); tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
/* we have to save the new inode */ /* we have to save the new inode */
state->need_write = 1; scan->need_write = 1;
} else { } else {
/* otherwise it's the case of not persistent inode, where doesn't */ /* otherwise it's the case of not persistent inode, where doesn't */
/* matter if the inode is different or equal, because they have no */ /* 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_disk* other_disk = i->data;
struct snapraid_file* other_file; struct snapraid_file* other_file;
stamp_lock(other_disk);
/* if the nanosecond part of the time stamp is valid, search */ /* if the nanosecond part of the time stamp is valid, search */
/* for name and stamp, otherwise for path and stamp */ /* for name and stamp, otherwise for path and stamp */
if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
else else
other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash); 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 found, and it's a fully hashed file */
if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_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)); 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) { 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 */ /* 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) { 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 { } else {
++scan->count_insert; ++scan->count_insert;
log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
if (is_diff) { 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) 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; struct snapraid_disk* disk = scan->disk;
/* state changed */ /* state changed */
state->need_write = 1; scan->need_write = 1;
/* remove the file from the dir containers */ /* remove the file from the dir containers */
tommy_hashdyn_remove_existing(&disk->dirset, &dir->nodeset); 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) 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; struct snapraid_disk* disk = scan->disk;
/* state changed */ /* state changed */
state->need_write = 1; scan->need_write = 1;
/* insert the dir in the dir containers */ /* insert the dir in the dir containers */
tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); 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. * Process a directory.
* Return != 0 if at least one file or link is processed. * 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_state* state = scan->state;
struct snapraid_disk* disk = scan->disk; 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; DIR* d;
tommy_list list; tommy_list list;
tommy_node* node; 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); tommy_list_init(&list);
d = opendir(dir); d = opendir(path_next);
if (!d) { if (!d) {
/* LCOV_EXCL_START */ /* 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) if (level == 0)
log_fatal("If this is the disk mount point, remember to create it manually\n"); log_fatal("If this is the disk mount point, remember to create it manually\n");
else 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); exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
/* read the full directory */ /* read the full directory */
while (1) { while (1) {
char path_next[PATH_MAX];
char sub_next[PATH_MAX];
struct dirent_sorted* entry; struct dirent_sorted* entry;
const char* name; const char* name;
struct dirent* dd; 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); dd = readdir(d);
if (dd == 0 && errno != 0) { if (dd == 0 && errno != 0) {
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); /* restore removing additions */
log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub); 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); exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */ /* 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))) if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
continue; continue;
pathprint(path_next, sizeof(path_next), "%s%s", dir, name); pathcatl(path_next, path_len, PATH_MAX, name);
pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
/* check for not supported file names */ /* check for not supported file names */
if (name[0] == 0) { 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) { if (closedir(d) != 0) {
/* LCOV_EXCL_START */ /* 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); exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */ /* 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 */ /* process the sorted dir entries */
node = list; node = list;
while (node != 0) { while (node != 0) {
char path_next[PATH_MAX];
char sub_next[PATH_MAX];
char out[PATH_MAX];
struct snapraid_filter* reason = 0; struct snapraid_filter* reason = 0;
struct dirent_sorted* dd = node->data; struct dirent_sorted* dd = node->data;
const char* name = dd->d_name; 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; struct stat st_buf;
#endif #endif
pathprint(path_next, sizeof(path_next), "%s%s", dir, name); pathcatl(path_next, path_len, PATH_MAX, name);
pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); pathcatl(sub_next, sub_len, PATH_MAX, name);
/* start with an unknown type */ /* start with an unknown type */
type = -1; 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); scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET);
processed = 1; processed = 1;
} else { } 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 */ } else if (type == 1) { /* LNK */
if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
char subnew[PATH_MAX];
int ret; int ret;
ret = readlink(path_next, subnew, sizeof(subnew)); ret = readlink(path_next, tmp, PATH_MAX);
if (ret >= PATH_MAX) { if (ret >= PATH_MAX) {
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next); 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); log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next);
/* readlink doesn't put the final 0 */ /* readlink doesn't put the final 0 */
subnew[ret] = 0; tmp[ret] = 0;
/* process as a symbolic link */ /* 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; processed = 1;
} else { } 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 */ } else if (type == 2) { /* DIR */
if (filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) { 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 } else
#endif #endif
{ {
char sub_dir[PATH_MAX];
/* recurse */ /* recurse */
pathslash(path_next, sizeof(path_next)); pathslash(path_next, PATH_MAX);
pathcpy(sub_dir, sizeof(sub_dir), sub_next); pathslash(sub_next, PATH_MAX);
pathslash(sub_dir, sizeof(sub_dir)); if (scan_sub(scan, level + 1, is_diff, path_next, sub_next, tmp) == 0) {
if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) { /* restore removing additions */
pathcatl(sub_next, sub_len, PATH_MAX, name);
/* scan the directory as empty dir */ /* scan the directory as empty dir */
scan_emptydir(scan, sub_next); 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; processed = 1;
} }
} else { } 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 { } else {
if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { 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); log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
} else { } 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; 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) static int state_diffscan(struct snapraid_state* state, int is_diff)
{ {
tommy_node* i; tommy_node* i;
@ -1482,76 +1627,44 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
if (is_diff) if (is_diff)
msg_progress("Comparing...\n"); 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) { for (i = state->disklist; i != 0; i = i->next) {
struct snapraid_disk* disk = i->data; struct snapraid_disk* disk = i->data;
struct snapraid_scan* scan; 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 = scan_alloc(state, disk, is_diff);
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);
tommy_list_insert_tail(&scanlist, &scan->node, scan); 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 */ /* we split the search in two phases because to detect files */
/* moved from one disk to another we have to start deletion */ /* moved from one disk to another we have to start deletion */
/* only when all disks have all the new files found */ /* 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)); log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
if (is_diff) { 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); 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)); log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
if (is_diff) { 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); 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 */ /* check for disks where all the previously existing files where removed */
if (!state->opt.force_empty) { if (!state->opt.force_empty) {
int all_missing = 0; int all_missing = 0;
@ -1896,7 +2017,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
} }
log_flush(); 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 */ /* check the file-system on all disks */
state_fscheck(state, "after scan"); state_fscheck(state, "after scan");

View File

@ -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_CONTENT_WRITE 302
#define OPT_TEST_SKIP_SPACE_HOLDER 303 #define OPT_TEST_SKIP_SPACE_HOLDER 303
#define OPT_TEST_FORMAT 304 #define OPT_TEST_FORMAT 304
#define OPT_TEST_SKIP_MULTI_SCAN 305
#if HAVE_GETOPT_LONG #if HAVE_GETOPT_LONG
struct option long_options[] = { struct option long_options[] = {
@ -475,6 +476,9 @@ struct option long_options[] = {
/* Set the output format */ /* Set the output format */
{ "test-fmt", 1, 0, OPT_TEST_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 } { 0, 0, 0, 0 }
}; };
#endif #endif
@ -929,6 +933,9 @@ int main(int argc, char* argv[])
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
break; break;
case OPT_TEST_SKIP_MULTI_SCAN :
opt.skip_multi_scan = 1;
break;
default : default :
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
log_fatal("Unknown option '%c'\n", (char)c); log_fatal("Unknown option '%c'\n", (char)c);

View File

@ -37,10 +37,6 @@
* writing to disk, but you'll need to access multiple times the same data, * writing to disk, but you'll need to access multiple times the same data,
* being potentially slower. * 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, * Multi thread for verify is instead always generally faster,
* so we enable it if possible. * 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; tommy_node* i;
int fail; int fail;
msg_progress("Verifying...\n");
/* start all reading threads */ /* start all reading threads */
i = tommy_list_head(&state->contentlist); i = tommy_list_head(&state->contentlist);
while (i) { while (i) {
@ -3912,8 +3910,6 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc)
char tmp[PATH_MAX]; char tmp[PATH_MAX];
STREAM* f; STREAM* f;
msg_progress("Verifying %s...\n", content->content);
pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
f = sopen_read(tmp); f = sopen_read(tmp);
if (f == 0) { if (f == 0) {

View File

@ -119,6 +119,7 @@ struct snapraid_option {
int auto_conf; /**< Allow to run without configuration file. */ int auto_conf; /**< Allow to run without configuration file. */
int force_stats; /**< Force stats print during process. */ int force_stats; /**< Force stats print during process. */
uint64_t parity_limit_size; /**< Test limit for parity files. */ uint64_t parity_limit_size; /**< Test limit for parity files. */
int skip_multi_scan; /**< Don't use threads in scan. */
}; };
struct snapraid_state { struct snapraid_state {

View File

@ -663,6 +663,20 @@ void pathcat(char* dst, size_t size, const char* src)
memcpy(dst + dst_len, src, src_len + 1); 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) void pathcatc(char* dst, size_t size, char c)
{ {
size_t dst_len = strlen(dst); size_t dst_len = strlen(dst);

View File

@ -265,6 +265,12 @@ void pathcpy(char* dst, size_t size, const char* src);
*/ */
void pathcat(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. * Concatenate a path limiting the size.
* Abort if too long. * Abort if too long.

View File

@ -474,7 +474,7 @@ static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size)
#endif #endif
/** /**
* Get the UUID using liblkid. * Get the UUID using libblkid.
* It uses a cache to work without root permission, resulting in UUID * It uses a cache to work without root permission, resulting in UUID
* not necessarily recent. * not necessarily recent.
* We could call blkid_probe_all() to refresh the UUID, but it would * We could call blkid_probe_all() to refresh the UUID, but it would

View File

@ -33,6 +33,10 @@
/* Define to 1 if you have the `clock_gettime' function. */ /* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME #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 <dirent.h> header file, and it defines `DIR'. /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/ */
#undef HAVE_DIRENT_H #undef HAVE_DIRENT_H

255
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # 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. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='snapraid' PACKAGE_NAME='snapraid'
PACKAGE_TARNAME='snapraid' PACKAGE_TARNAME='snapraid'
PACKAGE_VERSION='11.6' PACKAGE_VERSION='12.2'
PACKAGE_STRING='snapraid 11.6' PACKAGE_STRING='snapraid 12.2'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='http://www.snapraid.it' 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. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF 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]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1374,7 +1374,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of snapraid 11.6:";; short | recursive ) echo "Configuration of snapraid 12.2:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1496,7 +1496,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
snapraid configure 11.6 snapraid configure 12.2
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. 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 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func } # 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 cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. 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 generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $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 ac_compiler_gnu=$ac_cv_c_compiler_gnu
am__api_version='1.15' am__api_version='1.16'
ac_aux_dir= ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@ -2965,7 +3011,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='snapraid' PACKAGE='snapraid'
VERSION='11.6' VERSION='12.2'
cat >>confdefs.h <<_ACEOF 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 # For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see: # dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> # <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
mkdir_p='$(MKDIR_P)' mkdir_p='$(MKDIR_P)'
# We need awk for the "check" target (and possibly the TAP driver). The # 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. Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>. that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@ -5170,7 +5216,7 @@ fi
done 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 : do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` 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" ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@ -5636,54 +5682,6 @@ cat >>confdefs.h <<_ACEOF
_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 <sys/param.h>
#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#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 <sys/param.h>
#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#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 fi
@ -5759,7 +5757,7 @@ _ACEOF
fi fi
done done
for ac_func in fstatat flock statfs for ac_func in fstatat flock
do : do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -5944,6 +5942,119 @@ if test "$ac_res" != no; then :
fi 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 <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#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 <sys/param.h>
#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#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 <sys/param.h>
#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#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. # Check whether --with-blkid was given.
if test "${with_blkid+set}" = set; then : if test "${with_blkid+set}" = set; then :
@ -6333,6 +6444,22 @@ fi
rm -f conftest* 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. # Check whether --enable-asm was given.
if test "${enable_asm+set}" = set; then : if test "${enable_asm+set}" = set; then :
enableval=$enable_asm; 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 # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" 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 generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -7402,7 +7529,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
snapraid config.status 11.6 snapraid config.status 12.2
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -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([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([unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h])
AC_CHECK_HEADERS([pthread.h math.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]) AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h mach/mach_time.h execinfo.h])
dnl Checks for typedefs, structures, and compiler characteristics. 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 <unistd.h> #include <unistd.h>
#endif #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 <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
]])
AC_CHECK_FUNCS([statfs])
AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[ AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[
#if HAVE_SYS_PARAM_H #if HAVE_SYS_PARAM_H
#include <sys/param.h> #include <sys/param.h>
@ -79,6 +111,7 @@ AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[
#include <sys/statfs.h> #include <sys/statfs.h>
#endif #endif
]]) ]])
AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[ AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[
#if HAVE_SYS_PARAM_H #if HAVE_SYS_PARAM_H
#include <sys/param.h> #include <sys/param.h>
@ -94,22 +127,6 @@ AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[
#endif #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 dnl Checks for libblkid
AC_ARG_WITH([blkid], AC_ARG_WITH([blkid],
AS_HELP_STRING([--without-blkid], [Ignore presence of blkid and disable it])) 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([-Wuninitialized], CFLAGS="$CFLAGS -Wuninitialized", [])
AC_CHECK_CC_OPT([-Wshadow], CFLAGS="$CFLAGS -Wshadow", []) 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 dnl Checks for asm
AC_ARG_ENABLE([asm], AC_ARG_ENABLE([asm],
AS_HELP_STRING([--disable-asm], [Disable inline assembly])) 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]) AC_MSG_CHECKING([for sse42])
asmsse42=no asmsse42=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 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) unsigned f(unsigned crc, unsigned char b)
{ {
asm volatile("crc32b %1, %0" : "+r" (crc) : "rm" (b)); asm volatile("crc32b %1, %0" : "+r" (crc) : "rm" (b));

View File

@ -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 * This function identifies the failed data and parity blocks using the
* available redundancy. * 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 * The expected execution time is proportional at the binomial coefficient
* @np + @nd choose @np - 1, usually written as: * @np + @nd choose @np - 1, usually written as:
* *

View File

@ -35,7 +35,7 @@
* All the elements are reallocated in a single resize operation done inside * All the elements are reallocated in a single resize operation done inside
* tommy_hashdyn_insert() or tommy_hashdyn_remove(). * 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. * 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, * The resize also fragment the heap, as it involves allocating a double-sized table, copy elements,