Imported Upstream version 12.2
This commit is contained in:
parent
1f7c89fb07
commit
1aa8d4d499
14
HISTORY
14
HISTORY
@ -1,6 +1,20 @@
|
||||
SnapRAID HISTORY
|
||||
================
|
||||
|
||||
12.2 2022/08
|
||||
============
|
||||
* Fix build issue with GLIBC 2.36
|
||||
|
||||
12.1 2022/01
|
||||
============
|
||||
* Reduce stack usage to work in environments with limited stack size, like MUSL.
|
||||
* Increase the default disk cache from 8 MiB to 16 MiB.
|
||||
|
||||
12.0 2021/12
|
||||
============
|
||||
* Parallel disk scanning. It's always enabled but it doesn't cover the -m option
|
||||
that still process disks sequentially.
|
||||
|
||||
11.6 2021/10
|
||||
============
|
||||
* The 'fix' and 'check' command with the -e option now process the whole
|
||||
|
61
Makefile.in
61
Makefile.in
@ -1,7 +1,7 @@
|
||||
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.16.2 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@ -153,7 +153,7 @@ am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp =
|
||||
am__depfiles_maybe =
|
||||
am__maybe_remake_depfiles =
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
@ -205,8 +205,8 @@ man1dir = $(mandir)/man1
|
||||
NROFF = nroff
|
||||
MANS = $(man_MANS)
|
||||
HEADERS = $(noinst_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
|
||||
$(LISP)config.h.in
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
|
||||
config.h.in
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
@ -555,8 +555,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
@ -809,7 +809,10 @@ distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
@ -852,7 +855,7 @@ distdir: $(DISTFILES)
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r "$(distdir)"
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-bzip2: distdir
|
||||
@ -867,6 +870,10 @@ dist-xz: distdir
|
||||
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-zstd: distdir
|
||||
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
@echo WARNING: "Support for distribution archives compressed with" \
|
||||
"legacy program 'compress' is deprecated." >&2
|
||||
@ -878,7 +885,7 @@ dist-shar: distdir
|
||||
@echo WARNING: "Support for shar distribution archives is" \
|
||||
"deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
@ -896,7 +903,7 @@ dist dist-all:
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lz*) \
|
||||
@ -906,9 +913,11 @@ distcheck: dist
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
||||
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
*.tar.zst*) \
|
||||
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir)
|
||||
chmod u+w $(distdir)
|
||||
@ -1097,20 +1106,20 @@ uninstall-man: uninstall-man1
|
||||
check-local clean clean-binPROGRAMS clean-checkPROGRAMS \
|
||||
clean-cscope clean-generic clean-local cscope cscopelist-am \
|
||||
ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \
|
||||
dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \
|
||||
distclean distclean-compile distclean-generic distclean-hdr \
|
||||
distclean-tags distcleancheck distdir distuninstallcheck dvi \
|
||||
dvi-am html html-am info info-am install install-am \
|
||||
install-binPROGRAMS install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-man1 install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
maintainer-clean-local mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am uninstall-binPROGRAMS uninstall-man \
|
||||
uninstall-man1
|
||||
dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \
|
||||
distcheck distclean distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-tags distcleancheck distdir \
|
||||
distuninstallcheck dvi dvi-am html html-am info info-am \
|
||||
install install-am install-binPROGRAMS install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-man1 install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic maintainer-clean-local mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
|
||||
uninstall-man uninstall-man1
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
46
aclocal.m4
vendored
46
aclocal.m4
vendored
@ -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,
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
353
cmdline/scan.c
353
cmdline/scan.c
@ -25,6 +25,17 @@
|
||||
struct snapraid_scan {
|
||||
struct snapraid_state* state; /**< State used. */
|
||||
struct snapraid_disk* disk; /**< Disk used. */
|
||||
thread_id_t thread; /**< Thread used for scanning the disk */
|
||||
|
||||
int is_diff; /**< If it's a diff command or a scanning */
|
||||
int need_write; /**< If a state write is required */
|
||||
|
||||
#if HAVE_THREAD
|
||||
/**
|
||||
* Mutex for protecting the disk stampset table
|
||||
*/
|
||||
thread_mutex_t mutex;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Counters of changes.
|
||||
@ -45,16 +56,69 @@ struct snapraid_scan {
|
||||
tommy_node node;
|
||||
};
|
||||
|
||||
static struct snapraid_scan* scan_alloc(struct snapraid_state* state, struct snapraid_disk* disk, int is_diff)
|
||||
{
|
||||
struct snapraid_scan* scan;
|
||||
|
||||
scan = malloc_nofail(sizeof(struct snapraid_scan));
|
||||
scan->state = state;
|
||||
scan->disk = disk;
|
||||
scan->count_equal = 0;
|
||||
scan->count_move = 0;
|
||||
scan->count_copy = 0;
|
||||
scan->count_restore = 0;
|
||||
scan->count_change = 0;
|
||||
scan->count_remove = 0;
|
||||
scan->count_insert = 0;
|
||||
tommy_list_init(&scan->file_insert_list);
|
||||
tommy_list_init(&scan->link_insert_list);
|
||||
tommy_list_init(&scan->dir_insert_list);
|
||||
scan->is_diff = is_diff;
|
||||
scan->need_write = 0;
|
||||
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_init(&disk->stamp_mutex);
|
||||
#endif
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
static void scan_free(struct snapraid_scan* scan)
|
||||
{
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_destroy(&scan->disk->stamp_mutex);
|
||||
#endif
|
||||
|
||||
free(scan);
|
||||
}
|
||||
|
||||
static void stamp_lock(struct snapraid_disk* disk)
|
||||
{
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_lock(&disk->stamp_mutex);
|
||||
#else
|
||||
(void)disk;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void stamp_unlock(struct snapraid_disk* disk)
|
||||
{
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_unlock(&disk->stamp_mutex);
|
||||
#else
|
||||
(void)disk;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified link from the data set.
|
||||
*/
|
||||
static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* slink)
|
||||
{
|
||||
struct snapraid_state* state = scan->state;
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
|
||||
/* state changed */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
/* remove the file from the link containers */
|
||||
tommy_hashdyn_remove_existing(&disk->linkset, &slink->nodeset);
|
||||
@ -69,11 +133,10 @@ static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* s
|
||||
*/
|
||||
static void scan_link_insert(struct snapraid_scan* scan, struct snapraid_link* slink)
|
||||
{
|
||||
struct snapraid_state* state = scan->state;
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
|
||||
/* state changed */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
/* insert the link in the link containers */
|
||||
tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
|
||||
@ -116,13 +179,13 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
/* it's an update */
|
||||
|
||||
/* we have to save the linkto/type */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
++scan->count_change;
|
||||
|
||||
log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
|
||||
if (is_diff) {
|
||||
printf("update %s\n", fmt_term(disk, slink->sub, esc_buffer));
|
||||
msg_info("update %s\n", fmt_term(disk, slink->sub, esc_buffer));
|
||||
}
|
||||
|
||||
/* update it */
|
||||
@ -139,7 +202,7 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
|
||||
log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
|
||||
if (is_diff) {
|
||||
printf("add %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
msg_info("add %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
}
|
||||
|
||||
/* and continue to insert it */
|
||||
@ -166,7 +229,7 @@ static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file*
|
||||
block_off_t parity_pos;
|
||||
|
||||
/* state changed */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
/* allocate the blocks of the file */
|
||||
parity_pos = disk->first_free_block;
|
||||
@ -267,7 +330,7 @@ static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_fil
|
||||
tommy_list_remove_existing(&disk->filelist, &file->nodelist);
|
||||
|
||||
/* state changed */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
/* here we are supposed to adjust the ::first_free_block position */
|
||||
/* with the parity position we are deleting */
|
||||
@ -563,8 +626,11 @@ static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* f
|
||||
/* insert the file in the containers */
|
||||
if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
|
||||
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
|
||||
|
||||
stamp_lock(disk);
|
||||
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
|
||||
tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
|
||||
stamp_unlock(disk);
|
||||
|
||||
/* delayed allocation of the parity */
|
||||
scan_file_delayed_allocate(scan, file);
|
||||
@ -583,7 +649,10 @@ static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* f
|
||||
if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
|
||||
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
|
||||
tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
|
||||
|
||||
stamp_lock(disk);
|
||||
tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
|
||||
stamp_unlock(disk);
|
||||
|
||||
/* deallocate the file from the parity */
|
||||
scan_file_deallocate(scan, file);
|
||||
@ -706,7 +775,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
file->mtime_nsec = STAT_NSEC(st);
|
||||
|
||||
/* we have to save the new mtime */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
}
|
||||
|
||||
if (strcmp(file->sub, sub) != 0) {
|
||||
@ -715,7 +784,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
|
||||
log_tag("scan:move:%s:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(sub, esc_buffer_alt));
|
||||
if (is_diff) {
|
||||
printf("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt));
|
||||
msg_info("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt));
|
||||
}
|
||||
|
||||
/* remove from the name set */
|
||||
@ -728,7 +797,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
|
||||
|
||||
/* we have to save the new name */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
} else {
|
||||
/* otherwise it's equal */
|
||||
++scan->count_equal;
|
||||
@ -864,7 +933,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
file->mtime_nsec = STAT_NSEC(st);
|
||||
|
||||
/* we have to save the new mtime */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
}
|
||||
|
||||
/* if when processing the disk we used the past inodes values */
|
||||
@ -878,7 +947,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
|
||||
log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
|
||||
if (is_diff) {
|
||||
printf("restore %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
msg_info("restore %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
}
|
||||
|
||||
/* remove from the inode set */
|
||||
@ -891,7 +960,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
|
||||
|
||||
/* we have to save the new inode */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
} else {
|
||||
/* otherwise it's the case of not persistent inode, where doesn't */
|
||||
/* matter if the inode is different or equal, because they have no */
|
||||
@ -976,12 +1045,14 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
struct snapraid_disk* other_disk = i->data;
|
||||
struct snapraid_file* other_file;
|
||||
|
||||
stamp_lock(other_disk);
|
||||
/* if the nanosecond part of the time stamp is valid, search */
|
||||
/* for name and stamp, otherwise for path and stamp */
|
||||
if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
|
||||
other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
|
||||
else
|
||||
other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash);
|
||||
stamp_unlock(other_disk);
|
||||
|
||||
/* if found, and it's a fully hashed file */
|
||||
if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {
|
||||
@ -993,7 +1064,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
|
||||
log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc_tag(other_file->sub, esc_buffer), disk->name, esc_tag(file->sub, esc_buffer_alt));
|
||||
if (is_diff) {
|
||||
printf("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt));
|
||||
msg_info("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt));
|
||||
}
|
||||
|
||||
/* mark it as reported */
|
||||
@ -1017,14 +1088,14 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
);
|
||||
|
||||
if (is_diff) {
|
||||
printf("update %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
msg_info("update %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
}
|
||||
} else {
|
||||
++scan->count_insert;
|
||||
|
||||
log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
|
||||
if (is_diff) {
|
||||
printf("add %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
msg_info("add %s\n", fmt_term(disk, sub, esc_buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1038,11 +1109,10 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
||||
*/
|
||||
static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir* dir)
|
||||
{
|
||||
struct snapraid_state* state = scan->state;
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
|
||||
/* state changed */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
/* remove the file from the dir containers */
|
||||
tommy_hashdyn_remove_existing(&disk->dirset, &dir->nodeset);
|
||||
@ -1057,11 +1127,10 @@ static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir
|
||||
*/
|
||||
static void scan_emptydir_insert(struct snapraid_scan* scan, struct snapraid_dir* dir)
|
||||
{
|
||||
struct snapraid_state* state = scan->state;
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
|
||||
/* state changed */
|
||||
state->need_write = 1;
|
||||
scan->need_write = 1;
|
||||
|
||||
/* insert the dir in the dir containers */
|
||||
tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));
|
||||
@ -1172,7 +1241,7 @@ struct stat* dstat(const char* file, struct stat* st)
|
||||
* Process a directory.
|
||||
* Return != 0 if at least one file or link is processed.
|
||||
*/
|
||||
static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)
|
||||
static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* path_next, char* sub_next, char* tmp)
|
||||
{
|
||||
struct snapraid_state* state = scan->state;
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
@ -1180,25 +1249,28 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
DIR* d;
|
||||
tommy_list list;
|
||||
tommy_node* node;
|
||||
size_t path_len;
|
||||
size_t sub_len;
|
||||
|
||||
path_len = strlen(path_next);
|
||||
sub_len = strlen(sub_next);
|
||||
|
||||
tommy_list_init(&list);
|
||||
|
||||
d = opendir(dir);
|
||||
d = opendir(path_next);
|
||||
if (!d) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno));
|
||||
log_fatal("Error opening directory '%s'. %s.\n", path_next, strerror(errno));
|
||||
if (level == 0)
|
||||
log_fatal("If this is the disk mount point, remember to create it manually\n");
|
||||
else
|
||||
log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub);
|
||||
log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub_next);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* read the full directory */
|
||||
while (1) {
|
||||
char path_next[PATH_MAX];
|
||||
char sub_next[PATH_MAX];
|
||||
struct dirent_sorted* entry;
|
||||
const char* name;
|
||||
struct dirent* dd;
|
||||
@ -1215,8 +1287,11 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
dd = readdir(d);
|
||||
if (dd == 0 && errno != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
|
||||
log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub);
|
||||
/* restore removing additions */
|
||||
path_next[path_len] = 0;
|
||||
sub_next[sub_len] = 0;
|
||||
log_fatal("Error reading directory '%s'. %s.\n", path_next, strerror(errno));
|
||||
log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub_next);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
@ -1229,8 +1304,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
|
||||
continue;
|
||||
|
||||
pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
|
||||
pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
|
||||
pathcatl(path_next, path_len, PATH_MAX, name);
|
||||
|
||||
/* check for not supported file names */
|
||||
if (name[0] == 0) {
|
||||
@ -1276,7 +1350,9 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
|
||||
if (closedir(d) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno));
|
||||
/* restore removing additions */
|
||||
path_next[path_len] = 0;
|
||||
log_fatal("Error closing directory '%s'. %s.\n", path_next, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
@ -1299,9 +1375,6 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
/* process the sorted dir entries */
|
||||
node = list;
|
||||
while (node != 0) {
|
||||
char path_next[PATH_MAX];
|
||||
char sub_next[PATH_MAX];
|
||||
char out[PATH_MAX];
|
||||
struct snapraid_filter* reason = 0;
|
||||
struct dirent_sorted* dd = node->data;
|
||||
const char* name = dd->d_name;
|
||||
@ -1311,8 +1384,8 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
struct stat st_buf;
|
||||
#endif
|
||||
|
||||
pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
|
||||
pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
|
||||
pathcatl(path_next, path_len, PATH_MAX, name);
|
||||
pathcatl(sub_next, sub_len, PATH_MAX, name);
|
||||
|
||||
/* start with an unknown type */
|
||||
type = -1;
|
||||
@ -1383,14 +1456,13 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET);
|
||||
processed = 1;
|
||||
} else {
|
||||
msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
|
||||
msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
|
||||
}
|
||||
} else if (type == 1) { /* LNK */
|
||||
if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
|
||||
char subnew[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
ret = readlink(path_next, subnew, sizeof(subnew));
|
||||
ret = readlink(path_next, tmp, PATH_MAX);
|
||||
if (ret >= PATH_MAX) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next);
|
||||
@ -1407,13 +1479,13 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next);
|
||||
|
||||
/* readlink doesn't put the final 0 */
|
||||
subnew[ret] = 0;
|
||||
tmp[ret] = 0;
|
||||
|
||||
/* process as a symbolic link */
|
||||
scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK);
|
||||
scan_link(scan, is_diff, sub_next, tmp, FILE_IS_SYMLINK);
|
||||
processed = 1;
|
||||
} else {
|
||||
msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
|
||||
msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
|
||||
}
|
||||
} else if (type == 2) { /* DIR */
|
||||
if (filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
|
||||
@ -1429,13 +1501,12 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
char sub_dir[PATH_MAX];
|
||||
|
||||
/* recurse */
|
||||
pathslash(path_next, sizeof(path_next));
|
||||
pathcpy(sub_dir, sizeof(sub_dir), sub_next);
|
||||
pathslash(sub_dir, sizeof(sub_dir));
|
||||
if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) {
|
||||
pathslash(path_next, PATH_MAX);
|
||||
pathslash(sub_next, PATH_MAX);
|
||||
if (scan_sub(scan, level + 1, is_diff, path_next, sub_next, tmp) == 0) {
|
||||
/* restore removing additions */
|
||||
pathcatl(sub_next, sub_len, PATH_MAX, name);
|
||||
/* scan the directory as empty dir */
|
||||
scan_emptydir(scan, sub_next);
|
||||
}
|
||||
@ -1443,7 +1514,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
processed = 1;
|
||||
}
|
||||
} else {
|
||||
msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
|
||||
msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
|
||||
}
|
||||
} else {
|
||||
if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
|
||||
@ -1453,7 +1524,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
|
||||
log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
|
||||
} else {
|
||||
msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
|
||||
msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1467,6 +1538,80 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a directory.
|
||||
* Return != 0 if at least one file or link is processed.
|
||||
*/
|
||||
static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)
|
||||
{
|
||||
/* working buffers used by scan_sub() */
|
||||
char path_next[PATH_MAX];
|
||||
char sub_next[PATH_MAX];
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
pathcpy(path_next, sizeof(path_next), dir);
|
||||
pathcpy(sub_next, sizeof(sub_next), sub);
|
||||
|
||||
return scan_sub(scan, level, is_diff, path_next, sub_next, tmp);
|
||||
}
|
||||
|
||||
static void* scan_disk(void* arg)
|
||||
{
|
||||
struct snapraid_scan* scan = arg;
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
int ret;
|
||||
int has_persistent_inodes;
|
||||
int has_syncronized_hardlinks;
|
||||
uint64_t start;
|
||||
|
||||
/* check if the disk supports persistent inodes */
|
||||
ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0);
|
||||
if (ret < 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (!has_persistent_inodes) {
|
||||
disk->has_volatile_inodes = 1;
|
||||
}
|
||||
if (!has_syncronized_hardlinks) {
|
||||
disk->has_volatile_hardlinks = 1;
|
||||
}
|
||||
|
||||
/* if inodes or UUID are not persistent/changed/unsupported */
|
||||
if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {
|
||||
/* remove all the inodes from the inode collection */
|
||||
/* if they are not persistent, all of them could be changed now */
|
||||
/* and we don't want to find false matching ones */
|
||||
/* see scan_file() for more details */
|
||||
tommy_node* node = disk->filelist;
|
||||
while (node) {
|
||||
struct snapraid_file* file = node->data;
|
||||
|
||||
node = node->next;
|
||||
|
||||
/* remove from the inode set */
|
||||
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
|
||||
|
||||
/* clear the inode */
|
||||
file->inode = 0;
|
||||
|
||||
/* mark as missing inode */
|
||||
file_flag_set(file, FILE_IS_WITHOUT_INODE);
|
||||
}
|
||||
}
|
||||
|
||||
start = tick_ms();
|
||||
|
||||
scan_dir(scan, 0, scan->is_diff, disk->dir, "");
|
||||
|
||||
if (!scan->is_diff)
|
||||
msg_progress("Scanned %s in %" PRIu64 " seconds\n", disk->name, (tick_ms() - start) / 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int state_diffscan(struct snapraid_state* state, int is_diff)
|
||||
{
|
||||
tommy_node* i;
|
||||
@ -1482,76 +1627,44 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
||||
|
||||
if (is_diff)
|
||||
msg_progress("Comparing...\n");
|
||||
else
|
||||
msg_progress("Scanning...\n");
|
||||
|
||||
/* first scan all the directory and find new and deleted files */
|
||||
/* allocate all the scan data */
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
struct snapraid_scan* scan;
|
||||
tommy_node* node;
|
||||
int ret;
|
||||
int has_persistent_inodes;
|
||||
int has_syncronized_hardlinks;
|
||||
|
||||
scan = malloc_nofail(sizeof(struct snapraid_scan));
|
||||
scan->state = state;
|
||||
scan->disk = disk;
|
||||
scan->count_equal = 0;
|
||||
scan->count_move = 0;
|
||||
scan->count_copy = 0;
|
||||
scan->count_restore = 0;
|
||||
scan->count_change = 0;
|
||||
scan->count_remove = 0;
|
||||
scan->count_insert = 0;
|
||||
tommy_list_init(&scan->file_insert_list);
|
||||
tommy_list_init(&scan->link_insert_list);
|
||||
tommy_list_init(&scan->dir_insert_list);
|
||||
scan = scan_alloc(state, disk, is_diff);
|
||||
|
||||
tommy_list_insert_tail(&scanlist, &scan->node, scan);
|
||||
|
||||
if (!is_diff)
|
||||
msg_progress("Scanning disk %s...\n", disk->name);
|
||||
|
||||
/* check if the disk supports persistent inodes */
|
||||
ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0);
|
||||
if (ret < 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (!has_persistent_inodes) {
|
||||
disk->has_volatile_inodes = 1;
|
||||
}
|
||||
if (!has_syncronized_hardlinks) {
|
||||
disk->has_volatile_hardlinks = 1;
|
||||
}
|
||||
|
||||
/* if inodes or UUID are not persistent/changed/unsupported */
|
||||
if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {
|
||||
/* remove all the inodes from the inode collection */
|
||||
/* if they are not persistent, all of them could be changed now */
|
||||
/* and we don't want to find false matching ones */
|
||||
/* see scan_file() for more details */
|
||||
node = disk->filelist;
|
||||
while (node) {
|
||||
struct snapraid_file* file = node->data;
|
||||
|
||||
node = node->next;
|
||||
|
||||
/* remove from the inode set */
|
||||
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
|
||||
|
||||
/* clear the inode */
|
||||
file->inode = 0;
|
||||
|
||||
/* mark as missing inode */
|
||||
file_flag_set(file, FILE_IS_WITHOUT_INODE);
|
||||
}
|
||||
}
|
||||
|
||||
scan_dir(scan, 0, is_diff, disk->dir, "");
|
||||
}
|
||||
|
||||
/* first scan all the directory and find new and deleted files */
|
||||
for (i = scanlist; i != 0; i = i->next) {
|
||||
struct snapraid_scan* scan = i->data;
|
||||
#if HAVE_THREAD
|
||||
if (state->opt.skip_multi_scan)
|
||||
scan_disk(scan);
|
||||
else
|
||||
thread_create(&scan->thread, scan_disk, scan);
|
||||
#else
|
||||
scan_disk(scan);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_THREAD
|
||||
/* wait for all threads to terminate */
|
||||
for (i = scanlist; i != 0; i = i->next) {
|
||||
struct snapraid_scan* scan = i->data;
|
||||
void* retval;
|
||||
|
||||
/* wait for thread termination */
|
||||
if (!state->opt.skip_multi_scan)
|
||||
thread_join(scan->thread, &retval);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* we split the search in two phases because to detect files */
|
||||
/* moved from one disk to another we have to start deletion */
|
||||
/* only when all disks have all the new files found */
|
||||
@ -1580,7 +1693,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
||||
|
||||
log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
|
||||
if (is_diff) {
|
||||
printf("remove %s\n", fmt_term(disk, file->sub, esc_buffer));
|
||||
msg_info("remove %s\n", fmt_term(disk, file->sub, esc_buffer));
|
||||
}
|
||||
|
||||
scan_file_remove(scan, file);
|
||||
@ -1601,7 +1714,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
||||
|
||||
log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
|
||||
if (is_diff) {
|
||||
printf("remove %s\n", fmt_term(disk, slink->sub, esc_buffer));
|
||||
msg_info("remove %s\n", fmt_term(disk, slink->sub, esc_buffer));
|
||||
}
|
||||
|
||||
scan_link_remove(scan, slink);
|
||||
@ -1707,6 +1820,14 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
||||
}
|
||||
}
|
||||
|
||||
/* propagate the state change (after all the scan operations are called) */
|
||||
for (i = scanlist; i != 0; i = i->next) {
|
||||
struct snapraid_scan* scan = i->data;
|
||||
if (scan->need_write) {
|
||||
state->need_write = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for disks where all the previously existing files where removed */
|
||||
if (!state->opt.force_empty) {
|
||||
int all_missing = 0;
|
||||
@ -1896,7 +2017,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
||||
}
|
||||
log_flush();
|
||||
|
||||
tommy_list_foreach(&scanlist, (tommy_foreach_func*)free);
|
||||
tommy_list_foreach(&scanlist, (tommy_foreach_func*)scan_free);
|
||||
|
||||
/* check the file-system on all disks */
|
||||
state_fscheck(state, "after scan");
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
255
configure
vendored
@ -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\\"
|
||||
|
||||
|
54
configure.ac
54
configure.ac
@ -36,7 +36,7 @@ AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h])
|
||||
AC_CHECK_HEADERS([unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h])
|
||||
AC_CHECK_HEADERS([pthread.h math.h])
|
||||
AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h sys/sysmacros.h sys/mkdev.h])
|
||||
AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/sysmacros.h sys/mkdev.h])
|
||||
AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h mach/mach_time.h execinfo.h])
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
@ -65,6 +65,38 @@ AC_CHECK_MEMBERS([struct stat.st_nlink, struct stat.st_mtim.tv_nsec, struct stat
|
||||
#include <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]))
|
||||
|
@ -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:
|
||||
*
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user