From 781dd25025ad2cf219e0b15ecfe55278959272a8 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 18 Mar 2026 11:51:52 +0100 Subject: [PATCH] Move the FLAG_IS_RELOCATED to dedicated shared flags to avoid data races --- cmdline/elem.c | 1 + cmdline/elem.h | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/cmdline/elem.c b/cmdline/elem.c index bd92de0a..4b18fed1 100644 --- a/cmdline/elem.c +++ b/cmdline/elem.c @@ -392,6 +392,7 @@ struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_ file->inode = inode; file->physical = physical; file->flag = 0; + file->shared_flag = 0; file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); for (i = 0; i < file->blockmax; ++i) { diff --git a/cmdline/elem.h b/cmdline/elem.h index 22602930..c5dcbed3 100644 --- a/cmdline/elem.h +++ b/cmdline/elem.h @@ -265,6 +265,18 @@ struct snapraid_block { */ #define FILE_IS_MISSING 0x800 +#define FILE_IS_HARDLINK 0x1000 /**< If it's an hardlink. */ +#define FILE_IS_SYMLINK 0x2000 /**< If it's a file symlink. */ +#define FILE_IS_SYMDIR 0x4000 /**< If it's a dir symlink for Windows. Not yet supported. */ +#define FILE_IS_JUNCTION 0x8000 /**< If it's a junction for Windows. Not yet supported. */ +#define FILE_IS_LINK_MASK 0xF000 /**< Mask for link type. */ + +/** + * Flags from this bit are shared between multiple threads + * and goes in the shared_flags instead of flags + */ +#define FILE_FLAGS_SHARED_BIT 16 + /** * During scan if the file is found missing and relocated to another place * @@ -273,13 +285,7 @@ struct snapraid_block { * This specific bit is written using protection from the stamp_mutex during * the multithread scan. */ -#define FILE_IS_RELOCATED 0x1000 - -#define FILE_IS_HARDLINK 0x10000 /**< If it's an hardlink. */ -#define FILE_IS_SYMLINK 0x20000 /**< If it's a file symlink. */ -#define FILE_IS_SYMDIR 0x40000 /**< If it's a dir symlink for Windows. Not yet supported. */ -#define FILE_IS_JUNCTION 0x80000 /**< If it's a junction for Windows. Not yet supported. */ -#define FILE_IS_LINK_MASK 0xF0000 /**< Mask for link type. */ +#define FILE_IS_RELOCATED 0x10000 /** * File. @@ -292,7 +298,8 @@ struct snapraid_file { struct snapraid_block* blockvec; /**< All the blocks of the file. */ int mtime_nsec; /**< Modification time nanoseconds. In the range 0 <= x < 1,000,000,000, or STAT_NSEC_INVALID if not present. */ block_off_t blockmax; /**< Number of blocks. */ - unsigned flag; /**< FILE_IS_* flags. */ + uint16_t flag; /**< FILE_IS_* flags. */ + uint16_t shared_flag; /**< FILE_IS_RELOCATED flag. Keep it separated as it's accessed by multiple threads */ char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ /* nodes for data structures */ @@ -786,17 +793,32 @@ static inline int block_has_file_and_valid_parity(const struct snapraid_block* b static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) { - return (file->flag & mask) == mask; + if (mask >= (1 << FILE_FLAGS_SHARED_BIT)) { + mask >>= FILE_FLAGS_SHARED_BIT; + return (file->shared_flag & mask) == mask; + } else { + return (file->flag & mask) == mask; + } } static inline void file_flag_set(struct snapraid_file* file, unsigned mask) { - file->flag |= mask; + if (mask >= (1 << FILE_FLAGS_SHARED_BIT)) { + mask >>= FILE_FLAGS_SHARED_BIT; + file->shared_flag |= mask; + } else { + file->flag |= mask; + } } static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) { - file->flag &= ~mask; + if (mask >= (1 << FILE_FLAGS_SHARED_BIT)) { + mask >>= FILE_FLAGS_SHARED_BIT; + file->shared_flag &= ~mask; + } else { + file->flag &= ~mask; + } } /**