|
|
6c3643 |
diff -up scrub-2.6.1/libscrub/Makefile.am.extent-only scrub-2.6.1/libscrub/Makefile.am
|
|
|
6c3643 |
--- scrub-2.6.1/libscrub/Makefile.am.extent-only 2014-08-20 17:33:43.000000000 -0400
|
|
|
6c3643 |
+++ scrub-2.6.1/libscrub/Makefile.am 2021-02-22 14:24:32.439635010 -0500
|
|
|
6c3643 |
@@ -13,6 +13,7 @@ libscrub_la_SOURCES = \
|
|
|
6c3643 |
libscrub.c \
|
|
|
6c3643 |
scrub.h \
|
|
|
6c3643 |
../src/aes.c \
|
|
|
6c3643 |
+ ../src/fextent_apply.c \
|
|
|
6c3643 |
../src/filldentry.c \
|
|
|
6c3643 |
../src/fillfile.c \
|
|
|
6c3643 |
../src/genrand.c \
|
|
|
6c3643 |
diff -up scrub-2.6.1/man/scrub.1.in.extent-only scrub-2.6.1/man/scrub.1.in
|
|
|
6c3643 |
--- scrub-2.6.1/man/scrub.1.in.extent-only 2014-08-20 17:33:43.000000000 -0400
|
|
|
6c3643 |
+++ scrub-2.6.1/man/scrub.1.in 2021-02-22 14:24:32.439635010 -0500
|
|
|
6c3643 |
@@ -110,6 +110,13 @@ Do everything but write to targets.
|
|
|
6c3643 |
.TP
|
|
|
6c3643 |
\fI-h\fR, \fI--help\fR
|
|
|
6c3643 |
Print a summary of command line options on stderr.
|
|
|
6c3643 |
+.TP
|
|
|
6c3643 |
+\fI-E\fR, \fI--extent-only\fR
|
|
|
6c3643 |
+When scrubbing regular files, scrub only the file extents. This option is
|
|
|
6c3643 |
+useful in combination with large sparse files. If used, scrub will skip
|
|
|
6c3643 |
+the holes in the sparse file. Use this option with caution, the result may not
|
|
|
6c3643 |
+be compliant with cited standards and information about the actual on-disk
|
|
|
6c3643 |
+data allocation may leak since only the allocated parts will be scrubbed.
|
|
|
6c3643 |
.SH SCRUB METHODS
|
|
|
6c3643 |
.TP
|
|
|
6c3643 |
.I "nnsa"
|
|
|
6c3643 |
diff -up scrub-2.6.1/src/fextent_apply.c.extent-only scrub-2.6.1/src/fextent_apply.c
|
|
|
6c3643 |
--- scrub-2.6.1/src/fextent_apply.c.extent-only 2021-02-22 14:24:32.439635010 -0500
|
|
|
6c3643 |
+++ scrub-2.6.1/src/fextent_apply.c 2021-02-22 14:25:20.590843156 -0500
|
|
|
6c3643 |
@@ -0,0 +1,142 @@
|
|
|
6c3643 |
+/*
|
|
|
6c3643 |
+ * Copyright 2021 Red Hat, Inc.
|
|
|
6c3643 |
+ * All Rights Reserved.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * This program is free software; you can redistribute it and/or
|
|
|
6c3643 |
+ * modify it under the terms of the GNU General Public License
|
|
|
6c3643 |
+ * as published by the Free Software Foundation; either version
|
|
|
6c3643 |
+ * 2 of the License, or (at your option) any later version.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * This program is distributed in the hope that it will be useful,
|
|
|
6c3643 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
6c3643 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
6c3643 |
+ * General Public License for more details.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * You should have received a copy of the GNU General Public License
|
|
|
6c3643 |
+ * along with this program. If not, see:
|
|
|
6c3643 |
+ * <https://www.gnu.org/licenses/>.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * Authors:
|
|
|
6c3643 |
+ * Daniel Kopecek <dkopecek@redhat.com>
|
|
|
6c3643 |
+ */
|
|
|
6c3643 |
+#include <stdio.h>
|
|
|
6c3643 |
+#include <stdint.h>
|
|
|
6c3643 |
+#include <stdlib.h>
|
|
|
6c3643 |
+#include <string.h>
|
|
|
6c3643 |
+#include <unistd.h>
|
|
|
6c3643 |
+#include <errno.h>
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+#include <sys/types.h>
|
|
|
6c3643 |
+#include <sys/stat.h>
|
|
|
6c3643 |
+#include <sys/ioctl.h>
|
|
|
6c3643 |
+#include <sys/file.h>
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+#include <linux/fs.h>
|
|
|
6c3643 |
+#include <linux/fiemap.h>
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+#ifndef NDEBUG
|
|
|
6c3643 |
+# define dP(...) \
|
|
|
6c3643 |
+ do { int __tmp_errno = errno; \
|
|
|
6c3643 |
+ fprintf(stderr, "DEBUG: "__VA_ARGS__); \
|
|
|
6c3643 |
+ errno = __tmp_errno; \
|
|
|
6c3643 |
+ } while(0)
|
|
|
6c3643 |
+#else
|
|
|
6c3643 |
+# define dP(...) while(0)
|
|
|
6c3643 |
+#endif
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+int fextent_apply(int fd, int (*function)(int, struct fiemap_extent *, void *), void *arg)
|
|
|
6c3643 |
+{
|
|
|
6c3643 |
+ int ret = -1;
|
|
|
6c3643 |
+ struct stat st;
|
|
|
6c3643 |
+ struct fiemap *em;
|
|
|
6c3643 |
+ uint32_t extent_count, i;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ // lock, sync, stat
|
|
|
6c3643 |
+ if (flock(fd, LOCK_EX) != 0) {
|
|
|
6c3643 |
+ dP("flock(%d, LOCK_EX) failed: %s, %d.\n", fd, strerror(errno), errno);
|
|
|
6c3643 |
+ return -1;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (fsync(fd) != 0) {
|
|
|
6c3643 |
+ dP("fsync(%d) failed: %s, %d.\n", fd, strerror(errno), errno);
|
|
|
6c3643 |
+ goto exit_1;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (fstat(fd, &st) != 0) {
|
|
|
6c3643 |
+ dP("fstat(%d) failed: %s, %d.\n", fd, strerror(errno), errno);
|
|
|
6c3643 |
+ goto exit_1;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ /*
|
|
|
6c3643 |
+ * fiemap => get extent count
|
|
|
6c3643 |
+ */
|
|
|
6c3643 |
+ em = malloc(sizeof(struct fiemap));
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (em == NULL) {
|
|
|
6c3643 |
+ dP("malloc(%zu) returned NULL!\n", sizeof(struct fiemap));
|
|
|
6c3643 |
+ goto exit_1;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ memset(em, 0, sizeof(struct fiemap));
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ em->fm_start = 0;
|
|
|
6c3643 |
+ em->fm_length = st.st_size;
|
|
|
6c3643 |
+ em->fm_extent_count = 0;
|
|
|
6c3643 |
+ em->fm_mapped_extents = 0;
|
|
|
6c3643 |
+ em->fm_flags = 0;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (ioctl(fd, FS_IOC_FIEMAP, em) != 0) {
|
|
|
6c3643 |
+ dP("FS_IOC_FIEMAP: %s, %d.\n", strerror(errno), errno);
|
|
|
6c3643 |
+ goto exit_0;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ extent_count = em->fm_mapped_extents;
|
|
|
6c3643 |
+ free(em);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ /*
|
|
|
6c3643 |
+ * fiemap => get extents
|
|
|
6c3643 |
+ */
|
|
|
6c3643 |
+ em = malloc (sizeof(struct fiemap)
|
|
|
6c3643 |
+ + (sizeof(struct fiemap_extent) * extent_count));
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (em == NULL) {
|
|
|
6c3643 |
+ dP("malloc(%zu) returned NULL!\n", sizeof(struct fiemap)
|
|
|
6c3643 |
+ + (sizeof (struct fiemap_extent) * extent_count));
|
|
|
6c3643 |
+ goto exit_0;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ memset(em, 0, sizeof(struct fiemap)
|
|
|
6c3643 |
+ + (sizeof(struct fiemap_extent) * extent_count));
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ em[0].fm_start = 0;
|
|
|
6c3643 |
+ em[0].fm_length = st.st_size;
|
|
|
6c3643 |
+ em[0].fm_extent_count = extent_count;
|
|
|
6c3643 |
+ em[0].fm_flags = 0;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (ioctl(fd, FS_IOC_FIEMAP, em) != 0) {
|
|
|
6c3643 |
+ dP("FS_IOC_FIEMAP: %s, %d.\n", strerror(errno), errno);
|
|
|
6c3643 |
+ goto exit_0;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ for (i = 0; i < extent_count; ++i) {
|
|
|
6c3643 |
+ // seek to extent start
|
|
|
6c3643 |
+ if (lseek(fd, em->fm_extents[i].fe_logical, SEEK_SET) == (off_t)-1) {
|
|
|
6c3643 |
+ dP("lseek(%d, %llu, SET) failed: %s, %d.\n",
|
|
|
6c3643 |
+ fd, em->fm_extents[i].fe_logical, strerror(errno), errno);
|
|
|
6c3643 |
+ goto exit_0;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ ret = function(fd, em->fm_extents + i, arg);
|
|
|
6c3643 |
+ if (ret != 0)
|
|
|
6c3643 |
+ goto exit_0;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ ret = 0;
|
|
|
6c3643 |
+ exit_0:
|
|
|
6c3643 |
+ // release resources
|
|
|
6c3643 |
+ free (em);
|
|
|
6c3643 |
+ exit_1:
|
|
|
6c3643 |
+ // unlock
|
|
|
6c3643 |
+ if (flock(fd, LOCK_UN) != 0)
|
|
|
6c3643 |
+ ret = -1;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ return ret;
|
|
|
6c3643 |
+}
|
|
|
6c3643 |
diff -up scrub-2.6.1/src/fextent_apply.h.extent-only scrub-2.6.1/src/fextent_apply.h
|
|
|
6c3643 |
--- scrub-2.6.1/src/fextent_apply.h.extent-only 2021-02-22 14:24:32.439635010 -0500
|
|
|
6c3643 |
+++ scrub-2.6.1/src/fextent_apply.h 2021-02-22 14:24:32.439635010 -0500
|
|
|
6c3643 |
@@ -0,0 +1,30 @@
|
|
|
6c3643 |
+/*
|
|
|
6c3643 |
+ * Copyright 2021 Red Hat, Inc.
|
|
|
6c3643 |
+ * All Rights Reserved.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * This program is free software; you can redistribute it and/or
|
|
|
6c3643 |
+ * modify it under the terms of the GNU General Public License
|
|
|
6c3643 |
+ * as published by the Free Software Foundation; either version
|
|
|
6c3643 |
+ * 2 of the License, or (at your option) any later version.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * This program is distributed in the hope that it will be useful,
|
|
|
6c3643 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
6c3643 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
6c3643 |
+ * General Public License for more details.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * You should have received a copy of the GNU General Public License
|
|
|
6c3643 |
+ * along with this program. If not, see:
|
|
|
6c3643 |
+ * <https://www.gnu.org/licenses/>.
|
|
|
6c3643 |
+ *
|
|
|
6c3643 |
+ * Authors:
|
|
|
6c3643 |
+ * Daniel Kopecek <dkopecek@redhat.com>
|
|
|
6c3643 |
+ */
|
|
|
6c3643 |
+#ifndef FEXTENT_APPLY_H
|
|
|
6c3643 |
+#define FEXTENT_APPLY_H
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+#include <linux/fs.h>
|
|
|
6c3643 |
+#include <linux/fiemap.h>
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+int fextent_apply(int fd, int (*function)(int, struct fiemap_extent *, void *), void *arg);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+#endif /* FEXTENT_APPLY_H */
|
|
|
6c3643 |
diff -up scrub-2.6.1/src/fillfile.c.extent-only scrub-2.6.1/src/fillfile.c
|
|
|
6c3643 |
--- scrub-2.6.1/src/fillfile.c.extent-only 2014-08-20 17:33:43.000000000 -0400
|
|
|
6c3643 |
+++ scrub-2.6.1/src/fillfile.c 2021-02-22 14:24:32.439635010 -0500
|
|
|
6c3643 |
@@ -41,6 +41,7 @@
|
|
|
6c3643 |
|
|
|
6c3643 |
#include "util.h"
|
|
|
6c3643 |
#include "fillfile.h"
|
|
|
6c3643 |
+#include "fextent_apply.h"
|
|
|
6c3643 |
|
|
|
6c3643 |
static int no_threads = 0;
|
|
|
6c3643 |
|
|
|
6c3643 |
@@ -56,6 +57,20 @@ struct memstruct {
|
|
|
6c3643 |
|
|
|
6c3643 |
extern char *prog;
|
|
|
6c3643 |
|
|
|
6c3643 |
+struct fillfile_args {
|
|
|
6c3643 |
+ char *path;
|
|
|
6c3643 |
+ off_t filesize;
|
|
|
6c3643 |
+ unsigned char *mem;
|
|
|
6c3643 |
+ int memsize;
|
|
|
6c3643 |
+ progress_t progress;
|
|
|
6c3643 |
+ void *arg;
|
|
|
6c3643 |
+ refill_t refill;
|
|
|
6c3643 |
+ unsigned char *buf;
|
|
|
6c3643 |
+};
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+int fillextent(int fd, struct fiemap_extent *extent, void *pa);
|
|
|
6c3643 |
+int checkextent(int fd, struct fiemap_extent *extent, void *pa);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
#if defined(O_DIRECT) && (defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN))
|
|
|
6c3643 |
# define MY_O_DIRECT O_DIRECT
|
|
|
6c3643 |
#else
|
|
|
6c3643 |
@@ -154,11 +169,12 @@ refill_fini(struct memstruct *mp)
|
|
|
6c3643 |
* If 'sparse' is true, only scrub first and last blocks (for testing).
|
|
|
6c3643 |
* The number of bytes written is returned.
|
|
|
6c3643 |
* If 'creat' is true, open with O_CREAT and allow ENOSPC to be non-fatal.
|
|
|
6c3643 |
+ * If 'extentonly' is true, fill only file extents with the given pattern.
|
|
|
6c3643 |
*/
|
|
|
6c3643 |
off_t
|
|
|
6c3643 |
fillfile(char *path, off_t filesize, unsigned char *mem, int memsize,
|
|
|
6c3643 |
progress_t progress, void *arg, refill_t refill,
|
|
|
6c3643 |
- bool sparse, bool creat)
|
|
|
6c3643 |
+ bool sparse, bool creat, bool extentonly)
|
|
|
6c3643 |
{
|
|
|
6c3643 |
int fd = -1;
|
|
|
6c3643 |
off_t n;
|
|
|
6c3643 |
@@ -178,34 +194,52 @@ fillfile(char *path, off_t filesize, uns
|
|
|
6c3643 |
}
|
|
|
6c3643 |
if (fd < 0)
|
|
|
6c3643 |
goto error;
|
|
|
6c3643 |
- do {
|
|
|
6c3643 |
- if (written + memsize > filesize)
|
|
|
6c3643 |
- memsize = filesize - written;
|
|
|
6c3643 |
- if (refill && !sparse) {
|
|
|
6c3643 |
- if (!mp)
|
|
|
6c3643 |
- if (refill_init(&mp, refill, memsize) < 0)
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- if (refill_memcpy(mp, mem, memsize, filesize, written) < 0)
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- }
|
|
|
6c3643 |
- if (sparse && !(written == 0) && !(written + memsize == filesize)) {
|
|
|
6c3643 |
- if (lseek(fd, memsize, SEEK_CUR) < 0)
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- written += memsize;
|
|
|
6c3643 |
- } else {
|
|
|
6c3643 |
- n = write_all(fd, mem, memsize);
|
|
|
6c3643 |
- if (creat && n < 0 && errno == ENOSPC)
|
|
|
6c3643 |
- break;
|
|
|
6c3643 |
- if (n == 0) {
|
|
|
6c3643 |
- errno = EINVAL; /* write past end of device? */
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- } else if (n < 0)
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- written += n;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (extentonly) {
|
|
|
6c3643 |
+ struct fillfile_args fa;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ fa.path = path;
|
|
|
6c3643 |
+ fa.filesize = filesize;
|
|
|
6c3643 |
+ fa.mem = mem;
|
|
|
6c3643 |
+ fa.memsize = memsize;
|
|
|
6c3643 |
+ fa.progress = progress;
|
|
|
6c3643 |
+ fa.refill = refill;
|
|
|
6c3643 |
+ fa.arg = arg;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (fextent_apply(fd, fillextent, &fa) == 0) {
|
|
|
6c3643 |
+ written = filesize;
|
|
|
6c3643 |
}
|
|
|
6c3643 |
- if (progress)
|
|
|
6c3643 |
- progress(arg, (double)written/filesize);
|
|
|
6c3643 |
- } while (written < filesize);
|
|
|
6c3643 |
+ } else {
|
|
|
6c3643 |
+ do {
|
|
|
6c3643 |
+ if (written + memsize > filesize)
|
|
|
6c3643 |
+ memsize = filesize - written;
|
|
|
6c3643 |
+ if (refill && !sparse) {
|
|
|
6c3643 |
+ if (!mp)
|
|
|
6c3643 |
+ if (refill_init(&mp, refill, memsize) < 0)
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ if (refill_memcpy(mp, mem, memsize, filesize, written) < 0)
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (sparse && !(written == 0) && !(written + memsize == filesize)) {
|
|
|
6c3643 |
+ if (lseek(fd, memsize, SEEK_CUR) < 0)
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ written += memsize;
|
|
|
6c3643 |
+ } else {
|
|
|
6c3643 |
+ n = write_all(fd, mem, memsize);
|
|
|
6c3643 |
+ if (creat && n < 0 && errno == ENOSPC)
|
|
|
6c3643 |
+ break;
|
|
|
6c3643 |
+ if (n == 0) {
|
|
|
6c3643 |
+ errno = EINVAL; /* write past end of device? */
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ } else if (n < 0)
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ written += n;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (progress)
|
|
|
6c3643 |
+ progress(arg, (double)written/filesize);
|
|
|
6c3643 |
+ } while (written < filesize);
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
if (fsync(fd) < 0) {
|
|
|
6c3643 |
if (errno != EINVAL)
|
|
|
6c3643 |
goto error;
|
|
|
6c3643 |
@@ -232,7 +266,7 @@ error:
|
|
|
6c3643 |
*/
|
|
|
6c3643 |
off_t
|
|
|
6c3643 |
checkfile(char *path, off_t filesize, unsigned char *mem, int memsize,
|
|
|
6c3643 |
- progress_t progress, void *arg, bool sparse)
|
|
|
6c3643 |
+ progress_t progress, void *arg, bool sparse, bool extentonly)
|
|
|
6c3643 |
{
|
|
|
6c3643 |
int fd = -1;
|
|
|
6c3643 |
off_t n;
|
|
|
6c3643 |
@@ -240,8 +274,6 @@ checkfile(char *path, off_t filesize, un
|
|
|
6c3643 |
unsigned char *buf = NULL;
|
|
|
6c3643 |
int openflags = O_RDONLY;
|
|
|
6c3643 |
|
|
|
6c3643 |
- if (!(buf = alloc_buffer(memsize)))
|
|
|
6c3643 |
- goto nomem;
|
|
|
6c3643 |
if (filetype(path) != FILE_CHAR)
|
|
|
6c3643 |
openflags |= MY_O_DIRECT;
|
|
|
6c3643 |
fd = open(path, openflags);
|
|
|
6c3643 |
@@ -252,32 +284,58 @@ checkfile(char *path, off_t filesize, un
|
|
|
6c3643 |
}
|
|
|
6c3643 |
if (fd < 0)
|
|
|
6c3643 |
goto error;
|
|
|
6c3643 |
- do {
|
|
|
6c3643 |
- if (verified + memsize > filesize)
|
|
|
6c3643 |
- memsize = filesize - verified;
|
|
|
6c3643 |
- if (sparse && !(verified == 0) && !(verified + memsize == filesize)) {
|
|
|
6c3643 |
- if (lseek(fd, memsize, SEEK_CUR) < 0)
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- verified += memsize;
|
|
|
6c3643 |
- } else {
|
|
|
6c3643 |
- n = read_all(fd, buf, memsize);
|
|
|
6c3643 |
- if (n < 0)
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- if (n == 0) {
|
|
|
6c3643 |
- errno = EINVAL; /* early EOF */
|
|
|
6c3643 |
- goto error;
|
|
|
6c3643 |
- }
|
|
|
6c3643 |
- if (memcmp(mem, buf, memsize) != 0) {
|
|
|
6c3643 |
- break; /* return < filesize means verification failure */
|
|
|
6c3643 |
- }
|
|
|
6c3643 |
- verified += n;
|
|
|
6c3643 |
+ if (extentonly) {
|
|
|
6c3643 |
+ struct fillfile_args fa;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ fa.path = path;
|
|
|
6c3643 |
+ fa.filesize = filesize;
|
|
|
6c3643 |
+ fa.mem = mem;
|
|
|
6c3643 |
+ fa.memsize = memsize;
|
|
|
6c3643 |
+ fa.progress = progress;
|
|
|
6c3643 |
+ fa.arg = arg;
|
|
|
6c3643 |
+ fa.buf = alloc_buffer(memsize);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (fa.buf == NULL) {
|
|
|
6c3643 |
+ goto nomem;
|
|
|
6c3643 |
}
|
|
|
6c3643 |
- if (progress)
|
|
|
6c3643 |
- progress(arg, (double)verified/filesize);
|
|
|
6c3643 |
- } while (verified < filesize);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (fextent_apply(fd, checkextent, &fa) == 0)
|
|
|
6c3643 |
+ verified = filesize;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ free(fa.buf);
|
|
|
6c3643 |
+ } else {
|
|
|
6c3643 |
+ if (!(buf = alloc_buffer(memsize)))
|
|
|
6c3643 |
+ goto nomem;
|
|
|
6c3643 |
+ do {
|
|
|
6c3643 |
+ if (verified + memsize > filesize)
|
|
|
6c3643 |
+ memsize = filesize - verified;
|
|
|
6c3643 |
+ if (sparse && !(verified == 0) && !(verified + memsize == filesize)) {
|
|
|
6c3643 |
+ if (lseek(fd, memsize, SEEK_CUR) < 0)
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ verified += memsize;
|
|
|
6c3643 |
+ } else {
|
|
|
6c3643 |
+ n = read_all(fd, buf, memsize);
|
|
|
6c3643 |
+ if (n < 0)
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ if (n == 0) {
|
|
|
6c3643 |
+ errno = EINVAL; /* early EOF */
|
|
|
6c3643 |
+ goto error;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (memcmp(mem, buf, memsize) != 0) {
|
|
|
6c3643 |
+ break; /* return < filesize means verification failure */
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ verified += n;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (progress)
|
|
|
6c3643 |
+ progress(arg, (double)verified/filesize);
|
|
|
6c3643 |
+ } while (verified < filesize);
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+
|
|
|
6c3643 |
if (close(fd) < 0)
|
|
|
6c3643 |
goto error;
|
|
|
6c3643 |
- free(buf);
|
|
|
6c3643 |
+ if (buf != NULL) {
|
|
|
6c3643 |
+ free(buf);
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
return verified;
|
|
|
6c3643 |
nomem:
|
|
|
6c3643 |
errno = ENOMEM;
|
|
|
6c3643 |
@@ -295,6 +353,63 @@ disable_threads(void)
|
|
|
6c3643 |
no_threads = 1;
|
|
|
6c3643 |
}
|
|
|
6c3643 |
|
|
|
6c3643 |
+int fillextent(int fd, struct fiemap_extent *extent, void *pa)
|
|
|
6c3643 |
+{
|
|
|
6c3643 |
+ off_t n;
|
|
|
6c3643 |
+ off_t written = 0LL;
|
|
|
6c3643 |
+ struct fillfile_args args = *(struct fillfile_args *)(pa);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ do {
|
|
|
6c3643 |
+ if (args.refill)
|
|
|
6c3643 |
+ args.refill(args.mem, args.memsize);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (written + args.memsize > extent->fe_length)
|
|
|
6c3643 |
+ args.memsize = extent->fe_length - written;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ n = write_all(fd, args.mem, args.memsize);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (n < 0) {
|
|
|
6c3643 |
+ fprintf(stderr, "%s: write %s: %s\n", prog, args.path, strerror(errno));
|
|
|
6c3643 |
+ exit(1);
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ written += n;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ if (args.progress)
|
|
|
6c3643 |
+ args.progress(args.arg, (double)(extent->fe_logical + written)/args.filesize);
|
|
|
6c3643 |
+ } while (written < extent->fe_length);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ return 0;
|
|
|
6c3643 |
+}
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+int checkextent(int fd, struct fiemap_extent *extent, void *pa)
|
|
|
6c3643 |
+{
|
|
|
6c3643 |
+ off_t n;
|
|
|
6c3643 |
+ off_t verified = 0LL;
|
|
|
6c3643 |
+ struct fillfile_args args = *(struct fillfile_args *)(pa);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ do {
|
|
|
6c3643 |
+ if (verified + args.memsize > extent->fe_length)
|
|
|
6c3643 |
+ args.memsize = extent->fe_length - verified;
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ n = read_all(fd, args.buf, args.memsize);
|
|
|
6c3643 |
+ if (n < 0) {
|
|
|
6c3643 |
+ return -1;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (n == 0) {
|
|
|
6c3643 |
+ errno = EINVAL;
|
|
|
6c3643 |
+ return -1;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ if (memcmp(args.mem, args.buf, args.memsize) != 0) {
|
|
|
6c3643 |
+ break;
|
|
|
6c3643 |
+ }
|
|
|
6c3643 |
+ verified += n;
|
|
|
6c3643 |
+ if (args.progress)
|
|
|
6c3643 |
+ args.progress(args.arg, (double)(extent->fe_logical+verified)/args.filesize);
|
|
|
6c3643 |
+ } while (verified < extent->fe_length);
|
|
|
6c3643 |
+
|
|
|
6c3643 |
+ return 0;
|
|
|
6c3643 |
+}
|
|
|
6c3643 |
+
|
|
|
6c3643 |
/*
|
|
|
6c3643 |
* vi:tabstop=4 shiftwidth=4 expandtab
|
|
|
6c3643 |
*/
|
|
|
6c3643 |
diff -up scrub-2.6.1/src/fillfile.h.extent-only scrub-2.6.1/src/fillfile.h
|
|
|
6c3643 |
--- scrub-2.6.1/src/fillfile.h.extent-only 2014-08-20 17:33:43.000000000 -0400
|
|
|
6c3643 |
+++ scrub-2.6.1/src/fillfile.h 2021-02-22 14:24:32.440635014 -0500
|
|
|
6c3643 |
@@ -3,9 +3,9 @@ typedef void (*refill_t) (unsigned char
|
|
|
6c3643 |
|
|
|
6c3643 |
off_t fillfile(char *path, off_t filesize, unsigned char *mem, int memsize,
|
|
|
6c3643 |
progress_t progress, void *arg, refill_t refill,
|
|
|
6c3643 |
- bool sparse, bool creat);
|
|
|
6c3643 |
+ bool sparse, bool creat, bool extentonly);
|
|
|
6c3643 |
off_t checkfile(char *path, off_t filesize, unsigned char *mem, int memsize,
|
|
|
6c3643 |
- progress_t progress, void *arg, bool sparse);
|
|
|
6c3643 |
+ progress_t progress, void *arg, bool sparse, bool extentonly);
|
|
|
6c3643 |
void disable_threads(void);
|
|
|
6c3643 |
|
|
|
6c3643 |
/*
|
|
|
6c3643 |
diff -up scrub-2.6.1/src/Makefile.am.extent-only scrub-2.6.1/src/Makefile.am
|
|
|
6c3643 |
--- scrub-2.6.1/src/Makefile.am.extent-only 2021-02-22 14:24:32.438635006 -0500
|
|
|
6c3643 |
+++ scrub-2.6.1/src/Makefile.am 2021-02-22 14:24:32.440635014 -0500
|
|
|
6c3643 |
@@ -1,6 +1,8 @@
|
|
|
6c3643 |
bin_PROGRAMS = scrub
|
|
|
6c3643 |
|
|
|
6c3643 |
scrub_SOURCES = \
|
|
|
6c3643 |
+ fextent_apply.c \
|
|
|
6c3643 |
+ fextent_apply.h \
|
|
|
6c3643 |
filldentry.c \
|
|
|
6c3643 |
filldentry.h \
|
|
|
6c3643 |
fillfile.c \
|
|
|
6c3643 |
diff -up scrub-2.6.1/src/scrub.c.extent-only scrub-2.6.1/src/scrub.c
|
|
|
6c3643 |
--- scrub-2.6.1/src/scrub.c.extent-only 2021-02-22 14:24:32.438635006 -0500
|
|
|
6c3643 |
+++ scrub-2.6.1/src/scrub.c 2021-02-22 14:24:32.440635014 -0500
|
|
|
6c3643 |
@@ -68,10 +68,11 @@ struct opt_struct {
|
|
|
6c3643 |
bool nofollow;
|
|
|
6c3643 |
bool nohwrand;
|
|
|
6c3643 |
bool nothreads;
|
|
|
6c3643 |
+ bool extentonly;
|
|
|
6c3643 |
};
|
|
|
6c3643 |
|
|
|
6c3643 |
static bool scrub(char *path, off_t size, const sequence_t *seq,
|
|
|
6c3643 |
- int bufsize, bool nosig, bool sparse, bool enospc);
|
|
|
6c3643 |
+ int bufsize, bool nosig, bool sparse, bool enospc, bool extentonly);
|
|
|
6c3643 |
static void scrub_free(char *path, const struct opt_struct *opt);
|
|
|
6c3643 |
static void scrub_dirent(char *path, const struct opt_struct *opt);
|
|
|
6c3643 |
static void scrub_file(char *path, const struct opt_struct *opt);
|
|
|
6c3643 |
@@ -82,7 +83,7 @@ static void scrub_disk(char *path,
|
|
|
6c3643 |
static int scrub_object(char *path, const struct opt_struct *opt,
|
|
|
6c3643 |
bool noexec, bool dryrun);
|
|
|
6c3643 |
|
|
|
6c3643 |
-#define OPTIONS "p:D:Xb:s:fSrvTLRthn"
|
|
|
6c3643 |
+#define OPTIONS "p:D:Xb:s:fSrvTELRthn"
|
|
|
6c3643 |
#if HAVE_GETOPT_LONG
|
|
|
6c3643 |
#define GETOPT(ac,av,opt,lopt) getopt_long(ac,av,opt,lopt,NULL)
|
|
|
6c3643 |
static struct option longopts[] = {
|
|
|
6c3643 |
@@ -96,6 +97,7 @@ static struct option longopts[] = {
|
|
|
6c3643 |
{"remove", no_argument, 0, 'r'},
|
|
|
6c3643 |
{"version", no_argument, 0, 'v'},
|
|
|
6c3643 |
{"test-sparse", no_argument, 0, 'T'},
|
|
|
6c3643 |
+ {"extent-only", no_argument, 0, 'E'},
|
|
|
6c3643 |
{"no-link", no_argument, 0, 'L'},
|
|
|
6c3643 |
{"no-hwrand", no_argument, 0, 'R'},
|
|
|
6c3643 |
{"no-threads", no_argument, 0, 't'},
|
|
|
6c3643 |
@@ -123,6 +125,7 @@ usage(void)
|
|
|
6c3643 |
" -f, --force scrub despite signature from previous scrub\n"
|
|
|
6c3643 |
" -S, --no-signature do not write scrub signature after scrub\n"
|
|
|
6c3643 |
" -r, --remove remove file after scrub\n"
|
|
|
6c3643 |
+" -E, --extent-only scrub only file extents\n"
|
|
|
6c3643 |
" -L, --no-link do not scrub link target\n"
|
|
|
6c3643 |
" -R, --no-hwrand do not use a hardware random number generator\n"
|
|
|
6c3643 |
" -t, --no-threads do not compute random data in a parallel thread\n"
|
|
|
6c3643 |
@@ -212,6 +215,9 @@ main(int argc, char *argv[])
|
|
|
6c3643 |
case 'T': /* --test-sparse */
|
|
|
6c3643 |
opt.sparse = true;
|
|
|
6c3643 |
break;
|
|
|
6c3643 |
+ case 'E': /* --extent-only */
|
|
|
6c3643 |
+ opt.extentonly = true;
|
|
|
6c3643 |
+ break;
|
|
|
6c3643 |
case 'L': /* --no-link */
|
|
|
6c3643 |
opt.nofollow = true;
|
|
|
6c3643 |
break;
|
|
|
6c3643 |
@@ -430,14 +436,14 @@ static int progress_col (const sequence_
|
|
|
6c3643 |
*/
|
|
|
6c3643 |
static bool
|
|
|
6c3643 |
scrub(char *path, off_t size, const sequence_t *seq, int bufsize,
|
|
|
6c3643 |
- bool nosig, bool sparse, bool enospc)
|
|
|
6c3643 |
+ bool nosig, bool sparse, bool enospc, bool extentonly)
|
|
|
6c3643 |
{
|
|
|
6c3643 |
unsigned char *buf;
|
|
|
6c3643 |
int i;
|
|
|
6c3643 |
prog_t p;
|
|
|
6c3643 |
char sizestr[80];
|
|
|
6c3643 |
bool isfull = false;
|
|
|
6c3643 |
- off_t written, checked;
|
|
|
6c3643 |
+ off_t written = (off_t)-1, checked = (off_t)-1;
|
|
|
6c3643 |
int pcol = progress_col(seq);
|
|
|
6c3643 |
|
|
|
6c3643 |
if (!(buf = alloc_buffer(bufsize))) {
|
|
|
6c3643 |
@@ -468,7 +474,7 @@ scrub(char *path, off_t size, const sequ
|
|
|
6c3643 |
#endif /* HAVE_LIBGCRYPT. */
|
|
|
6c3643 |
written = fillfile(path, size, buf, bufsize,
|
|
|
6c3643 |
(progress_t)progress_update, p,
|
|
|
6c3643 |
- (refill_t)genrand, sparse, enospc);
|
|
|
6c3643 |
+ (refill_t)genrand, sparse, enospc, extentonly);
|
|
|
6c3643 |
if (written == (off_t)-1) {
|
|
|
6c3643 |
fprintf(stderr, "%s: %s: %s\n", prog, path,
|
|
|
6c3643 |
strerror(errno));
|
|
|
6c3643 |
@@ -482,7 +488,7 @@ scrub(char *path, off_t size, const sequ
|
|
|
6c3643 |
memset_pat(buf, seq->pat[i], bufsize);
|
|
|
6c3643 |
written = fillfile(path, size, buf, bufsize,
|
|
|
6c3643 |
(progress_t)progress_update, p,
|
|
|
6c3643 |
- NULL, sparse, enospc);
|
|
|
6c3643 |
+ NULL, sparse, enospc, extentonly);
|
|
|
6c3643 |
if (written == (off_t)-1) {
|
|
|
6c3643 |
fprintf(stderr, "%s: %s: %s\n", prog, path,
|
|
|
6c3643 |
strerror(errno));
|
|
|
6c3643 |
@@ -496,7 +502,7 @@ scrub(char *path, off_t size, const sequ
|
|
|
6c3643 |
memset_pat(buf, seq->pat[i], bufsize);
|
|
|
6c3643 |
written = fillfile(path, size, buf, bufsize,
|
|
|
6c3643 |
(progress_t)progress_update, p,
|
|
|
6c3643 |
- NULL, sparse, enospc);
|
|
|
6c3643 |
+ NULL, sparse, enospc, extentonly);
|
|
|
6c3643 |
if (written == (off_t)-1) {
|
|
|
6c3643 |
fprintf(stderr, "%s: %s: %s\n", prog, path,
|
|
|
6c3643 |
strerror(errno));
|
|
|
6c3643 |
@@ -506,7 +512,7 @@ scrub(char *path, off_t size, const sequ
|
|
|
6c3643 |
printf("%s: %-8s", prog, "verify");
|
|
|
6c3643 |
progress_create(&p, pcol);
|
|
|
6c3643 |
checked = checkfile(path, written, buf, bufsize,
|
|
|
6c3643 |
- (progress_t)progress_update, p, sparse);
|
|
|
6c3643 |
+ (progress_t)progress_update, p, sparse, extentonly);
|
|
|
6c3643 |
if (checked == (off_t)-1) {
|
|
|
6c3643 |
fprintf(stderr, "%s: %s: %s\n", prog, path,
|
|
|
6c3643 |
strerror(errno));
|
|
|
6c3643 |
@@ -600,7 +606,7 @@ scrub_free(char *dirpath, const struct o
|
|
|
6c3643 |
do {
|
|
|
6c3643 |
snprintf(path, sizeof(path), "%s/scrub.%.3d", dirpath, fileno++);
|
|
|
6c3643 |
isfull = scrub(path, size, opt->seq, opt->blocksize, opt->nosig,
|
|
|
6c3643 |
- false, true);
|
|
|
6c3643 |
+ false, true, false);
|
|
|
6c3643 |
} while (!isfull);
|
|
|
6c3643 |
while (--fileno >= 0) {
|
|
|
6c3643 |
snprintf(path, sizeof(path), "%s/scrub.%.3d", dirpath, fileno);
|
|
|
6c3643 |
@@ -678,7 +684,7 @@ scrub_file(char *path, const struct opt_
|
|
|
6c3643 |
prog, path, (int)(size - sb.st_size));
|
|
|
6c3643 |
}
|
|
|
6c3643 |
}
|
|
|
6c3643 |
- scrub(path, size, opt->seq, opt->blocksize, opt->nosig, opt->sparse, false);
|
|
|
6c3643 |
+ scrub(path, size, opt->seq, opt->blocksize, opt->nosig, opt->sparse, false, opt->extentonly);
|
|
|
6c3643 |
}
|
|
|
6c3643 |
|
|
|
6c3643 |
/* Scrub apple resource fork component of file.
|
|
|
6c3643 |
@@ -706,7 +712,7 @@ scrub_resfork(char *path, const struct o
|
|
|
6c3643 |
printf("%s: padding %s with %d bytes to fill last fs block\n",
|
|
|
6c3643 |
prog, rpath, (int)(rsize - rsb.st_size));
|
|
|
6c3643 |
}
|
|
|
6c3643 |
- scrub(rpath, rsize, opt->seq, opt->blocksize, false, false, false);
|
|
|
6c3643 |
+ scrub(rpath, rsize, opt->seq, opt->blocksize, false, false, false, false);
|
|
|
6c3643 |
}
|
|
|
6c3643 |
#endif
|
|
|
6c3643 |
|
|
|
6c3643 |
@@ -728,7 +734,7 @@ scrub_disk(char *path, const struct opt_
|
|
|
6c3643 |
printf("%s: please verify that device size below is correct!\n", prog);
|
|
|
6c3643 |
}
|
|
|
6c3643 |
scrub(path, devsize, opt->seq, opt->blocksize, opt->nosig, opt->sparse,
|
|
|
6c3643 |
- false);
|
|
|
6c3643 |
+ false, false);
|
|
|
6c3643 |
}
|
|
|
6c3643 |
|
|
|
6c3643 |
/*
|