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
================
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

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@
# 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

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
# 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:
# <http://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/msg00001.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
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: <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
'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,

View File

@ -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
/**

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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.
*/

View File

@ -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");

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_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);

View File

@ -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) {

View File

@ -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 {

View File

@ -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);

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);
/**
* 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.

View File

@ -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

View File

@ -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 <dirent.h> header file, and it defines `DIR'.
*/
#undef HAVE_DIRENT_H

255
configure vendored
View File

@ -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:
# <http://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/msg00001.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
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: <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
'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 <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
@ -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 <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.
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\\"

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([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 <unistd.h>
#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], [], [], [[
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
@ -79,6 +111,7 @@ AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[
#include <sys/statfs.h>
#endif
]])
AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
@ -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));

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
* 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:
*

View File

@ -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,