Add log of error during scan

This commit is contained in:
Andrea Mazzoleni 2026-05-03 11:25:24 +02:00
parent cc413aa062
commit 5731f3caf3

View file

@ -8,6 +8,14 @@
#include "state.h"
#include "parity.h"
static const char* es(int err)
{
if (is_hw(err))
return "error_io";
else
return "error";
}
struct snapraid_scan {
struct snapraid_state* state; /**< State used. */
struct snapraid_disk* disk; /**< Disk used. */
@ -379,6 +387,7 @@ static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_fil
static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file)
{
char esc_buffer[ESC_MAX];
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
@ -392,6 +401,7 @@ static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapra
if (filephy(path_next, file->size, &file->physical) != 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: File physycal offset error. %s.\n", es(errno), 0, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal(errno, "Error in getting the physical offset of file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -512,6 +522,7 @@ static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct s
static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical)
{
#if HAVE_LSTAT_SYNC
char esc_buffer[ESC_MAX];
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
@ -533,6 +544,7 @@ static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struc
if (lstat_sync(path_next, &synced_st, physical) != 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Stat error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error in stat file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -555,6 +567,7 @@ static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struc
* Why is the file size reported incorrectly for files that are still being written to?
* http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx
*/
log_tag("%s:%u:%s:%s: Uncached time change error.\n", es(ESOFT), 0, disk->name, esc_tag(sub, esc_buffer));
log_fatal(ESOFT, "WARNING! Detected uncached time change from %" PRIu64 ".%09u to %" PRIu64 ".%09u for file '%s'\n",
(uint64_t)st->st_mtime, (uint32_t)st->st_mtimensec, (uint64_t)synced_st.st_mtime, (uint32_t)synced_st.st_mtimensec, sub);
log_fatal(ESOFT, "It's better if you run SnapRAID without other processes running.\n");
@ -565,6 +578,7 @@ static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struc
if (st->st_size != synced_st.st_size) {
#ifndef _WIN32
log_tag("%s:%u:%s:%s: Uncached size change error.\n", es(ESOFT), 0, disk->name, esc_tag(sub, esc_buffer));
log_fatal(ESOFT, "WARNING! Detected uncached size change from %" PRIu64 " to %" PRIu64 " for file '%s'\n",
(uint64_t)st->st_size, (uint64_t)synced_st.st_size, sub);
log_fatal(ESOFT, "It's better if you run SnapRAID without other processes running.\n");
@ -574,6 +588,7 @@ static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struc
if (st->st_nlink != synced_st.st_nlink) {
#ifndef _WIN32
log_tag("%s:%u:%s:%s: Uncached nlink change error.\n", es(ESOFT), 0, disk->name, esc_tag(sub, esc_buffer));
log_fatal(ESOFT, "WARNING! Detected uncached nlink change from %u to %u for file '%s'\n",
(uint32_t)st->st_nlink, (uint32_t)synced_st.st_nlink, sub);
log_fatal(ESOFT, "It's better if you run SnapRAID without other processes running.\n");
@ -582,6 +597,7 @@ static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struc
}
if (st->st_ino != synced_st.st_ino) {
log_tag("%s:%u:%s:%s: Uncached inode change error.\n", es(ESOFT), 0, disk->name, esc_tag(sub, esc_buffer));
log_fatal(ESOFT, "DANGER! Detected uncached inode change from %" PRIu64 " to %" PRIu64 " for file '%s'\n",
(uint64_t)st->st_ino, (uint64_t)synced_st.st_ino, sub);
log_fatal(ESOFT, "It's better if you run SnapRAID without other processes running.\n");
@ -1230,11 +1246,13 @@ struct stat* dstat(struct dirent_sorted* dd)
return &dd->d_stat;
}
#else
#define DSTAT(file, dd, buf) dstat(file, buf)
struct stat* dstat(const char* file, struct stat* st)
#define DSTAT(file, dd, buf) dstat(disk, file, buf)
struct stat* dstat(struct snapraid_disk* disk, const char* file, struct stat* st)
{
char esc_buffer[ESC_MAX];
if (lstat(file, st) != 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Stat error. %s.\n", es(errno), 0, disk->name, esc_tag(file, esc_buffer), strerror(errno));
log_fatal(errno, "Error in stat file/directory '%s'. %s.\n", file, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -1249,6 +1267,7 @@ struct stat* dstat(const char* file, struct stat* st)
*/
static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* path_next, char* sub_next, char* tmp)
{
char esc_buffer[ESC_MAX];
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
int processed = 0;
@ -1266,11 +1285,12 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
d = opendir(path_next);
if (!d) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Open dir error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error opening directory '%s'. %s.\n", path_next, strerror(errno));
if (level == 0)
log_fatal(errno, "If this is the disk mount point, remember to create it manually\n");
else
log_fatal(errno, "If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub_next);
log_fatal(errno, "If it's a permission problem, you can exclude it in the config file with: exclude /%s\n", sub_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1296,8 +1316,9 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
/* restore removing additions */
path_next[path_len] = 0;
sub_next[sub_len] = 0;
log_tag("%s:%u:%s:%s: Read dir error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error reading directory '%s'. %s.\n", path_next, strerror(errno));
log_fatal(errno, "You can exclude it in the config file with:\n\texclude /%s\n", sub_next);
log_fatal(errno, "You can exclude it in the config file with: exclude /%s\n", sub_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1315,6 +1336,7 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
/* check for not supported file names */
if (name[0] == 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Unsupported name error.\n", es(ESOFT), 0, disk->name, esc_tag(path_next, esc_buffer));
log_fatal(ESOFT, "Unsupported name '%s' in file '%s'.\n", name, path_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -1362,6 +1384,7 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
/* LCOV_EXCL_START */
/* restore removing additions */
path_next[path_len] = 0;
log_tag("%s:%u:%s:%s: Close dir error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error closing directory '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -1426,6 +1449,7 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
if (st->st_mode == 0) {
if (lstat(path_next, st) != 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Stat error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -1457,6 +1481,7 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
if (st->st_ino == 0 || st->st_nlink == 0) {
if (lstat_sync(path_next, st, 0) != 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Stat error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error in stat file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -1477,12 +1502,14 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
ret = readlink(path_next, tmp, PATH_MAX);
if (ret >= PATH_MAX) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Readlink error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(EINTERNAL, "Error in readlink file '%s'. Symlink too long.\n", path_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (ret < 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Readlink error. %s.\n", es(errno), 0, disk->name, esc_tag(path_next, esc_buffer), strerror(errno));
log_fatal(errno, "Error in readlink file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -1507,9 +1534,12 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
if (!st)
st = DSTAT(path_next, dd, &st_buf);
/* in Unix don't follow mount points in different devices */
/* in Windows we are already skipping them reporting them as special files */
/*
* In Unix don't follow mount points in different devices
* in Windows we are already skipping them reporting them as special files
*/
if ((uint64_t)st->st_dev != disk->device) {
log_tag("%s:%u:%s:%s: Ignoring mount point.\n", es(ESOFT), 0, disk->name, esc_tag(path_next, esc_buffer));
log_fatal(ESOFT, "WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next);
} else
#endif
@ -1536,6 +1566,7 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa
if (!st)
st = DSTAT(path_next, dd, &st_buf);
log_tag("%s:%u:%s:%s: Ignoring special file.\n", es(ESOFT), 0, disk->name, esc_tag(path_next, esc_buffer));
log_fatal(ESOFT, "WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
} else {
msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
@ -1571,6 +1602,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
static void* scan_disk(void* arg)
{
char esc_buffer[ESC_MAX];
struct snapraid_scan* scan = arg;
struct snapraid_disk* disk = scan->disk;
int ret;
@ -1582,6 +1614,7 @@ static void* scan_disk(void* arg)
ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0, 0, 0, 0, 0);
if (ret < 0) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Filesystem info error. %s.\n", es(errno), 0, disk->name, esc_tag(disk->dir, esc_buffer), strerror(errno));
log_fatal(errno, "Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */