@@ -294,21 +294,24 @@ _("Disappeared during read error reporting."));
}
/* Scan a directory for matches in the read verify error list. */
-static bool
+static int
xfs_report_verify_dir(
struct scrub_ctx *ctx,
const char *path,
int dir_fd,
void *arg)
{
- return xfs_report_verify_fd(ctx, path, dir_fd, arg);
+ bool moveon;
+
+ moveon = xfs_report_verify_fd(ctx, path, dir_fd, arg);
+ return moveon ? 0 : -1;
}
/*
* Scan the inode associated with a directory entry for matches with
* the read verify error list.
*/
-static bool
+static int
xfs_report_verify_dirent(
struct scrub_ctx *ctx,
const char *path,
@@ -323,11 +326,11 @@ xfs_report_verify_dirent(
/* Ignore things we can't open. */
if (!S_ISREG(sb->st_mode) && !S_ISDIR(sb->st_mode))
- return true;
+ return 0;
/* Ignore . and .. */
if (!strcmp(".", dirent->d_name) || !strcmp("..", dirent->d_name))
- return true;
+ return 0;
/*
* If we were given a dirent, open the associated file under
@@ -336,8 +339,12 @@ xfs_report_verify_dirent(
*/
fd = openat(dir_fd, dirent->d_name,
O_RDONLY | O_NOATIME | O_NOFOLLOW | O_NOCTTY);
- if (fd < 0)
- return true;
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return 0;
+ str_errno(ctx, path);
+ return errno;
+ }
/* Go find the badness. */
moveon = xfs_report_verify_fd(ctx, path, fd, arg);
@@ -348,7 +355,7 @@ xfs_report_verify_dirent(
error = close(fd);
if (error)
str_errno(ctx, path);
- return moveon;
+ return moveon ? 0 : -1;
}
/* Report an IO error resulting from read-verify based off getfsmap. */
@@ -508,7 +515,6 @@ xfs_report_verify_errors(
struct scrub_ctx *ctx,
struct media_verify_state *vs)
{
- bool moveon;
int ret;
ret = walk_ioerrs(ctx, ctx->datadev, vs);
@@ -524,9 +530,9 @@ xfs_report_verify_errors(
}
/* Scan the directory tree to get file paths. */
- moveon = scan_fs_tree(ctx, xfs_report_verify_dir,
+ ret = scan_fs_tree(ctx, xfs_report_verify_dir,
xfs_report_verify_dirent, vs);
- if (!moveon)
+ if (ret)
return false;
/* Scan for unlinked files. */
@@ -30,7 +30,7 @@ struct scan_fs_tree {
pthread_mutex_t lock;
pthread_cond_t wakeup;
struct stat root_sb;
- bool moveon;
+ bool aborted;
scan_fs_tree_dir_fn dir_fn;
scan_fs_tree_dirent_fn dirent_fn;
void *arg;
@@ -138,8 +138,9 @@ scan_fs_dir(
}
/* Caller-specific directory checks. */
- if (!sft->dir_fn(ctx, sftd->path, dir_fd, sft->arg)) {
- sft->moveon = false;
+ error = sft->dir_fn(ctx, sftd->path, dir_fd, sft->arg);
+ if (error) {
+ sft->aborted = true;
error = close(dir_fd);
if (error)
str_errno(ctx, sftd->path);
@@ -150,11 +151,14 @@ scan_fs_dir(
dir = fdopendir(dir_fd);
if (!dir) {
str_errno(ctx, sftd->path);
+ sft->aborted = true;
close(dir_fd);
goto out;
}
rewinddir(dir);
- for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
+ for (dirent = readdir(dir);
+ !sft->aborted && dirent != NULL;
+ dirent = readdir(dir)) {
snprintf(newpath, PATH_MAX, "%s/%s", sftd->path,
dirent->d_name);
@@ -171,14 +175,15 @@ scan_fs_dir(
continue;
/* Caller-specific directory entry function. */
- if (!sft->dirent_fn(ctx, newpath, dir_fd, dirent, &sb,
- sft->arg)) {
- sft->moveon = false;
+ error = sft->dirent_fn(ctx, newpath, dir_fd, dirent, &sb,
+ sft->arg);
+ if (error) {
+ sft->aborted = true;
break;
}
if (xfs_scrub_excessive_errors(ctx)) {
- sft->moveon = false;
+ sft->aborted = true;
break;
}
@@ -189,7 +194,7 @@ scan_fs_dir(
if (error) {
str_liberror(ctx, error,
_("queueing subdirectory scan"));
- sft->moveon = false;
+ sft->aborted = true;
break;
}
}
@@ -206,8 +211,11 @@ _("queueing subdirectory scan"));
free(sftd);
}
-/* Scan the entire filesystem. */
-bool
+/*
+ * Scan the entire filesystem. This function returns 0 on success; if there
+ * are errors, this function will log them and returns nonzero.
+ */
+int
scan_fs_tree(
struct scrub_ctx *ctx,
scan_fs_tree_dir_fn dir_fn,
@@ -215,20 +223,18 @@ scan_fs_tree(
void *arg)
{
struct workqueue wq;
- struct scan_fs_tree sft;
- bool moveon = false;
+ struct scan_fs_tree sft = {
+ .root_sb = ctx->mnt_sb,
+ .dir_fn = dir_fn,
+ .dirent_fn = dirent_fn,
+ .arg = arg,
+ };
int ret;
- sft.moveon = true;
- sft.nr_dirs = 0;
- sft.root_sb = ctx->mnt_sb;
- sft.dir_fn = dir_fn;
- sft.dirent_fn = dirent_fn;
- sft.arg = arg;
ret = pthread_mutex_init(&sft.lock, NULL);
if (ret) {
str_liberror(ctx, ret, _("creating directory scan lock"));
- return false;
+ return ret;
}
ret = pthread_cond_init(&sft.wakeup, NULL);
if (ret) {
@@ -268,14 +274,16 @@ scan_fs_tree(
goto out_wq;
}
- moveon = sft.moveon;
+ if (!ret && sft.aborted)
+ ret = -1;
+
out_wq:
workqueue_destroy(&wq);
out_cond:
pthread_cond_destroy(&sft.wakeup);
out_mutex:
pthread_mutex_destroy(&sft.lock);
- return moveon;
+ return ret;
}
#ifndef FITRIM
@@ -6,12 +6,12 @@
#ifndef XFS_SCRUB_VFS_H_
#define XFS_SCRUB_VFS_H_
-typedef bool (*scan_fs_tree_dir_fn)(struct scrub_ctx *, const char *,
+typedef int (*scan_fs_tree_dir_fn)(struct scrub_ctx *, const char *,
int, void *);
-typedef bool (*scan_fs_tree_dirent_fn)(struct scrub_ctx *, const char *,
+typedef int (*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,
+int 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);