From 9f2a32a8fd08bb1b48f29c88bfa398fa4eb5f2a4 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 6 Jun 2018 11:59:16 +0200
Subject: [PATCH 159/173] fallocate: backport v2.32-164-g641af90dc
* add --dig-holes
* add --collapse-range
* add --insert-range
* add --zero-range
For backward compatibility with previous RHEL7 versions we keep
O_CREAT for open(). The current upstream uses O_CREAT only when
necessary.
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1528567
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/fallocate.1 | 195 ++++++++++++++++++++++------
sys-utils/fallocate.c | 349 +++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 428 insertions(+), 116 deletions(-)
diff --git a/sys-utils/fallocate.1 b/sys-utils/fallocate.1
index 376353013..d4821dcd1 100644
--- a/sys-utils/fallocate.1
+++ b/sys-utils/fallocate.1
@@ -1,72 +1,185 @@
-.\" -*- nroff -*-
-.TH FALLOCATE 1 "September 2011" "util-linux" "User Commands"
+.TH FALLOCATE 1 "April 2014" "util-linux" "User Commands"
.SH NAME
-fallocate \- preallocate space to a file
+fallocate \- preallocate or deallocate space to a file
.SH SYNOPSIS
.B fallocate
-.RB [ \-n ]
-.RB [ \-p ]
+.RB [ \-c | \-p | \-z ]
.RB [ \-o
.IR offset ]
.B \-l
-.IR length
+.I length
+.RB [ \-n ]
+.I filename
+.PP
+.B fallocate \-d
+.RB [ \-o
+.IR offset ]
+.RB [ \-l
+.IR length ]
.I filename
.PP
.B fallocate \-x
.RB [ \-o
.IR offset ]
-.RB \-l
-.IR length
+.B \-l
+.I length
.I filename
.SH DESCRIPTION
.B fallocate
-is used to preallocate blocks to a file. For filesystems which support the
-fallocate system call, this is done quickly by allocating blocks and marking
-them as uninitialized, requiring no IO to the data blocks. This is much faster
-than creating a file by filling it with zeros.
-.PP
-As of the Linux Kernel v2.6.31, the fallocate system call is supported by the
-btrfs, ext4, ocfs2, and xfs filesystems.
+is used to manipulate the allocated disk space for a file,
+either to deallocate or preallocate it.
+For filesystems which support the fallocate system call,
+preallocation is done quickly by allocating blocks and marking them as
+uninitialized, requiring no IO to the data blocks.
+This is much faster than creating a file by filling it with zeroes.
.PP
The exit code returned by
.B fallocate
is 0 on success and 1 on failure.
-.PP
.SH OPTIONS
-The \fIlength\fR and \fIoffset\fR arguments may be followed by the multiplicative
-suffixes KiB=1024, MiB=1024*1024, and so on for GiB, TiB, PiB, EiB, ZiB and YiB
-(the "iB" is optional, e.g. "K" has the same meaning as "KiB") or the suffixes
-KB=1000, MB=1000*1000, and so on for GB, TB, PB, EB, ZB and YB.
-.IP "\fB\-n, \-\-keep-size\fP"
+The
+.I length
+and
+.I offset
+arguments may be followed by the multiplicative suffixes KiB (=1024),
+MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB, and YiB (the "iB" is
+optional, e.g., "K" has the same meaning as "KiB") or the suffixes
+KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB, and YB.
+.PP
+The options
+.BR \-\-collapse\-range ", " \-\-dig\-holes ", " \-\-punch\-hole ,
+and
+.B \-\-zero\-range
+are mutually exclusive.
+.TP
+.BR \-c ", " \-\-collapse\-range
+Removes a byte range from a file, without leaving a hole.
+The byte range to be collapsed starts at
+.I offset
+and continues for
+.I length
+bytes.
+At the completion of the operation,
+the contents of the file starting at the location
+.IR offset + length
+will be appended at the location
+.IR offset ,
+and the file will be
+.I length
+bytes smaller.
+The option
+.B \-\-keep\-size
+may not be specified for the collapse-range operation.
+.sp
+Available since Linux 3.15 for ext4 (only for extent-based files) and XFS.
+.TP
+.BR \-d ", " \-\-dig\-holes
+Detect and dig holes.
+This makes the file sparse in-place, without using extra disk space.
+The minimum size of the hole depends on filesystem I/O block size
+(usually 4096 bytes).
+Also, when using this option,
+.B \-\-keep\-size
+is implied. If no range is specified by
+.B \-\-offset
+and
+.BR \-\-length ,
+then the entire file is analyzed for holes.
+.sp
+You can think of this option as doing a
+.RB """" "cp \-\-sparse" """"
+and then renaming the destination file to the original,
+without the need for extra disk space.
+.sp
+See \fB\-\-punch\-hole\fP for a list of supported filesystems.
+.TP
+.BR \-i ", " \-\-insert\-range
+Insert a hole of
+.I length
+bytes from
+.IR offset ,
+shifting existing data.
+.TP
+.BR \-l ", " "\-\-length " \fIlength
+Specifies the length of the range, in bytes.
+.TP
+.BR \-n ", " \-\-keep\-size
Do not modify the apparent length of the file. This may effectively allocate
blocks past EOF, which can be removed with a truncate.
-.IP "\fB\-p, \-\-punch-hole\fP"
-Punch holes in the file, the range should not exceed the length of the file.
-.IP "\fB\-o, \-\-offset\fP \fIoffset\fP
-Specifies the beginning offset of the allocation, in bytes.
-.IP "\fB\-l, \-\-length\fP \fIlength\fP
-Specifies the length of the allocation, in bytes.
-.IP "\fB\-x , \-\-posix\fP
-Enable POSIX operation mode. In that mode allocation operation always completes,
-but it may take longer time when fast allocation is not supported by the underlying filesystem.
-.IP "\fB\-h, \-\-help\fP"
-Print help and exit.
-.IP "\fB-V, \-\-version"
-Print version and exit.
+.TP
+.BR \-o ", " "\-\-offset " \fIoffset
+Specifies the beginning offset of the range, in bytes.
+.TP
+.BR \-p ", " \-\-punch\-hole
+Deallocates space (i.e., creates a hole) in the byte range starting at
+.I offset
+and continuing for
+.I length
+bytes.
+Within the specified range, partial filesystem blocks are zeroed,
+and whole filesystem blocks are removed from the file.
+After a successful call,
+subsequent reads from this range will return zeroes.
+This option may not be specified at the same time as the
+.B \-\-zero\-range
+option.
+Also, when using this option,
+.B \-\-keep\-size
+is implied.
+.sp
+Supported for XFS (since Linux 2.6.38), ext4 (since Linux 3.0),
+Btrfs (since Linux 3.7) and tmpfs (since Linux 3.5).
+.TP
+.BR \-v ", " \-\-verbose
+Enable verbose mode.
+.TP
+.BR \-x ", " \-\-posix
+Enable POSIX operation mode.
+In that mode allocation operation always completes,
+but it may take longer time when fast allocation is not supported by
+the underlying filesystem.
+.TP
+.BR \-z ", " \-\-zero\-range
+Zeroes space in the byte range starting at
+.I offset
+and continuing for
+.I length
+bytes.
+Within the specified range, blocks are preallocated for the regions
+that span the holes in the file.
+After a successful call,
+subsequent reads from this range will return zeroes.
+.sp
+Zeroing is done within the filesystem preferably by converting the
+range into unwritten extents. This approach means that the specified
+range will not be physically zeroed out on the device (except for
+partial blocks at the either end of the range), and I/O is
+(otherwise) required only to update metadata.
+.sp
+Option \fB\-\-keep\-size\fP can be specified to prevent file length
+modification.
+.sp
+Available since Linux 3.14 for ext4 (only for extent-based files) and XFS.
+.TP
+.BR \-V ", " \-\-version
+Display version information and exit.
+.TP
+.BR \-h ", " \-\-help
+Display help text and exit.
.SH AUTHORS
-.UR sandeen@redhat.com
+.MT sandeen@redhat.com
Eric Sandeen
-.UE
+.ME
.br
-.UR kzak@redhat.com
+.MT kzak@redhat.com
Karel Zak
-.UE
+.ME
.SH SEE ALSO
+.BR truncate (1),
.BR fallocate (2),
-.BR posix_fallocate (3),
-.BR truncate (1)
+.BR posix_fallocate (3)
.SH AVAILABILITY
The fallocate command is part of the util-linux package and is available from
-.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+.UR https://\:www.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
Linux Kernel Archive
.UE .
diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c
index 17ae5fe69..75d89a7a9 100644
--- a/sys-utils/fallocate.c
+++ b/sys-utils/fallocate.c
@@ -23,6 +23,7 @@
*/
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/mman.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -31,50 +32,110 @@
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
+#include <string.h>
#ifndef HAVE_FALLOCATE
# include <sys/syscall.h>
#endif
-#ifdef HAVE_LINUX_FALLOC_H
-# include <linux/falloc.h> /* for FALLOC_FL_* flags */
+#if defined(HAVE_LINUX_FALLOC_H) && \
+ (!defined(FALLOC_FL_KEEP_SIZE) || !defined(FALLOC_FL_PUNCH_HOLE) || \
+ !defined(FALLOC_FL_COLLAPSE_RANGE) || !defined(FALLOC_FL_ZERO_RANGE) || \
+ !defined(FALLOC_FL_INSERT_RANGE))
+# include <linux/falloc.h> /* non-libc fallback for FALLOC_FL_* flags */
#endif
+
#ifndef FALLOC_FL_KEEP_SIZE
-# define FALLOC_FL_KEEP_SIZE 1
+# define FALLOC_FL_KEEP_SIZE 0x1
#endif
#ifndef FALLOC_FL_PUNCH_HOLE
-# define FALLOC_FL_PUNCH_HOLE 2
+# define FALLOC_FL_PUNCH_HOLE 0x2
+#endif
+
+#ifndef FALLOC_FL_COLLAPSE_RANGE
+# define FALLOC_FL_COLLAPSE_RANGE 0x8
+#endif
+
+#ifndef FALLOC_FL_ZERO_RANGE
+# define FALLOC_FL_ZERO_RANGE 0x10
+#endif
+
+#ifndef FALLOC_FL_INSERT_RANGE
+# define FALLOC_FL_INSERT_RANGE 0x20
#endif
#include "nls.h"
#include "strutils.h"
#include "c.h"
#include "closestream.h"
+#include "xalloc.h"
#include "optutils.h"
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static int verbose;
+static char *filename;
+
+static void __attribute__((__noreturn__)) usage(void)
{
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out,
_(" %s [options] <filename>\n"), program_invocation_short_name);
+
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Preallocate space to, or deallocate space from a file.\n"), out);
+
fputs(USAGE_OPTIONS, out);
- fputs(_(" -n, --keep-size don't modify the length of the file\n"
- " -p, --punch-hole punch holes in the file\n"
- " -o, --offset <num> offset of the allocation, in bytes\n"
- " -l, --length <num> length of the allocation, in bytes\n"), out);
+ fputs(_(" -c, --collapse-range remove a range from the file\n"), out);
+ fputs(_(" -d, --dig-holes detect zeroes and replace with holes\n"), out);
+ fputs(_(" -i, --insert-range insert a hole at range, shifting existing data\n"), out);
+ fputs(_(" -l, --length <num> length for range operations, in bytes\n"), out);
+ fputs(_(" -n, --keep-size maintain the apparent size of the file\n"), out);
+ fputs(_(" -o, --offset <num> offset for range operations, in bytes\n"), out);
+ fputs(_(" -p, --punch-hole replace a range with a hole (implies -n)\n"), out);
+ fputs(_(" -z, --zero-range zero and ensure allocation of a range\n"), out);
#ifdef HAVE_POSIX_FALLOCATE
- fputs(_(" -x, --posix use posix_fallocate(3) instead of fallocate(2)\n"), out);
+ fputs(_(" -x, --posix use posix_fallocate(3) instead of fallocate(2)\n"), out);
#endif
+ fputs(_(" -v, --verbose verbose mode\n"), out);
+
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
- fprintf(out, USAGE_MAN_TAIL("fallocate(1)"));
+ printf(USAGE_HELP_OPTIONS(22));
+
+ printf(USAGE_MAN_TAIL("fallocate(1)"));
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
+static loff_t cvtnum(char *s)
+{
+ uintmax_t x;
+
+ if (strtosize(s, &x))
+ return -1LL;
+
+ return x;
+}
+
+static void xfallocate(int fd, int mode, off_t offset, off_t length)
+{
+ int error;
+#ifdef HAVE_FALLOCATE
+ error = fallocate(fd, mode, offset, length);
+#else
+ error = syscall(SYS_fallocate, fd, mode, offset, length);
+#endif
+ /*
+ * EOPNOTSUPP: The FALLOC_FL_KEEP_SIZE is unsupported
+ * ENOSYS: The filesystem does not support sys_fallocate
+ */
+ if (error < 0) {
+ if ((mode & FALLOC_FL_KEEP_SIZE) && errno == EOPNOTSUPP)
+ errx(EXIT_FAILURE, _("fallocate failed: keep size mode is unsupported"));
+ err(EXIT_FAILURE, _("fallocate failed"));
+ }
+}
#ifdef HAVE_POSIX_FALLOCATE
static void xposix_fallocate(int fd, off_t offset, off_t length)
@@ -86,41 +147,163 @@ static void xposix_fallocate(int fd, off_t offset, off_t length)
}
#endif
+/* The real buffer size has to be bufsize + sizeof(uintptr_t) */
+static int is_nul(void *buf, size_t bufsize)
+{
+ typedef uintptr_t word;
+ void const *vp;
+ char const *cbuf = buf, *cp;
+ word const *wp = buf;
-static loff_t cvtnum(char *s)
+ /* set sentinel */
+ memset((char *) buf + bufsize, '\1', sizeof(word));
+
+ /* Find first nonzero *word*, or the word with the sentinel. */
+ while (*wp++ == 0)
+ continue;
+
+ /* Find the first nonzero *byte*, or the sentinel. */
+ vp = wp - 1;
+ cp = vp;
+
+ while (*cp++ == 0)
+ continue;
+
+ return cbuf + bufsize < cp;
+}
+
+static void dig_holes(int fd, off_t file_off, off_t len)
{
- uintmax_t x;
+ off_t file_end = len ? file_off + len : 0;
+ off_t hole_start = 0, hole_sz = 0;
+ uintmax_t ct = 0;
+ size_t bufsz;
+ char *buf;
+ struct stat st;
+#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
+ off_t cache_start = file_off;
+ /*
+ * We don't want to call POSIX_FADV_DONTNEED to discard cached
+ * data in PAGE_SIZE steps. IMHO it's overkill (too many syscalls).
+ *
+ * Let's assume that 1MiB (on system with 4K page size) is just
+ * a good compromise.
+ * -- kzak Feb-2014
+ */
+ const size_t cachesz = getpagesize() * 256;
+#endif
- if (strtosize(s, &x))
- return -1LL;
+ if (fstat(fd, &st) != 0)
+ err(EXIT_FAILURE, _("stat of %s failed"), filename);
- return x;
+ bufsz = st.st_blksize;
+
+ if (lseek(fd, file_off, SEEK_SET) < 0)
+ err(EXIT_FAILURE, _("seek on %s failed"), filename);
+
+ /* buffer + extra space for is_nul() sentinel */
+ buf = xmalloc(bufsz + sizeof(uintptr_t));
+ while (file_end == 0 || file_off < file_end) {
+ /*
+ * Detect data area (skip holes)
+ */
+ off_t end, off;
+
+ off = lseek(fd, file_off, SEEK_DATA);
+ if ((off == -1 && errno == ENXIO) ||
+ (file_end && off >= file_end))
+ break;
+
+ end = lseek(fd, off, SEEK_HOLE);
+ if (file_end && end > file_end)
+ end = file_end;
+
+#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
+ posix_fadvise(fd, off, end, POSIX_FADV_SEQUENTIAL);
+#endif
+ /*
+ * Dig holes in the area
+ */
+ while (off < end) {
+ ssize_t rsz = pread(fd, buf, bufsz, off);
+ if (rsz < 0 && errno)
+ err(EXIT_FAILURE, _("%s: read failed"), filename);
+ if (end && rsz > 0 && off > end - rsz)
+ rsz = end - off;
+ if (rsz <= 0)
+ break;
+
+ if (is_nul(buf, rsz)) {
+ if (!hole_sz) /* new hole detected */
+ hole_start = off;
+ hole_sz += rsz;
+ } else if (hole_sz) {
+ xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
+ hole_start, hole_sz);
+ ct += hole_sz;
+ hole_sz = hole_start = 0;
+ }
+
+#if defined(POSIX_FADV_DONTNEED) && defined(HAVE_POSIX_FADVISE)
+ /* discard cached data */
+ if (off - cache_start > (off_t) cachesz) {
+ size_t clen = off - cache_start;
+
+ clen = (clen / cachesz) * cachesz;
+ posix_fadvise(fd, cache_start, clen, POSIX_FADV_DONTNEED);
+ cache_start = cache_start + clen;
+ }
+#endif
+ off += rsz;
+ }
+ if (hole_sz) {
+ xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
+ hole_start, hole_sz);
+ ct += hole_sz;
+ }
+ file_off = off;
+ }
+
+ free(buf);
+
+ if (verbose) {
+ char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, ct);
+ fprintf(stdout, _("%s: %s (%ju bytes) converted to sparse holes.\n"),
+ filename, str, ct);
+ free(str);
+ }
}
int main(int argc, char **argv)
{
- char *fname;
int c;
- int error = 0;
int fd;
int mode = 0;
- int posix = 0;
+ int dig = 0;
+ int posix = 0;
loff_t length = -2LL;
loff_t offset = 0;
static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "version", 0, 0, 'V' },
- { "keep-size", 0, 0, 'n' },
- { "punch-hole", 0, 0, 'p' },
- { "offset", 1, 0, 'o' },
- { "length", 1, 0, 'l' },
- { "posix", 0, 0, 'x' },
- { NULL, 0, 0, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "keep-size", no_argument, NULL, 'n' },
+ { "punch-hole", no_argument, NULL, 'p' },
+ { "collapse-range", no_argument, NULL, 'c' },
+ { "dig-holes", no_argument, NULL, 'd' },
+ { "insert-range", no_argument, NULL, 'i' },
+ { "zero-range", no_argument, NULL, 'z' },
+ { "offset", required_argument, NULL, 'o' },
+ { "length", required_argument, NULL, 'l' },
+ { "posix", no_argument, NULL, 'x' },
+ { "verbose", no_argument, NULL, 'v' },
+ { NULL, 0, NULL, 0 }
};
- static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
- { 'x', 'n', 'p' },
+ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
+ { 'c', 'd', 'p', 'z' },
+ { 'c', 'n' },
+ { 'x', 'c', 'd', 'i', 'n', 'p', 'z'},
{ 0 }
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
@@ -130,29 +313,39 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
atexit(close_stdout);
- while ((c = getopt_long(argc, argv, "hVnpl:o:x", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "hvVncpdizxl:o:", longopts, NULL))
+ != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
switch(c) {
case 'h':
- usage(stdout);
+ usage();
break;
- case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
- case 'p':
- mode |= FALLOC_FL_PUNCH_HOLE;
- /* fall through */
- case 'n':
- mode |= FALLOC_FL_KEEP_SIZE;
+ case 'c':
+ mode |= FALLOC_FL_COLLAPSE_RANGE;
+ break;
+ case 'd':
+ dig = 1;
+ break;
+ case 'i':
+ mode |= FALLOC_FL_INSERT_RANGE;
break;
case 'l':
length = cvtnum(optarg);
break;
+ case 'n':
+ mode |= FALLOC_FL_KEEP_SIZE;
+ break;
case 'o':
offset = cvtnum(optarg);
break;
+ case 'p':
+ mode |= FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+ break;
+ case 'z':
+ mode |= FALLOC_FL_ZERO_RANGE;
+ break;
case 'x':
#ifdef HAVE_POSIX_FALLOCATE
posix = 1;
@@ -160,53 +353,59 @@ int main(int argc, char **argv)
#else
errx(EXIT_FAILURE, _("posix_fallocate support is not compiled"))
#endif
- default:
- usage(stderr);
+ case 'v':
+ verbose++;
break;
+ case 'V':
+ printf(UTIL_LINUX_VERSION);
+ return EXIT_SUCCESS;
+ default:
+ errtryhelp(EXIT_FAILURE);
}
}
- if (length == -2LL)
- errx(EXIT_FAILURE, _("no length argument specified"));
- if (length <= 0)
- errx(EXIT_FAILURE, _("invalid length value specified"));
- if (offset < 0)
- errx(EXIT_FAILURE, _("invalid offset value specified"));
if (optind == argc)
- errx(EXIT_FAILURE, _("no filename specified."));
+ errx(EXIT_FAILURE, _("no filename specified"));
+
+ filename = argv[optind++];
- fname = argv[optind++];
+ if (optind != argc)
+ errx(EXIT_FAILURE, _("unexpected number of arguments"));
- if (optind != argc) {
- warnx(_("unexpected number of arguments"));
- usage(stderr);
+ if (dig) {
+ /* for --dig-holes the default is analyze all file */
+ if (length == -2LL)
+ length = 0;
+ if (length < 0)
+ errx(EXIT_FAILURE, _("invalid length value specified"));
+ } else {
+ /* it's safer to require the range specification (--length --offset) */
+ if (length == -2LL)
+ errx(EXIT_FAILURE, _("no length argument specified"));
+ if (length <= 0)
+ errx(EXIT_FAILURE, _("invalid length value specified"));
}
+ if (offset < 0)
+ errx(EXIT_FAILURE, _("invalid offset value specified"));
- fd = open(fname, O_WRONLY|O_CREAT, 0644);
+ /* O_CREAT makes sense only for the default fallocate(2) behavior
+ * when mode is no specified and new space is allocated
+ *
+ * RHEL7.6: for backward compatibility in RHEL7 we keep O_CREAT there.
+ */
+ fd = open(filename, O_RDWR | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd < 0)
- err(EXIT_FAILURE, _("cannot open %s"), fname);
+ err(EXIT_FAILURE, _("cannot open %s"), filename);
+ if (dig)
+ dig_holes(fd, offset, length);
#ifdef HAVE_POSIX_FALLOCATE
- if (posix)
+ else if (posix)
xposix_fallocate(fd, offset, length);
- else
#endif
-
-#ifdef HAVE_FALLOCATE
- error = fallocate(fd, mode, offset, length);
-#else
- error = syscall(SYS_fallocate, fd, mode, offset, length);
-#endif
- /*
- * EOPNOTSUPP: The FALLOC_FL_KEEP_SIZE is unsupported
- * ENOSYS: The filesystem does not support sys_fallocate
- */
- if (error < 0) {
- if ((mode & FALLOC_FL_KEEP_SIZE) && errno == EOPNOTSUPP)
- errx(EXIT_FAILURE,
- _("keep size mode (-n option) unsupported"));
- err(EXIT_FAILURE, _("%s: fallocate failed"), fname);
- }
+ else
+ xfallocate(fd, mode, offset, length);
close(fd);
return EXIT_SUCCESS;
--
2.14.4