mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Fix modified hardlink inode tracking during scan
This commit is contained in:
parent
3dfab5232c
commit
d5d999f11d
2 changed files with 43 additions and 10 deletions
|
|
@ -243,7 +243,7 @@ struct snapraid_block {
|
|||
#define FILE_IS_MODIFIED_OLD 0x10000
|
||||
|
||||
/**
|
||||
* Flag to indicate the new version of a modified/reallocated file during scanning.
|
||||
* Flag to indicate the new version of a modified file during scanning.
|
||||
*/
|
||||
#define FILE_IS_MODIFIED_NEW 0x20000
|
||||
|
||||
|
|
@ -252,6 +252,11 @@ struct snapraid_block {
|
|||
*/
|
||||
#define FILE_IS_REALLOC_OLD 0x40000
|
||||
|
||||
/**
|
||||
* Flag to indicate the new version of a kept file being reallocated during scanning.
|
||||
*/
|
||||
#define FILE_IS_REALLOC_NEW 0x80000
|
||||
|
||||
/**
|
||||
* Flags from this bit are shared between multiple threads
|
||||
* and goes in the shared_flags instead of flags
|
||||
|
|
|
|||
|
|
@ -626,15 +626,22 @@ static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struc
|
|||
}
|
||||
|
||||
/**
|
||||
* Insert the file in the data set.
|
||||
* Insert the file in the inode set.
|
||||
*/
|
||||
static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file)
|
||||
static void scan_file_inode_insert(struct snapraid_scan* scan, struct snapraid_file* file)
|
||||
{
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
|
||||
/* insert the file in the containers */
|
||||
if (file->inode != INODE_INVALID)
|
||||
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the file in the path and stamp sets.
|
||||
*/
|
||||
static void scan_file_stamp_insert(struct snapraid_scan* scan, struct snapraid_file* file)
|
||||
{
|
||||
struct snapraid_disk* disk = scan->disk;
|
||||
|
||||
stamp_lock(disk);
|
||||
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
|
||||
|
|
@ -705,7 +712,7 @@ static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* fil
|
|||
if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) {
|
||||
|
||||
struct snapraid_file* copy = file_dup(file);
|
||||
file_flag_set(copy, FILE_IS_MODIFIED_NEW);
|
||||
file_flag_set(copy, FILE_IS_REALLOC_NEW);
|
||||
|
||||
/* insert in the delayed allocation list */
|
||||
scan_file_delayed_allocate(scan, copy);
|
||||
|
|
@ -1003,10 +1010,16 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
|||
/* keep track if the original file was not of zero size */
|
||||
is_original_file_size_different_than_zero = file->size != 0;
|
||||
|
||||
/* the old version doesn't represent the current inode anymore */
|
||||
if (file->inode != INODE_INVALID) {
|
||||
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
|
||||
file->inode = INODE_INVALID;
|
||||
}
|
||||
|
||||
/* mark it as to be removed in Phase 2 */
|
||||
file_flag_set(file, FILE_IS_MODIFIED_OLD);
|
||||
|
||||
/* flag that we are inserting the modified version so we skip Phase 1 insertion sets */
|
||||
/* flag the modified version to defer path/stamp insertion to Phase 3 */
|
||||
is_file_modified = 1;
|
||||
|
||||
/* and continue to insert it again */
|
||||
|
|
@ -1158,9 +1171,16 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
|
|||
}
|
||||
}
|
||||
|
||||
if (!is_file_modified) { /* modified files are re-inserted in Phase 3 */
|
||||
scan_file_insert(scan, file);
|
||||
if (!is_file_modified) {
|
||||
scan_file_inode_insert(scan, file);
|
||||
scan_file_stamp_insert(scan, file);
|
||||
} else {
|
||||
/*
|
||||
* Insert the new inode before scanning the next path, so paths with the
|
||||
* same inode are recognized as hardlinks to this file. Keep the old
|
||||
* path/stamp entries until Phase 2; the new entries are inserted in Phase 3.
|
||||
*/
|
||||
scan_file_inode_insert(scan, file);
|
||||
file_flag_set(file, FILE_IS_MODIFIED_NEW);
|
||||
}
|
||||
|
||||
|
|
@ -1910,9 +1930,17 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
|||
/* next node */
|
||||
node = node->next;
|
||||
|
||||
/* if this is a modified file new version, insert it into sets now */
|
||||
/* insert the delayed containers before allocating the file */
|
||||
if (file_flag_has(file, FILE_IS_MODIFIED_NEW)) {
|
||||
scan_file_insert(scan, file);
|
||||
/*
|
||||
* The inode was already inserted in Phase 1, so later paths with the same
|
||||
* inode could be recognized as hardlinks. Now that Phase 2 removed the old
|
||||
* version, insert only the new path/stamp entries.
|
||||
*/
|
||||
scan_file_stamp_insert(scan, file);
|
||||
} else if (file_flag_has(file, FILE_IS_REALLOC_NEW)) {
|
||||
scan_file_inode_insert(scan, file);
|
||||
scan_file_stamp_insert(scan, file);
|
||||
}
|
||||
|
||||
/* insert in the parity */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue