Compare commits
11 Commits
upstream/1
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
73b05cde71 | ||
|
1aa8d4d499 | ||
|
2285cff2a6 | ||
|
a311749e46 | ||
|
1f7c89fb07 | ||
|
d767689d60 | ||
|
1dd99167db | ||
|
859826a091 | ||
|
36b5ac9c36 | ||
|
cfd0df25f8 | ||
|
2e8fba7836 |
2
.version
2
.version
@ -1 +1 @@
|
||||
11.5
|
||||
12.2
|
25
HISTORY
25
HISTORY
@ -1,6 +1,31 @@
|
||||
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
|
||||
files that have bad blocks, and not only the block marked bad.
|
||||
This allows to restore the timestamp and to print the paths of
|
||||
processed files and the final state of the files like 'recovered' or
|
||||
'unrecovered'. The previous behaviour is available with the -b,
|
||||
--filter-block-error option.
|
||||
* Improved the speed of the filtering in 'fix' and 'check'. This phase
|
||||
happens after the "Selecting..." message. [UhClem]
|
||||
|
||||
11.5 2020/05
|
||||
============
|
||||
* Removed the default -march=native to allow to deploy in any machine.
|
||||
|
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,
|
||||
|
@ -590,9 +590,11 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign
|
||||
* For each file, if we are at the last block, closes it,
|
||||
* adjust the timestamp, and print the result.
|
||||
*
|
||||
* This works with the assumption to always process the whole files to
|
||||
* fix. This assumption is not always correct, and in such case we have to
|
||||
* skip the whole postprocessing. And example, is when fixing only bad blocks.
|
||||
* This works only if the whole file is processed, including its last block.
|
||||
* This doesn't always happen, like with an explicit end block.
|
||||
*
|
||||
* In such case, the check/fix command won't report any information of the
|
||||
* files partially checked.
|
||||
*/
|
||||
static int file_post(struct snapraid_state* state, int fix, unsigned i, struct snapraid_handle* handle, unsigned diskmax)
|
||||
{
|
||||
@ -601,11 +603,6 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
|
||||
char esc_buffer[ESC_MAX];
|
||||
char esc_buffer_alt[ESC_MAX];
|
||||
|
||||
/* if we are processing only bad blocks, we don't have to do any post-processing */
|
||||
/* as we don't have any guarantee to process the last block of the fixed files */
|
||||
if (state->opt.badonly)
|
||||
return 0;
|
||||
|
||||
/* for all the files print the final status, and does the final time fix */
|
||||
/* we also ensure to close files after processing the last block */
|
||||
for (j = 0; j < diskmax; ++j) {
|
||||
@ -614,7 +611,6 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
|
||||
struct snapraid_file* collide_file;
|
||||
struct snapraid_file* file;
|
||||
block_off_t file_pos;
|
||||
char path[PATH_MAX];
|
||||
uint64_t inode;
|
||||
|
||||
disk = handle[j].disk;
|
||||
@ -630,7 +626,6 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
|
||||
}
|
||||
|
||||
file = fs_par2file_get(disk, i, &file_pos);
|
||||
pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
|
||||
|
||||
/* if it isn't the last block in the file */
|
||||
if (!file_block_is_last(file, file_pos)) {
|
||||
@ -654,8 +649,10 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
|
||||
/* if the file is damaged, meaning that a fix failed */
|
||||
if (file_flag_has(file, FILE_IS_DAMAGED)) {
|
||||
/* rename it to .unrecoverable */
|
||||
char path[PATH_MAX];
|
||||
char path_to[PATH_MAX];
|
||||
|
||||
pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
|
||||
pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub);
|
||||
|
||||
/* ensure to close the file before renaming */
|
||||
@ -801,30 +798,52 @@ close_and_continue:
|
||||
*/
|
||||
static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_handle* handle, unsigned diskmax)
|
||||
{
|
||||
snapraid_info info;
|
||||
unsigned j;
|
||||
unsigned l;
|
||||
|
||||
/* get block specific info */
|
||||
info = info_get(&state->infoarr, i);
|
||||
/* filter for bad blocks */
|
||||
if (state->opt.badblockonly) {
|
||||
snapraid_info info;
|
||||
|
||||
/* if we filter for only bad blocks */
|
||||
if (state->opt.badonly) {
|
||||
/* skip if this is not bad */
|
||||
if (!info_get_bad(info))
|
||||
return 0;
|
||||
/* get block specific info */
|
||||
info = info_get(&state->infoarr, i);
|
||||
|
||||
/*
|
||||
* Filter specifically only for bad blocks
|
||||
*/
|
||||
return info_get_bad(info);
|
||||
}
|
||||
|
||||
/* now apply the filters */
|
||||
/* filter for the parity */
|
||||
if (state->opt.badfileonly) {
|
||||
snapraid_info info;
|
||||
|
||||
/* if a parity is not excluded, include all blocks, even unused ones */
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
if (!state->parity[l].is_excluded_by_filter) {
|
||||
/* get block specific info */
|
||||
info = info_get(&state->infoarr, i);
|
||||
|
||||
/*
|
||||
* If the block is bad, it has to be processed
|
||||
*
|
||||
* This is not necessary in normal cases because if a block is bad,
|
||||
* it necessary needs to have a file related to it, and files with
|
||||
* bad blocks are fully included.
|
||||
*
|
||||
* But some files may be excluded by additional filter options,
|
||||
* so it's not always true, and this ensures to always check all
|
||||
* the bad blocks.
|
||||
*/
|
||||
if (info_get_bad(info))
|
||||
return 1;
|
||||
} else {
|
||||
/* if a parity is not excluded, include all blocks, even unused ones */
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
if (!state->parity[l].is_excluded_by_filter) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise include only used blocks */
|
||||
/* filter for the files */
|
||||
for (j = 0; j < diskmax; ++j) {
|
||||
struct snapraid_block* block;
|
||||
|
||||
@ -868,6 +887,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
||||
unsigned l;
|
||||
char esc_buffer[ESC_MAX];
|
||||
char esc_buffer_alt[ESC_MAX];
|
||||
bit_vect_t* block_enabled;
|
||||
|
||||
handle = handle_mapping(state, &diskmax);
|
||||
|
||||
@ -889,14 +909,25 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
||||
unrecoverable_error = 0;
|
||||
recovered_error = 0;
|
||||
|
||||
msg_progress("Selecting...\n");
|
||||
|
||||
/* first count the number of blocks to process */
|
||||
countmax = 0;
|
||||
block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */
|
||||
for (i = blockstart; i < blockmax; ++i) {
|
||||
if (!block_is_enabled(state, i, handle, diskmax))
|
||||
continue;
|
||||
bit_vect_set(block_enabled, i);
|
||||
++countmax;
|
||||
}
|
||||
|
||||
if (fix)
|
||||
msg_progress("Fixing...\n");
|
||||
else if (!state->opt.auditonly)
|
||||
msg_progress("Checking...\n");
|
||||
else
|
||||
msg_progress("Hashing...\n");
|
||||
|
||||
/* check all the blocks in files */
|
||||
countsize = 0;
|
||||
countpos = 0;
|
||||
@ -908,18 +939,8 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
||||
snapraid_info info;
|
||||
int rehash;
|
||||
|
||||
if (!block_is_enabled(state, i, handle, diskmax)) {
|
||||
/* post process the files */
|
||||
ret = file_post(state, fix, i, handle, diskmax);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Stopping at block %u\n", i);
|
||||
++unrecoverable_error;
|
||||
goto bail;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* and now continue with the next block */
|
||||
if (!bit_vect_test(block_enabled, i)) {
|
||||
/* continue with the next block */
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1906,6 +1927,7 @@ bail:
|
||||
|
||||
free(failed);
|
||||
free(failed_map);
|
||||
free(block_enabled);
|
||||
free(handle);
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
@ -2019,13 +2041,6 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
|
||||
parity_ptr[l] = 0;
|
||||
}
|
||||
|
||||
if (fix)
|
||||
msg_progress("Fixing...\n");
|
||||
else if (!state->opt.auditonly)
|
||||
msg_progress("Checking...\n");
|
||||
else
|
||||
msg_progress("Hashing...\n");
|
||||
|
||||
error = 0;
|
||||
|
||||
/* skip degenerated cases of empty parity, or skipping all */
|
||||
|
@ -28,17 +28,6 @@
|
||||
/****************************************************************************/
|
||||
/* dry */
|
||||
|
||||
/**
|
||||
* Check if we have to process the specified block index ::i.
|
||||
*/
|
||||
static int block_is_enabled(void* void_plan, block_off_t i)
|
||||
{
|
||||
(void)void_plan;
|
||||
(void)i;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
|
||||
{
|
||||
struct snapraid_io* io = worker->io;
|
||||
@ -208,7 +197,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
|
||||
countpos = 0;
|
||||
|
||||
/* start all the worker threads */
|
||||
io_start(&io, blockstart, blockmax, &block_is_enabled, 0);
|
||||
io_start(&io, blockstart, blockmax, 0);
|
||||
|
||||
state_progress_begin(state, blockstart, blockmax, countmax);
|
||||
while (1) {
|
||||
|
@ -41,18 +41,19 @@ struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_d
|
||||
struct snapraid_hash* hash;
|
||||
block_off_t i;
|
||||
unsigned char* buf;
|
||||
size_t hash_size = BLOCK_HASH_SIZE;
|
||||
|
||||
hash = malloc_nofail(sizeof(struct snapraid_hash));
|
||||
hash->disk = disk;
|
||||
hash->file = file;
|
||||
|
||||
buf = malloc_nofail(file->blockmax * BLOCK_HASH_SIZE);
|
||||
buf = malloc_nofail(file->blockmax * hash_size);
|
||||
|
||||
/* set the back pointer */
|
||||
for (i = 0; i < file->blockmax; ++i) {
|
||||
struct snapraid_block* block = fs_file2block_get(file, i);
|
||||
|
||||
memcpy(buf + i * BLOCK_HASH_SIZE, block->hash, BLOCK_HASH_SIZE);
|
||||
memcpy(buf + i * hash_size, block->hash, hash_size);
|
||||
|
||||
if (!block_has_updated_hash(block)) {
|
||||
free(buf);
|
||||
@ -61,7 +62,7 @@ struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_d
|
||||
}
|
||||
}
|
||||
|
||||
memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * BLOCK_HASH_SIZE);
|
||||
memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * hash_size);
|
||||
|
||||
free(buf);
|
||||
|
||||
|
@ -736,7 +736,7 @@ int dir_name_compare(const void* void_arg, const void* void_data)
|
||||
return strcmp(arg, dir->sub);
|
||||
}
|
||||
|
||||
struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip)
|
||||
struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip_access)
|
||||
{
|
||||
struct snapraid_disk* disk;
|
||||
|
||||
@ -748,8 +748,9 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev
|
||||
/* ensure that the dir terminate with "/" if it isn't empty */
|
||||
pathslash(disk->dir, sizeof(disk->dir));
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
thread_mutex_init(&disk->fs_mutex, 0);
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_init(&disk->fs_mutex);
|
||||
disk->fs_mutex_enabled = 0; /* lock will be enabled at threads start */
|
||||
#endif
|
||||
|
||||
disk->smartctl[0] = 0;
|
||||
@ -767,7 +768,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev
|
||||
disk->has_unsupported_uuid = *uuid == 0; /* empty UUID means unsupported */
|
||||
disk->had_empty_uuid = 0;
|
||||
disk->mapping_idx = -1;
|
||||
disk->skip_access = skip;
|
||||
disk->skip_access = skip_access;
|
||||
tommy_list_init(&disk->filelist);
|
||||
tommy_list_init(&disk->deletedlist);
|
||||
tommy_hashdyn_init(&disk->inodeset);
|
||||
@ -797,17 +798,27 @@ void disk_free(struct snapraid_disk* disk)
|
||||
tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free);
|
||||
tommy_hashdyn_done(&disk->dirset);
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_destroy(&disk->fs_mutex);
|
||||
#endif
|
||||
|
||||
free(disk);
|
||||
}
|
||||
|
||||
void disk_start_thread(struct snapraid_disk* disk)
|
||||
{
|
||||
#if HAVE_THREAD
|
||||
disk->fs_mutex_enabled = 1;
|
||||
#else
|
||||
(void)disk;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void fs_lock(struct snapraid_disk* disk)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
thread_mutex_lock(&disk->fs_mutex);
|
||||
#if HAVE_THREAD
|
||||
if (disk->fs_mutex_enabled)
|
||||
thread_mutex_lock(&disk->fs_mutex);
|
||||
#else
|
||||
(void)disk;
|
||||
#endif
|
||||
@ -815,8 +826,9 @@ static inline void fs_lock(struct snapraid_disk* disk)
|
||||
|
||||
static inline void fs_unlock(struct snapraid_disk* disk)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
thread_mutex_unlock(&disk->fs_mutex);
|
||||
#if HAVE_THREAD
|
||||
if (disk->fs_mutex_enabled)
|
||||
thread_mutex_unlock(&disk->fs_mutex);
|
||||
#else
|
||||
(void)disk;
|
||||
#endif
|
||||
|
@ -357,7 +357,7 @@ struct snapraid_disk {
|
||||
int mapping_idx; /**< Index in the mapping vector. Used only as buffer when writing the content file. */
|
||||
int skip_access; /**< If the disk is inaccessible and it should be skipped. */
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
/**
|
||||
* Mutex for protecting the filesystem structure.
|
||||
*
|
||||
@ -367,7 +367,15 @@ struct snapraid_disk {
|
||||
* Files, links and dirs are not protected as they are not expected to
|
||||
* change during multithread processing.
|
||||
*/
|
||||
pthread_mutex_t fs_mutex;
|
||||
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
|
||||
|
||||
/**
|
||||
@ -968,13 +976,18 @@ static inline tommy_uint32_t dir_name_hash(const char* name)
|
||||
/**
|
||||
* Allocate a disk.
|
||||
*/
|
||||
struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip);
|
||||
struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip_access);
|
||||
|
||||
/**
|
||||
* Deallocate a disk.
|
||||
*/
|
||||
void disk_free(struct snapraid_disk* disk);
|
||||
|
||||
/**
|
||||
* Enable multithread support for the disk.
|
||||
*/
|
||||
void disk_start_thread(struct snapraid_disk* disk);
|
||||
|
||||
/**
|
||||
* Get the size of the disk in blocks.
|
||||
*/
|
||||
|
64
cmdline/io.c
64
cmdline/io.c
@ -21,7 +21,7 @@
|
||||
|
||||
void (*io_start)(struct snapraid_io* io,
|
||||
block_off_t blockstart, block_off_t blockmax,
|
||||
int (*block_is_enabled)(void* arg, block_off_t), void* blockarg) = 0;
|
||||
bit_vect_t* block_enabled) = 0;
|
||||
void (*io_stop)(struct snapraid_io* io) = 0;
|
||||
block_off_t (*io_read_next)(struct snapraid_io* io, void*** buffer) = 0;
|
||||
struct snapraid_task* (*io_data_read)(struct snapraid_io* io, unsigned* diskcur, unsigned* waiting_map, unsigned* waiting_mac) = 0;
|
||||
@ -40,8 +40,10 @@ static block_off_t io_position_next(struct snapraid_io* io)
|
||||
block_off_t blockcur;
|
||||
|
||||
/* get the next position */
|
||||
while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next))
|
||||
++io->block_next;
|
||||
if (io->block_enabled) {
|
||||
while (io->block_next < io->block_max && !bit_vect_test(io->block_enabled, io->block_next))
|
||||
++io->block_next;
|
||||
}
|
||||
|
||||
blockcur = io->block_next;
|
||||
|
||||
@ -257,12 +259,11 @@ static void io_parity_write_mono(struct snapraid_io* io, unsigned* pos, unsigned
|
||||
|
||||
static void io_start_mono(struct snapraid_io* io,
|
||||
block_off_t blockstart, block_off_t blockmax,
|
||||
int (*block_is_enabled)(void* arg, block_off_t), void* blockarg)
|
||||
bit_vect_t* block_enabled)
|
||||
{
|
||||
io->block_start = blockstart;
|
||||
io->block_max = blockmax;
|
||||
io->block_is_enabled = block_is_enabled;
|
||||
io->block_arg = blockarg;
|
||||
io->block_enabled = block_enabled;
|
||||
io->block_next = blockstart;
|
||||
}
|
||||
|
||||
@ -275,7 +276,7 @@ static void io_stop_mono(struct snapraid_io* io)
|
||||
/* multi thread */
|
||||
|
||||
/* disable multithread if pthread is not present */
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
|
||||
/**
|
||||
* Get the next task to work on for a reader.
|
||||
@ -767,14 +768,20 @@ static void* io_writer_thread(void* arg)
|
||||
|
||||
static void io_start_thread(struct snapraid_io* io,
|
||||
block_off_t blockstart, block_off_t blockmax,
|
||||
int (*block_is_enabled)(void* arg, block_off_t), void* blockarg)
|
||||
bit_vect_t* block_enabled)
|
||||
{
|
||||
unsigned i;
|
||||
tommy_node* j;
|
||||
|
||||
/* enable the filesystem mutex in all disks */
|
||||
for (j = io->state->disklist; j != 0; j = j->next) {
|
||||
struct snapraid_disk* disk = j->data;
|
||||
disk_start_thread(disk);
|
||||
}
|
||||
|
||||
io->block_start = blockstart;
|
||||
io->block_max = blockmax;
|
||||
io->block_is_enabled = block_is_enabled;
|
||||
io->block_arg = blockarg;
|
||||
io->block_enabled = block_enabled;
|
||||
io->block_next = blockstart;
|
||||
|
||||
io->done = 0;
|
||||
@ -804,7 +811,7 @@ static void io_start_thread(struct snapraid_io* io,
|
||||
|
||||
worker->index = 0;
|
||||
|
||||
thread_create(&worker->thread, 0, io_reader_thread, worker);
|
||||
thread_create(&worker->thread, io_reader_thread, worker);
|
||||
}
|
||||
|
||||
/* start the writer threads */
|
||||
@ -813,7 +820,7 @@ static void io_start_thread(struct snapraid_io* io,
|
||||
|
||||
worker->index = io->io_max - 1;
|
||||
|
||||
thread_create(&worker->thread, 0, io_writer_thread, worker);
|
||||
thread_create(&worker->thread, io_writer_thread, worker);
|
||||
}
|
||||
}
|
||||
|
||||
@ -865,15 +872,16 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state,
|
||||
struct snapraid_parity_handle* parity_handle_map, unsigned parity_handle_max)
|
||||
{
|
||||
unsigned i;
|
||||
size_t allocated;
|
||||
size_t allocated_size;
|
||||
size_t block_size = state->block_size;
|
||||
|
||||
io->state = state;
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#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)
|
||||
@ -891,18 +899,18 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state,
|
||||
assert(io->io_max == 1 || (io->io_max >= IO_MIN && io->io_max <= IO_MAX));
|
||||
|
||||
io->buffer_max = buffer_max;
|
||||
allocated = 0;
|
||||
allocated_size = 0;
|
||||
for (i = 0; i < io->io_max; ++i) {
|
||||
if (state->file_mode != ADVISE_DIRECT)
|
||||
io->buffer_map[i] = malloc_nofail_vector_align(handle_max, buffer_max, state->block_size, &io->buffer_alloc_map[i]);
|
||||
io->buffer_map[i] = malloc_nofail_vector_align(handle_max, buffer_max, block_size, &io->buffer_alloc_map[i]);
|
||||
else
|
||||
io->buffer_map[i] = malloc_nofail_vector_direct(handle_max, buffer_max, state->block_size, &io->buffer_alloc_map[i]);
|
||||
io->buffer_map[i] = malloc_nofail_vector_direct(handle_max, buffer_max, block_size, &io->buffer_alloc_map[i]);
|
||||
if (!state->opt.skip_self)
|
||||
mtest_vector(io->buffer_max, state->block_size, io->buffer_map[i]);
|
||||
allocated += state->block_size * buffer_max;
|
||||
allocated_size += block_size * buffer_max;
|
||||
}
|
||||
|
||||
msg_progress("Using %u MiB of memory for %u cached blocks.\n", (unsigned)(allocated / MEBI), io->io_max);
|
||||
msg_progress("Using %u MiB of memory for %u cached blocks.\n", (unsigned)(allocated_size / MEBI), io->io_max);
|
||||
|
||||
if (parity_writer) {
|
||||
io->reader_max = handle_max;
|
||||
@ -960,7 +968,7 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state,
|
||||
worker->buffer_skew = handle_max;
|
||||
}
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
if (io->io_max > 1) {
|
||||
io_read_next = io_read_next_thread;
|
||||
io_write_preset = io_write_preset_thread;
|
||||
@ -972,11 +980,11 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state,
|
||||
io_start = io_start_thread;
|
||||
io_stop = io_stop_thread;
|
||||
|
||||
thread_mutex_init(&io->io_mutex, 0);
|
||||
thread_cond_init(&io->read_done, 0);
|
||||
thread_cond_init(&io->read_sched, 0);
|
||||
thread_cond_init(&io->write_done, 0);
|
||||
thread_cond_init(&io->write_sched, 0);
|
||||
thread_mutex_init(&io->io_mutex);
|
||||
thread_cond_init(&io->read_done);
|
||||
thread_cond_init(&io->read_sched);
|
||||
thread_cond_init(&io->write_done);
|
||||
thread_cond_init(&io->write_sched);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -1006,7 +1014,7 @@ void io_done(struct snapraid_io* io)
|
||||
free(io->writer_map);
|
||||
free(io->writer_list);
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
if (io->io_max > 1) {
|
||||
thread_mutex_destroy(&io->io_mutex);
|
||||
thread_cond_destroy(&io->read_done);
|
||||
|
25
cmdline/io.h
25
cmdline/io.h
@ -35,8 +35,8 @@
|
||||
* 4 - 452 MB/s, CPU 54%, speed 118%
|
||||
* 8 - 487 MB/s, CPU 60%, speed 128%
|
||||
* 16 - 505 MB/s, CPU 63%, speed 132%
|
||||
* 32 - 520 MB/s, CPU 64%, speed 136%
|
||||
* 64 - 524 MB/s, CPU 65%, speed 137%
|
||||
* 32 - 520 MB/s, CPU 64%, speed 136% [SnapRAID <= 12.0]
|
||||
* 64 - 524 MB/s, CPU 65%, speed 137% [SnapRAID > 12.0]
|
||||
* 128 - 525 MB/s, CPU 66%, speed 138%
|
||||
*/
|
||||
#define IO_MIN 3 /* required by writers, readers can work also with 2 */
|
||||
@ -87,8 +87,8 @@ struct snapraid_task {
|
||||
* from a specific disk.
|
||||
*/
|
||||
struct snapraid_worker {
|
||||
#if HAVE_PTHREAD
|
||||
pthread_t thread; /**< Thread context for the worker. */
|
||||
#if HAVE_THREAD
|
||||
thread_id_t thread; /**< Thread context for the worker. */
|
||||
#endif
|
||||
|
||||
struct snapraid_io* io; /**< Parent pointer. */
|
||||
@ -147,12 +147,12 @@ struct snapraid_io {
|
||||
*/
|
||||
unsigned io_max;
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
/**
|
||||
* Mutex used to protect the synchronization
|
||||
* between the io and the workers.
|
||||
*/
|
||||
pthread_mutex_t io_mutex;
|
||||
thread_mutex_t io_mutex;
|
||||
|
||||
/**
|
||||
* Condition for a new read is completed.
|
||||
@ -161,7 +161,7 @@ struct snapraid_io {
|
||||
* The IO waits on this condition when it's waiting for
|
||||
* a new read to be completed.
|
||||
*/
|
||||
pthread_cond_t read_done;
|
||||
thread_cond_t read_done;
|
||||
|
||||
/**
|
||||
* Condition for a new read scheduled.
|
||||
@ -170,7 +170,7 @@ struct snapraid_io {
|
||||
* read to process.
|
||||
* The IO signals this condition when new reads are scheduled.
|
||||
*/
|
||||
pthread_cond_t read_sched;
|
||||
thread_cond_t read_sched;
|
||||
|
||||
/**
|
||||
* Condition for a new write is completed.
|
||||
@ -179,7 +179,7 @@ struct snapraid_io {
|
||||
* The IO waits on this condition when it's waiting for
|
||||
* a new write to be completed.
|
||||
*/
|
||||
pthread_cond_t write_done;
|
||||
thread_cond_t write_done;
|
||||
|
||||
/**
|
||||
* Condition for a new write scheduled.
|
||||
@ -188,7 +188,7 @@ struct snapraid_io {
|
||||
* write to process.
|
||||
* The IO signals this condition when new writes are scheduled.
|
||||
*/
|
||||
pthread_cond_t write_sched;
|
||||
thread_cond_t write_sched;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -217,8 +217,7 @@ struct snapraid_io {
|
||||
block_off_t block_start;
|
||||
block_off_t block_max;
|
||||
block_off_t block_next;
|
||||
int (*block_is_enabled)(void* arg, block_off_t);
|
||||
void* block_arg;
|
||||
bit_vect_t* block_enabled;
|
||||
|
||||
/**
|
||||
* Buffers for data.
|
||||
@ -315,7 +314,7 @@ void io_done(struct snapraid_io* io);
|
||||
*/
|
||||
extern void (*io_start)(struct snapraid_io* io,
|
||||
block_off_t blockstart, block_off_t blockmax,
|
||||
int (*block_is_enabled)(void* arg, block_off_t), void* blockarg);
|
||||
bit_vect_t* block_enabled);
|
||||
|
||||
/**
|
||||
* Stop all the worker threads.
|
||||
|
258
cmdline/mingw.c
258
cmdline/mingw.c
@ -31,14 +31,26 @@ int exit_sync_needed = 2;
|
||||
/* Add missing Windows declaration */
|
||||
|
||||
/* For SetThreadExecutionState */
|
||||
#ifndef WIN32_ES_SYSTEM_REQUIRED
|
||||
#define WIN32_ES_SYSTEM_REQUIRED 0x00000001L
|
||||
#endif
|
||||
#ifndef WIN32_ES_DISPLAY_REQUIRED
|
||||
#define WIN32_ES_DISPLAY_REQUIRED 0x00000002L
|
||||
#endif
|
||||
#ifndef WIN32_ES_USER_PRESENT
|
||||
#define WIN32_ES_USER_PRESENT 0x00000004L
|
||||
#endif
|
||||
#ifndef WIN32_ES_AWAYMODE_REQUIRED
|
||||
#define WIN32_ES_AWAYMODE_REQUIRED 0x00000040L
|
||||
#endif
|
||||
#ifndef WIN32_ES_CONTINUOUS
|
||||
#define WIN32_ES_CONTINUOUS 0x80000000L
|
||||
#endif
|
||||
|
||||
/* File Index */
|
||||
#ifndef FILE_INVALID_FILE_ID
|
||||
#define FILE_INVALID_FILE_ID ((ULONGLONG)-1LL)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Direct access to RtlGenRandom().
|
||||
@ -56,12 +68,12 @@ static ULONGLONG (WINAPI* ptr_GetTickCount64)(void);
|
||||
* Description of the last error.
|
||||
* It's stored in the thread local storage.
|
||||
*/
|
||||
static pthread_key_t last_error;
|
||||
static windows_key_t last_error;
|
||||
|
||||
/**
|
||||
* Monotone tick counter
|
||||
*/
|
||||
static pthread_mutex_t tick_lock;
|
||||
static windows_mutex_t tick_lock;
|
||||
static uint64_t tick_last;
|
||||
|
||||
/**
|
||||
@ -119,14 +131,14 @@ void os_init(int opt)
|
||||
is_scan_winfind = opt != 0;
|
||||
|
||||
/* initialize the thread local storage for strerror(), using free() as destructor */
|
||||
if (pthread_key_create(&last_error, free) != 0) {
|
||||
log_fatal("Error calling pthread_key_create().\n");
|
||||
if (windows_key_create(&last_error, free) != 0) {
|
||||
log_fatal("Error calling windows_key_create().\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tick_last = 0;
|
||||
if (pthread_mutex_init(&tick_lock, 0) != 0) {
|
||||
log_fatal("Error calling pthread_mutex_init().\n");
|
||||
if (windows_mutex_init(&tick_lock, 0) != 0) {
|
||||
log_fatal("Error calling windows_mutex_init().\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -173,9 +185,9 @@ void os_init(int opt)
|
||||
void os_done(void)
|
||||
{
|
||||
/* delete the thread local storage for strerror() */
|
||||
pthread_key_delete(last_error);
|
||||
windows_key_delete(last_error);
|
||||
|
||||
pthread_mutex_destroy(&tick_lock);
|
||||
windows_mutex_destroy(&tick_lock);
|
||||
|
||||
/* restore the normal execution level */
|
||||
SetThreadExecutionState(WIN32_ES_CONTINUOUS);
|
||||
@ -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
|
||||
@ -1811,10 +1823,10 @@ const char* windows_strerror(int err)
|
||||
snprintf(error, len, "%s [%d/%u]", str, err, (unsigned)GetLastError());
|
||||
|
||||
/* get previous one, if any */
|
||||
previous = pthread_getspecific(last_error);
|
||||
previous = windows_getspecific(last_error);
|
||||
|
||||
/* store in the thread local storage */
|
||||
if (pthread_setspecific(last_error, error) != 0) {
|
||||
if (windows_setspecific(last_error, error) != 0) {
|
||||
free(error);
|
||||
return str;
|
||||
}
|
||||
@ -2024,7 +2036,7 @@ uint64_t tick(void)
|
||||
* We had reports of invalid stats due faulty High Precision Event Timer.
|
||||
* See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/a2122fd6/
|
||||
*/
|
||||
pthread_mutex_lock(&tick_lock);
|
||||
windows_mutex_lock(&tick_lock);
|
||||
|
||||
/*
|
||||
* MSDN 'QueryPerformanceCounter'
|
||||
@ -2039,7 +2051,7 @@ uint64_t tick(void)
|
||||
r = tick_last;
|
||||
tick_last = r;
|
||||
|
||||
pthread_mutex_unlock(&tick_lock);
|
||||
windows_mutex_unlock(&tick_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -2600,7 +2612,7 @@ static int device_thread(tommy_list* list, void* (*func)(void* arg))
|
||||
for (i = tommy_list_head(list); i != 0; i = i->next) {
|
||||
devinfo_t* devinfo = i->data;
|
||||
|
||||
thread_create(&devinfo->thread, 0, func, devinfo);
|
||||
thread_create(&devinfo->thread, func, devinfo);
|
||||
}
|
||||
|
||||
/* joins all threads */
|
||||
@ -2690,109 +2702,221 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* thread */
|
||||
/* pthread like interface */
|
||||
|
||||
int windows_mutex_init(windows_mutex_t* mutex, void* attr)
|
||||
{
|
||||
CRITICAL_SECTION* cs;
|
||||
|
||||
(void)attr;
|
||||
|
||||
cs = malloc(sizeof(CRITICAL_SECTION));
|
||||
if (!cs)
|
||||
return -1;
|
||||
|
||||
InitializeCriticalSection(cs);
|
||||
|
||||
*mutex = cs;
|
||||
InitializeCriticalSection(mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_mutex_destroy(windows_mutex_t* mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = *mutex;
|
||||
|
||||
DeleteCriticalSection(cs);
|
||||
|
||||
free(cs);
|
||||
DeleteCriticalSection(mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_mutex_lock(windows_mutex_t* mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = *mutex;
|
||||
|
||||
EnterCriticalSection(cs);
|
||||
EnterCriticalSection(mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_mutex_unlock(windows_mutex_t* mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = *mutex;
|
||||
|
||||
LeaveCriticalSection(cs);
|
||||
LeaveCriticalSection(mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_cond_init(windows_cond_t* cond, void* attr)
|
||||
{
|
||||
CONDITION_VARIABLE* cv;
|
||||
|
||||
(void)attr;
|
||||
|
||||
cv = malloc(sizeof(CONDITION_VARIABLE));
|
||||
if (!cv)
|
||||
return -1;
|
||||
|
||||
InitializeConditionVariable(cv);
|
||||
|
||||
*cond = cv;
|
||||
InitializeConditionVariable(cond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_cond_destroy(windows_cond_t* cond)
|
||||
{
|
||||
CONDITION_VARIABLE* cv = *cond;
|
||||
|
||||
/* note that in Windows there is no DeleteConditionVariable() to call */
|
||||
free(cv);
|
||||
(void)cond;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_cond_signal(windows_cond_t* cond)
|
||||
{
|
||||
CONDITION_VARIABLE* cv = *cond;
|
||||
|
||||
WakeConditionVariable(cv);
|
||||
WakeConditionVariable(cond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_cond_broadcast(windows_cond_t* cond)
|
||||
{
|
||||
CONDITION_VARIABLE* cv = *cond;
|
||||
|
||||
WakeAllConditionVariable(cv);
|
||||
WakeAllConditionVariable(cond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_cond_wait(windows_cond_t* cond, windows_mutex_t* mutex)
|
||||
{
|
||||
CONDITION_VARIABLE* cv = *cond;
|
||||
CRITICAL_SECTION* cs = *mutex;
|
||||
|
||||
if (!SleepConditionVariableCS(cv, cs, INFINITE))
|
||||
if (!SleepConditionVariableCS(cond, mutex, INFINITE))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct windows_key_context {
|
||||
void (* func)(void *);
|
||||
DWORD key;
|
||||
tommy_node node;
|
||||
};
|
||||
|
||||
/* list of all keys with destructor */
|
||||
static tommy_list windows_key_list = { 0 };
|
||||
|
||||
int windows_key_create(windows_key_t* key, void(* destructor)(void*))
|
||||
{
|
||||
struct windows_key_context* context;
|
||||
|
||||
context = malloc(sizeof(struct windows_key_context));
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
context->func = destructor;
|
||||
context->key = TlsAlloc();
|
||||
if (context->key == 0xFFFFFFFF) {
|
||||
windows_errno(GetLastError());
|
||||
free(context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* insert in the list of destructors */
|
||||
if (context->func)
|
||||
tommy_list_insert_tail(&windows_key_list, &context->node, context);
|
||||
|
||||
*key = context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_key_delete(windows_key_t key)
|
||||
{
|
||||
struct windows_key_context* context = key;
|
||||
|
||||
/* remove from the list of destructors */
|
||||
if (context->func)
|
||||
tommy_list_remove_existing(&windows_key_list, &context->node);
|
||||
|
||||
TlsFree(context->key);
|
||||
|
||||
free(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* windows_getspecific(windows_key_t key)
|
||||
{
|
||||
struct windows_key_context* context = key;
|
||||
|
||||
return TlsGetValue(context->key);
|
||||
}
|
||||
|
||||
int windows_setspecific(windows_key_t key, void* value)
|
||||
{
|
||||
struct windows_key_context* context = key;
|
||||
|
||||
if (!TlsSetValue(context->key, value)) {
|
||||
windows_errno(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct windows_thread_context {
|
||||
HANDLE h;
|
||||
unsigned id;
|
||||
void* (* func)(void *);
|
||||
void* arg;
|
||||
void* ret;
|
||||
};
|
||||
|
||||
/* forwarder to change the function declaration */
|
||||
static unsigned __stdcall windows_thread_func(void* arg)
|
||||
{
|
||||
struct windows_thread_context* context = arg;
|
||||
tommy_node* i;
|
||||
|
||||
context->ret = context->func(context->arg);
|
||||
|
||||
/* call the destructor of all the keys */
|
||||
i = tommy_list_head(&windows_key_list);
|
||||
while (i) {
|
||||
struct windows_key_context* key = i->data;
|
||||
if (key->func) {
|
||||
void* value = windows_getspecific(key);
|
||||
if (value)
|
||||
key->func(value);
|
||||
}
|
||||
i = i->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_create(thread_id_t* thread, void* attr, void* (* func)(void *), void* arg)
|
||||
{
|
||||
struct windows_thread_context* context;
|
||||
|
||||
(void)attr;
|
||||
|
||||
context = malloc(sizeof(struct windows_thread_context));
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
context->func = func;
|
||||
context->arg = arg;
|
||||
context->ret = 0;
|
||||
context->h = (void*)_beginthreadex(0, 0, windows_thread_func, context, 0, &context->id);
|
||||
|
||||
if (context->h == 0) {
|
||||
free(context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*thread = context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_join(thread_id_t thread, void** retval)
|
||||
{
|
||||
struct windows_thread_context* context = thread;
|
||||
|
||||
if (WaitForSingleObject(context->h, INFINITE) != WAIT_OBJECT_0) {
|
||||
windows_errno(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!CloseHandle(context->h)) {
|
||||
windows_errno(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
*retval = context->ret;
|
||||
|
||||
free(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -385,23 +385,8 @@ size_t windows_direct_size(void);
|
||||
/****************************************************************************/
|
||||
/* thread */
|
||||
|
||||
#define pthread_mutex_t windows_mutex_t
|
||||
#define pthread_cond_t windows_cond_t
|
||||
#define pthread_mutex_init windows_mutex_init
|
||||
#define pthread_mutex_destroy windows_mutex_destroy
|
||||
#define pthread_mutex_lock windows_mutex_lock
|
||||
#define pthread_mutex_unlock windows_mutex_unlock
|
||||
#define pthread_cond_init windows_cond_init
|
||||
#define pthread_cond_destroy windows_cond_destroy
|
||||
#define pthread_cond_signal windows_cond_signal
|
||||
#define pthread_cond_broadcast windows_cond_broadcast
|
||||
#define pthread_cond_wait windows_cond_wait
|
||||
|
||||
typedef void* windows_mutex_t;
|
||||
typedef void* windows_cond_t;
|
||||
|
||||
/**
|
||||
* Like pthread_* equivalent.
|
||||
* Like the pthread_* equivalent.
|
||||
*/
|
||||
int windows_mutex_init(windows_mutex_t* mutex, void* attr);
|
||||
int windows_mutex_destroy(windows_mutex_t* mutex);
|
||||
@ -412,6 +397,12 @@ int windows_cond_destroy(windows_cond_t* cond);
|
||||
int windows_cond_signal(windows_cond_t* cond);
|
||||
int windows_cond_broadcast(windows_cond_t* cond);
|
||||
int windows_cond_wait(windows_cond_t* cond, windows_mutex_t* mutex);
|
||||
int windows_key_create(windows_key_t* key, void(* destructor)(void*));
|
||||
int windows_key_delete(windows_key_t key);
|
||||
void* windows_getspecific(windows_key_t key);
|
||||
int windows_setspecific(windows_key_t key, void* value);
|
||||
int windows_create(thread_id_t* thread, void* attr, void* (* func)(void *), void *arg);
|
||||
int windows_join(thread_id_t thread, void** retval);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -230,10 +230,6 @@
|
||||
#include "fnmatch.h"
|
||||
#endif
|
||||
|
||||
#if HAVE_PTHREAD_H
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_MATH_H
|
||||
#include <math.h>
|
||||
#endif
|
||||
@ -245,8 +241,37 @@
|
||||
/**
|
||||
* Enable thread use.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define HAVE_THREAD 1
|
||||
typedef void* windows_thread_t;
|
||||
typedef CRITICAL_SECTION windows_mutex_t;
|
||||
typedef CONDITION_VARIABLE windows_cond_t;
|
||||
typedef void* windows_key_t;
|
||||
/* remap to pthread */
|
||||
#define thread_id_t windows_thread_t
|
||||
#define thread_mutex_t windows_mutex_t
|
||||
#define thread_cond_t windows_cond_t
|
||||
#define pthread_mutex_init windows_mutex_init
|
||||
#define pthread_mutex_destroy windows_mutex_destroy
|
||||
#define pthread_mutex_lock windows_mutex_lock
|
||||
#define pthread_mutex_unlock windows_mutex_unlock
|
||||
#define pthread_cond_init windows_cond_init
|
||||
#define pthread_cond_destroy windows_cond_destroy
|
||||
#define pthread_cond_signal windows_cond_signal
|
||||
#define pthread_cond_broadcast windows_cond_broadcast
|
||||
#define pthread_cond_wait windows_cond_wait
|
||||
#define pthread_create windows_create
|
||||
#define pthread_join windows_join
|
||||
#else
|
||||
#if HAVE_PTHREAD_H
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#if HAVE_PTHREAD_CREATE
|
||||
#define HAVE_PTHREAD 1
|
||||
#define HAVE_THREAD 1
|
||||
typedef pthread_t thread_id_t;
|
||||
typedef pthread_mutex_t thread_mutex_t;
|
||||
typedef pthread_cond_t thread_cond_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -337,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.
|
||||
*/
|
||||
@ -470,8 +495,8 @@ struct devinfo_struct {
|
||||
char smart_serial[SMART_MAX]; /**< SMART serial number. */
|
||||
char smart_vendor[SMART_MAX]; /**< SMART vendor. */
|
||||
char smart_model[SMART_MAX]; /**< SMART model. */
|
||||
#if HAVE_PTHREAD
|
||||
pthread_t thread;
|
||||
#if HAVE_THREAD
|
||||
thread_id_t thread;
|
||||
#endif
|
||||
tommy_node node;
|
||||
};
|
||||
|
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");
|
||||
|
@ -50,9 +50,8 @@ struct snapraid_plan {
|
||||
/**
|
||||
* Check if we have to process the specified block index ::i.
|
||||
*/
|
||||
static int block_is_enabled(void* void_plan, block_off_t i)
|
||||
static int block_is_enabled(struct snapraid_plan* plan, block_off_t i)
|
||||
{
|
||||
struct snapraid_plan* plan = void_plan;
|
||||
time_t blocktime;
|
||||
snapraid_info info;
|
||||
|
||||
@ -268,6 +267,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
||||
unsigned* waiting_map;
|
||||
unsigned waiting_mac;
|
||||
char esc_buffer[ESC_MAX];
|
||||
bit_vect_t* block_enabled;
|
||||
|
||||
/* maps the disks to handles */
|
||||
handle = handle_mapping(state, &diskmax);
|
||||
@ -289,12 +289,16 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
||||
silent_error = 0;
|
||||
io_error = 0;
|
||||
|
||||
msg_progress("Selecting...\n");
|
||||
|
||||
/* first count the number of blocks to process */
|
||||
countmax = 0;
|
||||
plan->countlast = 0;
|
||||
block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */
|
||||
for (blockcur = blockstart; blockcur < blockmax; ++blockcur) {
|
||||
if (!block_is_enabled(plan, blockcur))
|
||||
continue;
|
||||
bit_vect_set(block_enabled, blockcur);
|
||||
++countmax;
|
||||
}
|
||||
|
||||
@ -310,10 +314,11 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
||||
|
||||
countsize = 0;
|
||||
countpos = 0;
|
||||
plan->countlast = 0;
|
||||
|
||||
msg_progress("Scrubbing...\n");
|
||||
|
||||
/* start all the worker threads */
|
||||
io_start(&io, blockstart, blockmax, &block_is_enabled, plan);
|
||||
io_start(&io, blockstart, blockmax, block_enabled);
|
||||
|
||||
state_progress_begin(state, blockstart, blockmax, countmax);
|
||||
while (1) {
|
||||
@ -700,6 +705,7 @@ bail:
|
||||
free(rehandle_alloc);
|
||||
free(waiting_map);
|
||||
io_done(&io);
|
||||
free(block_enabled);
|
||||
|
||||
if (state->opt.expect_recoverable) {
|
||||
if (error + silent_error + io_error == 0)
|
||||
@ -874,8 +880,6 @@ int state_scrub(struct snapraid_state* state, int plan, int olderthan)
|
||||
}
|
||||
}
|
||||
|
||||
msg_progress("Scrubbing...\n");
|
||||
|
||||
error = 0;
|
||||
|
||||
ret = state_scrub_process(state, parity_handle, 0, blockmax, &ps, now);
|
||||
|
@ -131,13 +131,20 @@ void log_open(const char* file)
|
||||
char text_D[32];
|
||||
time_t t;
|
||||
struct tm* tm;
|
||||
#if HAVE_LOCALTIME_R
|
||||
struct tm tm_res;
|
||||
#endif
|
||||
|
||||
/* leave stdlog at 0 if not specified */
|
||||
if (file == 0)
|
||||
return;
|
||||
|
||||
t = time(0);
|
||||
#if HAVE_LOCALTIME_R
|
||||
tm = localtime_r(&t, &tm_res);
|
||||
#else
|
||||
tm = localtime(&t);
|
||||
#endif
|
||||
if (tm) {
|
||||
strftime(text_T, sizeof(text_T), "%H%M%S", tm);
|
||||
strftime(text_D, sizeof(text_T), "%Y%m%d", tm);
|
||||
@ -300,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[] = {
|
||||
@ -308,6 +316,7 @@ struct option long_options[] = {
|
||||
{ "filter-disk", 1, 0, 'd' },
|
||||
{ "filter-missing", 0, 0, 'm' },
|
||||
{ "filter-error", 0, 0, 'e' },
|
||||
{ "filter-block-error", 0, 0, 'b' },
|
||||
{ "percentage", 1, 0, 'p' }, /* legacy name for --plan */
|
||||
{ "plan", 1, 0, 'p' },
|
||||
{ "older-than", 1, 0, 'o' },
|
||||
@ -467,11 +476,14 @@ 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
|
||||
|
||||
#define OPTIONS "c:f:d:mep:o:S:B:L:i:l:ZEUDNFRahTC:vqHVG"
|
||||
#define OPTIONS "c:f:d:mebp:o:S:B:L:i:l:ZEUDNFRahTC:vqHVG"
|
||||
|
||||
volatile int global_interrupt = 0;
|
||||
|
||||
@ -552,6 +564,9 @@ int main(int argc, char* argv[])
|
||||
int period;
|
||||
time_t t;
|
||||
struct tm* tm;
|
||||
#if HAVE_LOCALTIME_R
|
||||
struct tm tm_res;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
test(argc, argv);
|
||||
@ -617,10 +632,18 @@ int main(int argc, char* argv[])
|
||||
opt.expected_missing = 1;
|
||||
break;
|
||||
case 'e' :
|
||||
/* when processing only error, we filter both files and blocks */
|
||||
/* when processing only error, we filter files */
|
||||
/* and we apply fixes only to synced ones */
|
||||
filter_error = 1;
|
||||
opt.badonly = 1;
|
||||
opt.badfileonly = 1;
|
||||
opt.syncedonly = 1;
|
||||
break;
|
||||
case 'b' :
|
||||
/* when processing only block with error, we filter both files and blocks */
|
||||
/* and we apply fixes only to synced ones */
|
||||
filter_error = 1;
|
||||
opt.badfileonly = 1;
|
||||
opt.badblockonly = 1;
|
||||
opt.syncedonly = 1;
|
||||
break;
|
||||
case 'p' :
|
||||
@ -862,7 +885,7 @@ int main(int argc, char* argv[])
|
||||
opt.force_stats = 1;
|
||||
break;
|
||||
case OPT_TEST_COND_SIGNAL_OUTSIDE :
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_cond_signal_outside = 1;
|
||||
#endif
|
||||
break;
|
||||
@ -910,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);
|
||||
@ -1225,7 +1251,11 @@ int main(int argc, char* argv[])
|
||||
|
||||
/* print generic info into the log */
|
||||
t = time(0);
|
||||
#if HAVE_LOCALTIME_R
|
||||
tm = localtime_r(&t, &tm_res);
|
||||
#else
|
||||
tm = localtime(&t);
|
||||
#endif
|
||||
log_tag("version:%s\n", PACKAGE_VERSION);
|
||||
log_tag("unixtime:%" PRIi64 "\n", (int64_t)t);
|
||||
if (tm) {
|
||||
|
@ -37,14 +37,10 @@
|
||||
* 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.
|
||||
*/
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
/* #define HAVE_MT_WRITE 1 */
|
||||
#define HAVE_MT_VERIFY 1
|
||||
#endif
|
||||
@ -2881,7 +2877,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
||||
struct state_write_thread_context {
|
||||
struct snapraid_state* state;
|
||||
#if HAVE_MT_WRITE
|
||||
pthread_t thread;
|
||||
thread_id_t thread;
|
||||
#endif
|
||||
/* input */
|
||||
block_off_t blockmax;
|
||||
@ -3498,7 +3494,7 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
|
||||
context->info_has_rehash = info_has_rehash;
|
||||
context->f = f;
|
||||
|
||||
thread_create(&context->thread, 0, state_write_thread, context);
|
||||
thread_create(&context->thread, state_write_thread, context);
|
||||
|
||||
i = i->next;
|
||||
}
|
||||
@ -3843,7 +3839,7 @@ struct state_verify_thread_context {
|
||||
struct snapraid_state* state;
|
||||
struct snapraid_content* content;
|
||||
#if HAVE_MT_VERIFY
|
||||
pthread_t thread;
|
||||
thread_id_t thread;
|
||||
#else
|
||||
void* retval;
|
||||
#endif
|
||||
@ -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) {
|
||||
@ -3934,7 +3930,7 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc)
|
||||
context->f = f;
|
||||
|
||||
#if HAVE_MT_VERIFY
|
||||
thread_create(&context->thread, 0, state_verify_thread, context);
|
||||
thread_create(&context->thread, state_verify_thread, context);
|
||||
#else
|
||||
context->retval = state_verify_thread(context);
|
||||
#endif
|
||||
@ -4117,7 +4113,7 @@ void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tom
|
||||
if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk))
|
||||
return;
|
||||
|
||||
msg_progress("Filtering...\n");
|
||||
msg_progress("Selecting...\n");
|
||||
|
||||
for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) {
|
||||
struct snapraid_filter* filter = i->data;
|
||||
@ -4564,7 +4560,7 @@ int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_o
|
||||
out_size_speed = (unsigned)(delta_size / MEGA / delta_time);
|
||||
|
||||
/* estimate the speed in block/s */
|
||||
if (delta_pos != 0)
|
||||
if (delta_time != 0)
|
||||
out_block_speed = (unsigned)(delta_pos / delta_time);
|
||||
|
||||
/* estimate the cpu usage percentage */
|
||||
@ -4591,7 +4587,7 @@ int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_o
|
||||
msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA));
|
||||
if (out_computed) {
|
||||
msg_bar(", %u MB/s", out_size_speed);
|
||||
msg_bar(", %u block/s", out_block_speed);
|
||||
msg_bar(", %u stripe/s", out_block_speed);
|
||||
msg_bar(", CPU %u%%", out_cpu);
|
||||
msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60);
|
||||
}
|
||||
|
@ -73,7 +73,8 @@ extern volatile int global_interrupt;
|
||||
struct snapraid_option {
|
||||
int gui; /**< Gui output. */
|
||||
int auditonly; /**< In check, checks only the hash and not the parity. */
|
||||
int badonly; /**< In fix, fixes only the blocks marked as bad. */
|
||||
int badfileonly; /**< In fix, fixes only files marked as bad. */
|
||||
int badblockonly; /**< In fix, fixes only the blocks marked as bad. */
|
||||
int syncedonly; /**< In fix, fixes only files that are synced. */
|
||||
int prehash; /**< Enables the prehash mode for sync. */
|
||||
unsigned io_error_limit; /**< Max number of input/output errors before aborting. */
|
||||
@ -118,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 {
|
||||
|
@ -501,15 +501,34 @@ int sgetu32(STREAM* f, uint32_t* value)
|
||||
int c;
|
||||
|
||||
c = sgetc(f);
|
||||
if (c >= '0' && c <= '9') {
|
||||
if (c == '0') {
|
||||
*value = 0;
|
||||
return 0;
|
||||
} else if (c >= '1' && c <= '9') {
|
||||
uint32_t v;
|
||||
|
||||
v = c - '0';
|
||||
|
||||
c = sgetc(f);
|
||||
while (c >= '0' && c <= '9') {
|
||||
uint32_t digit;
|
||||
if (v > 0xFFFFFFFFU / 10) {
|
||||
/* LCOV_EXCL_START */
|
||||
/* overflow */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
v *= 10;
|
||||
v += c - '0';
|
||||
|
||||
digit = c - '0';
|
||||
if (v > 0xFFFFFFFFU - digit) {
|
||||
/* LCOV_EXCL_START */
|
||||
/* overflow */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
v += digit;
|
||||
|
||||
c = sgetc(f);
|
||||
}
|
||||
|
||||
|
@ -25,51 +25,51 @@
|
||||
/**
|
||||
* Locks used externally.
|
||||
*/
|
||||
#if HAVE_PTHREAD
|
||||
static pthread_mutex_t msg_lock;
|
||||
static pthread_mutex_t memory_lock;
|
||||
#if HAVE_THREAD
|
||||
static thread_mutex_t msg_lock;
|
||||
static thread_mutex_t memory_lock;
|
||||
#endif
|
||||
|
||||
void lock_msg(void)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_lock(&msg_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock_msg(void)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_unlock(&msg_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock_memory(void)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_lock(&memory_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock_memory(void)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_unlock(&memory_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock_init(void)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
/* initialize the locks as first operation as log_fatal depends on them */
|
||||
thread_mutex_init(&msg_lock, 0);
|
||||
thread_mutex_init(&memory_lock, 0);
|
||||
thread_mutex_init(&msg_lock);
|
||||
thread_mutex_init(&memory_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock_done(void)
|
||||
{
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
thread_mutex_destroy(&msg_lock);
|
||||
thread_mutex_destroy(&memory_lock);
|
||||
#endif
|
||||
@ -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);
|
||||
@ -1539,10 +1553,10 @@ int smartctl_flush(FILE* f, const char* file, const char* name)
|
||||
/****************************************************************************/
|
||||
/* thread */
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr)
|
||||
#if HAVE_THREAD
|
||||
void thread_mutex_init(thread_mutex_t* mutex)
|
||||
{
|
||||
if (pthread_mutex_init(mutex, attr) != 0) {
|
||||
if (pthread_mutex_init(mutex, 0) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Failed call to pthread_mutex_init().\n");
|
||||
os_abort();
|
||||
@ -1550,7 +1564,7 @@ void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_mutex_destroy(pthread_mutex_t* mutex)
|
||||
void thread_mutex_destroy(thread_mutex_t* mutex)
|
||||
{
|
||||
if (pthread_mutex_destroy(mutex) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1560,7 +1574,7 @@ void thread_mutex_destroy(pthread_mutex_t* mutex)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_mutex_lock(pthread_mutex_t* mutex)
|
||||
void thread_mutex_lock(thread_mutex_t* mutex)
|
||||
{
|
||||
if (pthread_mutex_lock(mutex) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1570,7 +1584,7 @@ void thread_mutex_lock(pthread_mutex_t* mutex)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_mutex_unlock(pthread_mutex_t* mutex)
|
||||
void thread_mutex_unlock(thread_mutex_t* mutex)
|
||||
{
|
||||
if (pthread_mutex_unlock(mutex) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1580,9 +1594,9 @@ void thread_mutex_unlock(pthread_mutex_t* mutex)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr)
|
||||
void thread_cond_init(thread_cond_t* cond)
|
||||
{
|
||||
if (pthread_cond_init(cond, attr) != 0) {
|
||||
if (pthread_cond_init(cond, 0) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Failed call to pthread_cond_init().\n");
|
||||
os_abort();
|
||||
@ -1590,7 +1604,7 @@ void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_cond_destroy(pthread_cond_t* cond)
|
||||
void thread_cond_destroy(thread_cond_t* cond)
|
||||
{
|
||||
if (pthread_cond_destroy(cond) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1600,7 +1614,7 @@ void thread_cond_destroy(pthread_cond_t* cond)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_cond_signal(pthread_cond_t* cond)
|
||||
void thread_cond_signal(thread_cond_t* cond)
|
||||
{
|
||||
if (pthread_cond_signal(cond) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1610,7 +1624,7 @@ void thread_cond_signal(pthread_cond_t* cond)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_cond_broadcast(pthread_cond_t* cond)
|
||||
void thread_cond_broadcast(thread_cond_t* cond)
|
||||
{
|
||||
if (pthread_cond_broadcast(cond) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1620,7 +1634,7 @@ void thread_cond_broadcast(pthread_cond_t* cond)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
|
||||
void thread_cond_wait(thread_cond_t* cond, thread_mutex_t* mutex)
|
||||
{
|
||||
if (pthread_cond_wait(cond, mutex) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
@ -1659,7 +1673,7 @@ void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
|
||||
*/
|
||||
int thread_cond_signal_outside = 0;
|
||||
|
||||
void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
|
||||
void thread_cond_signal_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex)
|
||||
{
|
||||
if (thread_cond_signal_outside) {
|
||||
/* without the thread checker unlock before signaling, */
|
||||
@ -1676,7 +1690,7 @@ void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
|
||||
}
|
||||
}
|
||||
|
||||
void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex)
|
||||
void thread_cond_broadcast_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex)
|
||||
{
|
||||
if (thread_cond_signal_outside) {
|
||||
/* without the thread checker unlock before signaling, */
|
||||
@ -1693,9 +1707,9 @@ void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mut
|
||||
}
|
||||
}
|
||||
|
||||
void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg)
|
||||
void thread_create(thread_id_t* thread, void* (* func)(void *), void *arg)
|
||||
{
|
||||
if (pthread_create(thread, attr, func, arg) != 0) {
|
||||
if (pthread_create(thread, 0, func, arg) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Failed call to pthread_create().\n");
|
||||
os_abort();
|
||||
@ -1703,7 +1717,7 @@ void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void
|
||||
}
|
||||
}
|
||||
|
||||
void thread_join(pthread_t thread, void** retval)
|
||||
void thread_join(thread_id_t thread, void** retval)
|
||||
{
|
||||
if (pthread_join(thread, retval) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
|
@ -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.
|
||||
@ -407,7 +413,7 @@ int smartctl_flush(FILE* f, const char* file, const char* name);
|
||||
/****************************************************************************/
|
||||
/* thread */
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
/**
|
||||
* Control when to signal the condition variables.
|
||||
*
|
||||
@ -420,19 +426,19 @@ extern int thread_cond_signal_outside;
|
||||
/**
|
||||
* Thread wrappers to handle error conditions.
|
||||
*/
|
||||
void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr);
|
||||
void thread_mutex_destroy(pthread_mutex_t* mutex);
|
||||
void thread_mutex_lock(pthread_mutex_t* mutex);
|
||||
void thread_mutex_unlock(pthread_mutex_t* mutex);
|
||||
void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr);
|
||||
void thread_cond_destroy(pthread_cond_t* cond);
|
||||
void thread_cond_signal(pthread_cond_t* cond);
|
||||
void thread_cond_broadcast(pthread_cond_t* cond);
|
||||
void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
|
||||
void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex);
|
||||
void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex);
|
||||
void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg);
|
||||
void thread_join(pthread_t thread, void** retval);
|
||||
void thread_mutex_init(thread_mutex_t* mutex);
|
||||
void thread_mutex_destroy(thread_mutex_t* mutex);
|
||||
void thread_mutex_lock(thread_mutex_t* mutex);
|
||||
void thread_mutex_unlock(thread_mutex_t* mutex);
|
||||
void thread_cond_init(thread_cond_t* cond);
|
||||
void thread_cond_destroy(thread_cond_t* cond);
|
||||
void thread_cond_signal(thread_cond_t* cond);
|
||||
void thread_cond_broadcast(thread_cond_t* cond);
|
||||
void thread_cond_wait(thread_cond_t* cond, thread_mutex_t* mutex);
|
||||
void thread_cond_signal_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex);
|
||||
void thread_cond_broadcast_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex);
|
||||
void thread_create(thread_id_t* thread, void* (* func)(void *), void *arg);
|
||||
void thread_join(thread_id_t thread, void** retval);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -440,9 +440,8 @@ struct snapraid_rehash {
|
||||
/**
|
||||
* Check if we have to process the specified block index ::i.
|
||||
*/
|
||||
static int block_is_enabled(void* void_plan, block_off_t i)
|
||||
static int block_is_enabled(struct snapraid_plan* plan, block_off_t i)
|
||||
{
|
||||
struct snapraid_plan* plan = void_plan;
|
||||
unsigned j;
|
||||
int one_invalid;
|
||||
int one_valid;
|
||||
@ -693,6 +692,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
||||
unsigned* waiting_map;
|
||||
unsigned waiting_mac;
|
||||
char esc_buffer[ESC_MAX];
|
||||
bit_vect_t* block_enabled;
|
||||
|
||||
/* the sync process assumes that all the hashes are correct */
|
||||
/* including the ones from CHG and DELETED blocks */
|
||||
@ -732,14 +732,18 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
||||
silent_error = 0;
|
||||
io_error = 0;
|
||||
|
||||
msg_progress("Selecting...\n");
|
||||
|
||||
/* first count the number of blocks to process */
|
||||
countmax = 0;
|
||||
plan.handle_max = diskmax;
|
||||
plan.handle_map = handle;
|
||||
plan.force_full = state->opt.force_full;
|
||||
block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */
|
||||
for (blockcur = blockstart; blockcur < blockmax; ++blockcur) {
|
||||
if (!block_is_enabled(&plan, blockcur))
|
||||
continue;
|
||||
bit_vect_set(block_enabled, blockcur);
|
||||
++countmax;
|
||||
}
|
||||
|
||||
@ -756,8 +760,10 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
||||
countsize = 0;
|
||||
countpos = 0;
|
||||
|
||||
msg_progress("Syncing...\n");
|
||||
|
||||
/* start all the worker threads */
|
||||
io_start(&io, blockstart, blockmax, &block_is_enabled, &plan);
|
||||
io_start(&io, blockstart, blockmax, block_enabled);
|
||||
|
||||
if (!state_progress_begin(state, blockstart, blockmax, countmax))
|
||||
goto end;
|
||||
@ -1413,6 +1419,7 @@ bail:
|
||||
free(failed_map);
|
||||
free(waiting_map);
|
||||
io_done(&io);
|
||||
free(block_enabled);
|
||||
|
||||
if (state->opt.expect_recoverable) {
|
||||
if (error + silent_error + io_error == 0)
|
||||
@ -1575,8 +1582,6 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
|
||||
log_fatal("WARNING! Skipped state write for --test-skip-content-write option.\n");
|
||||
}
|
||||
|
||||
msg_progress("Syncing...\n");
|
||||
|
||||
/* skip degenerated cases of empty parity, or skipping all */
|
||||
if (blockstart < blockmax) {
|
||||
ret = state_sync_process(state, parity_handle, blockstart, blockmax);
|
||||
|
@ -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
|
||||
@ -1325,12 +1325,12 @@ static int device_thread(tommy_list* list, void* (*func)(void* arg))
|
||||
int fail = 0;
|
||||
tommy_node* i;
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#if HAVE_THREAD
|
||||
/* start all threads */
|
||||
for (i = tommy_list_head(list); i != 0; i = i->next) {
|
||||
devinfo_t* devinfo = i->data;
|
||||
|
||||
thread_create(&devinfo->thread, 0, func, devinfo);
|
||||
thread_create(&devinfo->thread, func, devinfo);
|
||||
}
|
||||
|
||||
/* join all threads */
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef __UTIL_H
|
||||
#define __UTIL_H
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* memory */
|
||||
|
||||
@ -221,5 +222,34 @@ int lock_lock(const char* file);
|
||||
*/
|
||||
int lock_unlock(int f);
|
||||
|
||||
/****************************************************************************/
|
||||
/* bitvect */
|
||||
|
||||
typedef unsigned char bit_vect_t;
|
||||
#define BIT_VECT_SIZE (sizeof(bit_vect_t) * 8)
|
||||
|
||||
static inline size_t bit_vect_size(size_t max)
|
||||
{
|
||||
return (max + BIT_VECT_SIZE - 1) / BIT_VECT_SIZE;
|
||||
}
|
||||
|
||||
static inline void bit_vect_set(bit_vect_t* bit_vect, size_t off)
|
||||
{
|
||||
bit_vect_t mask = 1 << (off % BIT_VECT_SIZE);
|
||||
bit_vect[off / BIT_VECT_SIZE] |= mask;
|
||||
}
|
||||
|
||||
static inline void bit_vect_clear(bit_vect_t* bit_vect, size_t off)
|
||||
{
|
||||
bit_vect_t mask = 1 << (off % BIT_VECT_SIZE);
|
||||
bit_vect[off / BIT_VECT_SIZE] &= ~mask;
|
||||
}
|
||||
|
||||
static inline int bit_vect_test(bit_vect_t* bit_vect, size_t off)
|
||||
{
|
||||
bit_vect_t mask = 1 << (off % BIT_VECT_SIZE);
|
||||
return (bit_vect[off / BIT_VECT_SIZE] & mask) != 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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.5.
|
||||
# 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.5'
|
||||
PACKAGE_STRING='snapraid 11.5'
|
||||
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.5 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.5:";;
|
||||
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.5
|
||||
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.5, 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.5'
|
||||
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.5, 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.5
|
||||
snapraid config.status 12.2
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
56
configure.ac
56
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]))
|
||||
@ -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));
|
||||
|
693
debian/changelog
vendored
Normal file
693
debian/changelog
vendored
Normal file
@ -0,0 +1,693 @@
|
||||
snapraid (11.6-0) UNRELEASED; urgency=medium
|
||||
|
||||
* Bump
|
||||
* Bump
|
||||
|
||||
-- Mario Fetka <mario.fetka@gmail.com> Fri, 11 Sep 2020 13:42:38 +0200
|
||||
|
||||
snapraid (11.2-0tikhonov1) xenial; urgency=medium
|
||||
|
||||
[11.2 2017/12]
|
||||
* Fixed recognition of NTFS hardlinks. They behave differently than
|
||||
standard Unix hardlinks and this could result in SnapRAID reporting
|
||||
internal inconsistency errors for detecting links to the same file
|
||||
with different metadata attributes.
|
||||
* More efficient 'pool' command that updates only the links
|
||||
that need to be updated. This ensures that no change is
|
||||
done, avoiding to trigger a directory rescan of other programs.
|
||||
* In Linux use by default the advise "discard" mode instead of "flush".
|
||||
This avoids to swap-out the other process memory, leaving the system
|
||||
more responsive.
|
||||
* Changed the fallocate() use to work better with Btrfs with parity disks.
|
||||
* Changed the --test-io-stats screen to print the file name in process
|
||||
for each disk.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Wed, 18 Jul 2018 19:44:46 +0400
|
||||
|
||||
snapraid (11.1-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[11.1 2017/05]
|
||||
* Fixed the check command to correctly ignore errors on unused parity.
|
||||
This was broken in version 9.0.
|
||||
* Allow increasing the number of parity splits of existing parity.
|
||||
* Fixed quoting when printing in Linux. This fixes the UTF-8 screen
|
||||
output. Windows version was not affected.
|
||||
* Fixed recognition of 'hashsize' in the configuration file.
|
||||
The previous incorrect 'hash_size' is still supported for backward
|
||||
compatibility.
|
||||
* Fixed building in platforms that don't provide major/minor definitions
|
||||
in sys/types.h.
|
||||
* When creating 'pool' symbolic links, set their time as the linked files.
|
||||
* Added support for the Windows 10 symbolic link unprivileged creation,
|
||||
using SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE.
|
||||
* Windows binaries built with gcc 4.9.4 using the MXE cross compiler at
|
||||
commit ae56efa2b23a793b0146508bfef33027cdb09fd2 with targets
|
||||
i686-w64-mingw32 and x86_64-w64-mingw32 and optimization -O2.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Mon, 28 Aug 2017 12:41:29 +0400
|
||||
|
||||
snapraid (11.0-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[11.0 2016/11]
|
||||
* Added support for splitting the parity in multiple partitions. You
|
||||
can now specify multiple files for a single parity. As soon a file
|
||||
cannot grow anymore, the next one starts growing.
|
||||
In the configuration file, just put more files in the same 'parity'
|
||||
line, separated by , (comma).
|
||||
Note that if this feature is used, the saved content file won't be
|
||||
read by older SnapRAID versions.
|
||||
In Windows, 256 MB are left free in each disk to avoid the warning
|
||||
about full disks.
|
||||
* Added a new 'hashsize' configuration option. It could be useful in
|
||||
systems with low memory, to reduce the memory usage.
|
||||
Note that if this feature is used, the saved content file won't be
|
||||
read by older SnapRAID versions.
|
||||
* In Linux added the missing support for Btrfs file-systems. Note that
|
||||
to have full support you need also the 'libblkid' library, otherwise
|
||||
you won't get the UUIDs.
|
||||
* In screen messages don't print the disk directory in file path. You
|
||||
can control the format with the test option:
|
||||
--test-fmt file|disk|path.
|
||||
* In Windows allows to use the escape char '^' to handle file patterns
|
||||
containing real characters matching the globbing '*?[]' ones. In Unix
|
||||
it was already possible to do the same escaping with '\'.
|
||||
* Added a new -R, --force-realloc option to reallocate all the
|
||||
parity information keeping the precomputed hash.
|
||||
This is the previous -F, --force-full that instead now maintains the
|
||||
same parity organization and just recomputes it.
|
||||
* Added test options for selecting the file advise mode to use:
|
||||
--test-io-advise-none for standard mode
|
||||
--test-io-advise-sequential advise sequential access (Linux/Windows)
|
||||
--test-io-advise-flush flush cache after every operation (Linux)
|
||||
--test-io-advise-flush-window flush cache every 8 MB (Linux)
|
||||
--test-io-advise-discard discard cache after every operation (Linux)
|
||||
--test-io-advise-discard-window discard cache every 8 MB (Linux)
|
||||
--test-io-advise-direct use direct/unbuffered mode (Linux/Windows)
|
||||
The new default mode is 'flush' in Linux (before it was 'sequential'),
|
||||
and 'sequential' in Windows (like before).
|
||||
* For Seagate SMR (Shingled Magnetic Recording) ignore the SMART
|
||||
attribute Command_Timeout 188 as not reliable.
|
||||
* Fixed running in Windows platforms that miss the RtlGenRandom()
|
||||
function.
|
||||
* Added the --test-io-cache=1 option to disable the multi-thread IO
|
||||
mode.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Thu, 01 Dec 2016 16:25:21 +0400
|
||||
|
||||
snapraid (10.0-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[ 10.0 2016/02 ]
|
||||
* Boosts the speed of the 'sync' and 'scrub' commands with a new
|
||||
multi-thread implementation. It uses one thread for each disk,
|
||||
dedicated exclusively to read-ahead data and parity and to
|
||||
write-behind parity. This maximizes the data throughput keeping
|
||||
disks always busy.
|
||||
You can control the number of blocks to cache with the option
|
||||
--test-io-cache=NUMBER, where the number is between 3 and 128.
|
||||
The default is 8 MiB of blocks.
|
||||
You can show run-time stats during the process with the
|
||||
--test-io-stats option. You will see a graph with the number of
|
||||
cached blocks, and a graph with the wait time percentage for all the
|
||||
disks and computations.
|
||||
* The -h, --pre-hash command, saves the content file only after having
|
||||
verified all the hashes. This allows recovering of moved files in
|
||||
case a silent error is found during the hash verification check.
|
||||
* Allows to use the -d, --filter-disk option in the 'up' and 'down'
|
||||
commands.
|
||||
* Allows to run the 'smart' command without a configuration file.
|
||||
In such case it operates on all the disks of the machine.
|
||||
* In the configuration file 'data' is now a synonymous of 'disk'.
|
||||
* Adds the 'touch' command intended to arbitrarily set all the zero
|
||||
sub-second timestamps. This improves the SnapRAID capabilities to
|
||||
identify files. The 'status' command recommends to run 'touch' if
|
||||
required.
|
||||
* Restores the functionality of the -D, --force-device option when used
|
||||
to workaround the use of the same disk for two logical data drives
|
||||
when running the 'fix' command.
|
||||
* Uses a correct shell quoting in the example commands that involve
|
||||
files.
|
||||
* The minimum Windows version supported is now Windows Vista. This is
|
||||
required to use the native Windows thread support for the new
|
||||
multi-thread implementation. If you need to run on Windows XP, you
|
||||
have to stick on SnapRAID 9.x.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Sat, 05 Mar 2016 17:44:53 +0400
|
||||
|
||||
snapraid (9.3-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[ 9.3 2016/01 ]
|
||||
* Fixes an invalid assumption in the copy detection mechanism that
|
||||
could result in an internal inconsistency, and with the impossibility
|
||||
to run the 'sync' and 'diff' commands.
|
||||
This was triggered by a very specific pattern of identical files.
|
||||
At least three of them, with one already in the parity, and at a
|
||||
higher disk number than the others that should be instead new ones.
|
||||
This had no bad effect, if not preventing the 'sync' command to run.
|
||||
A workaround was to just run 'sync' one time with the -N,
|
||||
--force-nocopy option to disable the copy detection.
|
||||
* Restored the -O2 optimization option for Windows binaries, as -Og has
|
||||
a too big performance penality.
|
||||
|
||||
[ 9.2 2016/01 ]
|
||||
* Fixes support for symlinks pointing to an empty target. Before they
|
||||
were only partially supported, and their presence could result in a
|
||||
content file not readable.
|
||||
This also disables multi-thread content write, as this was the issue
|
||||
we tried to detect with this feature, and it doesn't provide a
|
||||
performance advantage. Content verification is instead still multi
|
||||
thread.
|
||||
* Autorename disks using the matching UUID. To rename a disk you can
|
||||
now change directly the name in the configuration file, and run a
|
||||
'sync' command.
|
||||
* Improves the physical offset ordering for the Btrfs file-system,
|
||||
correctly detecting files that have not a physical offset, for
|
||||
whatever reason.
|
||||
* Adds UUID support to Btrfs file-systems. It's present only if the
|
||||
'libblkid' development library is available on the system.
|
||||
Usually this requires to install the libblkid-dev or libblkid-devel
|
||||
package.
|
||||
* Added a new --no-warnings option to disable some repetitive warnings
|
||||
that could be annoying to power users.
|
||||
* Improves the error reporting, printing a complete stack trace, that
|
||||
can be used to track down bugs more easily.
|
||||
For this reason the Windows binaries are now built with optimization
|
||||
option -Og, instead than -O2.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Tue, 02 Feb 2016 12:59:13 +0400
|
||||
|
||||
snapraid (9.1-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[ 9.1 2015/11 ]
|
||||
* Fixes a bug when reading a content file with a deleted entry bigger
|
||||
than 4 GB. This was a regression introduced in version 9.0 that
|
||||
could result in the impossibility to read a valid content file,
|
||||
after a deletion of a file bigger than 4 GB in the array.
|
||||
If this happened to you, just upgrading to 9.1 fixes the issue, and
|
||||
it allows you to continue to work.
|
||||
Note that this bug only prevented to run 9.0, but your data was still
|
||||
protected and could have been recovered using the versions 8.1 or 9.1.
|
||||
* In Windows disables the file zero check requiring the --force-zero
|
||||
option. This check is intended for possible case using ext3/4 in Linux,
|
||||
and there is no evidence that in Windows it's possible at all.
|
||||
* Windows binaries built with gcc 4.9.3 using the MXE cross compiler at
|
||||
commit 62bcdbee56e87c81f1faa105b8777a5879d4e2e with targets
|
||||
i686-w64-mingw32 and x86_64-w64-mingw32 and optimization -O2.
|
||||
|
||||
[ 9.0 2015/11 ]
|
||||
* Fixes an invalid assumption that could happen when using the
|
||||
-e, --filter-error option with "fix" or "check".
|
||||
This was triggered by a very specific pattern of fragmented files
|
||||
and bad blocks combination, not so easy to reproduce.
|
||||
This had no bad effect, if not preventing the command to run.
|
||||
* Drastically reduces the memory usage. For each block, it now
|
||||
uses 17 bytes of memory, instead of the previous 28 bytes
|
||||
(for 32 bit) or 36 bytes (for 64 bit).
|
||||
This could result is a memory saving of up the 50%.
|
||||
* The -p, --plan option (old --percentage) can be used to
|
||||
define a scrub plan: "new", "bad" and "full".
|
||||
The "new" plan scrubs all the new synced blocks not yet scrubbed.
|
||||
This allows to verify as early as possible that the written
|
||||
parity during sync is really correct. You can use the "status"
|
||||
command to show the amount blocks not yet scrubbed.
|
||||
The "bad" plan scrubs only bad blocks.
|
||||
The "full" plan scrubs all blocks.
|
||||
* The graph in the "status" command now show scrubbed blocks
|
||||
with '*', and synced, but not yet scrubbed, blocks with 'o'.
|
||||
Note that when upgrading from a previous version, all blocks
|
||||
are assumed scrubbed the first time.
|
||||
* Content files are now written asyncronously from different
|
||||
threads to avoid the unfortunate condition that a memory
|
||||
error affects all of them in the same way.
|
||||
After writing, they are read again to verify their CRC.
|
||||
This is done to ensure thay they are really OK, even in the
|
||||
case of the worst possible silent errors.
|
||||
* Extends the -D, --force-device option to ignore more
|
||||
erroneous conditions in the 'fix' command, like unaccessible
|
||||
disks, or disks sharing the same physical device.
|
||||
* Extends the -d, --filter-disk option to allow to filter also
|
||||
by parity disk.
|
||||
* Extends the -h, --pre-hash option to also verify moved and
|
||||
copied files into the array before running a 'sync'.
|
||||
* Updates 'best' RAID functions for recent Atom CPUs.
|
||||
* Validates filters specifications rejecting relative paths.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Tue, 01 Dec 2015 23:50:52 +0400
|
||||
|
||||
snapraid (8.1-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[ 8.1 2015/05 ]
|
||||
* Fix build issues in generic Unix platforms, including Mac OS X.
|
||||
* The "diff" command returns with error code 2 if a "sync" is
|
||||
required, to differentiate with the generic error code 1.
|
||||
* Reduced the effect of SMART attribute 193 on the failure
|
||||
probability to avoid some false positive reports.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Sun, 17 May 2015 23:29:11 +0400
|
||||
|
||||
snapraid (8.0-0tikhonov1~trusty) trusty; urgency=medium
|
||||
|
||||
[ 8.0 2015/04 ]
|
||||
* Allows "sync" and "scrub" to continue after the first bunch of disk
|
||||
errors. Blocks with errors are marked as bad, and you can fix them
|
||||
with the "fix -e" command.
|
||||
The fix is expected to force the disk firmware to reallocate the
|
||||
bad sector, likely fixing the problem.
|
||||
You can control the number of allowed errors with the new
|
||||
-L, --error-limit option. The default is 100.
|
||||
* The -e, --filter-error option doesn't write anymore fixes to
|
||||
unsynced files. This helps in case you are running it on a not
|
||||
synced array, removing the risk to revert some files to an old state.
|
||||
* The -e, --filter-error option is now optimal and reads only the
|
||||
minimal amount of data necessary to fix the errors.
|
||||
* The "diff" command returns with an error code if a "sync" is
|
||||
required.
|
||||
* Adds new "smart" command to print a SMART report of the array.
|
||||
* Adds new "up" and "down" commands to spin up and down the disks of
|
||||
the array.
|
||||
* Adds new "devices" command to print the devices associations in
|
||||
the array.
|
||||
* Changes the log handling. If no log file is specified, all the
|
||||
warnings and not fatal errors messages goes to stderr. If a log file
|
||||
is specified, only fatal error messages are printed on the screen.
|
||||
You can control the amount of informative messages on stdout with
|
||||
the -q, --quiet and -v, --verbose options, that can be specified
|
||||
multiple times to be more quiet or verbose.
|
||||
* In the "status" command the "Wasted" column now shows a negative
|
||||
number for the amount of space that you can still waste without
|
||||
filling up the parity.
|
||||
* In the "status" and others commands we now use GB instead of GiB,
|
||||
when referring to disk space.
|
||||
* Renames the -s and -t options to -S and -B as they are intended to
|
||||
be manual only operations.
|
||||
* Windows binary built with gcc 4.8.1 using the MXE cross compiler 2.23,
|
||||
with targets i686-w64-mingw32 and x86_64-w64-mingw32. Before the x86
|
||||
target was i686-pc-mingw32.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Thu, 30 Apr 2015 23:01:55 +0400
|
||||
|
||||
snapraid (7.1-0tikhonov1~precise) precise; urgency=medium
|
||||
|
||||
[ 7.1 2015/01 ]
|
||||
* In 'scrub' and 'sync' detects and reports Input/Output errors
|
||||
separately from generic file system errors.
|
||||
* In 'diff' doesn't print the "add" entry if a "copy" one is already
|
||||
printed.
|
||||
* Fixes build with old compilers in the x64 platforms [Leigh Phillips].
|
||||
* Fixes out-of-dir builds [Christoph Junghans].
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Wed, 11 Mar 2015 20:36:58 +0400
|
||||
|
||||
snapraid (7.0-0tikhonov2~precise) precise; urgency=medium
|
||||
|
||||
[ 7.0 2014/11 ]
|
||||
* In 'check' and 'fix' the array is scanned to find any moved files
|
||||
that could be used to recover missing data. Files are identified by
|
||||
timestamp, and then they are recognized also if moved to a different
|
||||
disk. Note that even if there are false positive they are identified
|
||||
checking the hash, so they have not effect, besides making the
|
||||
process a little slower. To disable this new behaviour you can use
|
||||
the -N, --force-nocopy option.
|
||||
* The -i, --import command now identifies files by timestamp making it
|
||||
very fast in importing directories.
|
||||
* More detailed 'status' report with single disk stats and free space
|
||||
available.
|
||||
* A lot faster directory listing for Windows.
|
||||
* Adds AVX2 support to improve parity generation speed.
|
||||
* Prints the time spent waiting for each disk also in 'scrub'.
|
||||
* The CPU usage, speed and ETA estimations are now based on the last 100
|
||||
seconds rather than from the start.
|
||||
* Keeps track of the UUID of the parity disks to check them before
|
||||
operating.
|
||||
* Windows binary built with gcc 4.8.1 using the MXE cross compiler 2.23.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Thu, 27 Nov 2014 00:36:59 +0400
|
||||
|
||||
snapraid (6.2-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
[ 6.2 2014/5 ]
|
||||
* Fixed the regression test when run as root.
|
||||
* Added a new heuristic to detect file copies. Now a file is assumed
|
||||
to be a copy if name, size and nanosecond timestamp are matching,
|
||||
but if the nanosecond part of the timestamp is 0, it requires
|
||||
the full path matching and not only the name.
|
||||
* Added the -N, --force-nocopy option to disable completely
|
||||
the copy detection. SnapRAID also suggests to use this option
|
||||
in the error message of a data mismatch if likely caused by the
|
||||
copy detection.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Wed, 16 Jul 2014 01:01:09 +0400
|
||||
|
||||
snapraid (6.1-0tikhonov1~precise) precise; urgency=high
|
||||
|
||||
[ 6.1 2014/4 ]
|
||||
* Fix build and regression test in Mac OS X.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Tue, 22 Apr 2014 00:22:07 +0400
|
||||
|
||||
snapraid (6.0-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
[ 6.0 2014/3 ]
|
||||
* In "sync", even if a silent error is found, continue to update
|
||||
the parity if it's possible to correct the error.
|
||||
Note that the block will be marked bad, and the data
|
||||
will be fixed only at the next "fix -e" call.
|
||||
But any new data added will be protected if you are using
|
||||
enough parity to fix both the silent error and at least
|
||||
another potential error.
|
||||
* Detect copied files from one disk to another and reuse the already
|
||||
computed hash information to validate them in "sync".
|
||||
Files are assumed copied if they matches the name, size and timestamp.
|
||||
* For "sync", added a new -h, --pre-hash option to run a preliminary
|
||||
hashing step for all the new files to ensure to detect silent errors
|
||||
caused by the heavy machine usage of the parity computation.
|
||||
* In "fix", if a previous fixing attempt was made resulting in a
|
||||
.unrecoverable file, uses this file as starting point for the
|
||||
new attempt.
|
||||
* In the log file name allows the use of the '>>', %D, %T modifiers
|
||||
to select append mode, and to insert the date and time in the name.
|
||||
* The options -p, --percentage and -o, --older-than now keep their
|
||||
default value even if the other one is specified.
|
||||
* Moved the .lock file in the same dir of the first specified content
|
||||
file. This avoid to spin-up the parity disks in all commands.
|
||||
* The "diff", "list", "dup", "status" and "pool" commands don't access
|
||||
anymore the parity disks that can now stay powered down.
|
||||
* The default configuration file in Windows is now searched in the same
|
||||
directory where the snapraid.exe file resides.
|
||||
* New source code organization. The RAID engine is now
|
||||
an external component usable also in other projects.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Fri, 11 Apr 2014 02:43:52 +0400
|
||||
|
||||
snapraid (5.3-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
[ 5.3 2014/3 ]
|
||||
* Don't warn about UUID changed if it's for an empty disk.
|
||||
* Fixed the number of blocks that scrub has to process when
|
||||
selecting a high percentage of the array.
|
||||
* Removed duplicate recovery attempts in synced state.
|
||||
|
||||
[ 5.2 2013/12 ]
|
||||
* If a disk changes UUID, automatically disable the inode
|
||||
recognition, because this is likely a new filesystem with
|
||||
all the inodes reassigned, and we don't want to risk a false
|
||||
positive when searching for inode/timestamp/size.
|
||||
* Allow to run a fix command with disks that doesn't need to be
|
||||
fixed mounted as read-only.
|
||||
* After a failed sync, always reallocates new files with a not
|
||||
yet computed parity to ensure to minimize the parity usage,
|
||||
if some other file is deleted in the meantime.
|
||||
* Doesn't count empty dirs as files in the diff counters.
|
||||
* Added a new "share" configuration option to allow to share
|
||||
in the network the pool directory also in Windows.
|
||||
* Fixed build problems in OpenBSD due the old assembler.
|
||||
* Fixed build problems in platforms different than x86.
|
||||
|
||||
[ 5.1 2013/12 ]
|
||||
* Fixed a potential crash if a file is deleted during a "sync/scrub".
|
||||
This is a problem introduced in version 5.0 due new logging.
|
||||
If happened to you to have a crash in sync, you don't need to
|
||||
take any special action, just run "sync" again.
|
||||
* Restored the functionality of -C, --gen-conf command.
|
||||
* Prints the files with duplicate physical offset if the
|
||||
-v, --verbose option is specified.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Tue, 11 Mar 2014 18:56:46 +0400
|
||||
|
||||
snapraid (5.0-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog 4.4 ]
|
||||
* Added support for up to six levels of parity.
|
||||
* Added a specific and faster triple parity format for CPUs that
|
||||
don't support SSSE3 instructions like ARM and AMD Phenom, Athlon
|
||||
and Opteron.
|
||||
* Faster RAID5 and RAID6 implementation for ARM 64 bit CPUs.
|
||||
* If a silent error is found during a "sync" command, directly marks
|
||||
the block as bad like in "scrub", without stopping the the "sync"
|
||||
process.
|
||||
* Sort files by inode when listing the directory. This improves
|
||||
the scanning performance.
|
||||
* For files with changes only in some blocks, updates the parity
|
||||
only for blocks that really are changed.
|
||||
This improves the performance in sync for modified files.
|
||||
* Added a new "list" command to see the stored list of files.
|
||||
* Removed the detailed list of errors from the screen output.
|
||||
To get it you must explicitely use the -l, --log option.
|
||||
It's now too detailed for the screen, because it contains a lot
|
||||
of info.
|
||||
* Changed the output format of some commands to make it similar
|
||||
at the new "list" one.
|
||||
* Reduced memory usage removing some unnecessary allocations.
|
||||
* Added a memory test on the memory buffers used in sync/scrub/check/fix
|
||||
before using them.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Mon, 25 Nov 2013 15:58:37 +0400
|
||||
|
||||
snapraid (4.4-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog 4.4 ]
|
||||
* Relaxed the check about small parity files, to allow to recover after a
|
||||
failed sync before resizing the parity files.
|
||||
|
||||
[ Upstream changelog 4.3 ]
|
||||
* Fixed the scrub command with the -p0 option. Now it really scrubs only the
|
||||
blocks marked as bad and not the full array.
|
||||
|
||||
[ Upstream changelog 4.2 ]
|
||||
* Fixed the wrong warning about physical offsets not supported caused by files
|
||||
not having a real offset because too small. For example, in NTFS it's possible
|
||||
to store such files in the MFT. It's just a cosmetic change, and not a
|
||||
functional one.
|
||||
* Remove unexpected 'Restore' entries in the diff output when dealing with
|
||||
filesystem without persistent inodes like NTFS in Linux.
|
||||
* Added support for filenames containing newlines. This happens in Mac OS X.
|
||||
|
||||
[ Upstream changelog 4.1 ]
|
||||
* If the underline filesystem doesn't support the FIEMAP command, automatically
|
||||
fallback to use FIBMAP for sorting files.
|
||||
* Fixed the import of content files from previous version of SnapRAID that are
|
||||
the result of an incomplete sync.
|
||||
* Added a new -C, --gen-conf option to generate a dummy configuration file from
|
||||
the info in the content file. Just in case that you lose everything, except
|
||||
the content file.
|
||||
* At the end of sync/scrub/check/fix prints "Everything OK" if no error was found.
|
||||
This should make clear that everything is really OK.
|
||||
|
||||
[ Upstream changelog 4.0 ]
|
||||
* New 'scrub' command to periodically check the oldest blocks for silent
|
||||
errors without the need to scan the whole array.
|
||||
* New 'status' command to check the fragmentation, the last check time
|
||||
distribution, and the silent error status of the array.
|
||||
* Added the new Spooky hash. It's faster in 64 bit architectures. To
|
||||
convert you can use the new 'rehash' command.
|
||||
* Changed to a binary content file to improve speed and reduce size.
|
||||
* Removed the --find-by-name, -N option. Now it always searches
|
||||
by name if a file is not found searching by inode, automatically
|
||||
reassigning inodes in restored files without needing to sync
|
||||
again the file. This happens only if the file has the same path, size
|
||||
and timestamp at nanosecond precision.
|
||||
* Added a hash seed to make harder intentional collision attacks.
|
||||
* When inserting files for the first time, sort them by their physical
|
||||
address to improve read performance.
|
||||
* Optimized the cache use for the all the RAID computations.
|
||||
This improves a lot the RAID performance.
|
||||
* Better selection of the RAID6 implementation for different CPUs.
|
||||
* Added RAID5/RAID6 mmx and sse2 implementations with unrolling by 4.
|
||||
They are a little faster than the previous unroll by 2.
|
||||
* Added a lock file to avoid multiple running instances on the same array.
|
||||
The file is named as parity file adding the .lock extension.
|
||||
There is also the undocumented --test-skip-lock to avoid to check it.
|
||||
* Automatically ignores, with warning, mount points inside the array
|
||||
directory tree.
|
||||
* Changes the 'dup' output format to include the size of each duplicate file.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Fri, 01 Nov 2013 00:04:46 +0400
|
||||
|
||||
snapraid (3.2-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog 3.2 ]
|
||||
* Fix a directory creation problem in Windows when the "disk" option points to
|
||||
the root directory of a drive. Now SnapRAID won't complain about the
|
||||
inability to create such directory.
|
||||
If you encouter this problem when trying to recover your data, just upgrade
|
||||
to this version, and you'll be able to complete the recovering process.
|
||||
No need to upgrade for platforms different than Windows.
|
||||
|
||||
[ Upstream changelog 3.1 ]
|
||||
* Direct use of Windows API for disk access to improve error reporting.
|
||||
* If the 'fix' process is aborted, it removes all the new files partially
|
||||
recovered, to allow to reuse again the '-m, --filter-missing' flag.
|
||||
* In Windows don't exclude anymore system files. Only system directories are
|
||||
excluded.
|
||||
* In Windows applies filters in case insensitive way.
|
||||
* The Windows binaries are now built with gcc 4.7.2.
|
||||
* Reduced memory occupation for hardlinks and directories.
|
||||
* In 'dup' don't list file with 0 size.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Fri, 09 Aug 2013 17:43:06 +0400
|
||||
|
||||
snapraid (3.0-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Added pooling support with the new 'pool' command. It creates a virtual
|
||||
view of the array using symbolic links pointing to the original files.
|
||||
* Added a new -m, --filter-missing option that allow to undelete files,
|
||||
without checking/fixing the others.
|
||||
* Added a new -i, --import option to automatically import deleted files
|
||||
when fixing.
|
||||
* Added a new -l, --log option to save to disk the detailed log.
|
||||
* Added support also for hardlinks and empty directories.
|
||||
* Added support to save symlinks to files in Windows. Note that only the
|
||||
symlink is saved and not the linked file.
|
||||
Symlinks to dirs and junctions are still not supported in Windows.
|
||||
* Files without read permission generate an error instead of a warning.
|
||||
You now must explicitely exclude them in the configuration file with
|
||||
exclusion rules.
|
||||
* In 'check' and 'fix', if verbose is enabled, prints the result for each
|
||||
processed file.
|
||||
* Added an UUID check to detect when a disk is replaced, and to prevent
|
||||
unwanted disk swaps.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Wed, 03 Apr 2013 13:01:53 +0400
|
||||
|
||||
snapraid (2.1-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Checks for wrong empty fields in the configuration file.
|
||||
* Filter rules for files are not anymore applied to directories.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Mon, 28 Jan 2013 02:10:28 +0400
|
||||
|
||||
snapraid (2.0-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Added a new -a option to make the 'check' command to only check file hashes
|
||||
without checking the parity data.
|
||||
* Added a new -d option to filter by disk name.
|
||||
* The file modification time is now saved using nanosecond precision.
|
||||
This allows to restore the exact modification time in 'fix'.
|
||||
The new 'content' files written with this version are not backward
|
||||
compatible, but it's still possible to read the old 'content' format.
|
||||
* Fixed hard-links automatic exclusion. All the hardlinks after the first one
|
||||
are now correctly ignored.
|
||||
* If it isn't possible to grow a parity file, prints the list of files
|
||||
outside the maximum size allocated.
|
||||
* Autosave isn't triggered if we are near the end of the 'sync' process.
|
||||
* Before starting a 'sync', we wait for two seconds, to workaround the FAT
|
||||
limitation of having two seconds modification time precision.
|
||||
This a safe measure to be 100% sure to always detect file changes.
|
||||
* Always fill the memory after allocating it to avoid the OOM (Out Of Memory)
|
||||
killer in Linux.
|
||||
* Fixed compilation in Solaris/OpenIndiana for lacking both futimes()
|
||||
and futimens().
|
||||
* Now 'sync' ensures that the parity files are not too small to contain the
|
||||
just loaded data.
|
||||
* Removed the '-H,--filter-nohidden' option. It doesn't make sense to
|
||||
have it as command line option.
|
||||
You must use the 'nohidden' option in the configuration file.
|
||||
* When opening files in read-only mode, also specify the noatime flag,
|
||||
to avoid to update the file access time.
|
||||
* Exclude rules for files are now also applied to directories.
|
||||
This allows to excludes some file/directory without the need to call
|
||||
the stat() function on them.
|
||||
* The -N, --find-by-name option also ignores the nanosecond part of
|
||||
timestamps to work with copy programs not supporting nanoseconds.
|
||||
* Fixed deduplicated files handling in Windows Server 2012.
|
||||
* Removed MD5 support.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Thu, 06 Dec 2012 00:38:20 +0400
|
||||
|
||||
snapraid (1.13-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Fixed a Segmentation Fault when checking/fixing if there are three or
|
||||
more errors in a specific block.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Mon, 05 Nov 2012 16:31:22 +0400
|
||||
|
||||
snapraid (1.12-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release 1.12.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Fixed file renaming in Windows during a 'fix' command. This is only a
|
||||
Windows issue, no reason to upgrade for other platforms.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Thu, 20 Sep 2012 13:13:40 +0400
|
||||
|
||||
snapraid (1.11-0tikhonov1~precise) precise; urgency=high
|
||||
|
||||
* New upstream release 1.11.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Fixed again directories inclusion. Exclusion rules for directories were ignored.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Mon, 09 Jul 2012 19:06:01 +0400
|
||||
|
||||
snapraid (1.10-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release 1.10.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Fixed directory inclusion, in case the last rule is an "include" one.
|
||||
* Fixed very long paths in Windows. We now always use the special '\\?' prefix to remove the 260 chars limitation.
|
||||
* If a file is excluded, it prints explicitely which attribute caused the exclusion.
|
||||
* Automatically excludes also the temporary copy of content file, the one with the ".tmp" extension.
|
||||
* Avoid the Windows system to go in automatic sleep mode when running.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Sun, 01 Jul 2012 21:43:16 +0400
|
||||
|
||||
snapraid (1.9-0tikhonov1~precise) precise; urgency=low
|
||||
|
||||
* New upstream release 1.9.
|
||||
|
||||
[ Upstream changelog ]
|
||||
* Implemented a more sophisticated recovering in case a harddisk failure happens during a 'sync'
|
||||
command. When using RAID6 it improves the chances of recovering data after an aborted 'sync'.
|
||||
* Fixed the count of new files.
|
||||
* Added a new 'autosave' configuration option to save the intermediate 'sync' state.
|
||||
* Supported filesystems with read requests returning less data than requested.
|
||||
* In Windows ensures that the disk serial number is not zero.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Tue, 10 Apr 2012 17:31:51 +0400
|
||||
|
||||
snapraid (1.8-0tikhonov1~oneiric) oneiric; urgency=low
|
||||
|
||||
* New upstream release 1.8.
|
||||
|
||||
Upstream changelog:
|
||||
* Added a new "dup" command to find all the duplicate files.
|
||||
* Added a new option "--filter-nohidden" to exclude hidden files.
|
||||
* Faster and parallel writing of content files.
|
||||
* The example configuration files now put the content files in the data
|
||||
disks instead than in the parity disks.
|
||||
* Added a checksum at the content file to ensure its integrity.
|
||||
* Using fallocate() instead posix_fallocate() to avoid the very slow
|
||||
posix_fallocate() fallback of writing the whole file.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Sat, 17 Mar 2012 19:15:07 +0400
|
||||
|
||||
snapraid (1.7-0tikhonov2~oneiric) oneiric; urgency=low
|
||||
|
||||
* Fixed example snapraid.conf.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Sat, 24 Dec 2011 01:28:39 +0400
|
||||
|
||||
snapraid (1.7-0tikhonov1~oneiric) oneiric; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Maxim Tikhonov <flaterichd@gmail.com> Thu, 22 Dec 2011 19:46:17 +0400
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
||||
7
|
28
debian/control
vendored
Normal file
28
debian/control
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
Source: snapraid
|
||||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: Maxim Tikhonov <flaterichd@gmail.com>
|
||||
Build-Depends: debhelper (>= 7.0.0), autotools-dev
|
||||
Standards-Version: 3.9.2
|
||||
Homepage: http://snapraid.sourceforge.net/
|
||||
|
||||
Package: snapraid
|
||||
Architecture: any
|
||||
Depends:
|
||||
${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
Description: SnapRAID is a backup program for disk arrays.
|
||||
SnapRAID is a backup program for disk arrays.
|
||||
.
|
||||
SnapRAID stores redundancy information in the disk array, and it allows recovering from up to two disk failures.
|
||||
.
|
||||
SnapRAID is mainly targeted for a home media center, where you have a lot of big files that rarely change.
|
||||
.
|
||||
Beside the ability to recover from disk failures, the other features of SnapRAID are:
|
||||
- You can start using SnapRAID with already filled disks.
|
||||
- The disks of the array can have different sizes.
|
||||
- You can add more disks at any time.
|
||||
- If you accidentally delete some files in a disk, you can recover them.
|
||||
- If more than two disks fail, you lose the data only on the failed disks. All the data in the other disks is safe.
|
||||
- It doesn't lock-in your data. You can stop using SnapRAID at any time without the need to reformat or move data.
|
||||
- All your data is hashed to ensure data integrity and avoid silent corruption.
|
40
debian/copyright
vendored
Normal file
40
debian/copyright
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
Format: http://dep.debian.net/deps/dep5
|
||||
Name: snapraid
|
||||
Upstream-Name: snapraid
|
||||
Maintainer: Maxim Tikhonov <flaterichd@gmail.com>
|
||||
Source: http://sourceforge.net/projects/snapraid/files/
|
||||
|
||||
Files: *
|
||||
Copyright: 2011 Andrea Mazzoleni <amadvance@users.sourceforge.net>
|
||||
License: GPL-3
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL-3'.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2011 Maxim Tikhonov <flaterichd@gmail.com>
|
||||
License: GPL-2+
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
9
debian/docs
vendored
Normal file
9
debian/docs
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
AUTHORS
|
||||
CHECK
|
||||
COPYING
|
||||
HISTORY
|
||||
INSTALL
|
||||
README
|
||||
TODO
|
||||
snapraid.conf.example
|
||||
snapraid.txt
|
2
debian/install
vendored
Normal file
2
debian/install
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
debian/snapraid.conf etc
|
||||
snapraid usr/bin
|
1
debian/manpage.1
vendored
Symbolic link
1
debian/manpage.1
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../snapraid.1
|
21
debian/rules
vendored
Executable file
21
debian/rules
vendored
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
#
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
#
|
||||
# Modified to make a template file for a multi-binary package with separated
|
||||
# build-arch and build-indep targets by Bill Allombert 2001
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
# This has to be exported to make some magic below work.
|
||||
export DH_OPTIONS
|
||||
|
||||
|
||||
%:
|
||||
dh $@
|
86
debian/snapraid.conf
vendored
Normal file
86
debian/snapraid.conf
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
# Example configuration for snapraid
|
||||
|
||||
# Defines the file to use as parity storage
|
||||
# It must NOT be in a data disk
|
||||
# Format: "parity FILE_PATH"
|
||||
parity /mnt/diskp/snapraid.parity
|
||||
|
||||
# Defines the files to use as additional parity storage.
|
||||
# If specified, they enable the multiple failures protection
|
||||
# from two to six level of parity.
|
||||
# To enable, uncomment one parity file for each level of extra
|
||||
# protection required. Start from 2-parity, and follow in order.
|
||||
# It must NOT be in a data disk
|
||||
# Format: "X-parity FILE_PATH"
|
||||
#2-parity /mnt/diskq/snapraid.2-parity
|
||||
#3-parity /mnt/diskr/snapraid.3-parity
|
||||
#4-parity /mnt/disks/snapraid.4-parity
|
||||
#5-parity /mnt/diskt/snapraid.5-parity
|
||||
#6-parity /mnt/disku/snapraid.6-parity
|
||||
|
||||
# Defines the files to use as content list
|
||||
# You can use multiple specification to store more copies
|
||||
# You must have least one copy for each parity file plus one. Some more don't hurt
|
||||
# They can be in the disks used for data, parity or boot,
|
||||
# but each file must be in a different disk
|
||||
# Format: "content FILE_PATH"
|
||||
content /var/snapraid.content
|
||||
content /mnt/disk1/snapraid.content
|
||||
content /mnt/disk2/snapraid.content
|
||||
|
||||
# Defines the data disks to use
|
||||
# The name and mount point association is relevant for parity, do not change it
|
||||
# WARNING: Adding here your /home, /var or /tmp disks is NOT a good idea!
|
||||
# SnapRAID is better suited for files that rarely changes!
|
||||
# Format: "disk DISK_NAME DISK_MOUNT_POINT"
|
||||
data d1 /mnt/disk1/
|
||||
data d2 /mnt/disk2/
|
||||
data d3 /mnt/disk3/
|
||||
|
||||
# Excludes hidden files and directories (uncomment to enable).
|
||||
#nohidden
|
||||
|
||||
# Defines files and directories to exclude
|
||||
# Remember that all the paths are relative at the mount points
|
||||
# Format: "exclude FILE"
|
||||
# Format: "exclude DIR/"
|
||||
# Format: "exclude /PATH/FILE"
|
||||
# Format: "exclude /PATH/DIR/"
|
||||
exclude *.unrecoverable
|
||||
exclude /tmp/
|
||||
exclude /lost+found/
|
||||
|
||||
# Defines the block size in kibi bytes (1024 bytes) (uncomment to enable).
|
||||
# Default value is 256 -> 256 kibi bytes -> 262144 bytes
|
||||
# Format: "blocksize SIZE_IN_KiB"
|
||||
#blocksize 256
|
||||
|
||||
# Automatically save the state when syncing after the specified amount
|
||||
# of GB processed (uncomment to enable).
|
||||
# This option is useful to avoid to restart from scratch long 'sync'
|
||||
# commands interrupted by a machine crash.
|
||||
# It also improves the recovering if a disk break during a 'sync'.
|
||||
# Default value is 0, meaning disabled.
|
||||
# Format: "autosave SIZE_IN_GB"
|
||||
#autosave 500
|
||||
|
||||
# Defines the pooling directory where the virtual view of the disk
|
||||
# array is created using the "pool" command (uncomment to enable).
|
||||
# The files are not really copied here, but just linked using
|
||||
# symbolic links.
|
||||
# This directory must be outside the array.
|
||||
# Format: "pool DIR"
|
||||
#pool /pool
|
||||
|
||||
# Defines a custom smartctl command to obtain the SMART attributes
|
||||
# for each disk. This may be required for RAID controllers and for
|
||||
# some USB disk that cannot be autodetected.
|
||||
# In the specified options, the "%s" string is replaced by the device name.
|
||||
# Refers at the smartmontools documentation about the possible options:
|
||||
# RAID -> https://www.smartmontools.org/wiki/Supported_RAID-Controllers
|
||||
# USB -> https://www.smartmontools.org/wiki/Supported_USB-Devices
|
||||
#smartctl d1 -d sat %s
|
||||
#smartctl d2 -d usbjmicron %s
|
||||
#smartctl parity -d areca,1/1 /dev/sg0
|
||||
#smartctl 2-parity -d areca,2/1 /dev/sg0
|
||||
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
2
debian/watch
vendored
Normal file
2
debian/watch
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
version=3
|
||||
https://github.com/amadvance/snapraid/releases .*snapraid-([0-9.]*\.[0-9.]*).tar.gz
|
@ -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:
|
||||
*
|
||||
|
15
snapraid.1
15
snapraid.1
@ -1041,9 +1041,9 @@ Note that it cannot be used with \[dq]sync\[dq] and \[dq]scrub\[dq], because the
|
||||
process the whole array.
|
||||
.TP
|
||||
.B \-e, \-\-filter\-error
|
||||
Filters the blocks to process in \[dq]check\[dq] and \[dq]fix\[dq].
|
||||
It processes only the blocks marked with silent or input/output
|
||||
errors during \[dq]sync\[dq] and \[dq]scrub\[dq], and listed in \[dq]status\[dq].
|
||||
Process the files with errors in \[dq]check\[dq] and \[dq]fix\[dq].
|
||||
It processes only files that have blocks marked with silent
|
||||
or input/output errors during \[dq]sync\[dq] and \[dq]scrub\[dq], and listed in \[dq]status\[dq].
|
||||
This option can be used only with \[dq]check\[dq] and \[dq]fix\[dq].
|
||||
.TP
|
||||
.B \-p, \-\-plan PERC|bad|new|full
|
||||
@ -1152,10 +1152,10 @@ option allows to resolve them.
|
||||
This option can be used only with \[dq]sync\[dq], \[dq]check\[dq] and \[dq]fix\[dq].
|
||||
.TP
|
||||
.B \-F, \-\-force\-full
|
||||
In \[dq]sync\[dq] forces a full rebuild of the parity.
|
||||
In \[dq]sync\[dq] forces a full recomputation of the parity.
|
||||
This option can be used when you add a new parity level, or if
|
||||
you reverted back to an old content file using a more recent parity data.
|
||||
Instead of recomputing the parity from scratch, this allows
|
||||
Instead of recreating the parity from scratch, this allows
|
||||
to reuse the hashes present in the content file to validate data,
|
||||
and to maintain data protection during the \[dq]sync\[dq] process using
|
||||
the parity data you have.
|
||||
@ -1166,9 +1166,10 @@ In \[dq]sync\[dq] forces a full reallocation of files and rebuild of the parity.
|
||||
This option can be used to completely reallocate all the files
|
||||
removing the fragmentation, but reusing the hashes present in the content
|
||||
file to validate data.
|
||||
Compared to \-F, \-\-force\-full, this option reallocates all the parity
|
||||
not having data protection during the operation.
|
||||
This option can be used only with \[dq]sync\[dq].
|
||||
WARNING! This option is for experts only, and it\'s highly
|
||||
recommended to not use it.
|
||||
You DO NOT have data protection during the \[dq]sync\[dq] operation.
|
||||
.TP
|
||||
.B \-l, \-\-log FILE
|
||||
Write a detailed log in the specified file.
|
||||
|
15
snapraid.d
15
snapraid.d
@ -737,9 +737,9 @@ Options
|
||||
process the whole array.
|
||||
|
||||
-e, --filter-error
|
||||
Filters the blocks to process in "check" and "fix".
|
||||
It processes only the blocks marked with silent or input/output
|
||||
errors during "sync" and "scrub", and listed in "status".
|
||||
Process the files with errors in "check" and "fix".
|
||||
It processes only files that have blocks marked with silent
|
||||
or input/output errors during "sync" and "scrub", and listed in "status".
|
||||
This option can be used only with "check" and "fix".
|
||||
|
||||
-p, --plan PERC|bad|new|full
|
||||
@ -848,10 +848,10 @@ Options
|
||||
This option can be used only with "sync", "check" and "fix".
|
||||
|
||||
-F, --force-full
|
||||
In "sync" forces a full rebuild of the parity.
|
||||
In "sync" forces a full recomputation of the parity.
|
||||
This option can be used when you add a new parity level, or if
|
||||
you reverted back to an old content file using a more recent parity data.
|
||||
Instead of recomputing the parity from scratch, this allows
|
||||
Instead of recreating the parity from scratch, this allows
|
||||
to reuse the hashes present in the content file to validate data,
|
||||
and to maintain data protection during the "sync" process using
|
||||
the parity data you have.
|
||||
@ -862,9 +862,10 @@ Options
|
||||
This option can be used to completely reallocate all the files
|
||||
removing the fragmentation, but reusing the hashes present in the content
|
||||
file to validate data.
|
||||
Compared to -F, --force-full, this option reallocates all the parity
|
||||
not having data protection during the operation.
|
||||
This option can be used only with "sync".
|
||||
WARNING! This option is for experts only, and it's highly
|
||||
recommended to not use it.
|
||||
You DO NOT have data protection during the "sync" operation.
|
||||
|
||||
-l, --log FILE
|
||||
Write a detailed log in the specified file.
|
||||
|
15
snapraid.txt
15
snapraid.txt
@ -794,9 +794,9 @@ SnapRAID provides the following options:
|
||||
process the whole array.
|
||||
|
||||
-e, --filter-error
|
||||
Filters the blocks to process in "check" and "fix".
|
||||
It processes only the blocks marked with silent or input/output
|
||||
errors during "sync" and "scrub", and listed in "status".
|
||||
Process the files with errors in "check" and "fix".
|
||||
It processes only files that have blocks marked with silent
|
||||
or input/output errors during "sync" and "scrub", and listed in "status".
|
||||
This option can be used only with "check" and "fix".
|
||||
|
||||
-p, --plan PERC|bad|new|full
|
||||
@ -905,10 +905,10 @@ SnapRAID provides the following options:
|
||||
This option can be used only with "sync", "check" and "fix".
|
||||
|
||||
-F, --force-full
|
||||
In "sync" forces a full rebuild of the parity.
|
||||
In "sync" forces a full recomputation of the parity.
|
||||
This option can be used when you add a new parity level, or if
|
||||
you reverted back to an old content file using a more recent parity data.
|
||||
Instead of recomputing the parity from scratch, this allows
|
||||
Instead of recreating the parity from scratch, this allows
|
||||
to reuse the hashes present in the content file to validate data,
|
||||
and to maintain data protection during the "sync" process using
|
||||
the parity data you have.
|
||||
@ -919,9 +919,10 @@ SnapRAID provides the following options:
|
||||
This option can be used to completely reallocate all the files
|
||||
removing the fragmentation, but reusing the hashes present in the content
|
||||
file to validate data.
|
||||
Compared to -F, --force-full, this option reallocates all the parity
|
||||
not having data protection during the operation.
|
||||
This option can be used only with "sync".
|
||||
WARNING! This option is for experts only, and it's highly
|
||||
recommended to not use it.
|
||||
You DO NOT have data protection during the "sync" operation.
|
||||
|
||||
-l, --log FILE
|
||||
Write a detailed log in the specified 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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user