xfsprogs: online scrub/repair support
cover xfsprogs: online scrub/repair support
Hi all,
This is the eleventh revision (+ more fixes suggested by Eric Sandeen) of a patchset that adds to XFS userland tools support for online metadata scrubbing and repair. Since v10 I've rebased to the latest for-next, fixed some wonky error messages, and fixed a few minor problems I found via code inspection. This patch series is more or less the same as a couple of weeks ago.
We start by creating the basic shell of the program that can do argument parsing and error reporting, create some abstractions for the XFS ioctls that we use to iterate and scrub metadata, and then tie together all the in-kernel scrubbing in separate scrub phases.
Next, we move on to checking the directory tree for connectivity and naming problems and add the infrastructure to perform an (optional) scan of the in-use parts of the disk media. We also implement a minimal preen -- if the fs checks out, we can try to run fstrim; and some basic progress reporting if the program is running interactively.
Finally, we add some wrapper scripts to schedule scrubs of all the mounted filesystems; and the necessary systemd / cron infrastructure that is needed to automatically scan everything once a week. All of this is disabled by default. The systemd integration allows us to give scrub exactly the privileges it needs while walling off the rest of the system.
If you're going to start using this mess, you probably ought to just pull from my git tree for xfsprogs[1]. This series relies on the libfrog patches sent earlier. Kernel support appeared in 4.15 and will become substantially more robust in 4.16.
Comments and questions are, as always, welcome.
--D
[1] https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=djwong-devel
PATCH 1/29 xfs_scrub: create online filesystem scrub program
From: Darrick J. Wong <[email protected]>
Create the foundations of a filesystem scrubbing tool that asks the kernel to inspect all metadata in the filesystem and (ultimately) to repair anything that's broken. Also create the man page for the utility.
--- .gitignore | 1 Makefile | 3 + man/man8/xfs_scrub.8 | 135 ++++++++++++++++++++++++++++++++++++++++++ scrub/Makefile | 42 +++++++++++++ scrub/common.c | 20 ++++++ scrub/common.h | 23 +++++++ scrub/xfs_scrub.c | 109 ++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.h | 23 +++++++ tools/find-api-violations.sh | 2 - 9 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 man/man8/xfs_scrub.8 create mode 100644 scrub/Makefile create mode 100644 scrub/common.c create mode 100644 scrub/common.h create mode 100644 scrub/xfs_scrub.c create mode 100644 scrub/xfs_scrub.h
.gitignore +1 -0
@@ -68,6 +68,7 @@ cscope.* /repair/xfs_repair /rtcp/xfs_rtcp /spaceman/xfs_spaceman +/scrub/xfs_scrub # generated crc files /libxfs/crc32selftest
Makefile +2 -1
@@ -48,7 +48,7 @@ LIBFROG_SUBDIR = libfrog DLIB_SUBDIRS = libxlog libxcmd libhandle LIB_SUBDIRS = libxfs $(DLIB_SUBDIRS) TOOL_SUBDIRS = copy db estimate fsck growfs io logprint mkfs quota \ - mdrestore repair rtcp m4 man doc debian spaceman + mdrestore repair rtcp m4 man doc debian spaceman scrub ifneq ("$(PKG_PLATFORM)","darwin") TOOL_SUBDIRS += fsr
@@ -91,6 +91,7 @@ repair: libxlog libxcmd copy: libxlog mkfs: libxcmd spaceman: libxcmd +scrub: libhandle libxcmd ifeq ($(HAVE_BUILDDEFS), yes) include $(BUILDRULES)
man/man8/xfs_scrub.8 new file +135 -0
135 lines not on this page · raw message
scrub/Makefile new file +42 -0
42 lines not on this page · raw message
scrub/common.c new file +20 -0
@@ -0,0 +1,20 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include "common.h"
scrub/common.h new file +23 -0
@@ -0,0 +1,23 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_COMMON_H_ +#define XFS_SCRUB_COMMON_H_ + +#endif /* XFS_SCRUB_COMMON_H_ */
scrub/xfs_scrub.c new file +109 -0
109 lines not on this page · raw message
scrub/xfs_scrub.h new file +23 -0
@@ -0,0 +1,23 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_XFS_SCRUB_H_ +#define XFS_SCRUB_XFS_SCRUB_H_ + +#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
tools/find-api-violations.sh +1 -1
@@ -6,7 +6,7 @@ # NOTE: This script doesn't look for API violations in function parameters. -tool_dirs="copy db estimate fsck fsr growfs io logprint mdrestore mkfs quota repair rtcp" +tool_dirs="copy db estimate fsck fsr growfs io logprint mdrestore mkfs quota repair rtcp scrub" # Calls to xfs_* functions in libxfs/*.c without the libxfs_ prefix find_possible_api_calls() {
PATCH 2/29 xfs_scrub: common error handling
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Standardize how we record and report errors.
--- scrub/common.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/common.h | 30 ++++++++++++++++++ scrub/xfs_scrub.c | 5 +++ scrub/xfs_scrub.h | 11 +++++++ 4 files changed, 133 insertions(+)
scrub/common.c +87 -0
@@ -17,4 +17,91 @@* along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <stdio.h> +#include <pthread.h> +#include <stdbool.h> +#include "platform_defs.h" +#include "xfs.h" +#include "xfs_scrub.h" #include "common.h" + +/* +* Reporting Status to the Console +* +* We aim for a roughly standard reporting format -- the severity of the +* status being reported, a textual description of the object being +* reported, and whatever the status happens to be. +* +* Errors are the most severe and reflect filesystem corruption. +* Warnings indicate that something is amiss and needs the attention of +* the administrator, but does not constitute a corruption. Information +* is merely advisory. +*/ + +/* Too many errors? Bail out. */ +bool +xfs_scrub_excessive_errors ( +struct scrub_ctx *ctx) +{ +bool ret; + +pthread_mutex_lock (&ctx->lock); + ret = ctx->max_errors >0 && ctx->errors_found >= ctx->max_errors; +pthread_mutex_unlock (&ctx->lock); + +return ret; +} + +static const char *err_str[] = { + [S_ERROR ] ="Error" , + [S_WARN ] ="Warning" , + [S_INFO ] ="Info" , +}; + +/* Print a warning string and some warning text. */ +void +__str_out ( +struct scrub_ctx *ctx, +const char *descr, +enum error_level level, +int error, +const char *file, +int line, +const char *format, + ...) +{ +FILE *stream = stderr; +va_list args; +char buf[DESCR_BUFSZ ]; + +/* print strerror or format of choice but not both */ +assert (!(error && format)); + +if (level >=S_INFO ) + stream = stdout; + +pthread_mutex_lock (&ctx->lock); +fprintf (stream,"%s: %s: " ,_ (err_str[level]), descr); +if (error) { +fprintf (stream,_ ("%s." ),strerror_r (error, buf,DESCR_BUFSZ )); + }else { +va_start (args, format); +vfprintf (stream, format, args); +va_end (args); + } + +if (debug) +fprintf (stream,_ (" (%s line %d)" ), file, line); +fprintf (stream,"\n" ); +if (stream == stdout) +fflush (stream); + +if (error)/* A syscall failed */ + ctx->runtime_errors++; +else if (level ==S_ERROR ) + ctx->errors_found++; +else if (level ==S_WARN ) + ctx->warnings_found++; + +pthread_mutex_unlock (&ctx->lock); +}
scrub/common.h +30 -0
@@ -20,4 +20,34 @@#ifndef XFS_SCRUB_COMMON_H_ #define XFS_SCRUB_COMMON_H_ +/* +* When reporting a defective metadata object to the console, this +* is the size of the buffer to use to store the description of that +* item. +*/ +#define DESCR_BUFSZ 256 + +bool xfs_scrub_excessive_errors (struct scrub_ctx *ctx); + +enum error_level { +S_ERROR =0 , +S_WARN , +S_INFO , +}; + +void __str_out (struct scrub_ctx *ctx,const char *descr,enum error_level level, +int error,const char *file,int line,const char *format, ...); + +#define str_errno (ctx, str) \ + __str_out(ctx, str, S_ERROR, errno, __FILE__, __LINE__, NULL) +#define str_error (ctx, str, ...) \ + __str_out(ctx, str, S_ERROR, 0, __FILE__, __LINE__, __VA_ARGS__) +#define str_warn (ctx, str, ...) \ + __str_out(ctx, str, S_WARN, 0, __FILE__, __LINE__, __VA_ARGS__) +#define str_info (ctx, str, ...) \ + __str_out(ctx, str, S_INFO, 0, __FILE__, __LINE__, __VA_ARGS__) + +#define dbg_printf (fmt, ...) \ + do {if (debug > 1) {printf(fmt, __VA_ARGS__);}} while (0) +#endif /* XFS_SCRUB_COMMON_H_ */
scrub/xfs_scrub.c +5 -0
@@ -18,6 +18,8 @@* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <stdio.h> +#include <pthread.h> +#include <stdbool.h> #include "xfs_scrub.h" /*
@@ -99,6 +101,9 @@/* Program name; needed for libfrog error reports. */ char *progname ="xfs_scrub" ; +/* Debug level; higher values mean more verbosity. */ +unsigned int debug; + int main( int argc,
scrub/xfs_scrub.h +11 -0
@@ -20,4 +20,15 @@#ifndef XFS_SCRUB_XFS_SCRUB_H_ #define XFS_SCRUB_XFS_SCRUB_H_ +extern unsigned int debug; + +struct scrub_ctx { +/* Mutable scrub state; use lock. */ +pthread_mutex_t lock; +unsigned long long max_errors; +unsigned long long runtime_errors; +unsigned long long errors_found; +unsigned long long warnings_found; +}; +#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 3/29 xfs_scrub: set up command line argument parsing
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Parse command line options in order to set up the context in which we will scrub the filesystem.
--- scrub/common.h | 8 ++ scrub/xfs_scrub.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.h | 32 +++++++ 3 files changed, 266 insertions(+), 1 deletion(-)
scrub/common.h +8 -0
@@ -50,4 +50,12 @@ void __str_out(struct scrub_ctx *ctx, const char *descr, enum error_level level,#define dbg_printf (fmt, ...) \ do {if (debug > 1) {printf(fmt, __VA_ARGS__);}} while (0) +/* Is this debug tweak enabled? */ +static inline bool +debug_tweak_on ( +const char *name) +{ +return debug &&getenv (name) !=NULL ; +} +#endif /* XFS_SCRUB_COMMON_H_ */
scrub/xfs_scrub.c +226 -1
250 lines not on this page · raw message
scrub/xfs_scrub.h +32 -0
@@ -20,15 +20,47 @@#ifndef XFS_SCRUB_XFS_SCRUB_H_ #define XFS_SCRUB_XFS_SCRUB_H_ +#define _PATH_PROC_MOUNTS "/proc/mounts" + +extern unsigned int nr_threads; +extern unsigned int bg_mode;extern unsigned int debug; +extern int nproc; +extern bool verbose; +extern long page_size; + +enum scrub_mode { +SCRUB_MODE_DRY_RUN , +SCRUB_MODE_PREEN , +SCRUB_MODE_REPAIR , +}; +#define SCRUB_MODE_DEFAULT SCRUB_MODE_PREEN + +enum error_action { +ERRORS_CONTINUE , +ERRORS_SHUTDOWN , +};struct scrub_ctx { +/* Immutable scrub state. */ + +/* Strings we need for presentation */ +char *mntpoint; +char *blkdev; + +/* What does the user want us to do? */ +enum scrub_mode mode; + +/* How does the user want us to react to errors? */ +enum error_action error_action; +/* Mutable scrub state; use lock. */ pthread_mutex_t lock;unsigned long long max_errors;unsigned long long runtime_errors;unsigned long long errors_found;unsigned long long warnings_found; +bool need_repair; };#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 4/29 xfs_scrub: dispatch the various phases of the scrub program
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create the dispatching routines that we'll use to call out to each separate phase of the program.
--- configure.ac | 1 include/builddefs.in | 1 m4/package_libcdev.m4 | 18 +++ scrub/Makefile | 4 + scrub/common.c | 63 +++++++++++ scrub/common.h | 4 + scrub/xfs_scrub.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 371 insertions(+)
configure.ac +1 -0
@@ -165,6 +165,7 @@ AC_HAVE_GETFSMAP AC_HAVE_STATFS_FLAGS AC_HAVE_MAP_SYNC AC_HAVE_DEVMAPPER +AC_HAVE_MALLINFO if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
include/builddefs.in +1 -0
@@ -119,6 +119,7 @@ HAVE_GETFSMAP = @have_getfsmap@ HAVE_STATFS_FLAGS = @have_statfs_flags@ HAVE_MAP_SYNC = @have_map_sync@ HAVE_DEVMAPPER = @have_devmapper@ +HAVE_MALLINFO = @have_mallinfo@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/package_libcdev.m4 +18 -0
@@ -344,3 +344,21 @@ AC_DEFUN([AC_HAVE_MAP_SYNC], AC_MSG_RESULT(no)) AC_SUBST(have_map_sync) ]) + +# +# Check if we have a mallinfo libc call +# +AC_DEFUN([AC_HAVE_MALLINFO], + [ AC_MSG_CHECKING([for mallinfo ]) + AC_TRY_COMPILE([ +#include <malloc.h> + ], [ + struct mallinfo test; + + test.arena = 0; test.hblkhd = 0; test.uordblks = 0; test.fordblks = 0; + test = mallinfo(); + ], have_mallinfo=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + AC_SUBST(have_mallinfo) + ])
scrub/Makefile +4 -0
@@ -27,6 +27,10 @@ LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) LTDEPENDENCIES += $(LIBHANDLE) $(LIBFROG) LLDFLAGS = -static +ifeq ($(HAVE_MALLINFO),yes) +LCFLAGS += -DHAVE_MALLINFO +endif + default: depend $(LTCOMMAND) include $(BUILDRULES)
scrub/common.c +63 -0
66 lines not on this page · raw message
scrub/common.h +4 -0
@@ -58,4 +58,8 @@ debug_tweak_on( return debug && getenv(name) != NULL; } +double timeval_subtract (struct timeval *tv1,struct timeval *tv2); +double auto_space_units (unsigned long long kilobytes,char **units); +double auto_units (unsigned long long number,char **units); +#endif /* XFS_SCRUB_COMMON_H_ */
scrub/xfs_scrub.c +280 -0
316 lines not on this page · raw message
PATCH 5/29 xfs_scrub: figure out how many threads we're going to need
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create the plumbing to figure out how many threads we're going to want to do all of our scrubbing.
--- scrub/common.c | 26 ++++++++++++++++++++++++++ scrub/common.h | 2 ++ scrub/xfs_scrub.h | 3 +++ 3 files changed, 31 insertions(+)
scrub/common.c +26 -0
@@ -168,3 +168,29 @@ auto_units( *units ="" ;return number; } + +/* How many threads to kick off? */ +unsigned int +scrub_nproc ( +struct scrub_ctx *ctx) +{ +if (nr_threads) +return nr_threads; +return ctx->nr_io_threads; +} + +/* +* How many threads to kick off for a workqueue? If we only want one +* thread, save ourselves the overhead and just run it in the main thread. +*/ +unsigned int +scrub_nproc_workqueue ( +struct scrub_ctx *ctx) +{ +unsigned int x; + + x =scrub_nproc (ctx); +if (x ==1 ) + x =0 ; +return x; +}
scrub/common.h +2 -0
@@ -61,5 +61,7 @@ debug_tweak_on(double timeval_subtract (struct timeval *tv1,struct timeval *tv2);double auto_space_units (unsigned long long kilobytes,char **units);double auto_units (unsigned long long number,char **units); +unsigned int scrub_nproc (struct scrub_ctx *ctx); +unsigned int scrub_nproc_workqueue (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_COMMON_H_ */
scrub/xfs_scrub.h +3 -0
@@ -54,6 +54,9 @@ struct scrub_ctx {/* How does the user want us to react to errors? */ enum error_action error_action; +/* Number of threads for metadata scrubbing */ +unsigned int nr_io_threads; +/* Mutable scrub state; use lock. */ pthread_mutex_t lock;unsigned long long max_errors;
PATCH 6/29 xfs_scrub: create an abstraction for a block device
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create an abstraction to handle all of our low level disk operations. We'll eventually use it to bind to a fs mount point and block device.
--- scrub/Makefile | 2 + scrub/disk.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/disk.h | 39 +++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 scrub/disk.c create mode 100644 scrub/disk.h
scrub/Makefile +2 -0
@@ -17,10 +17,12 @@ endif # scrub_prereqs HFILES = \ common.h \ +disk.h \ xfs_scrub.h CFILES = \ common.c \ +disk.c \ xfs_scrub.c LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD)
scrub/disk.c new file +168 -0
168 lines not on this page · raw message
scrub/disk.h new file +39 -0
@@ -0,0 +1,39 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_DISK_H_ +#define XFS_SCRUB_DISK_H_ + +struct disk { +struct stat d_sb; +int d_fd; +int d_lbalog; +unsigned int d_flags; +unsigned int d_blksize;/* bytes */ +uint64_t d_size;/* bytes */ +uint64_t d_start;/* bytes */ +}; + +unsigned int disk_heads (struct disk *disk); +struct disk *disk_open (const char *pathname); +int disk_close (struct disk *disk); +ssize_t disk_read_verify (struct disk *disk,void *buf,uint64_t startblock, +uint64_t blockcount); + +#endif /* XFS_SCRUB_DISK_H_ */
PATCH 7/29 xfs_scrub: find XFS filesystem geometry
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Discover the geometry of the XFS filesystem that we've been told to scan, and set up some common functions that will be used by the scrub phases.
--- scrub/Makefile | 5 + scrub/common.c | 72 +++++++++++++++++ scrub/common.h | 10 ++ scrub/disk.c | 3 + scrub/phase1.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.c | 35 ++++++++ scrub/xfs_scrub.h | 29 +++++++ 7 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 scrub/phase1.c
scrub/Makefile +5 -0
@@ -23,6 +23,7 @@ xfs_scrub.h CFILES = \ common.c \ disk.c \ +phase1.c \ xfs_scrub.c LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD)
@@ -33,6 +34,10 @@ ifeq ($(HAVE_MALLINFO),yes) LCFLAGS += -DHAVE_MALLINFO endif +ifeq ($(HAVE_SYNCFS),yes) +LCFLAGS += -DHAVE_SYNCFS +endif + default: depend $(LTCOMMAND) include $(BUILDRULES)
scrub/common.c +72 -0
83 lines not on this page · raw message
scrub/common.h +10 -0
@@ -64,4 +64,14 @@ double auto_units(unsigned long long number, char **units);unsigned int scrub_nproc (struct scrub_ctx *ctx);unsigned int scrub_nproc_workqueue (struct scrub_ctx *ctx); +#ifndef HAVE_SYNCFS +static inline int syncfs (int fd) +{ +sync (); +return 0 ; +} +#endif + +bool find_mountpoint (char *mtab,struct scrub_ctx *ctx); +#endif /* XFS_SCRUB_COMMON_H_ */
scrub/disk.c +3 -0
@@ -31,6 +31,9 @@#include <linux/fs.h> #include "platform_defs.h" #include "libfrog.h" +#include "xfs.h" +#include "path.h" +#include "xfs_fs.h" #include "xfs_scrub.h" #include "disk.h"
scrub/phase1.c new file +223 -0
223 lines not on this page · raw message
scrub/xfs_scrub.c +34 -1
@@ -23,9 +23,12 @@#include <stdlib.h> #include <sys/time.h> #include <sys/resource.h> +#include <sys/statvfs.h> #include "platform_defs.h" #include "xfs.h" +#include "xfs_fs.h" #include "input.h" +#include "path.h" #include "xfs_scrub.h" #include "common.h"
@@ -360,6 +363,8 @@ run_scrub_phases( { { .descr = _("Find filesystem geometry."), + .fn = xfs_setup_fs, + .must_run = true, }, { .descr = _("Check internal metadata."),
@@ -440,6 +445,7 @@ main(char *repairstr ="" ;unsigned long long total_errors;bool moveon = true; +bool ismnt;int c;int ret =SCRUB_RET_SUCCESS ;
@@ -539,6 +545,15 @@ _("Only one of the options -n or -y may be specified.\n")); ctx.mntpoint =strdup (argv[optind]); +/* Find the mount record for the passed-in argument. */ +if (stat (argv[optind], &ctx.mnt_sb) <0 ) { +fprintf (stderr, +_ ("%s: could not stat: %s: %s\n" ), + progname, argv[optind],strerror (errno)); + ctx.runtime_errors++; + goto out; + } +/* * If the user did not specify an explicit mount table, try to use * /proc/mounts if it is available, else /etc/mtab. We prefer
@@ -558,6 +573,15 @@ _("Only one of the options -n or -y may be specified.\n"));if (!moveon) goto out; + ismnt =find_mountpoint (mtab, &ctx); +if (!ismnt) { +fprintf (stderr, +_ ("%s: Not a XFS mount point or block device.\n" ), + ctx.mntpoint); + ret |=SCRUB_RET_SYNTAX ; + goto out; + } +/* How many CPUs? */ nproc =sysconf (_SC_NPROCESSORS_ONLN);if (nproc <1 )
@@ -589,6 +613,11 @@ _("Only one of the options -n or -y may be specified.\n"));if (debug_tweak_on ("XFS_SCRUB_FORCE_ERROR" ))str_error (&ctx, ctx.mntpoint,_ ("Injecting error." )); +/* Clean up scan data. */ + moveon =xfs_cleanup_fs (&ctx); +if (!moveon && ctx.runtime_errors ==0 ) + ctx.runtime_errors++; + out: total_errors = ctx.errors_found + ctx.runtime_errors;if (ctx.need_repair)
@@ -606,13 +635,17 @@ _("%s: %llu errors found.%s\n"),fprintf (stderr,_ ("%s: %llu warnings found.\n" ), ctx.mntpoint, ctx.warnings_found); -if (ctx.errors_found) +if (ctx.errors_found) { +if (ctx.error_action ==ERRORS_SHUTDOWN ) +xfs_shutdown_fs (&ctx); ret |=SCRUB_RET_CORRUPT ; + }if (ctx.warnings_found) ret |=SCRUB_RET_UNOPTIMIZED ;if (ctx.runtime_errors) ret |=SCRUB_RET_OPERROR ;phase_end (&all_pi,0 ); +free (ctx.blkdev);free (ctx.mntpoint);return ret;
scrub/xfs_scrub.h +29 -0
@@ -48,15 +48,38 @@ struct scrub_ctx {char *mntpoint;char *blkdev; +/* Mountpoint info */ +struct stat mnt_sb; +struct statvfs mnt_sv; +struct statfs mnt_sf; + +/* Open block devices */ +struct disk *datadev; +struct disk *logdev; +struct disk *rtdev; +/* What does the user want us to do? */ enum scrub_mode mode;/* How does the user want us to react to errors? */ enum error_action error_action; +/* fd to filesystem mount point */ +int mnt_fd; +/* Number of threads for metadata scrubbing */ unsigned int nr_io_threads; +/* XFS specific geometry */ +struct xfs_fsop_geom geo; +struct fs_path fsinfo; +unsigned int agblklog; +unsigned int blocklog; +unsigned int inodelog; +unsigned int inopblog; +void *fshandle; +size_t fshandle_len; +/* Mutable scrub state; use lock. */ pthread_mutex_t lock;unsigned long long max_errors;
@@ -64,6 +87,12 @@ struct scrub_ctx {unsigned long long errors_found;unsigned long long warnings_found;bool need_repair; + bool preen_triggers[XFS_SCRUB_TYPE_NR]; }; +/* Phase helper functions */ +void xfs_shutdown_fs (struct scrub_ctx *ctx); +bool xfs_cleanup_fs (struct scrub_ctx *ctx); +bool xfs_setup_fs (struct scrub_ctx *ctx); +#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 8/29 xfs_scrub: add inode iteration functions
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
These helpers enable userspace to count or iterate all inodes in a filesystem. The counting function uses INUMBERS, while the inode iterator uses INUMBERS and BULKSTAT to iterate over every inode that should be in the filesystem.
--- scrub/Makefile | 2 scrub/inodes.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/inodes.h | 32 ++++++ 3 files changed, 331 insertions(+) create mode 100644 scrub/inodes.c create mode 100644 scrub/inodes.h
scrub/Makefile +2 -0
@@ -18,11 +18,13 @@ endif # scrub_prereqs HFILES = \ common.h \ disk.h \ +inodes.h \ xfs_scrub.h CFILES = \ common.c \ disk.c \ +inodes.c \ phase1.c \ xfs_scrub.c
scrub/inodes.c new file +297 -0
297 lines not on this page · raw message
scrub/inodes.h new file +32 -0
@@ -0,0 +1,32 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_INODES_H_ +#define XFS_SCRUB_INODES_H_ + +typedef int (*xfs_inode_iter_fn )(struct scrub_ctx *ctx, +struct xfs_handle *handle,struct xfs_bstat *bs,void *arg); + +#define XFS_ITERATE_INODES_ABORT (-1) +bool xfs_scan_all_inodes (struct scrub_ctx *ctx,xfs_inode_iter_fn fn, +void *arg); + +int xfs_open_handle (struct xfs_handle *handle); + +#endif /* XFS_SCRUB_INODES_H_ */
PATCH 9/29 xfs_scrub: add space map iteration functions
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
These helpers enable userspace to iterate all the space map information in a filesystem. The iteration function uses GETFSMAP.
--- scrub/Makefile | 2 scrub/spacemap.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/spacemap.h | 31 +++++++ 3 files changed, 289 insertions(+) create mode 100644 scrub/spacemap.c create mode 100644 scrub/spacemap.h
scrub/Makefile +2 -0
@@ -19,6 +19,7 @@ HFILES = \ common.h \ disk.h \ inodes.h \ +spacemap.h \ xfs_scrub.h CFILES = \
@@ -26,6 +27,7 @@ common.c \ disk.c \ inodes.c \ phase1.c \ +spacemap.c \ xfs_scrub.c LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD)
scrub/spacemap.c new file +256 -0
256 lines not on this page · raw message
scrub/spacemap.h new file +31 -0
@@ -0,0 +1,31 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_SPACEMAP_H_ +#define XFS_SCRUB_SPACEMAP_H_ + +typedef bool (*xfs_fsmap_iter_fn )(struct scrub_ctx *ctx,const char *descr, +struct fsmap *fsr,void *arg); + +bool xfs_iterate_fsmap (struct scrub_ctx *ctx,const char *descr, +struct fsmap *keys,xfs_fsmap_iter_fn fn,void *arg); +bool xfs_scan_all_spacemaps (struct scrub_ctx *ctx,xfs_fsmap_iter_fn fn, +void *arg); + +#endif /* XFS_SCRUB_SPACEMAP_H_ */
PATCH 10/29 xfs_scrub: add file space map iteration functions
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
These helpers enable userspace to iterate all the space map information for a file. The iteration function uses GETBMAPX.
--- scrub/Makefile | 2 + scrub/filemap.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/filemap.h | 39 ++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 scrub/filemap.c create mode 100644 scrub/filemap.h
scrub/Makefile +2 -0
@@ -18,6 +18,7 @@ endif # scrub_prereqs HFILES = \ common.h \ disk.h \ +filemap.h \ inodes.h \ spacemap.h \ xfs_scrub.h
@@ -25,6 +26,7 @@ xfs_scrub.h CFILES = \ common.c \ disk.c \ +filemap.c \ inodes.c \ phase1.c \ spacemap.c \
scrub/filemap.c new file +157 -0
157 lines not on this page · raw message
scrub/filemap.h new file +39 -0
@@ -0,0 +1,39 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_FILEMAP_H_ +#define XFS_SCRUB_FILEMAP_H_ + +/* inode fork block mapping */ +struct xfs_bmap { +uint64_t bm_offset;/* file offset of segment in bytes */ +uint64_t bm_physical;/* physical starting byte */ +uint64_t bm_length;/* length of segment, bytes */ +uint32_t bm_flags;/* output flags */ +}; + +typedef bool (*xfs_bmap_iter_fn )(struct scrub_ctx *ctx,const char *descr, +int fd,int whichfork,struct fsxattr *fsx, +struct xfs_bmap *bmap,void *arg); + +bool xfs_iterate_filemaps (struct scrub_ctx *ctx,const char *descr,int fd, +int whichfork,struct xfs_bmap *key,xfs_bmap_iter_fn fn, +void *arg); + +#endif /* XFS_SCRUB_FILEMAP_H_ */
PATCH 11/29 xfs_scrub: filesystem counter collection functions
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Add a couple of helper functions to estimate the inode and block counters on the filesystem.
--- scrub/Makefile | 2 scrub/fscounters.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/fscounters.h | 29 +++++++ 3 files changed, 243 insertions(+) create mode 100644 scrub/fscounters.c create mode 100644 scrub/fscounters.h
scrub/Makefile +2 -0
@@ -19,6 +19,7 @@ HFILES = \ common.h \ disk.h \ filemap.h \ +fscounters.h \ inodes.h \ spacemap.h \ xfs_scrub.h
@@ -27,6 +28,7 @@ CFILES = \ common.c \ disk.c \ filemap.c \ +fscounters.c \ inodes.c \ phase1.c \ spacemap.c \
scrub/fscounters.c new file +212 -0
212 lines not on this page · raw message
scrub/fscounters.h new file +29 -0
@@ -0,0 +1,29 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_FSCOUNTERS_H_ +#define XFS_SCRUB_FSCOUNTERS_H_ + +bool xfs_scan_estimate_blocks (struct scrub_ctx *ctx, +unsigned long long *d_blocks,unsigned long long *d_bfree, +unsigned long long *r_blocks,unsigned long long *r_bfree, +unsigned long long *f_files,unsigned long long *f_free); +bool xfs_count_all_inodes (struct scrub_ctx *ctx,uint64_t *count); + +#endif /* XFS_SCRUB_FSCOUNTERS_H_ */
PATCH 12/29 xfs_scrub: wrap the scrub ioctl
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create some wrappers to call the scrub ioctls.
--- scrub/Makefile | 2 scrub/common.c | 19 ++ scrub/common.h | 1 scrub/phase1.c | 11 + scrub/scrub.c | 621 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/scrub.h | 62 ++++++ 6 files changed, 716 insertions(+) create mode 100644 scrub/scrub.c create mode 100644 scrub/scrub.h
scrub/Makefile +2 -0
@@ -21,6 +21,7 @@ disk.h \ filemap.h \ fscounters.h \ inodes.h \ +scrub.h \ spacemap.h \ xfs_scrub.h
@@ -31,6 +32,7 @@ filemap.c \ fscounters.c \ inodes.c \ phase1.c \ +scrub.c \ spacemap.c \ xfs_scrub.c
scrub/common.c +19 -0
@@ -266,3 +266,22 @@ find_mountpoint(platform_mntent_close (&cursor);return found; } + +/* +* Sleep for 100ms * however many -b we got past the initial one. +* This is an (albeit clumsy) way to throttle scrub activity. +*/ +void +background_sleep (void ) +{ +unsigned long long time; +struct timespec tv; + +if (bg_mode <2 ) +return ; + + time =100000ULL * (bg_mode -1 ); + tv.tv_sec = time /1000000 ; + tv.tv_nsec = time %1000000 ; +nanosleep (&tv,NULL ); +}
scrub/common.h +1 -0
@@ -73,5 +73,6 @@ static inline int syncfs(int fd)#endif bool find_mountpoint (char *mtab,struct scrub_ctx *ctx); +void background_sleep (void );#endif /* XFS_SCRUB_COMMON_H_ */
scrub/phase1.c +11 -0
@@ -46,6 +46,7 @@#include "xfs_scrub.h" #include "common.h" #include "disk.h" +#include "scrub.h" /* Phase 1: Find filesystem geometry (and clean up after) */
@@ -168,6 +169,16 @@ _("Does not appear to be an XFS filesystem!"));return false; } +/* Do we have kernel-assisted metadata scrubbing? */ +if (!xfs_can_scrub_fs_metadata (ctx) || !xfs_can_scrub_inode (ctx) || + !xfs_can_scrub_bmap (ctx) || !xfs_can_scrub_dir (ctx) || + !xfs_can_scrub_attr (ctx) || !xfs_can_scrub_symlink (ctx) || + !xfs_can_scrub_parent (ctx)) { +str_error (ctx, ctx->mntpoint, +_ ("Kernel metadata scrubbing facility is required." )); +return false; + } +/* Go find the XFS devices if we have a usable fsmap. */ fs_table_initialise (0 ,NULL ,0 ,NULL ); errno =0 ;
scrub/scrub.c new file +621 -0
621 lines not on this page · raw message
scrub/scrub.h new file +62 -0
62 lines not on this page · raw message
PATCH 13/29 xfs_scrub: scan filesystem and AG metadata
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Scrub the filesystem and per-AG metadata.
--- scrub/Makefile | 1 scrub/phase2.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.c | 1 scrub/xfs_scrub.h | 1 4 files changed, 136 insertions(+) create mode 100644 scrub/phase2.c
scrub/Makefile +1 -0
@@ -32,6 +32,7 @@ filemap.c \ fscounters.c \ inodes.c \ phase1.c \ +phase2.c \ scrub.c \ spacemap.c \ xfs_scrub.c
scrub/phase2.c new file +133 -0
133 lines not on this page · raw message
scrub/xfs_scrub.c +1 -0
@@ -368,6 +368,7 @@ run_scrub_phases( }, { .descr = _("Check internal metadata."), + .fn = xfs_scan_metadata, }, { .descr = _("Scan all inodes."),
scrub/xfs_scrub.h +1 -0
@@ -94,5 +94,6 @@ struct scrub_ctx {void xfs_shutdown_fs (struct scrub_ctx *ctx);bool xfs_cleanup_fs (struct scrub_ctx *ctx);bool xfs_setup_fs (struct scrub_ctx *ctx); +bool xfs_scan_metadata (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 14/29 xfs_scrub: thread-safe stats counter
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create a threaded stats counter that we'll use to track scan progress. This includes things like how much of the disk blocks we've scanned, or later how much progress we've made in each phase.
--- include/ptvar.h | 32 +++++++++++++ libfrog/Makefile | 1 libfrog/ptvar.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/Makefile | 2 + scrub/counter.c | 104 ++++++++++++++++++++++++++++++++++++++++++ scrub/counter.h | 29 ++++++++++++ 6 files changed, 301 insertions(+) create mode 100644 include/ptvar.h create mode 100644 libfrog/ptvar.c create mode 100644 scrub/counter.c create mode 100644 scrub/counter.h
include/ptvar.h new file +32 -0
@@ -0,0 +1,32 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef LIBFROG_PERCPU_H_ +#define LIBFROG_PERCPU_H_ + +struct ptvar ; + +typedef bool (*ptvar_iter_fn )(struct ptvar *ptv,void *data,void *foreach_arg); + +struct ptvar *ptvar_init (size_t nr,size_t size); +void ptvar_free (struct ptvar *ptv); +void *ptvar_get (struct ptvar *ptv); +bool ptvar_foreach (struct ptvar *ptv,ptvar_iter_fn fn,void *foreach_arg); + +#endif /* LIBFROG_PERCPU_H_ */
libfrog/Makefile +1 -0
@@ -16,6 +16,7 @@ convert.c \ list_sort.c \ paths.c \ projects.c \ +ptvar.c \ radix-tree.c \ topology.c \ util.c \
libfrog/ptvar.c new file +133 -0
133 lines not on this page · raw message
scrub/Makefile +2 -0
@@ -17,6 +17,7 @@ endif # scrub_prereqs HFILES = \ common.h \ +counter.h \ disk.h \ filemap.h \ fscounters.h \
@@ -27,6 +28,7 @@ xfs_scrub.h CFILES = \ common.c \ +counter.c \ disk.c \ filemap.c \ fscounters.c \
scrub/counter.c new file +104 -0
104 lines not on this page · raw message
scrub/counter.h new file +29 -0
@@ -0,0 +1,29 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_COUNTER_H_ +#define XFS_SCRUB_COUNTER_H_ + +struct ptcounter ; +struct ptcounter *ptcounter_init (size_t nr); +void ptcounter_free (struct ptcounter *ptc); +void ptcounter_add (struct ptcounter *ptc,int64_t nr); +uint64_t ptcounter_value (struct ptcounter *ptc); + +#endif /* XFS_SCRUB_COUNTER_H_ */
PATCH 15/29 xfs_scrub: scan inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Scan all the inodes in the system for problems.
--- scrub/Makefile | 1 scrub/phase3.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.c | 1 scrub/xfs_scrub.h | 2 + 4 files changed, 156 insertions(+) create mode 100644 scrub/phase3.c
scrub/Makefile +1 -0
@@ -35,6 +35,7 @@ fscounters.c \ inodes.c \ phase1.c \ phase2.c \ +phase3.c \ scrub.c \ spacemap.c \ xfs_scrub.c
scrub/phase3.c new file +152 -0
152 lines not on this page · raw message
scrub/xfs_scrub.c +1 -0
@@ -372,6 +372,7 @@ run_scrub_phases( }, { .descr = _("Scan all inodes."), + .fn = xfs_scan_inodes, }, { .descr = _("Defer filesystem repairs."),
scrub/xfs_scrub.h +2 -0
@@ -86,6 +86,7 @@ struct scrub_ctx {unsigned long long runtime_errors;unsigned long long errors_found;unsigned long long warnings_found; +unsigned long long inodes_checked;bool need_repair;bool preen_triggers[XFS_SCRUB_TYPE_NR ]; };
@@ -95,5 +96,6 @@ void xfs_shutdown_fs(struct scrub_ctx *ctx);bool xfs_cleanup_fs (struct scrub_ctx *ctx);bool xfs_setup_fs (struct scrub_ctx *ctx);bool xfs_scan_metadata (struct scrub_ctx *ctx); +bool xfs_scan_inodes (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 16/29 xfs_scrub: check directory connectivity
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Opening directories by file handle will cause the kernel to perform parent lookups all the way to the root directory. Take advantage of this to ensure that directories actually connect to the root. Some day we'll have parent pointers and can make this more comprehensive.
--- scrub/Makefile | 1 + scrub/phase5.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.c | 1 + scrub/xfs_scrub.h | 1 + 4 files changed, 104 insertions(+) create mode 100644 scrub/phase5.c
scrub/Makefile +1 -0
@@ -36,6 +36,7 @@ inodes.c \ phase1.c \ phase2.c \ phase3.c \ +phase5.c \ scrub.c \ spacemap.c \ xfs_scrub.c
scrub/phase5.c new file +101 -0
101 lines not on this page · raw message
scrub/xfs_scrub.c +1 -0
@@ -380,6 +380,7 @@ run_scrub_phases( }, { .descr = _("Check directory tree."), + .fn = xfs_scan_connections, }, { .descr = _("Verify data file integrity."),
scrub/xfs_scrub.h +1 -0
@@ -97,5 +97,6 @@ bool xfs_cleanup_fs(struct scrub_ctx *ctx);bool xfs_setup_fs (struct scrub_ctx *ctx);bool xfs_scan_metadata (struct scrub_ctx *ctx);bool xfs_scan_inodes (struct scrub_ctx *ctx); +bool xfs_scan_connections (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 17/29 xfs_scrub: warn about suspicious characters in directory/xattr names
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Look for control characters and punctuation that interfere with shell globbing in directory entry names and extended attribute key names. Technically these aren't filesystem corruptions because names are arbitrary sequences of bytes, but they've been known to cause problems in the Unix environment so warn if we see them.
--- configure.ac | 2 + debian/control | 2 - include/builddefs.in | 1 m4/Makefile | 1 m4/package_attr.m4 | 23 ++++++ scrub/Makefile | 6 ++ scrub/common.c | 54 ++++++++++++++ scrub/common.h | 4 + scrub/phase5.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.h | 1 10 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 m4/package_attr.m4
configure.ac +2 -0
@@ -166,6 +166,8 @@ AC_HAVE_STATFS_FLAGS AC_HAVE_MAP_SYNC AC_HAVE_DEVMAPPER AC_HAVE_MALLINFO +AC_PACKAGE_WANT_ATTRIBUTES_H +AC_HAVE_LIBATTR if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
debian/control +1 -1
@@ -3,7 +3,7 @@ Section: admin Priority: optional Maintainer: XFS Development Team <[email protected]> Uploaders: Nathan Scott <[email protected]>, Anibal Monsalve Salazar <[email protected]> -Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev +Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev Standards-Version: 3.9.1 Homepage: https://xfs.wiki.kernel.org/
include/builddefs.in +1 -0
@@ -120,6 +120,7 @@ HAVE_STATFS_FLAGS = @have_statfs_flags@ HAVE_MAP_SYNC = @have_map_sync@ HAVE_DEVMAPPER = @have_devmapper@ HAVE_MALLINFO = @have_mallinfo@ +HAVE_LIBATTR = @have_libattr@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/Makefile +1 -0
@@ -17,6 +17,7 @@ LSRCFILES = \ package_blkid.m4 \ package_devmapper.m4 \ package_globals.m4 \ + package_attr.m4 \ package_libcdev.m4 \ package_pthread.m4 \ package_sanitizer.m4 \
m4/package_attr.m4 new file +23 -0
@@ -0,0 +1,23 @@ +AC_DEFUN([AC_PACKAGE_WANT_ATTRIBUTES_H], + [ + AC_CHECK_HEADERS(attr/attributes.h) + ]) + +# +# Check if we have a ATTR_ROOT flag and libattr structures +# +AC_DEFUN([AC_HAVE_LIBATTR], + [ AC_MSG_CHECKING([for struct attrlist_cursor]) + AC_TRY_COMPILE([ +#include <sys/types.h> +#include <attr/attributes.h> + ], [ +struct attrlist_cursor *cur; +struct attrlist *list; +struct attrlist_ent *ent; +int flags = ATTR_ROOT; + ], have_libattr=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + AC_SUBST(have_libattr) + ])
scrub/Makefile +6 -0
@@ -53,8 +53,14 @@ ifeq ($(HAVE_SYNCFS),yes) LCFLAGS += -DHAVE_SYNCFS endif +ifeq ($(HAVE_LIBATTR),yes) +LCFLAGS += -DHAVE_LIBATTR +endif + default: depend $(LTCOMMAND) +phase5.o: $(TOPDIR)/include/builddefs + include $(BUILDRULES) install: default $(INSTALL_SCRUB)
scrub/common.c +54 -0
57 lines not on this page · raw message
scrub/common.h +4 -0
@@ -74,5 +74,9 @@ static inline int syncfs(int fd)bool find_mountpoint (char *mtab,struct scrub_ctx *ctx);void background_sleep (void ); +char *string_escape (const char *in); + +#define TOO_MANY_NAME_WARNINGS 10000 +bool should_warn_about_name (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_COMMON_H_ */
scrub/phase5.c +192 -0
220 lines not on this page · raw message
scrub/xfs_scrub.h +1 -0
@@ -87,6 +87,7 @@ struct scrub_ctx {unsigned long long errors_found;unsigned long long warnings_found;unsigned long long inodes_checked; +unsigned long long naming_warnings;bool need_repair;bool preen_triggers[XFS_SCRUB_TYPE_NR ]; };
PATCH 18/29 xfs_scrub: warn about normalized Unicode name collisions
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Iterate all directory and xattr names to look for name collisions amongst Unicode normalized names. This is generally a sign of buggy programs or malicious duplicate files.
--- configure.ac | 2 debian/control | 2 include/builddefs.in | 2 m4/Makefile | 1 m4/package_unistring.m4 | 19 ++ scrub/Makefile | 12 + scrub/phase5.c | 62 +++++-- scrub/unicrash.c | 392 +++++++++++++++++++++++++++++++++++++++++++++++ scrub/unicrash.h | 47 ++++++ scrub/xfs_scrub.c | 1 10 files changed, 514 insertions(+), 26 deletions(-) create mode 100644 m4/package_unistring.m4 create mode 100644 scrub/unicrash.c create mode 100644 scrub/unicrash.h
configure.ac +2 -0
@@ -168,6 +168,8 @@ AC_HAVE_DEVMAPPER AC_HAVE_MALLINFO AC_PACKAGE_WANT_ATTRIBUTES_H AC_HAVE_LIBATTR +AC_PACKAGE_WANT_UNINORM_H +AC_HAVE_U8NORMALIZE if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
debian/control +1 -1
@@ -3,7 +3,7 @@ Section: admin Priority: optional Maintainer: XFS Development Team <[email protected]> Uploaders: Nathan Scott <[email protected]>, Anibal Monsalve Salazar <[email protected]> -Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev +Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev Standards-Version: 3.9.1 Homepage: https://xfs.wiki.kernel.org/
include/builddefs.in +2 -0
@@ -36,6 +36,7 @@ LIBEDITLINE = @libeditline@ LIBREADLINE = @libreadline@ LIBBLKID = @libblkid@ LIBDEVMAPPER = @libdevmapper@ +LIBUNISTRING = @libunistring@ LIBXFS = $(TOPDIR)/libxfs/libxfs.la LIBFROG = $(TOPDIR)/libfrog/libfrog.la LIBXCMD = $(TOPDIR)/libxcmd/libxcmd.la
@@ -121,6 +122,7 @@ HAVE_MAP_SYNC = @have_map_sync@ HAVE_DEVMAPPER = @have_devmapper@ HAVE_MALLINFO = @have_mallinfo@ HAVE_LIBATTR = @have_libattr@ +HAVE_U8NORMALIZE = @have_u8normalize@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/Makefile +1 -0
@@ -22,6 +22,7 @@ LSRCFILES = \ package_pthread.m4 \ package_sanitizer.m4 \ package_types.m4 \ + package_unistring.m4 \ package_utilies.m4 \ package_uuiddev.m4 \ multilib.m4 \
m4/package_unistring.m4 new file +19 -0
@@ -0,0 +1,19 @@ +AC_DEFUN([AC_PACKAGE_WANT_UNINORM_H], + [ AC_CHECK_HEADERS(uninorm.h) + if test $ac_cv_header_uninorm_h = no; then + AC_CHECK_HEADERS(uninorm.h,, [ + echo + echo 'WARNING: could not find a valid uninorm.h header.']) + fi + ]) + +AC_DEFUN([AC_HAVE_U8NORMALIZE], + [ AC_CHECK_LIB(unistring, u8_normalize,[ + libunistring=-lunistring + have_u8normalize=yes + ],[ + echo + echo 'WARNING: xfs_scrub will not be built with Unicode libraries.']) + AC_SUBST(libunistring) + AC_SUBST(have_u8normalize) + ])
scrub/Makefile +9 -3
@@ -24,6 +24,7 @@ fscounters.h \ inodes.h \ scrub.h \ spacemap.h \ +unicrash.h \ xfs_scrub.h CFILES = \
@@ -41,8 +42,8 @@ scrub.c \ spacemap.c \ xfs_scrub.c -LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) -LTDEPENDENCIES += $(LIBHANDLE) $(LIBFROG) +LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBUNISTRING) +LTDEPENDENCIES += $(LIBHANDLE) $(LIBFROG) $(LIBUNISTRING) LLDFLAGS = -static ifeq ($(HAVE_MALLINFO),yes)
@@ -57,9 +58,14 @@ ifeq ($(HAVE_LIBATTR),yes) LCFLAGS += -DHAVE_LIBATTR endif +ifeq ($(HAVE_U8NORMALIZE),yes) +CFILES += unicrash.c +LCFLAGS += -DHAVE_U8NORMALIZE +endif + default: depend $(LTCOMMAND) -phase5.o: $(TOPDIR)/include/builddefs +phase5.o unicrash.o xfs.o: $(TOPDIR)/include/builddefs include $(BUILDRULES)
scrub/phase5.c +40 -22
160 lines not on this page · raw message
scrub/unicrash.c new file +392 -0
392 lines not on this page · raw message
scrub/unicrash.h new file +47 -0
47 lines not on this page · raw message
scrub/xfs_scrub.c +1 -0
@@ -31,6 +31,7 @@#include "path.h" #include "xfs_scrub.h" #include "common.h" +#include "unicrash.h" /* * XFS Online Metadata Scrub (and Repair)
PATCH 19/29 xfs_scrub: create a bitmap data structure
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create an efficient tree-based bitmap data structure. We will use this during the data block scan to record the LBAs of IO errors so that we can report broken files to userspace.
--- scrub/Makefile | 2 scrub/bitmap.c | 410 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/bitmap.h | 38 +++++ 3 files changed, 450 insertions(+) create mode 100644 scrub/bitmap.c create mode 100644 scrub/bitmap.h
scrub/Makefile +2 -0
@@ -16,6 +16,7 @@ INSTALL_SCRUB = install-scrub endif # scrub_prereqs HFILES = \ +bitmap.h \ common.h \ counter.h \ disk.h \
@@ -28,6 +29,7 @@ unicrash.h \ xfs_scrub.h CFILES = \ +bitmap.c \ common.c \ counter.c \ disk.c \
scrub/bitmap.c new file +410 -0
410 lines not on this page · raw message
scrub/bitmap.h new file +38 -0
@@ -0,0 +1,38 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_BITMAP_H_ +#define XFS_SCRUB_BITMAP_H_ + +struct bitmap { +pthread_mutex_t bt_lock; +struct avl64tree_desc *bt_tree; +}; + +bool bitmap_init (struct bitmap **bmap); +void bitmap_free (struct bitmap **bmap); +bool bitmap_set (struct bitmap *bmap,uint64_t start,uint64_t length); +bool bitmap_iterate (struct bitmap *bmap, +bool (*fn)(uint64_t ,uint64_t ,void *),void *arg); +bool bitmap_test (struct bitmap *bmap,uint64_t start, +uint64_t len); +bool bitmap_empty (struct bitmap *bmap); +void bitmap_dump (struct bitmap *bmap); + +#endif /* XFS_SCRUB_BITMAP_H_ */
PATCH 20/29 xfs_scrub: create infrastructure to read verify data blocks
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Manage the scheduling, issuance, and reporting of data block verification reads. This enables us to combine adjacent (or nearly adjacent) read requests, and to take advantage of high-IOPS devices by issuing IO from multiple threads.
--- scrub/Makefile | 2 scrub/read_verify.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/read_verify.h | 50 ++++++++++ scrub/xfs_scrub.h | 3 + 4 files changed, 323 insertions(+) create mode 100644 scrub/read_verify.c create mode 100644 scrub/read_verify.h
scrub/Makefile +2 -0
@@ -23,6 +23,7 @@ disk.h \ filemap.h \ fscounters.h \ inodes.h \ +read_verify.h \ scrub.h \ spacemap.h \ unicrash.h \
@@ -40,6 +41,7 @@ phase1.c \ phase2.c \ phase3.c \ phase5.c \ +read_verify.c \ scrub.c \ spacemap.c \ xfs_scrub.c
scrub/read_verify.c new file +268 -0
268 lines not on this page · raw message
scrub/read_verify.h new file +50 -0
50 lines not on this page · raw message
scrub/xfs_scrub.h +3 -0
@@ -80,6 +80,9 @@ struct scrub_ctx {void *fshandle;size_t fshandle_len; +/* Data block read verification buffer */ +void *readbuf; +/* Mutable scrub state; use lock. */ pthread_mutex_t lock;unsigned long long max_errors;
PATCH 21/29 xfs_scrub: scrub file data blocks
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Read all data blocks from the disk, hoping to catch IO errors.
--- configure.ac | 2 include/builddefs.in | 2 m4/package_libcdev.m4 | 28 +++ scrub/Makefile | 7 - scrub/phase6.c | 516 +++++++++++++++++++++++++++++++++++++++++++++++++ scrub/vfs.c | 225 +++++++++++++++++++++ scrub/vfs.h | 31 +++ scrub/xfs_scrub.c | 4 scrub/xfs_scrub.h | 2 9 files changed, 815 insertions(+), 2 deletions(-) create mode 100644 scrub/phase6.c create mode 100644 scrub/vfs.c create mode 100644 scrub/vfs.h
configure.ac +2 -0
@@ -170,6 +170,8 @@ AC_PACKAGE_WANT_ATTRIBUTES_H AC_HAVE_LIBATTR AC_PACKAGE_WANT_UNINORM_H AC_HAVE_U8NORMALIZE +AC_HAVE_OPENAT +AC_HAVE_FSTATAT if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
include/builddefs.in +2 -0
@@ -123,6 +123,8 @@ HAVE_DEVMAPPER = @have_devmapper@ HAVE_MALLINFO = @have_mallinfo@ HAVE_LIBATTR = @have_libattr@ HAVE_U8NORMALIZE = @have_u8normalize@ +HAVE_OPENAT = @have_openat@ +HAVE_FSTATAT = @have_fstatat@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/package_libcdev.m4 +28 -0
@@ -362,3 +362,31 @@ AC_DEFUN([AC_HAVE_MALLINFO], AC_MSG_RESULT(no)) AC_SUBST(have_mallinfo) ]) + +# +# Check if we have a openat call +# +AC_DEFUN([AC_HAVE_OPENAT], + [ AC_CHECK_DECL([openat], + have_openat=yes, + [], + [#include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h>] + ) + AC_SUBST(have_openat) + ]) + +# +# Check if we have a fstatat call +# +AC_DEFUN([AC_HAVE_FSTATAT], + [ AC_CHECK_DECL([fstatat], + have_fstatat=yes, + [], + [#define _GNU_SOURCE + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h>]) + AC_SUBST(have_fstatat) + ])
scrub/Makefile +5 -2
@@ -8,9 +8,9 @@ include $(TOPDIR)/include/builddefs # On linux we get fsmap from the system or define it ourselves # so include this based on platform type. If this reverts to only # the autoconf check w/o local definition, change to testing HAVE_GETFSMAP -SCRUB_PREREQS=$(PKG_PLATFORM) +SCRUB_PREREQS=$(PKG_PLATFORM)$(HAVE_OPENAT)$(HAVE_FSTATAT) -ifeq ($(SCRUB_PREREQS),linux) +ifeq ($(SCRUB_PREREQS),linuxyesyes) LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub endif # scrub_prereqs
@@ -27,6 +27,7 @@ read_verify.h \ scrub.h \ spacemap.h \ unicrash.h \ +vfs.h \ xfs_scrub.h CFILES = \
@@ -41,9 +42,11 @@ phase1.c \ phase2.c \ phase3.c \ phase5.c \ +phase6.c \ read_verify.c \ scrub.c \ spacemap.c \ +vfs.c \ xfs_scrub.c LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBUNISTRING)
scrub/phase6.c new file +516 -0
516 lines not on this page · raw message
scrub/vfs.c new file +225 -0
225 lines not on this page · raw message
scrub/vfs.h new file +31 -0
@@ -0,0 +1,31 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_VFS_H_ +#define XFS_SCRUB_VFS_H_ + +typedef bool (*scan_fs_tree_dir_fn )(struct scrub_ctx *,const char *, +int ,void *); +typedef bool (*scan_fs_tree_dirent_fn )(struct scrub_ctx *,const char *, +int ,struct dirent *,struct stat *,void *); + +bool scan_fs_tree (struct scrub_ctx *ctx,scan_fs_tree_dir_fn dir_fn, +scan_fs_tree_dirent_fn dirent_fn,void *arg); + +#endif /* XFS_SCRUB_VFS_H_ */
scrub/xfs_scrub.c +4 -0
@@ -405,6 +405,10 @@ run_scrub_phases(/* Run all phases of the scrub tool. */ for (phase =1 , sp = phases; sp->fn; sp++, phase++) { +/* Turn on certain phases if user said to. */ +if (sp->fn ==DATASCAN_DUMMY_FN && scrub_data) + sp->fn = xfs_scan_blocks; +/* Skip certain phases unless they're turned on. */ if (sp->fn ==REPAIR_DUMMY_FN || sp->fn ==DATASCAN_DUMMY_FN )
scrub/xfs_scrub.h +2 -0
@@ -90,6 +90,7 @@ struct scrub_ctx {unsigned long long errors_found;unsigned long long warnings_found;unsigned long long inodes_checked; +unsigned long long bytes_checked;unsigned long long naming_warnings;bool need_repair;bool preen_triggers[XFS_SCRUB_TYPE_NR ];
@@ -102,5 +103,6 @@ bool xfs_setup_fs(struct scrub_ctx *ctx);bool xfs_scan_metadata (struct scrub_ctx *ctx);bool xfs_scan_inodes (struct scrub_ctx *ctx);bool xfs_scan_connections (struct scrub_ctx *ctx); +bool xfs_scan_blocks (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 22/29 xfs_scrub: optionally use SCSI READ VERIFY commands to scrub data blocks on disk
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
If we sense that we're talking to a raw SCSI disk, use the SCSI READ VERIFY command to ask the disk to verify a disk internally. This can sharply reduce the runtime of the data block verification phase on devices whose internal bandwidth exceeds their link bandwidth.
--- configure.ac | 2 + include/builddefs.in | 2 + m4/package_libcdev.m4 | 30 ++++++++++ scrub/Makefile | 8 +++ scrub/disk.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ scrub/disk.h | 1 6 files changed, 188 insertions(+), 1 deletion(-)
configure.ac +2 -0
@@ -172,6 +172,8 @@ AC_PACKAGE_WANT_UNINORM_H AC_HAVE_U8NORMALIZE AC_HAVE_OPENAT AC_HAVE_FSTATAT +AC_HAVE_SG_IO +AC_HAVE_HDIO_GETGEO if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
include/builddefs.in +2 -0
@@ -125,6 +125,8 @@ HAVE_LIBATTR = @have_libattr@ HAVE_U8NORMALIZE = @have_u8normalize@ HAVE_OPENAT = @have_openat@ HAVE_FSTATAT = @have_fstatat@ +HAVE_SG_IO = @have_sg_io@ +HAVE_HDIO_GETGEO = @have_hdio_getgeo@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/package_libcdev.m4 +30 -0
@@ -390,3 +390,33 @@ AC_DEFUN([AC_HAVE_FSTATAT], #include <unistd.h>]) AC_SUBST(have_fstatat) ]) + +# +# Check if we have the SG_IO ioctl +# +AC_DEFUN([AC_HAVE_SG_IO], + [ AC_MSG_CHECKING([for struct sg_io_hdr ]) + AC_TRY_COMPILE([#include <scsi/sg.h>], + [ + struct sg_io_hdr hdr; + ioctl(0, SG_IO, &hdr); + ], have_sg_io=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + AC_SUBST(have_sg_io) + ]) + +# +# Check if we have the HDIO_GETGEO ioctl +# +AC_DEFUN([AC_HAVE_HDIO_GETGEO], + [ AC_MSG_CHECKING([for struct hd_geometry ]) + AC_TRY_COMPILE([#include <linux/hdreg.h>], + [ + struct hd_geometry hdr; + ioctl(0, HDIO_GETGEO, &hdr); + ], have_hdio_getgeo=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + AC_SUBST(have_hdio_getgeo) + ])
scrub/Makefile +8 -0
@@ -70,6 +70,14 @@ CFILES += unicrash.c LCFLAGS += -DHAVE_U8NORMALIZE endif +ifeq ($(HAVE_SG_IO),yes) +LCFLAGS += -DHAVE_SG_IO +endif + +ifeq ($(HAVE_HDIO_GETGEO),yes) +LCFLAGS += -DHAVE_HDIO_GETGEO +endif + default: depend $(LTCOMMAND) phase5.o unicrash.o xfs.o: $(TOPDIR)/include/builddefs
scrub/disk.c +145 -1
193 lines not on this page · raw message
scrub/disk.h +1 -0
@@ -20,6 +20,7 @@ #ifndef XFS_SCRUB_DISK_H_ #define XFS_SCRUB_DISK_H_ +#define DISK_FLAG_SCSI_VERIFY 0x1 struct disk { struct stat d_sb; int d_fd;
PATCH 23/29 xfs_scrub: check summary counters
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Make sure the filesystem summary counters are somewhat close to what we can find by scanning the filesystem.
--- scrub/Makefile | 1 scrub/common.c | 28 ++++++ scrub/common.h | 4 + scrub/phase7.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/xfs_scrub.c | 3 - scrub/xfs_scrub.h | 1 6 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 scrub/phase7.c
scrub/Makefile +1 -0
@@ -43,6 +43,7 @@ phase2.c \ phase3.c \ phase5.c \ phase6.c \ +phase7.c \ read_verify.c \ scrub.c \ spacemap.c \
scrub/common.c +28 -0
@@ -339,3 +339,31 @@ _("More than %u naming warnings, shutting up."),return debug || verbose || res; } + +/* Decide if a value is within +/- (n/d) of a desired value. */ +bool +within_range ( +struct scrub_ctx *ctx, +unsigned long long value, +unsigned long long desired, +unsigned long long abs_threshold, +unsigned int n, +unsigned int d, +const char *descr) +{ +assert (n < d); + +/* Don't complain if difference does not exceed an absolute value. */ +if (value < desired && desired - value < abs_threshold) +return true; +if (value > desired && value - desired < abs_threshold) +return true; + +/* Complain if the difference exceeds a certain percentage. */ +if (value < desired * (d - n) / d) +return false; +if (value > desired * (d + n) / d) +return false; + +return true; +}
scrub/common.h +4 -0
@@ -79,4 +79,8 @@ char *string_escape(const char *in);#define TOO_MANY_NAME_WARNINGS 10000bool should_warn_about_name (struct scrub_ctx *ctx); +bool within_range (struct scrub_ctx *ctx,unsigned long long value, +unsigned long long desired,unsigned long long abs_threshold, +unsigned int n,unsigned int d,const char *descr); +#endif /* XFS_SCRUB_COMMON_H_ */
scrub/phase7.c new file +266 -0
266 lines not on this page · raw message
scrub/xfs_scrub.c +2 -1
@@ -389,6 +389,8 @@ run_scrub_phases( }, { .descr = _("Check summary counters."), + .fn = xfs_scan_summary, + .must_run = true, }, {NULL
@@ -458,7 +460,6 @@ main(int ret =SCRUB_RET_SUCCESS ;fprintf (stdout,"EXPERIMENTAL xfs_scrub program in use! Use at your own risk!\n" ); -return SCRUB_RET_OPERROR ; progname =basename (argv[0 ]);setlocale (LC_ALL ,"" );
scrub/xfs_scrub.h +1 -0
@@ -104,5 +104,6 @@ bool xfs_scan_metadata(struct scrub_ctx *ctx);bool xfs_scan_inodes (struct scrub_ctx *ctx);bool xfs_scan_connections (struct scrub_ctx *ctx);bool xfs_scan_blocks (struct scrub_ctx *ctx); +bool xfs_scan_summary (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 24/29 xfs_scrub: fstrim the free areas if there are no errors on the filesystem
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
If the filesystem scan comes out clean or fixes all the problems, call fstrim to clean out the free areas (if it's an ssd/thinp/whatever).
--- man/man8/xfs_scrub.8 | 3 ++ scrub/Makefile | 1 + scrub/phase4.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/vfs.c | 23 +++++++++++++++ scrub/vfs.h | 2 + scrub/xfs_scrub.c | 22 +++++++++++++- scrub/xfs_scrub.h | 3 ++ 7 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 scrub/phase4.c
man/man8/xfs_scrub.8 +3 -0
@@ -63,6 +63,9 @@ If is given, no action is taken if errors are found; this is the default behavior. .TP +.B \-k +Do not call FITRIM on the free space. +.TP .BI \-m " file" Search this file for mounted filesystems instead of /etc/mtab. .TP
scrub/Makefile +1 -0
@@ -41,6 +41,7 @@ inodes.c \ phase1.c \ phase2.c \ phase3.c \ +phase4.c \ phase5.c \ phase6.c \ phase7.c \
scrub/phase4.c new file +79 -0
79 lines not on this page · raw message
scrub/vfs.c +23 -0
@@ -223,3 +223,26 @@ _("Could not queue directory scan work."));free (sftd);return false; } + +#ifndef FITRIM +struct fstrim_range { +__u64 start; +__u64 len; +__u64 minlen; +}; +#define FITRIM _IOWR('X', 121, struct fstrim_range)/* Trim */ +#endif + +/* Call FITRIM to trim all the unused space in a filesystem. */ +void +fstrim ( +struct scrub_ctx *ctx) +{ +struct fstrim_range range = {0 }; +int error; + + range.len =ULLONG_MAX ; + error =ioctl (ctx->mnt_fd,FITRIM , &range); +if (error && errno !=EOPNOTSUPP && errno !=ENOTTY ) +perror (_ ("fstrim" )); +}
scrub/vfs.h +2 -0
@@ -28,4 +28,6 @@ typedef bool (*scan_fs_tree_dirent_fn)(struct scrub_ctx *, const char *,bool scan_fs_tree (struct scrub_ctx *ctx,scan_fs_tree_dir_fn dir_fn,scan_fs_tree_dirent_fn dirent_fn,void *arg); +void fstrim (struct scrub_ctx *ctx); +#endif /* XFS_SCRUB_VFS_H_ */
scrub/xfs_scrub.c +20 -2
@@ -146,6 +146,9 @@ static bool scrub_data;/* Size of a memory page. */ long page_size; +/* Should we FSTRIM after a successful run? */ +bool want_fstrim = true; +#define SCRUB_RET_SUCCESS (0)/* no problems left behind */ #define SCRUB_RET_CORRUPT (1)/* corruption remains on fs */ #define SCRUB_RET_UNOPTIMIZED (2)/* fs could be optimized */
@@ -161,6 +164,7 @@ usage(void)fprintf (stderr,_ (" -a count Stop after this many errors are found.\n" ));fprintf (stderr,_ (" -b Background mode.\n" ));fprintf (stderr,_ (" -e behavior What to do if errors are found.\n" )); +fprintf (stderr,_ (" -k Do not FITRIM the free space.\n" ));fprintf (stderr,_ (" -m path Path to /etc/mtab.\n" ));fprintf (stderr,_ (" -n Dry run. Do not modify anything.\n" ));fprintf (stderr,_ (" -T Display timing/usage information.\n" ));
@@ -408,8 +412,19 @@ run_scrub_phases(/* Run all phases of the scrub tool. */ for (phase =1 , sp = phases; sp->fn; sp++, phase++) {/* Turn on certain phases if user said to. */ -if (sp->fn ==DATASCAN_DUMMY_FN && scrub_data) +if (sp->fn ==DATASCAN_DUMMY_FN && scrub_data) { sp->fn = xfs_scan_blocks; + }else if (sp->fn ==REPAIR_DUMMY_FN ) { +if (ctx->mode ==SCRUB_MODE_PREEN ) { + sp->descr =_ ("Optimize filesystem." ); + sp->fn = xfs_optimize_fs; + sp->must_run = true; + }else if (ctx->mode ==SCRUB_MODE_REPAIR ) { + sp->descr =_ ("Repair filesystem." ); + sp->fn = xfs_repair_fs; + sp->must_run = true; + } + }/* Skip certain phases unless they're turned on. */ if (sp->fn == REPAIR_DUMMY_FN ||
@@ -469,7 +484,7 @@ main(pthread_mutex_init (&ctx.lock,NULL ); ctx.mode =SCRUB_MODE_DEFAULT ; ctx.error_action =ERRORS_CONTINUE ; -while ((c =getopt (argc, argv,"a:bde:m:nTvxVy" )) !=EOF ) { +while ((c =getopt (argc, argv,"a:bde:km:nTvxVy" )) !=EOF ) {switch (c) {case 'a' : ctx.max_errors =cvt_u64 (optarg,10 );
@@ -497,6 +512,9 @@ main(usage (); }break ; +case 'k' : + want_fstrim = false; +break ;case 'm' : mtab = optarg;break ;
scrub/xfs_scrub.h +3 -0
@@ -28,6 +28,7 @@ extern unsigned int debug;extern int nproc;extern bool verbose;extern long page_size; +extern bool want_fstrim;enum scrub_mode {SCRUB_MODE_DRY_RUN ,
@@ -105,5 +106,7 @@ bool xfs_scan_inodes(struct scrub_ctx *ctx);bool xfs_scan_connections (struct scrub_ctx *ctx);bool xfs_scan_blocks (struct scrub_ctx *ctx);bool xfs_scan_summary (struct scrub_ctx *ctx); +bool xfs_repair_fs (struct scrub_ctx *ctx); +bool xfs_optimize_fs (struct scrub_ctx *ctx);#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 25/29 xfs_scrub: progress indicator
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Implement a progress indicator.
--- man/man8/xfs_scrub.8 | 11 ++ scrub/Makefile | 6 + scrub/common.c | 12 ++- scrub/phase2.c | 14 +++ scrub/phase3.c | 16 ++++ scrub/phase4.c | 19 ++++ scrub/phase5.c | 2 scrub/phase6.c | 28 ++++++ scrub/progress.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/progress.h | 33 +++++++ scrub/read_verify.c | 2 scrub/scrub.c | 28 ++++++ scrub/xfs_scrub.c | 60 +++++++++++++ scrub/xfs_scrub.h | 14 +++ 14 files changed, 460 insertions(+), 8 deletions(-) create mode 100644 scrub/progress.c create mode 100644 scrub/progress.h
man/man8/xfs_scrub.8 +10 -1
@@ -4,7 +4,7 @@ xfs_scrub \- scrub the contents of an XFS filesystem .SH SYNOPSIS .B xfs_scrub [ -.B \-abemnTvxy +.B \-abCemnTvxy ] .RI "[" mount-point " | " block-device "]" .br
@@ -53,6 +53,15 @@ time. If given more than once, an artificial delay of 100us is added to each scrub call to reduce CPU overhead even further. .TP +.BI \-C " fd" +This option causes xfs_scrub to write progress information to the +specified file description so that the progress of the filesystem check +can be monitored. +If the file description is a tty, a fancy progress bar is rendered. +Otherwise, a simple numeric status dump compatible with the +.B fsck -C +format is output. +.TP .B \-e Specifies what happens when errors are detected. If
scrub/Makefile +4 -2
@@ -23,6 +23,7 @@ disk.h \ filemap.h \ fscounters.h \ inodes.h \ +progress.h \ read_verify.h \ scrub.h \ spacemap.h \
@@ -45,14 +46,15 @@ phase4.c \ phase5.c \ phase6.c \ phase7.c \ +progress.c \ read_verify.c \ scrub.c \ spacemap.c \ vfs.c \ xfs_scrub.c -LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBUNISTRING) -LTDEPENDENCIES += $(LIBHANDLE) $(LIBFROG) $(LIBUNISTRING) +LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBUNISTRING) $(LIBRT) +LTDEPENDENCIES += $(LIBHANDLE) $(LIBFROG) $(LIBUNISTRING) $(LIBRT) LLDFLAGS = -static ifeq ($(HAVE_MALLINFO),yes)
scrub/common.c +11 -1
@@ -27,6 +27,7 @@#include "path.h" #include "xfs_scrub.h" #include "common.h" +#include "progress.h" /* * Reporting Status to the Console
@@ -61,6 +62,14 @@ static const char *err_str[] = { [S_INFO] = "Info", }; +/* If stream is a tty, clear to end of line to clean up progress bar. */ +static inline const char *stream_start (FILE *stream) +{ +if (stream == stderr) +return stderr_isatty ?CLEAR_EOL :"" ; +return stdout_isatty ?CLEAR_EOL :"" ; +} +/* Print a warning string and some warning text. */ void __str_out(
@@ -84,7 +93,8 @@ __str_out( stream = stdout;pthread_mutex_lock (&ctx->lock); -fprintf (stream,"%s: %s: " ,_ (err_str[level]), descr); +fprintf (stream,"%s%s: %s: " ,stream_start (stream),_ (err_str[level]), + descr);if (error) {fprintf (stream,_ ("%s." ),strerror_r (error, buf,DESCR_BUFSZ )); }else {
scrub/phase2.c +14 -0
@@ -131,3 +131,17 @@ _("Could not queue filesystem scrub work."));workqueue_destroy (&wq);return moveon; } + +/* Estimate how much work we're going to do. */ +bool +xfs_estimate_metadata_work ( +struct scrub_ctx *ctx, +uint64_t *items, +unsigned int *nr_threads, +int *rshift) +{ + *items =xfs_scrub_estimate_ag_work (ctx); + *nr_threads =scrub_nproc (ctx); + *rshift =0 ; +return true; +}
scrub/phase3.c +16 -0
@@ -30,6 +30,7 @@#include "common.h" #include "counter.h" #include "inodes.h" +#include "progress.h" #include "scrub.h" /* Phase 3: Scan all inodes. */
@@ -116,6 +117,7 @@ xfs_scrub_inode( out:ptcounter_add (icount,1 ); +progress_add (1 );if (fd >=0 )close (fd);if (!moveon)
@@ -150,3 +152,17 @@ xfs_scan_inodes(ptcounter_free (ictx.icount);return ictx.moveon; } + +/* Estimate how much work we're going to do. */ +bool +xfs_estimate_inodes_work ( +struct scrub_ctx *ctx, +uint64_t *items, +unsigned int *nr_threads, +int *rshift) +{ + *items = ctx->mnt_sv.f_files - ctx->mnt_sv.f_ffree; + *nr_threads =scrub_nproc (ctx); + *rshift =0 ; +return true; +}
scrub/phase4.c +18 -1
@@ -31,6 +31,7 @@#include "workqueue.h" #include "xfs_scrub.h" #include "common.h" +#include "progress.h" #include "scrub.h" #include "vfs.h"
@@ -44,8 +45,10 @@ xfs_process_action_items(bool moveon = true;pthread_mutex_lock (&ctx->lock); -if (moveon && ctx->errors_found ==0 && want_fstrim) +if (moveon && ctx->errors_found ==0 && want_fstrim) {fstrim (ctx); +progress_add (1 ); + }pthread_mutex_unlock (&ctx->lock);return moveon;
@@ -77,3 +80,17 @@ _("Errors found, please re-run with -y."));return xfs_process_action_items (ctx); } + +/* Estimate how much work we're going to do. */ +bool +xfs_estimate_repair_work ( +struct scrub_ctx *ctx, +uint64_t *items, +unsigned int *nr_threads, +int *rshift) +{ + *items =1 ; + *nr_threads =1 ; + *rshift =0 ; +return true; +}
scrub/phase5.c +2 -0
@@ -34,6 +34,7 @@#include "xfs_scrub.h" #include "common.h" #include "inodes.h" +#include "progress.h" #include "scrub.h" #include "unicrash.h"
@@ -280,6 +281,7 @@ xfs_scrub_connections( } out: +progress_add (1 );if (fd >=0 )close (fd);if (!moveon)
scrub/phase6.c +28 -0
@@ -33,6 +33,7 @@#include "bitmap.h" #include "disk.h" #include "filemap.h" +#include "fscounters.h" #include "inodes.h" #include "read_verify.h" #include "spacemap.h"
@@ -514,3 +515,30 @@ _("Could not create media verifier."));ptvar_free (ve.rvstate);return moveon; } + +/* Estimate how much work we're going to do. */ +bool +xfs_estimate_verify_work ( +struct scrub_ctx *ctx, +uint64_t *items, +unsigned int *nr_threads, +int *rshift) +{ +unsigned long long d_blocks; +unsigned long long d_bfree; +unsigned long long r_blocks; +unsigned long long r_bfree; +unsigned long long f_files; +unsigned long long f_free; +bool moveon; + + moveon =xfs_scan_estimate_blocks (ctx, &d_blocks, &d_bfree, + &r_blocks, &r_bfree, &f_files, &f_free); +if (!moveon) +return moveon; + + *items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->blocklog; + *nr_threads =disk_heads (ctx->datadev); + *rshift =20 ; +return moveon; +}
scrub/progress.c new file +223 -0
223 lines not on this page · raw message
scrub/progress.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* Copyright (C) 2018 Oracle. All Rights Reserved. +* +* Author: Darrick J. Wong <[email protected]> +* +* 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 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it would 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, write the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef XFS_SCRUB_PROGRESS_H_ +#define XFS_SCRUB_PROGRESS_H_ + +#define CLEAR_EOL "\033[K" +#define START_IGNORE '\001' +#define END_IGNORE '\002' + +bool progress_init_phase (struct scrub_ctx *ctx,FILE *progress_fp, +unsigned int phase,uint64_t max,int rshift, +unsigned int nr_threads); +void progress_end_phase (void ); +void progress_add (uint64_t x); + +#endif /* XFS_SCRUB_PROGRESS_H_ */
scrub/read_verify.c +2 -0
@@ -31,6 +31,7 @@#include "counter.h" #include "disk.h" #include "read_verify.h" +#include "progress.h" /* * Read Verify Pool
@@ -154,6 +155,7 @@ read_verify( errno, rv->io_end_arg); } +progress_add (len); verified += len; rv->io_start += len; rv->io_length -= len;
scrub/scrub.c +28 -0
@@ -31,6 +31,7 @@#include "path.h" #include "xfs_scrub.h" #include "common.h" +#include "progress.h" #include "scrub.h" #include "xfs_errortag.h"
@@ -343,6 +344,7 @@ xfs_scrub_metadata(/* Check the item. */ fix =xfs_check_metadata (ctx, ctx->mnt_fd, &meta, false); +progress_add (1 );switch (fix) {case CHECK_ABORT :return false;
@@ -416,6 +418,32 @@ xfs_scrub_fs_metadata(return xfs_scrub_metadata (ctx,ST_FS ,0 ); } +/* How many items do we have to check? */ +unsigned int +xfs_scrub_estimate_ag_work ( +struct scrub_ctx *ctx) +{ +const struct scrub_descr *sc; +int type; +unsigned int estimate =0 ; + + sc = scrubbers; +for (type =0 ; type <XFS_SCRUB_TYPE_NR ; type++, sc++) { +switch (sc->type) { +case ST_AGHEADER : +case ST_PERAG : + estimate += ctx->geo.agcount; +break ; +case ST_FS : + estimate++; +break ; +default : +break ; + } + } +return estimate; +} +/* Scrub inode metadata. */ static bool __xfs_scrub_file(
scrub/xfs_scrub.c +57 -3
173 lines not on this page · raw message
scrub/xfs_scrub.h +14 -0
@@ -29,6 +29,8 @@ extern int nproc;extern bool verbose;extern long page_size;extern bool want_fstrim; +extern bool stderr_isatty; +extern bool stdout_isatty;enum scrub_mode {SCRUB_MODE_DRY_RUN ,
@@ -109,4 +111,16 @@ bool xfs_scan_summary(struct scrub_ctx *ctx);bool xfs_repair_fs (struct scrub_ctx *ctx);bool xfs_optimize_fs (struct scrub_ctx *ctx); +/* Progress estimator functions */ +uint64_t xfs_estimate_inodes (struct scrub_ctx *ctx); +unsigned int xfs_scrub_estimate_ag_work (struct scrub_ctx *ctx); +bool xfs_estimate_metadata_work (struct scrub_ctx *ctx,uint64_t *items, +unsigned int *nr_threads,int *rshift); +bool xfs_estimate_inodes_work (struct scrub_ctx *ctx,uint64_t *items, +unsigned int *nr_threads,int *rshift); +bool xfs_estimate_repair_work (struct scrub_ctx *ctx,uint64_t *items, +unsigned int *nr_threads,int *rshift); +bool xfs_estimate_verify_work (struct scrub_ctx *ctx,uint64_t *items, +unsigned int *nr_threads,int *rshift); +#endif /* XFS_SCRUB_XFS_SCRUB_H_ */
PATCH 26/29 xfs_scrub: create a script to scrub all xfs filesystems
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create an xfs_scrub_all command to find all XFS filesystems and run an online scrub against them all.
--- debian/control | 3 + debian/rules | 1 man/man8/xfs_scrub_all.8 | 32 ++++++++++ scrub/Makefile | 15 ++++ scrub/xfs_scrub_all.in | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 201 insertions(+), 4 deletions(-) create mode 100644 man/man8/xfs_scrub_all.8 create mode 100644 scrub/xfs_scrub_all.in
debian/control +2 -1
@@ -3,12 +3,13 @@ Section: admin Priority: optional Maintainer: XFS Development Team <[email protected]> Uploaders: Nathan Scott <[email protected]>, Anibal Monsalve Salazar <[email protected]> -Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev +Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev, dh-python Standards-Version: 3.9.1 Homepage: https://xfs.wiki.kernel.org/ Package: xfsprogs Depends: ${shlibs:Depends}, ${misc:Depends} +Recommends: ${python3:Depends}, util-linux Provides: fsck-backend Suggests: xfsdump, acl, attr, quota Breaks: xfsdump (<< 3.0.0)
debian/rules +1 -0
@@ -76,6 +76,7 @@ binary-arch: checkroot built $(pkgdi) $(MAKE) -C debian install-d-i $(pkgme) $(MAKE) dist rmdir debian/xfslibs-dev/usr/share/doc/xfsprogs + dh_python3 dh_installdocs dh_installchangelogs dh_strip
man/man8/xfs_scrub_all.8 new file +32 -0
@@ -0,0 +1,32 @@ +.TH xfs_scrub_all 8 +.SH NAME +xfs_scrub_all \- scrub all mounted XFS filesystems +.SH SYNOPSIS +.B xfs_scrub_all +.SH DESCRIPTION +.B xfs_scrub_all +attempts to read and check all the metadata on all mounted XFS filesystems. +The online scrub is performed via the +.B xfs_scrub +tool, either by running it directly or by using systemd to start it +in a restricted fashion. +Mounted filesystems are mapped to physical storage devices so that scrub +operations can be run in parallel so long as no two scrubbers access +the same device simultaneously. +.SH EXIT CODE +The exit code returned by +.B xfs_scrub_all +is the sum of the following conditions: +.br +\ 0\ \-\ No errors +.br +\ 4\ \-\ File system errors left uncorrected +.br +\ 8\ \-\ Operational error +.br +\ 16\ \-\ Usage or syntax error +.TP +These are the same error codes returned by xfs_scrub. +.br +.SH SEE ALSO +.BR xfs_scrub (8).
scrub/Makefile +12 -3
@@ -13,6 +13,8 @@ SCRUB_PREREQS=$(PKG_PLATFORM)$(HAVE_OPENAT)$(HAVE_FSTATAT) ifeq ($(SCRUB_PREREQS),linuxyesyes) LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub +XFS_SCRUB_ALL_PROG = xfs_scrub_all +XFS_SCRUB_ARGS = -b -n endif # scrub_prereqs HFILES = \
@@ -82,17 +84,24 @@ ifeq ($(HAVE_HDIO_GETGEO),yes) LCFLAGS += -DHAVE_HDIO_GETGEO endif -default: depend $(LTCOMMAND) +default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) + +xfs_scrub_all: xfs_scrub_all.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" \ + -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" < $< > $@ + $(Q)chmod a+x $@ phase5.o unicrash.o xfs.o: $(TOPDIR)/include/builddefs include $(BUILDRULES) -install: default $(INSTALL_SCRUB) +install: $(INSTALL_SCRUB) -install-scrub: +install-scrub: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) + $(INSTALL) -m 755 $(XFS_SCRUB_ALL_PROG) $(PKG_ROOT_SBIN_DIR) install-dev:
scrub/xfs_scrub_all.in new file +154 -0
154 lines not on this page · raw message
PATCH v2 26/29 xfs_scrub: create a script to scrub all xfs filesystems
From: Darrick J. Wong <[email protected]>
Subject: [PATCH] xfs_scrub: create a script to scrub all xfs filesystems
Create an xfs_scrub_all command to find all XFS filesystems and run an online scrub against them all.
---
v2: fix some of the debian packaging weirdness, kudos to Nathan Scott!
--- debian/control | 4 + man/man8/xfs_scrub_all.8 | 32 ++++++++++ scrub/Makefile | 15 ++++ scrub/xfs_scrub_all.in | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 man/man8/xfs_scrub_all.8 create mode 100644 scrub/xfs_scrub_all.in
debian/control +2 -2
@@ -3,12 +3,12 @@ Section: admin Priority: optional Maintainer: XFS Development Team <[email protected]> Uploaders: Nathan Scott <[email protected]>, Anibal Monsalve Salazar <[email protected]> -Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev +Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev, dh-python Standards-Version: 3.9.1 Homepage: https://xfs.wiki.kernel.org/ Package: xfsprogs -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, python3:any Provides: fsck-backend Suggests: xfsdump, acl, attr, quota Breaks: xfsdump (<< 3.0.0)
man/man8/xfs_scrub_all.8 new file +32 -0
@@ -0,0 +1,32 @@ +.TH xfs_scrub_all 8 +.SH NAME +xfs_scrub_all \- scrub all mounted XFS filesystems +.SH SYNOPSIS +.B xfs_scrub_all +.SH DESCRIPTION +.B xfs_scrub_all +attempts to read and check all the metadata on all mounted XFS filesystems. +The online scrub is performed via the +.B xfs_scrub +tool, either by running it directly or by using systemd to start it +in a restricted fashion. +Mounted filesystems are mapped to physical storage devices so that scrub +operations can be run in parallel so long as no two scrubbers access +the same device simultaneously. +.SH EXIT CODE +The exit code returned by +.B xfs_scrub_all +is the sum of the following conditions: +.br +\ 0\ \-\ No errors +.br +\ 4\ \-\ File system errors left uncorrected +.br +\ 8\ \-\ Operational error +.br +\ 16\ \-\ Usage or syntax error +.TP +These are the same error codes returned by xfs_scrub. +.br +.SH SEE ALSO +.BR xfs_scrub (8).
scrub/Makefile +12 -3
@@ -13,6 +13,8 @@ SCRUB_PREREQS=$(PKG_PLATFORM)$(HAVE_OPENAT)$(HAVE_FSTATAT) ifeq ($(SCRUB_PREREQS),linuxyesyes) LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub +XFS_SCRUB_ALL_PROG = xfs_scrub_all +XFS_SCRUB_ARGS = -b -n endif # scrub_prereqs HFILES = \
@@ -82,17 +84,24 @@ ifeq ($(HAVE_HDIO_GETGEO),yes) LCFLAGS += -DHAVE_HDIO_GETGEO endif -default: depend $(LTCOMMAND) +default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) + +xfs_scrub_all: xfs_scrub_all.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" \ + -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" < $< > $@ + $(Q)chmod a+x $@ phase5.o unicrash.o xfs.o: $(TOPDIR)/include/builddefs include $(BUILDRULES) -install: default $(INSTALL_SCRUB) +install: $(INSTALL_SCRUB) -install-scrub: +install-scrub: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) + $(INSTALL) -m 755 $(XFS_SCRUB_ALL_PROG) $(PKG_ROOT_SBIN_DIR) install-dev:
scrub/xfs_scrub_all.in new file +154 -0
154 lines not on this page · raw message
PATCH 27/29 xfs_scrub: integrate services with systemd
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create a systemd service unit so that we can run the online scrubber under systemd with (somewhat) appropriate containment.
--- .gitignore | 4 ++ configure.ac | 2 + debian/postinst | 3 ++ include/builddefs.in | 4 ++ m4/Makefile | 1 + m4/package_services.m4 | 73 ++++++++++++++++++++++++++++++++++++++ scrub/Makefile | 36 ++++++++++++++++++- scrub/xfs_scrub.c | 32 +++++++++++++++++ scrub/[email protected] | 19 ++++++++++ scrub/xfs_scrub_all.cron.in | 1 + scrub/xfs_scrub_all.in | 49 ++++++++++++++++++++++++++ scrub/xfs_scrub_all.service.in | 9 +++++ scrub/xfs_scrub_all.timer | 11 ++++++ scrub/xfs_scrub_fail | 26 ++++++++++++++ scrub/[email protected] | 10 +++++ 15 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 m4/package_services.m4 create mode 100644 scrub/[email protected] create mode 100644 scrub/xfs_scrub_all.cron.in create mode 100644 scrub/xfs_scrub_all.service.in create mode 100644 scrub/xfs_scrub_all.timer create mode 100755 scrub/xfs_scrub_fail create mode 100644 scrub/[email protected]
.gitignore +4 -0
@@ -69,6 +69,10 @@ cscope.* /rtcp/xfs_rtcp /spaceman/xfs_spaceman /scrub/xfs_scrub +/scrub/[email protected] +/scrub/xfs_scrub_all +/scrub/xfs_scrub_all.service +/scrub/[email protected] # generated crc files /libxfs/crc32selftest
configure.ac +2 -0
@@ -174,6 +174,8 @@ AC_HAVE_OPENAT AC_HAVE_FSTATAT AC_HAVE_SG_IO AC_HAVE_HDIO_GETGEO +AC_CONFIG_SYSTEMD_SYSTEM_UNIT_DIR +AC_CONFIG_CROND_DIR if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
debian/postinst +3 -0
@@ -8,6 +8,9 @@ case "${1}" in then update-initramfs -u fi + if [ -x /bin/systemctl ]; then + /bin/systemctl daemon-reload + fi ;; abort-upgrade|abort-remove|abort-deconfigure)
include/builddefs.in +4 -0
@@ -127,6 +127,10 @@ HAVE_OPENAT = @have_openat@ HAVE_FSTATAT = @have_fstatat@ HAVE_SG_IO = @have_sg_io@ HAVE_HDIO_GETGEO = @have_hdio_getgeo@ +HAVE_SYSTEMD = @have_systemd@ +SYSTEMD_SYSTEM_UNIT_DIR = @systemd_system_unit_dir@ +HAVE_CROND = @have_crond@ +CROND_DIR = @crond_dir@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/Makefile +1 -0
@@ -21,6 +21,7 @@ LSRCFILES = \ package_libcdev.m4 \ package_pthread.m4 \ package_sanitizer.m4 \ + package_services.m4 \ package_types.m4 \ package_unistring.m4 \ package_utilies.m4 \
m4/package_services.m4 new file +73 -0
73 lines not on this page · raw message
scrub/Makefile +35 -1
@@ -15,6 +15,19 @@ LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub XFS_SCRUB_ALL_PROG = xfs_scrub_all XFS_SCRUB_ARGS = -b -n +ifeq ($(HAVE_SYSTEMD),yes) +INSTALL_SCRUB += install-systemd +SYSTEMD_SERVICES = [email protected] xfs_scrub_all.service xfs_scrub_all.timer [email protected] +OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) +endif +ifeq ($(HAVE_CROND),yes) +INSTALL_SCRUB += install-crond +CRONTABS = xfs_scrub_all.cron +OPTIONAL_TARGETS += $(CRONTABS) +# Don't enable the crontab by default for now +CROND_DIR = $(PKG_LIB_DIR)/$(PKG_NAME) +endif + endif # scrub_prereqs HFILES = \
@@ -84,7 +97,7 @@ ifeq ($(HAVE_HDIO_GETGEO),yes) LCFLAGS += -DHAVE_HDIO_GETGEO endif -default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) +default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(OPTIONAL_TARGETS) xfs_scrub_all: xfs_scrub_all.in @echo " [SED] $@"
@@ -98,6 +111,27 @@ include $(BUILDRULES) install: $(INSTALL_SCRUB) +%.service: %.service.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" \ + -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" \ + -e "s|@pkg_lib_dir@|$(PKG_LIB_DIR)|g" \ + -e "s|@pkg_name@|$(PKG_NAME)|g" < $< > $@ + +%.cron: %.cron.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" < $< > $@ + +install-systemd: default $(SYSTEMD_SERVICES) + $(INSTALL) -m 755 -d $(SYSTEMD_SYSTEM_UNIT_DIR) + $(INSTALL) -m 644 $(SYSTEMD_SERVICES) $(SYSTEMD_SYSTEM_UNIT_DIR) + $(INSTALL) -m 755 -d $(PKG_LIB_DIR)/$(PKG_NAME) + $(INSTALL) -m 755 xfs_scrub_fail $(PKG_LIB_DIR)/$(PKG_NAME) + +install-crond: default $(CRONTABS) + $(INSTALL) -m 755 -d $(CROND_DIR) + $(INSTALL) -m 644 $(CRONTABS) $(CROND_DIR) + install-scrub: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR)
scrub/xfs_scrub.c +32 -0
@@ -118,6 +118,10 @@* XFS_SCRUB_NO_SCSI_VERIFY -- disable SCSI VERIFY (if present) * XFS_SCRUB_PHASE -- run only this scrub phase * XFS_SCRUB_THREADS -- start exactly this number of threads +* +* Available even in non-debug mode: +* SERVICE_MODE -- compress all error codes to 1 for LSB +* service action compliance */ /* Program name; needed for libfrog error reports. */
@@ -154,6 +158,12 @@ bool want_fstrim = true;bool stderr_isatty;bool stdout_isatty; +/* +* If we are running as a service, we need to be careful about what +* error codes we return to the calling process. +*/ +static bool is_service; +#define SCRUB_RET_SUCCESS (0)/* no problems left behind */ #define SCRUB_RET_CORRUPT (1)/* corruption remains on fs */ #define SCRUB_RET_UNOPTIMIZED (2)/* fs could be optimized */
@@ -624,6 +634,9 @@ _("Only one of the options -n or -y may be specified.\n"));if (stdout_isatty && !progress_fp) progress_fp =fdopen (1 ,"w+" ); +if (getenv ("SERVICE_MODE" )) + is_service = true; +/* Find the mount record for the passed-in argument. */ if (stat (argv[optind], &ctx.mnt_sb) <0 ) { fprintf(stderr,
@@ -729,5 +742,24 @@ _("%s: %llu warnings found.\n"),free (ctx.blkdev);free (ctx.mntpoint); +/* +* If we're being run as a service, the return code must fit the LSB +* init script action error guidelines, which is to say that we +* compress all errors to 1 ("generic or unspecified error", LSB 5.0 +* section 22.2) and hope the admin will scan the log for what +* actually happened. +* +* We have to sleep 2 seconds here because journald uses the pid to +* connect our log messages to the systemd service. This is critical +* for capturing all the log messages if the scrub fails, because the +* fail service uses the service name to gather log messages for the +* error report. +*/ +if (is_service) { +sleep (2 ); +if (ret !=SCRUB_RET_SUCCESS ) +return 1 ; + } +return ret; }
scrub/[email protected] new file +19 -0
@@ -0,0 +1,19 @@ +[Unit] +Description=Online XFS Metadata Check for %I +OnFailure=xfs_scrub_fail@%i.service + +[Service] +Type=oneshot +WorkingDirectory=%I +PrivateNetwork=true +ProtectSystem=full +ProtectHome=read-only +PrivateTmp=yes +AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_SYS_RAWIO +NoNewPrivileges=yes +User=nobody +IOSchedulingClass=idle +CPUSchedulingPolicy=idle +Environment=SERVICE_MODE=1 +ExecStart=@sbindir@/xfs_scrub @scrub_args@ %I +SyslogIdentifier=%N
scrub/xfs_scrub_all.cron.in new file +1 -0
@@ -0,0 +1 @@ +10 3 * * 0 root test -e /run/systemd/system || @sbindir@/xfs_scrub_all
scrub/xfs_scrub_all.in +49 -0
83 lines not on this page · raw message
scrub/xfs_scrub_all.service.in new file +9 -0
@@ -0,0 +1,9 @@ +[Unit] +Description=Online XFS Metadata Check for All Filesystems +ConditionACPower=true + +[Service] +Type=oneshot +Environment=SERVICE_MODE=1 +ExecStart=@sbindir@/xfs_scrub_all +SyslogIdentifier=xfs_scrub_all
scrub/xfs_scrub_all.timer new file +11 -0
@@ -0,0 +1,11 @@ +[Unit] +Description=Periodic XFS Online Metadata Check for All Filesystems + +[Timer] +# Run on Sunday at 3:10am, to avoid running afoul of DST changes +OnCalendar=Sun *-*-* 03:10:00 +RandomizedDelaySec=60 +Persistent=true + +[Install] +WantedBy=timers.target
scrub/xfs_scrub_fail new file +26 -0
@@ -0,0 +1,26 @@ +#!/bin/bash + +# Email logs of failed xfs_scrub unit runs + +mailer=/usr/sbin/sendmail +recipient="$1" +test -z "${recipient}" && exit 0 +mntpoint="$2" +test -z "${mntpoint}" && exit 0 +hostname="$(hostname -f 2>/dev/null)" +test -z "${hostname}" && hostname="${HOSTNAME}" +if [ ! -x "${mailer}" ]; then + echo "${mailer}: Mailer program not found." + exit 1 +fi + +(cat << ENDL +To: $1 +From: <xfs_scrub@${hostname}> +Subject: xfs_scrub failure on ${mntpoint} + +So sorry, the automatic xfs_scrub of ${mntpoint} on ${hostname} failed. + +A log of what happened follows: +ENDL +systemctl status --full --lines 4294967295 "xfs_scrub@${mntpoint}") | "${mailer}" -t -i
scrub/[email protected] new file +10 -0
@@ -0,0 +1,10 @@ +[Unit] +Description=Online XFS Metadata Check Failure Reporting for %I + +[Service] +Type=oneshot +Environment=EMAIL_ADDR=root +ExecStart=@pkg_lib_dir@/@pkg_name@/xfs_scrub_fail "${EMAIL_ADDR}" %I +User=mail +Group=mail +SupplementaryGroups=systemd-journal
PATCH v2 27/29 xfs_scrub: integrate services with systemd
From: Darrick J. Wong <[email protected]>
Create a systemd service unit so that we can run the online scrubber under systemd with (somewhat) appropriate containment.
---
v2: fix some of the debian packaging weirdness, kudos to Nathan Scott!
--- .gitignore | 4 ++ configure.ac | 2 + debian/postinst | 3 ++ include/builddefs.in | 4 ++ m4/Makefile | 1 + m4/package_services.m4 | 73 ++++++++++++++++++++++++++++++++++++++ scrub/Makefile | 36 ++++++++++++++++++- scrub/xfs_scrub.c | 32 +++++++++++++++++ scrub/[email protected] | 20 ++++++++++ scrub/xfs_scrub_all.cron.in | 1 + scrub/xfs_scrub_all.in | 49 ++++++++++++++++++++++++++ scrub/xfs_scrub_all.service.in | 10 +++++ scrub/xfs_scrub_all.timer | 11 ++++++ scrub/xfs_scrub_fail | 26 ++++++++++++++ scrub/[email protected] | 10 +++++ 15 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 m4/package_services.m4 create mode 100644 scrub/[email protected] create mode 100644 scrub/xfs_scrub_all.cron.in create mode 100644 scrub/xfs_scrub_all.service.in create mode 100644 scrub/xfs_scrub_all.timer create mode 100755 scrub/xfs_scrub_fail create mode 100644 scrub/[email protected]
.gitignore +4 -0
@@ -69,6 +69,10 @@ cscope.* /rtcp/xfs_rtcp /spaceman/xfs_spaceman /scrub/xfs_scrub +/scrub/[email protected] +/scrub/xfs_scrub_all +/scrub/xfs_scrub_all.service +/scrub/[email protected] # generated crc files /libxfs/crc32selftest
configure.ac +2 -0
@@ -174,6 +174,8 @@ AC_HAVE_OPENAT AC_HAVE_FSTATAT AC_HAVE_SG_IO AC_HAVE_HDIO_GETGEO +AC_CONFIG_SYSTEMD_SYSTEM_UNIT_DIR +AC_CONFIG_CROND_DIR if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
debian/postinst +3 -0
@@ -8,6 +8,9 @@ case "${1}" in then update-initramfs -u fi + if [ -x /bin/systemctl ]; then + /bin/systemctl daemon-reload + fi ;; abort-upgrade|abort-remove|abort-deconfigure)
include/builddefs.in +4 -0
@@ -127,6 +127,10 @@ HAVE_OPENAT = @have_openat@ HAVE_FSTATAT = @have_fstatat@ HAVE_SG_IO = @have_sg_io@ HAVE_HDIO_GETGEO = @have_hdio_getgeo@ +HAVE_SYSTEMD = @have_systemd@ +SYSTEMD_SYSTEM_UNIT_DIR = @systemd_system_unit_dir@ +HAVE_CROND = @have_crond@ +CROND_DIR = @crond_dir@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/Makefile +1 -0
@@ -21,6 +21,7 @@ LSRCFILES = \ package_libcdev.m4 \ package_pthread.m4 \ package_sanitizer.m4 \ + package_services.m4 \ package_types.m4 \ package_unistring.m4 \ package_utilies.m4 \
m4/package_services.m4 new file +73 -0
73 lines not on this page · raw message
scrub/Makefile +35 -1
@@ -15,6 +15,19 @@ LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub XFS_SCRUB_ALL_PROG = xfs_scrub_all XFS_SCRUB_ARGS = -b -n +ifeq ($(HAVE_SYSTEMD),yes) +INSTALL_SCRUB += install-systemd +SYSTEMD_SERVICES = [email protected] xfs_scrub_all.service xfs_scrub_all.timer [email protected] +OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) +endif +ifeq ($(HAVE_CROND),yes) +INSTALL_SCRUB += install-crond +CRONTABS = xfs_scrub_all.cron +OPTIONAL_TARGETS += $(CRONTABS) +# Don't enable the crontab by default for now +CROND_DIR = $(PKG_LIB_DIR)/$(PKG_NAME) +endif + endif # scrub_prereqs HFILES = \
@@ -84,7 +97,7 @@ ifeq ($(HAVE_HDIO_GETGEO),yes) LCFLAGS += -DHAVE_HDIO_GETGEO endif -default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) +default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(OPTIONAL_TARGETS) xfs_scrub_all: xfs_scrub_all.in @echo " [SED] $@"
@@ -98,6 +111,27 @@ include $(BUILDRULES) install: $(INSTALL_SCRUB) +%.service: %.service.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" \ + -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" \ + -e "s|@pkg_lib_dir@|$(PKG_LIB_DIR)|g" \ + -e "s|@pkg_name@|$(PKG_NAME)|g" < $< > $@ + +%.cron: %.cron.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" < $< > $@ + +install-systemd: default $(SYSTEMD_SERVICES) + $(INSTALL) -m 755 -d $(SYSTEMD_SYSTEM_UNIT_DIR) + $(INSTALL) -m 644 $(SYSTEMD_SERVICES) $(SYSTEMD_SYSTEM_UNIT_DIR) + $(INSTALL) -m 755 -d $(PKG_LIB_DIR)/$(PKG_NAME) + $(INSTALL) -m 755 xfs_scrub_fail $(PKG_LIB_DIR)/$(PKG_NAME) + +install-crond: default $(CRONTABS) + $(INSTALL) -m 755 -d $(CROND_DIR) + $(INSTALL) -m 644 $(CRONTABS) $(CROND_DIR) + install-scrub: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR)
scrub/xfs_scrub.c +32 -0
@@ -118,6 +118,10 @@* XFS_SCRUB_NO_SCSI_VERIFY -- disable SCSI VERIFY (if present) * XFS_SCRUB_PHASE -- run only this scrub phase * XFS_SCRUB_THREADS -- start exactly this number of threads +* +* Available even in non-debug mode: +* SERVICE_MODE -- compress all error codes to 1 for LSB +* service action compliance */ /* Program name; needed for libfrog error reports. */
@@ -154,6 +158,12 @@ bool want_fstrim = true;bool stderr_isatty;bool stdout_isatty; +/* +* If we are running as a service, we need to be careful about what +* error codes we return to the calling process. +*/ +static bool is_service; +#define SCRUB_RET_SUCCESS (0)/* no problems left behind */ #define SCRUB_RET_CORRUPT (1)/* corruption remains on fs */ #define SCRUB_RET_UNOPTIMIZED (2)/* fs could be optimized */
@@ -624,6 +634,9 @@ _("Only one of the options -n or -y may be specified.\n"));if (stdout_isatty && !progress_fp) progress_fp =fdopen (1 ,"w+" ); +if (getenv ("SERVICE_MODE" )) + is_service = true; +/* Find the mount record for the passed-in argument. */ if (stat (argv[optind], &ctx.mnt_sb) <0 ) { fprintf(stderr,
@@ -729,5 +742,24 @@ _("%s: %llu warnings found.\n"),free (ctx.blkdev);free (ctx.mntpoint); +/* +* If we're being run as a service, the return code must fit the LSB +* init script action error guidelines, which is to say that we +* compress all errors to 1 ("generic or unspecified error", LSB 5.0 +* section 22.2) and hope the admin will scan the log for what +* actually happened. +* +* We have to sleep 2 seconds here because journald uses the pid to +* connect our log messages to the systemd service. This is critical +* for capturing all the log messages if the scrub fails, because the +* fail service uses the service name to gather log messages for the +* error report. +*/ +if (is_service) { +sleep (2 ); +if (ret !=SCRUB_RET_SUCCESS ) +return 1 ; + } +return ret; }
scrub/[email protected] new file +20 -0
@@ -0,0 +1,20 @@ +[Unit] +Description=Online XFS Metadata Check for %I +OnFailure=xfs_scrub_fail@%i.service +Documentation=man:xfs_scrub(8) + +[Service] +Type=oneshot +WorkingDirectory=%I +PrivateNetwork=true +ProtectSystem=full +ProtectHome=read-only +PrivateTmp=yes +AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_SYS_RAWIO +NoNewPrivileges=yes +User=nobody +IOSchedulingClass=idle +CPUSchedulingPolicy=idle +Environment=SERVICE_MODE=1 +ExecStart=@sbindir@/xfs_scrub @scrub_args@ %I +SyslogIdentifier=%N
scrub/xfs_scrub_all.cron.in new file +1 -0
@@ -0,0 +1 @@ +10 3 * * 0 root test -e /run/systemd/system || @sbindir@/xfs_scrub_all
scrub/xfs_scrub_all.in +49 -0
83 lines not on this page · raw message
scrub/xfs_scrub_all.service.in new file +10 -0
@@ -0,0 +1,10 @@ +[Unit] +Description=Online XFS Metadata Check for All Filesystems +ConditionACPower=true +Documentation=man:xfs_scrub_all(8) + +[Service] +Type=oneshot +Environment=SERVICE_MODE=1 +ExecStart=@sbindir@/xfs_scrub_all +SyslogIdentifier=xfs_scrub_all
scrub/xfs_scrub_all.timer new file +11 -0
@@ -0,0 +1,11 @@ +[Unit] +Description=Periodic XFS Online Metadata Check for All Filesystems + +[Timer] +# Run on Sunday at 3:10am, to avoid running afoul of DST changes +OnCalendar=Sun *-*-* 03:10:00 +RandomizedDelaySec=60 +Persistent=true + +[Install] +WantedBy=timers.target
scrub/xfs_scrub_fail new file +26 -0
@@ -0,0 +1,26 @@ +#!/bin/bash + +# Email logs of failed xfs_scrub unit runs + +mailer=/usr/sbin/sendmail +recipient="$1" +test -z "${recipient}" && exit 0 +mntpoint="$2" +test -z "${mntpoint}" && exit 0 +hostname="$(hostname -f 2>/dev/null)" +test -z "${hostname}" && hostname="${HOSTNAME}" +if [ ! -x "${mailer}" ]; then + echo "${mailer}: Mailer program not found." + exit 1 +fi + +(cat << ENDL +To: $1 +From: <xfs_scrub@${hostname}> +Subject: xfs_scrub failure on ${mntpoint} + +So sorry, the automatic xfs_scrub of ${mntpoint} on ${hostname} failed. + +A log of what happened follows: +ENDL +systemctl status --full --lines 4294967295 "xfs_scrub@${mntpoint}") | "${mailer}" -t -i
scrub/[email protected] new file +10 -0
@@ -0,0 +1,10 @@ +[Unit] +Description=Online XFS Metadata Check Failure Reporting for %I + +[Service] +Type=oneshot +Environment=EMAIL_ADDR=root +ExecStart=@pkg_lib_dir@/@pkg_name@/xfs_scrub_fail "${EMAIL_ADDR}" %I +User=mail +Group=mail +SupplementaryGroups=systemd-journal
Re: [PATCH v2 27/29] xfs_scrub: integrate services with systemd
Quoted 8 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
Create a systemd service unit so that we can run the online scrubber under systemd with (somewhat) appropriate containment.
Signed-off-by Darrick J. Wong <[email protected]>---
v2: fix some of the debian packaging weirdness, kudos to Nathan Scott!
Er, hang on:
checking for SYSTEMD... configure: error: Package requirements (systemd) were not met:
now systemd is a /build/ requirement for xfsprogs? nope nope. :)
This is only used for unit file install targets, right? If systemd is missing, surely those install targets should just be skipped.
Looks like the Makefile DTRT, but the stuff in m4/ should be non-fatal?
(I can't tell what makes this fatal ... I think its' fatal?
Quoted 7 lines
checking for SYSTEMD... configure: error: Package requirements (systemd) were not met:
No package 'systemd' found
Consider adjusting the
PKG_CONFIG_PATHenvironment variable if you installed software in a non-standard prefix.
Quoted 6 lines
Alternatively, you may set the environment variables
SYSTEMD_CFLAGSandSYSTEMD_LIBSto avoid the need to call pkg-config. See the pkg-config man page for more details.# echo $? 1
looks fatal.)
...
Quoted 10 lines
scrub/Makefile +2
-0@@ -15,6 +15,19 @@ LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub XFS_SCRUB_ALL_PROG = xfs_scrub_all XFS_SCRUB_ARGS = -b -n +ifeq ($(HAVE_SYSTEMD),yes) +INSTALL_SCRUB += install-systemd
scrub/Makefile LTCOMMAND = xfs_scrub · line 29
Quoted 10 lines
scrub/Makefile +10
-0+SYSTEMD_SERVICES = [email protected] xfs_scrub_all.service xfs_scrub_all.timer [email protected] +OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) +endif +ifeq ($(HAVE_CROND),yes) +INSTALL_SCRUB += install-crond +CRONTABS = xfs_scrub_all.cron +OPTIONAL_TARGETS += $(CRONTABS) +# Don't enable the crontab by default for now +CROND_DIR = $(PKG_LIB_DIR)/$(PKG_NAME) +endif
Wouldn't an else if arrangement make more sense? Why would we install both? I'd have expected "Install systemd if available, else install crond if available, else don't install anything."
... and then the cron job can stop checking for systemd too:
scrub/xfs_scrub_all.in
Quoted 8 lines
scrub/xfs_scrub_all.cron.in new file +1
-0@@ -0,0 +1 @@ +10 3 * * 0 root test -e /run/systemd/system || @sbindir@/xfs_scrub_allscrub/xfs_scrub_all.in +0
-0
unless I'm missing something?
Thanks,
-Eric
Re: [PATCH v2 27/29] xfs_scrub: integrate services with systemd
Quoted 14 lines · Eric Sandeen
Quoted 8 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
Create a systemd service unit so that we can run the online scrubber under systemd with (somewhat) appropriate containment.
Signed-off-by Darrick J. Wong <[email protected]>---
v2: fix some of the debian packaging weirdness, kudos to Nathan Scott!Er, hang on:
checking for SYSTEMD... configure: error: Package requirements (systemd) were not met:
Quoted 8 lines
now systemd is a /build/ requirement for xfsprogs? nope nope. :)
This is only used for unit file install targets, right? If systemd is missing, surely those install targets should just be skipped.
Looks like the
MakefileDTRT, but the stuff in m4/ should be non-fatal?(I can't tell what makes this fatal ... I think its' fatal?
Yeah, I forgot to hoist the pkg-config bits into the if-true and neutralize the if-not parts of the PKG_CHECK_MODULES call.
--D
Quoted 65 lines
Quoted 8 lines
checking for SYSTEMD... configure: error: Package requirements (systemd) were not met:
No package 'systemd' found
Consider adjusting the
PKG_CONFIG_PATHenvironment variable if you installed software in a non-standard prefix.Quoted 6 lines
Alternatively, you may set the environment variables
SYSTEMD_CFLAGSandSYSTEMD_LIBSto avoid the need to call pkg-config. See the pkg-config man page for more details.# echo $? 1looks fatal.)
...
Quoted 10 lines
scrub/Makefile +2
-0@@ -15,6 +15,19 @@ LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub XFS_SCRUB_ALL_PROG = xfs_scrub_all XFS_SCRUB_ARGS = -b -n +ifeq ($(HAVE_SYSTEMD),yes) +INSTALL_SCRUB += install-systemdscrub/Makefile LTCOMMAND = xfs_scrub · line 29
Quoted 10 lines
scrub/Makefile +10
-0+SYSTEMD_SERVICES = [email protected] xfs_scrub_all.service xfs_scrub_all.timer [email protected] +OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) +endif +ifeq ($(HAVE_CROND),yes) +INSTALL_SCRUB += install-crond +CRONTABS = xfs_scrub_all.cron +OPTIONAL_TARGETS += $(CRONTABS) +# Don't enable the crontab by default for now +CROND_DIR = $(PKG_LIB_DIR)/$(PKG_NAME) +endifWouldn't an else if arrangement make more sense? Why would we install both? I'd have expected "Install systemd if available, else install crond if available, else don't install anything."
... and then the cron job can stop checking for systemd too:scrub/xfs_scrub_all.in
Quoted 8 lines
scrub/xfs_scrub_all.cron.in new file +1
-0@@ -0,0 +1 @@ +10 3 * * 0 root test -e /run/systemd/system || @sbindir@/xfs_scrub_allscrub/xfs_scrub_all.in +0
-0unless I'm missing something?
Thanks,
-Eric
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 27/29 xfs_scrub: integrate services with systemd
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create a systemd service unit so that we can run the online scrubber under systemd with (somewhat) appropriate containment.
---
v3: fix pkgconfig autoconf thinko
v2: fix some of the debian packaging weirdness, kudos to Nathan Scott!
--- .gitignore | 4 ++ configure.ac | 2 + debian/postinst | 3 + include/builddefs.in | 4 ++ m4/Makefile | 1 m4/package_services.m4 | 77 ++++++++++++++++++++++++++++++++++++++ scrub/Makefile | 36 +++++++++++++++++- scrub/xfs_scrub.c | 32 ++++++++++++++++ scrub/[email protected] | 20 ++++++++++ scrub/xfs_scrub_all.cron.in | 1 scrub/xfs_scrub_all.in | 49 ++++++++++++++++++++++++ scrub/xfs_scrub_all.service.in | 10 +++++ scrub/xfs_scrub_all.timer | 11 +++++ scrub/xfs_scrub_fail | 26 +++++++++++++ scrub/[email protected] | 10 +++++ 15 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 m4/package_services.m4 create mode 100644 scrub/[email protected] create mode 100644 scrub/xfs_scrub_all.cron.in create mode 100644 scrub/xfs_scrub_all.service.in create mode 100644 scrub/xfs_scrub_all.timer create mode 100755 scrub/xfs_scrub_fail create mode 100644 scrub/[email protected]
.gitignore +4 -0
@@ -69,6 +69,10 @@ cscope.* /rtcp/xfs_rtcp /spaceman/xfs_spaceman /scrub/xfs_scrub +/scrub/[email protected] +/scrub/xfs_scrub_all +/scrub/xfs_scrub_all.service +/scrub/[email protected] # generated crc files /libxfs/crc32selftest
configure.ac +2 -0
@@ -174,6 +174,8 @@ AC_HAVE_OPENAT AC_HAVE_FSTATAT AC_HAVE_SG_IO AC_HAVE_HDIO_GETGEO +AC_CONFIG_SYSTEMD_SYSTEM_UNIT_DIR +AC_CONFIG_CROND_DIR if test "$enable_blkid" = yes; then AC_HAVE_BLKID_TOPO
debian/postinst +3 -0
@@ -8,6 +8,9 @@ case "${1}" in then update-initramfs -u fi + if [ -x /bin/systemctl ]; then + /bin/systemctl daemon-reload + fi ;; abort-upgrade|abort-remove|abort-deconfigure)
include/builddefs.in +4 -0
@@ -127,6 +127,10 @@ HAVE_OPENAT = @have_openat@ HAVE_FSTATAT = @have_fstatat@ HAVE_SG_IO = @have_sg_io@ HAVE_HDIO_GETGEO = @have_hdio_getgeo@ +HAVE_SYSTEMD = @have_systemd@ +SYSTEMD_SYSTEM_UNIT_DIR = @systemd_system_unit_dir@ +HAVE_CROND = @have_crond@ +CROND_DIR = @crond_dir@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
m4/Makefile +1 -0
@@ -21,6 +21,7 @@ LSRCFILES = \ package_libcdev.m4 \ package_pthread.m4 \ package_sanitizer.m4 \ + package_services.m4 \ package_types.m4 \ package_unistring.m4 \ package_utilies.m4 \
m4/package_services.m4 new file +77 -0
77 lines not on this page · raw message
scrub/Makefile +35 -1
@@ -15,6 +15,19 @@ LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub XFS_SCRUB_ALL_PROG = xfs_scrub_all XFS_SCRUB_ARGS = -b -n +ifeq ($(HAVE_SYSTEMD),yes) +INSTALL_SCRUB += install-systemd +SYSTEMD_SERVICES = [email protected] xfs_scrub_all.service xfs_scrub_all.timer [email protected] +OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) +endif +ifeq ($(HAVE_CROND),yes) +INSTALL_SCRUB += install-crond +CRONTABS = xfs_scrub_all.cron +OPTIONAL_TARGETS += $(CRONTABS) +# Don't enable the crontab by default for now +CROND_DIR = $(PKG_LIB_DIR)/$(PKG_NAME) +endif + endif # scrub_prereqs HFILES = \
@@ -84,7 +97,7 @@ ifeq ($(HAVE_HDIO_GETGEO),yes) LCFLAGS += -DHAVE_HDIO_GETGEO endif -default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) +default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(OPTIONAL_TARGETS) xfs_scrub_all: xfs_scrub_all.in @echo " [SED] $@"
@@ -98,6 +111,27 @@ include $(BUILDRULES) install: $(INSTALL_SCRUB) +%.service: %.service.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" \ + -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" \ + -e "s|@pkg_lib_dir@|$(PKG_LIB_DIR)|g" \ + -e "s|@pkg_name@|$(PKG_NAME)|g" < $< > $@ + +%.cron: %.cron.in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_ROOT_SBIN_DIR)|g" < $< > $@ + +install-systemd: default $(SYSTEMD_SERVICES) + $(INSTALL) -m 755 -d $(SYSTEMD_SYSTEM_UNIT_DIR) + $(INSTALL) -m 644 $(SYSTEMD_SERVICES) $(SYSTEMD_SYSTEM_UNIT_DIR) + $(INSTALL) -m 755 -d $(PKG_LIB_DIR)/$(PKG_NAME) + $(INSTALL) -m 755 xfs_scrub_fail $(PKG_LIB_DIR)/$(PKG_NAME) + +install-crond: default $(CRONTABS) + $(INSTALL) -m 755 -d $(CROND_DIR) + $(INSTALL) -m 644 $(CRONTABS) $(CROND_DIR) + install-scrub: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR)
scrub/xfs_scrub.c +32 -0
@@ -118,6 +118,10 @@* XFS_SCRUB_NO_SCSI_VERIFY -- disable SCSI VERIFY (if present) * XFS_SCRUB_PHASE -- run only this scrub phase * XFS_SCRUB_THREADS -- start exactly this number of threads +* +* Available even in non-debug mode: +* SERVICE_MODE -- compress all error codes to 1 for LSB +* service action compliance */ /* Program name; needed for libfrog error reports. */
@@ -154,6 +158,12 @@ bool want_fstrim = true;bool stderr_isatty;bool stdout_isatty; +/* +* If we are running as a service, we need to be careful about what +* error codes we return to the calling process. +*/ +static bool is_service; +#define SCRUB_RET_SUCCESS (0)/* no problems left behind */ #define SCRUB_RET_CORRUPT (1)/* corruption remains on fs */ #define SCRUB_RET_UNOPTIMIZED (2)/* fs could be optimized */
@@ -624,6 +634,9 @@ _("Only one of the options -n or -y may be specified.\n"));if (stdout_isatty && !progress_fp) progress_fp =fdopen (1 ,"w+" ); +if (getenv ("SERVICE_MODE" )) + is_service = true; +/* Find the mount record for the passed-in argument. */ if (stat (argv[optind], &ctx.mnt_sb) <0 ) { fprintf(stderr,
@@ -729,5 +742,24 @@ _("%s: %llu warnings found.\n"),free (ctx.blkdev);free (ctx.mntpoint); +/* +* If we're being run as a service, the return code must fit the LSB +* init script action error guidelines, which is to say that we +* compress all errors to 1 ("generic or unspecified error", LSB 5.0 +* section 22.2) and hope the admin will scan the log for what +* actually happened. +* +* We have to sleep 2 seconds here because journald uses the pid to +* connect our log messages to the systemd service. This is critical +* for capturing all the log messages if the scrub fails, because the +* fail service uses the service name to gather log messages for the +* error report. +*/ +if (is_service) { +sleep (2 ); +if (ret !=SCRUB_RET_SUCCESS ) +return 1 ; + } +return ret; }
scrub/[email protected] new file +20 -0
@@ -0,0 +1,20 @@ +[Unit] +Description=Online XFS Metadata Check for %I +OnFailure=xfs_scrub_fail@%i.service +Documentation=man:xfs_scrub(8) + +[Service] +Type=oneshot +WorkingDirectory=%I +PrivateNetwork=true +ProtectSystem=full +ProtectHome=read-only +PrivateTmp=yes +AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_SYS_RAWIO +NoNewPrivileges=yes +User=nobody +IOSchedulingClass=idle +CPUSchedulingPolicy=idle +Environment=SERVICE_MODE=1 +ExecStart=@sbindir@/xfs_scrub @scrub_args@ %I +SyslogIdentifier=%N
scrub/xfs_scrub_all.cron.in new file +1 -0
@@ -0,0 +1 @@ +10 3 * * 0 root test -e /run/systemd/system || @sbindir@/xfs_scrub_all
scrub/xfs_scrub_all.in +49 -0
83 lines not on this page · raw message
scrub/xfs_scrub_all.service.in new file +10 -0
@@ -0,0 +1,10 @@ +[Unit] +Description=Online XFS Metadata Check for All Filesystems +ConditionACPower=true +Documentation=man:xfs_scrub_all(8) + +[Service] +Type=oneshot +Environment=SERVICE_MODE=1 +ExecStart=@sbindir@/xfs_scrub_all +SyslogIdentifier=xfs_scrub_all
scrub/xfs_scrub_all.timer new file +11 -0
@@ -0,0 +1,11 @@ +[Unit] +Description=Periodic XFS Online Metadata Check for All Filesystems + +[Timer] +# Run on Sunday at 3:10am, to avoid running afoul of DST changes +OnCalendar=Sun *-*-* 03:10:00 +RandomizedDelaySec=60 +Persistent=true + +[Install] +WantedBy=timers.target
scrub/xfs_scrub_fail new file +26 -0
@@ -0,0 +1,26 @@ +#!/bin/bash + +# Email logs of failed xfs_scrub unit runs + +mailer=/usr/sbin/sendmail +recipient="$1" +test -z "${recipient}" && exit 0 +mntpoint="$2" +test -z "${mntpoint}" && exit 0 +hostname="$(hostname -f 2>/dev/null)" +test -z "${hostname}" && hostname="${HOSTNAME}" +if [ ! -x "${mailer}" ]; then + echo "${mailer}: Mailer program not found." + exit 1 +fi + +(cat << ENDL +To: $1 +From: <xfs_scrub@${hostname}> +Subject: xfs_scrub failure on ${mntpoint} + +So sorry, the automatic xfs_scrub of ${mntpoint} on ${hostname} failed. + +A log of what happened follows: +ENDL +systemctl status --full --lines 4294967295 "xfs_scrub@${mntpoint}") | "${mailer}" -t -i
scrub/[email protected] new file +10 -0
@@ -0,0 +1,10 @@ +[Unit] +Description=Online XFS Metadata Check Failure Reporting for %I + +[Service] +Type=oneshot +Environment=EMAIL_ADDR=root +ExecStart=@pkg_lib_dir@/@pkg_name@/xfs_scrub_fail "${EMAIL_ADDR}" %I +User=mail +Group=mail +SupplementaryGroups=systemd-journal
PATCH 28/29 xfs_scrub: wire up repair ioctl
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create the mechanism we need to actually call the kernel's online repair functionality. The interface will consume a repair description; the descriptor management will follow in the next patch.
--- scrub/common.c | 12 +++++ scrub/common.h | 6 ++ scrub/phase1.c | 11 ++++ scrub/phase2.c | 1 scrub/phase3.c | 1 scrub/phase5.c | 1 scrub/scrub.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/scrub.h | 20 ++++++++ scrub/xfs_scrub.h | 2 + 9 files changed, 188 insertions(+)
scrub/common.c +12 -0
@@ -59,7 +59,9 @@ xfs_scrub_excessive_errors(static const char *err_str[] = { [S_ERROR ] ="Error" , [S_WARN ] ="Warning" , + [S_REPAIR ] ="Repaired" , [S_INFO ] ="Info" , + [S_PREEN ] ="Optimized" , };/* If stream is a tty, clear to end of line to clean up progress bar. */
@@ -93,6 +95,11 @@ __str_out( stream = stdout;pthread_mutex_lock (&ctx->lock); + +/* We only want to hear about optimizing when in debug/verbose mode. */ +if (level ==S_PREEN && !debug && !verbose) + goto out_record; +fprintf (stream,"%s%s: %s: " ,stream_start (stream),_ (err_str[level]), descr);if (error) {
@@ -109,12 +116,17 @@ __str_out(if (stream == stdout)fflush (stream); +out_record:if (error)/* A syscall failed */ ctx->runtime_errors++;else if (level ==S_ERROR ) ctx->errors_found++;else if (level ==S_WARN ) ctx->warnings_found++; +else if (level ==S_REPAIR ) + ctx->repairs++; +else if (level ==S_PREEN ) + ctx->preens++;pthread_mutex_unlock (&ctx->lock); }
scrub/common.h +6 -0
@@ -32,7 +32,9 @@ bool xfs_scrub_excessive_errors(struct scrub_ctx *ctx);enum error_level {S_ERROR =0 ,S_WARN , +S_REPAIR ,S_INFO , +S_PREEN , }; void __str_out(struct scrub_ctx *ctx, const char *descr, enum error_level level,
@@ -46,6 +48,10 @@ void __str_out(struct scrub_ctx *ctx, const char *descr, enum error_level level, __str_out(ctx, str, S_WARN, 0, __FILE__, __LINE__, __VA_ARGS__)#define str_info (ctx, str, ...) \ __str_out(ctx, str, S_INFO, 0, __FILE__, __LINE__, __VA_ARGS__) +#define record_repair (ctx, str, ...) \ + __str_out(ctx, str, S_REPAIR, 0, __FILE__, __LINE__, __VA_ARGS__) +#define record_preen (ctx, str, ...) \ + __str_out(ctx, str, S_PREEN, 0, __FILE__, __LINE__, __VA_ARGS__)#define dbg_printf (fmt, ...) \ do {if (debug > 1) {printf(fmt, __VA_ARGS__);}} while (0)
scrub/phase1.c +11 -0
@@ -179,6 +179,17 @@ _("Kernel metadata scrubbing facility is required."));return false; } +/* Do we need kernel-assisted metadata repair? */ +if (ctx->mode !=SCRUB_MODE_DRY_RUN && !xfs_can_repair (ctx)) { +if (ctx->mode ==SCRUB_MODE_PREEN ) +str_error (ctx, ctx->mntpoint, +_ ("Kernel metadata optimization facility is required." )); +else +str_error (ctx, ctx->mntpoint, +_ ("Kernel metadata repair facility is required." )); +return false; + } +/* Go find the XFS devices if we have a usable fsmap. */ fs_table_initialise (0 ,NULL ,0 ,NULL ); errno =0 ;
scrub/phase2.c +1 -0
@@ -24,6 +24,7 @@#include <sys/stat.h> #include <sys/statvfs.h> #include "xfs.h" +#include "list.h" #include "path.h" #include "workqueue.h" #include "xfs_scrub.h"
scrub/phase3.c +1 -0
@@ -24,6 +24,7 @@#include <sys/stat.h> #include <sys/statvfs.h> #include "xfs.h" +#include "list.h" #include "path.h" #include "workqueue.h" #include "xfs_scrub.h"
scrub/phase5.c +1 -0
@@ -29,6 +29,7 @@#endif #include "xfs.h" #include "handle.h" +#include "list.h" #include "path.h" #include "workqueue.h" #include "xfs_scrub.h"
scrub/scrub.c +134 -0
153 lines not on this page · raw message
scrub/scrub.h +20 -0
@@ -41,6 +41,7 @@ bool xfs_can_scrub_dir(struct scrub_ctx *ctx);bool xfs_can_scrub_attr (struct scrub_ctx *ctx);bool xfs_can_scrub_symlink (struct scrub_ctx *ctx);bool xfs_can_scrub_parent (struct scrub_ctx *ctx); +bool xfs_can_repair (struct scrub_ctx *ctx);bool xfs_scrub_inode_fields (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen,int fd);
@@ -59,4 +60,23 @@ bool xfs_scrub_symlink(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,bool xfs_scrub_parent (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen,int fd); +/* Repair parameters are the scrub inputs and retry count. */ +struct repair_item { +struct list_head list; +__u64 ino; +__u32 type; +__u32 flags; +__u32 gen; +__u32 agno; +}; + +/* Only perform repairs; leave optimization-only actions for later. */ +#define XRM_REPAIR_ONLY (1U << 0) + +/* Complain if still broken even after fix. */ +#define XRM_NOFIX_COMPLAIN (1U << 1) + +enum check_outcome xfs_repair_metadata (struct scrub_ctx *ctx,int fd, +struct repair_item *ri,unsigned int repair_flags); +#endif /* XFS_SCRUB_SCRUB_H_ */
scrub/xfs_scrub.h +2 -0
@@ -95,6 +95,8 @@ struct scrub_ctx {unsigned long long inodes_checked;unsigned long long bytes_checked;unsigned long long naming_warnings; +unsigned long long repairs; +unsigned long long preens;bool need_repair;bool preen_triggers[XFS_SCRUB_TYPE_NR ]; };
PATCH 29/29 xfs_scrub: schedule and manage optimizations/repairs to the filesystem
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Teach xfs_scrub to remember scrub requests that failed (or indicated that optimization is a possibility) as action items. Depending on the circumstances, certain items are acted upon immediately (e.g. metadata that needs to be healthy in order to finish the scan, or files that are already open) or deferred until later. Expand the repair phase to deal with the deferred actions.
--- man/man8/xfs_scrub.8 | 27 ++++- scrub/Makefile | 2 scrub/phase1.c | 7 + scrub/phase2.c | 59 +++++++++- scrub/phase3.c | 42 +++++-- scrub/phase4.c | 76 ++++++++++++- scrub/repair.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/repair.h | 55 +++++++++ scrub/scrub.c | 123 +++++++++++++++------ scrub/scrub.h | 36 ++++-- scrub/xfs_scrub.c | 22 ++++ scrub/xfs_scrub.h | 1 12 files changed, 676 insertions(+), 72 deletions(-) create mode 100644 scrub/repair.c create mode 100644 scrub/repair.h
man/man8/xfs_scrub.8 +21 -6
@@ -114,9 +114,27 @@ Instructing the underlying storage to discard unused extents via the .B FITRIM ioctl. .SH REPAIRS -This program currently does not support making any repairs. -Corruptions can only be fixed by unmounting the filesystem and running -.BR xfs_repair (8). +Repairs are performed by calling into the kernel. +This limits the scope of repair activities to rebuilding primary data +structures from secondary data structures, or secondary structures from +primary structures. +The existence of secondary data structures may require features that can +only be turned on from +.BR mkfs.xfs (8). +If errors cannot be repaired, the filesystem must be +unmounted and +.BR xfs_repair (8) +run. +Repairs supported by the kernel include, but are not limited to: +.IP \[bu] 2 +Reconstructing extent allocation data from the reverse mapping data. +.IP \[bu] +Reconstructing reverse mapping data from primary extent allocation data. +.IP \[bu] +Scheduling a quotacheck for the next mount. +.PP +If corrupt metadata is successfully repaired, this program will log that +a repair has succeeded instead of a corruption report. .SH EXIT CODE The exit code returned by .B xfs_scrub
@@ -140,8 +158,5 @@ This program takes advantage of in-kernel scrubbing to verify a given data structure with locks held and can keep the filesystem busy for a long time. The kernel must be new enough to support the SCRUB_METADATA ioctl. -.PP -If errors are found and cannot be repaired, the filesystem must be -unmounted and repaired. .SH SEE ALSO .BR xfs_repair (8).
scrub/Makefile +2 -0
@@ -40,6 +40,7 @@ fscounters.h \ inodes.h \ progress.h \ read_verify.h \ +repair.h \ scrub.h \ spacemap.h \ unicrash.h \
@@ -63,6 +64,7 @@ phase6.c \ phase7.c \ progress.c \ read_verify.c \ +repair.c \ scrub.c \ spacemap.c \ vfs.c \
scrub/phase1.c +7 -0
@@ -47,6 +47,7 @@#include "common.h" #include "disk.h" #include "scrub.h" +#include "repair.h" /* Phase 1: Find filesystem geometry (and clean up after) */
@@ -68,6 +69,7 @@ boolxfs_cleanup_fs ( struct scrub_ctx *ctx) { +xfs_action_lists_free (&ctx->action_lists);if (ctx->fshandle)free_handle (ctx->fshandle, ctx->fshandle_len);if (ctx->rtdev)
@@ -157,6 +159,11 @@ _("Does not appear to be an XFS filesystem!"));return false; } +if (!xfs_action_lists_alloc (ctx->geo.agcount, &ctx->action_lists)) { +str_error (ctx, ctx->mntpoint,_ ("Not enough memory." )); +return false; + } + ctx->agblklog =log2_roundup (ctx->geo.agblocks); ctx->blocklog =highbit32 (ctx->geo.blocksize); ctx->inodelog =highbit32 (ctx->geo.inodesize);
scrub/phase2.c +55 -4
109 lines not on this page · raw message
scrub/phase3.c +31 -11
103 lines not on this page · raw message
scrub/phase4.c +74 -2
98 lines not on this page · raw message
scrub/repair.c new file +298 -0
298 lines not on this page · raw message
scrub/repair.h new file +55 -0
55 lines not on this page · raw message
scrub/scrub.c +88 -35
269 lines not on this page · raw message
scrub/scrub.h +22 -14
@@ -28,11 +28,19 @@ enum check_outcome { CHECK_RETRY, /* repair failed, try again later */ }; +struct action_item ; +void xfs_scrub_report_preen_triggers (struct scrub_ctx *ctx); -bool xfs_scrub_primary_super (struct scrub_ctx *ctx); -bool xfs_scrub_ag_headers (struct scrub_ctx *ctx,xfs_agnumber_t agno); -bool xfs_scrub_ag_metadata (struct scrub_ctx *ctx,xfs_agnumber_t agno); -bool xfs_scrub_fs_metadata (struct scrub_ctx *ctx); +bool xfs_scrub_primary_super (struct scrub_ctx *ctx, +struct xfs_action_list *alist); +bool xfs_scrub_ag_headers (struct scrub_ctx *ctx,xfs_agnumber_t agno, +struct xfs_action_list *alist); +bool xfs_scrub_ag_metadata (struct scrub_ctx *ctx,xfs_agnumber_t agno, +struct xfs_action_list *alist); +bool xfs_scrub_fs_metadata (struct scrub_ctx *ctx, +struct xfs_action_list *alist); +enum check_outcome xfs_repair_metadata (struct scrub_ctx *ctx,int fd, +struct action_item *aitem,unsigned int flags);bool xfs_can_scrub_fs_metadata (struct scrub_ctx *ctx);bool xfs_can_scrub_inode (struct scrub_ctx *ctx);
@@ -44,24 +52,24 @@ bool xfs_can_scrub_parent(struct scrub_ctx *ctx);bool xfs_can_repair (struct scrub_ctx *ctx);bool xfs_scrub_inode_fields (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_data_fork (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_attr_fork (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_cow_fork (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_dir (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_attr (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_symlink (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);bool xfs_scrub_parent (struct scrub_ctx *ctx,uint64_t ino,uint32_t gen, -int fd); +int fd,struct xfs_action_list *alist);/* Repair parameters are the scrub inputs and retry count. */ -struct repair_item { +struct action_item {struct list_head list;__u64 ino;__u32 type;
@@ -77,6 +85,6 @@ struct repair_item {#define XRM_NOFIX_COMPLAIN (1U << 1)enum check_outcome xfs_repair_metadata (struct scrub_ctx *ctx,int fd, -struct repair_item *ri,unsigned int repair_flags); +struct action_item *aitem,unsigned int repair_flags);#endif /* XFS_SCRUB_SCRUB_H_ */
scrub/xfs_scrub.c +22 -0
@@ -88,6 +88,15 @@* the previous two phases are retried here; if there are uncorrectable * errors, xfs_scrub stops here. * +* To perform the actual repairs (or optimizations), we iterate all the +* items on the per-AG action item list and ask the kernel to repair +* them. Items which are successfully repaired are removed from the +* list. If an item is not acted upon successfully (or the kernel asks us +* to try again), we retry the actions until there is nothing left to +* fix or we fail to make forward progress. In that event, the +* unfinished items are recorded as errors. If there are no errors at +* this point, we call FSTRIM on the filesystem. +* * The next phase is the "check directory tree" phase. In this phase, * every directory is opened (via file handle) to confirm that each * directory is connected to the root. Directory entries are checked
@@ -711,6 +720,19 @@ _("%s: Not a XFS mount point or block device.\n"), ctx.runtime_errors++; out: +if (ctx.repairs && ctx.preens) +fprintf (stdout, +_ ("%s: %llu repairs and %llu optimizations made.\n" ), + ctx.mntpoint, ctx.repairs, ctx.preens); +else if (ctx.repairs && ctx.preens ==0 ) +fprintf (stdout, +_ ("%s: %llu repairs made.\n" ), + ctx.mntpoint, ctx.repairs); +else if (ctx.repairs ==0 && ctx.preens) +fprintf (stdout, +_ ("%s: %llu optimizations made.\n" ), + ctx.mntpoint, ctx.preens); + total_errors = ctx.errors_found + ctx.runtime_errors;if (ctx.need_repair) repairstr =_ (" Unmount and run xfs_repair." );
scrub/xfs_scrub.h +1 -0
@@ -88,6 +88,7 @@ struct scrub_ctx {/* Mutable scrub state; use lock. */ pthread_mutex_t lock; +struct xfs_action_list *action_lists;unsigned long long max_errors;unsigned long long runtime_errors;unsigned long long errors_found;
[PATCH 30/29] debian/control: remove nonexistent libreadline5-dev build dependency
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
libreadline5-dev hasn't existed as a package for quite some time now; even Debian "oldoldstable" doesn't know what that is. Drop it in favor of libreadline-gplv2-dev.
--- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
debian/control +1 -1
@@ -3,7 +3,7 @@ Section: admin Priority: optional Maintainer: XFS Development Team <[email protected]> Uploaders: Nathan Scott <[email protected]>, Anibal Monsalve Salazar <[email protected]> -Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev | libreadline5-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev, dh-python +Build-Depends: uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libreadline-gplv2-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libunistring-dev, dh-python Standards-Version: 3.9.1 Homepage: https://xfs.wiki.kernel.org/
[PATCH 31/29] xfs_scrub: handle scrub-only kernels more helpfully
If xfs_scrub is run today against a 4.15 kernel, it fails with
EXPERIMENTAL xfs_scrub program in use! Use at your own risk!
Error: /home: Kernel metadata optimization facility is required.
Info: /home: Scrub aborted after phase 1.
/home: 2 errors found.
Be a bit kinder to the user and suggest a path forward. By the time we fail for missing preen or repair functionality, we do know that scrub is available, so suggest it.
Further, rather than stating what is required, state what was not found ... we're failing, so state what was missing, vs. what is required - seems a bit more definitive.
---
scrub/phase1.c +3 -3
@@ -175,7 +175,7 @@ _("Does not appear to be an XFS filesystem!")); !xfs_can_scrub_attr(ctx) || !xfs_can_scrub_symlink(ctx) || !xfs_can_scrub_parent(ctx)) {str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata scrubbing facility is required." )); +_ ("Kernel metadata scrubbing facility not available." ));return false; }
@@ -183,10 +183,10 @@ _("Kernel metadata scrubbing facility is required."));if (ctx->mode !=SCRUB_MODE_DRY_RUN && !xfs_can_repair (ctx)) {if (ctx->mode ==SCRUB_MODE_PREEN )str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata optimization facility is required." )); +_ ("Kernel metadata optimization facility not available. Please use -n." ));else str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata repair facility is required." )); +_ ("Kernel metadata repair facility not not available. Please use -n." ));return false; }
Re: [PATCH 31/29] xfs_scrub: handle scrub-only kernels more helpfully
Quoted 23 lines · Eric Sandeen
If
xfs_scrubis run today against a 4.15 kernel, it fails withEXPERIMENTAL
xfs_scrubprogram in use! Use at your own risk!
Error: /home: Kernel metadata optimization facility is required.
Info: /home: Scrub aborted after phase 1.
/home: 2 errors found.Be a bit kinder to the user and suggest a path forward. By the time we fail for missing preen or repair functionality, we do know that scrub is available, so suggest it.
Further, rather than stating what is required, state what was not found ... we're failing, so state what was missing, vs. what is required - seems a bit more definitive.
Signed-off-by Eric Sandeen <[email protected]>---
scrub/phase1.c +0
-0
scrub/phase1.c _("Does not appear to be an XFS filesystem!")); · line 178
Quoted 5 lines
scrub/phase1.c +1
-1@@ -175,7 +175,7 @@ _("Does not appear to be an XFS filesystem!")); !xfs_can_scrub_attr(ctx) || !xfs_can_scrub_symlink(ctx) || !xfs_can_scrub_parent(ctx)) {str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata scrubbing facility is required." )); +_ ("Kernel metadata scrubbing facility not available." ));
"is not available"?
scrub/phase1.c _("Kernel metadata scrubbing facility is required.")); · line 186
Quoted 9 lines
scrub/phase1.c +1
-1return false; }@@ -183,10 +183,10 @@ _("Kernel metadata scrubbing facility is required."));if (ctx->mode !=SCRUB_MODE_DRY_RUN && !xfs_can_repair (ctx)) {if (ctx->mode ==SCRUB_MODE_PREEN )str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata optimization facility is required." )); +_ ("Kernel metadata optimization facility not available. Please use -n." ));
I approve of s/is required/is not available/, but I have trouble with the bare suggestion of running with -n. We're telling users that the strategy they asked for (e.g. -y) is not available, so the only realistic option is to choose a different strategy (i.e. -n). I don't want them to get the impression that -n is some magic fixit for -y not working (but maybe sysadmins are smarter than that?)
"Kernel metadata repair faciility not available. You can request a metadata check with -n."
scrub/phase1.c _("Kernel metadata scrubbing facility is required.")); · line 189
Quoted 4 lines
scrub/phase1.c +1
-1else str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata repair facility is required." )); +_ ("Kernel metadata repair facility not not available. Please use -n." ));
not not available? So it is? :)
--D
Quoted 9 lines
scrub/phase1.c +0
-1return false; } --To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 31/29 v2] xfs_scrub: handle scrub-only kernels more helpfully
In reply to Eric SandeenIf xfs_scrub is run today against a 4.15 kernel, it fails with
EXPERIMENTAL xfs_scrub program in use! Use at your own risk!
Error: /home: Kernel metadata optimization facility is required.
Info: /home: Scrub aborted after phase 1.
/home: 2 errors found.
Be a bit kinder to the user and suggest a path forward. By the time we fail for missing preen or repair functionality, we do know that scrub is available, so suggest it.
Further, rather than stating what is required, state what was not found ... we're failing, so state what was missing, vs. what is required - seems a bit more definitive.
---
V2: change verbiage to make it more better and not not not confusing.
scrub/phase1.c +3 -3
@@ -175,7 +175,7 @@ _("Does not appear to be an XFS filesystem!")); !xfs_can_scrub_attr(ctx) || !xfs_can_scrub_symlink(ctx) || !xfs_can_scrub_parent(ctx)) {str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata scrubbing facility is required." )); +_ ("Kernel metadata scrubbing facility is not available." ));return false; }
@@ -183,10 +183,10 @@ _("Kernel metadata scrubbing facility is required."));if (ctx->mode !=SCRUB_MODE_DRY_RUN && !xfs_can_repair (ctx)) {if (ctx->mode ==SCRUB_MODE_PREEN )str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata optimization facility is required." )); +_ ("Kernel metadata optimization facility is not available. Use -n to scrub." ));else str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata repair facility is required." )); +_ ("Kernel metadata repair facility is not available. Use -n to scrub." ));return false; }
Bill O'Donnell
Reviewed-byRe: [PATCH 31/29 v2] xfs_scrub: handle scrub-only kernels more helpfully
Quoted 13 lines · Eric Sandeen
If
xfs_scrubis run today against a 4.15 kernel, it fails withEXPERIMENTAL
xfs_scrubprogram in use! Use at your own risk!
Error: /home: Kernel metadata optimization facility is required.
Info: /home: Scrub aborted after phase 1.
/home: 2 errors found.Be a bit kinder to the user and suggest a path forward. By the time we fail for missing preen or repair functionality, we do know that scrub is available, so suggest it.
Quoted 5 lines
Further, rather than stating what is required, state what was not found ... we're failing, so state what was missing, vs. what is required - seems a bit more definitive.
Signed-off-by Eric Sandeen <[email protected]>
looks good.
Quoted 36 lines
---
V2: change verbiage to make it more better and not not not confusing.
scrub/phase1.c +3
-4@@ -175,7 +175,7 @@ _("Does not appear to be an XFS filesystem!")); !xfs_can_scrub_attr(ctx) || !xfs_can_scrub_symlink(ctx) || !xfs_can_scrub_parent(ctx)) {str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata scrubbing facility is required." )); +_ ("Kernel metadata scrubbing facility is not available." ));return false; }@@ -183,10 +183,10 @@ _("Kernel metadata scrubbing facility is required."));if (ctx->mode !=SCRUB_MODE_DRY_RUN && !xfs_can_repair (ctx)) {if (ctx->mode ==SCRUB_MODE_PREEN )str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata optimization facility is required." )); +_ ("Kernel metadata optimization facility is not available. Use -n to scrub." ));else str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata repair facility is required." )); +_ ("Kernel metadata repair facility is not available. Use -n to scrub." ));return false; } --To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Darrick J. Wong
Reviewed-byRe: [PATCH 31/29 v2] xfs_scrub: handle scrub-only kernels more helpfully
In reply to Eric SandeenQuoted 13 lines · Eric Sandeen
If
xfs_scrubis run today against a 4.15 kernel, it fails withEXPERIMENTAL
xfs_scrubprogram in use! Use at your own risk!
Error: /home: Kernel metadata optimization facility is required.
Info: /home: Scrub aborted after phase 1.
/home: 2 errors found.Be a bit kinder to the user and suggest a path forward. By the time we fail for missing preen or repair functionality, we do know that scrub is available, so suggest it.
Quoted 5 lines
Further, rather than stating what is required, state what was not found ... we're failing, so state what was missing, vs. what is required - seems a bit more definitive.
Signed-off-by Eric Sandeen <[email protected]>
Looks ok,
Quoted 36 lines
---
V2: change verbiage to make it more better and not not not confusing.
scrub/phase1.c +3
-4@@ -175,7 +175,7 @@ _("Does not appear to be an XFS filesystem!")); !xfs_can_scrub_attr(ctx) || !xfs_can_scrub_symlink(ctx) || !xfs_can_scrub_parent(ctx)) {str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata scrubbing facility is required." )); +_ ("Kernel metadata scrubbing facility is not available." ));return false; }@@ -183,10 +183,10 @@ _("Kernel metadata scrubbing facility is required."));if (ctx->mode !=SCRUB_MODE_DRY_RUN && !xfs_can_repair (ctx)) {if (ctx->mode ==SCRUB_MODE_PREEN )str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata optimization facility is required." )); +_ ("Kernel metadata optimization facility is not available. Use -n to scrub." ));else str_error (ctx, ctx->mntpoint, -_ ("Kernel metadata repair facility is required." )); +_ ("Kernel metadata repair facility is not available. Use -n to scrub." ));return false; } --To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html