diff --git a/HISTORY b/HISTORY index 56804129..e4fb74c9 100644 --- a/HISTORY +++ b/HISTORY @@ -1,7 +1,7 @@ SnapRAID HISTORY ================ -1.8 2011/12 +1.8 2012/1 =========== * Added a new "dup" command to find all the duplicate files. * Added a new option "--filter-nohidden" to exclude hidden files. @@ -9,6 +9,8 @@ SnapRAID HISTORY * 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. 1.7 2011/11 =========== diff --git a/configure.ac b/configure.ac index 2e120692..19c2485b 100644 --- a/configure.ac +++ b/configure.ac @@ -43,7 +43,7 @@ dnl Checks for library functions. AC_SYS_LARGEFILE AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul]) AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf]) -AC_CHECK_FUNCS([ftruncate fsync access posix_fallocate posix_fadvise pread pwrite getc_unlocked ferror_unlocked fnmatch]) +AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise pread pwrite getc_unlocked ferror_unlocked fnmatch]) dnl Checks for architecture AC_C_BIGENDIAN diff --git a/parity.c b/parity.c index 3211f94f..f86bacb4 100644 --- a/parity.c +++ b/parity.c @@ -73,9 +73,25 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t s parity->valid_size = parity->st.st_size; if (parity->st.st_size < size) { -#if HAVE_POSIX_FALLOCATE - /* allocate real space */ - ret = posix_fallocate(parity->f, 0, size); +#if HAVE_FALLOCATE + /* allocate real space using the specific Linux fallocate() operation. */ + /* If the underline filesystem doesn't support it, it's going to fail with the ENOSYS error. */ + /* Note that posix_fallocate() doesn't fail in such case, and fallbacks to write the whole file. */ + ret = fallocate(parity->f, 0, 0, size); + + /* fallocate() returns the error number, and it doesn't set errno, just like posix_fallocate() */ + /* It's not clear if this is correct or a bug, as the official manpage says otherwise */ + /* http://www.kernel.org/doc/man-pages/online/pages/man2/fallocate.2.html */ + if (ret > 0) { /* if an error is returned, move it to errno */ + errno = ret; + ret = -1; + } + + /* if the operation is not supported, like in ext3 */ + if (errno == EOPNOTSUPP || errno == ENOSYS) { + /* fallback using ftruncate() */ + ret = ftruncate(parity->f, size); + } #else /* allocate using a sparse file */ ret = ftruncate(parity->f, size);