mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Merge branch 'b4'
This commit is contained in:
commit
f3eb9d9d22
6 changed files with 49 additions and 35 deletions
8
HISTORY
8
HISTORY
|
|
@ -14,8 +14,10 @@ SnapRAID HISTORY
|
|||
4.1 2013/9 (BETA)
|
||||
=================
|
||||
* If the underline filesystem doesn't support the FIEMAP command,
|
||||
fallback to use the inode number for sorting files.
|
||||
This happens with reiserfs in Linux.
|
||||
automatically fallback to use FIBMAP and then the inode number for sorting
|
||||
files.
|
||||
* Fixes the import of content files from previous version of SnapRAID that
|
||||
are the result of an incomplete sync.
|
||||
* Added a new -C, --gen-conf option to generate a dummy configuration
|
||||
file from the info in the content file.
|
||||
Just in case that you lose everything, except the content file.
|
||||
|
|
@ -38,7 +40,7 @@ SnapRAID HISTORY
|
|||
This happens only if the file has the same path, size and timestamp
|
||||
at nanosecond precision.
|
||||
* Added a hash seed to make harder intentional collision attacks.
|
||||
* When insering files for the first time, sort them by their physical
|
||||
* When inserting files for the first time, sort them by their physical
|
||||
address to improve read performance.
|
||||
* Optimized the cache use for the all the RAID computations.
|
||||
This improves a lot the RAID performance.
|
||||
|
|
|
|||
2
elem.c
2
elem.c
|
|
@ -583,7 +583,7 @@ int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax)
|
|||
/* if there is a deleted block, the disk is not empty */
|
||||
return 0;
|
||||
default:
|
||||
fprintf(stderr, "Internal incosistency for used block in disk '%s' without files\n", disk->name);
|
||||
fprintf(stderr, "Internal inconsistency for used block in disk '%s' without files\n", disk->name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
rehash.c
2
rehash.c
|
|
@ -66,7 +66,7 @@ void state_rehash(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
if (info_get_rehash(info)) {
|
||||
fprintf(stderr, "Internal incosistency for a rehash already in progress\n");
|
||||
fprintf(stderr, "Internal inconsistency for a rehash already in progress\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
|||
2
scan.c
2
scan.c
|
|
@ -919,6 +919,8 @@ void state_scan(struct snapraid_state* state, int output)
|
|||
}
|
||||
|
||||
/* sort the files before inserting them */
|
||||
/* we use a stable sort to ensure that if the reported physical offset/inode */
|
||||
/* are always 0, we keep at least the directory order */
|
||||
switch (state->opt.force_order) {
|
||||
case SORT_PHYSICAL :
|
||||
tommy_list_sort(&scan->file_insert_list, file_physical_compare);
|
||||
|
|
|
|||
22
state.c
22
state.c
|
|
@ -770,7 +770,7 @@ static void state_map(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
if (j==0) {
|
||||
fprintf(stderr, "Internal incosistency for mapping '%s'\n", map->name);
|
||||
fprintf(stderr, "Internal inconsistency for mapping '%s'\n", map->name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -1075,7 +1075,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE
|
|||
rehash = 1;
|
||||
|
||||
if (state->prevhash == HASH_UNDEFINED) {
|
||||
fprintf(stderr, "Internal incosistency for missing previous checksum in '%s' at line %u\n", path, line);
|
||||
fprintf(stderr, "Internal inconsistency for missing previous checksum in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1115,10 +1115,6 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE
|
|||
|
||||
deleted->block.parity_pos = v_pos;
|
||||
|
||||
/* keep track of the max block number used in parity */
|
||||
if (v_pos + 1 > blockmax)
|
||||
blockmax = v_pos + 1;
|
||||
|
||||
/* read the hash */
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
|
|
@ -1638,7 +1634,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE
|
|||
|
||||
/* check that the stored parity size matches the loaded state */
|
||||
if (blockmax != parity_size(state)) {
|
||||
fprintf(stderr, "Internal incosistency in parity size in '%s' at line %u\n", path, line);
|
||||
fprintf(stderr, "Internal inconsistency in parity size in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
state->loaded_blockmax = blockmax;
|
||||
|
|
@ -1746,7 +1742,7 @@ static void state_write_text(struct snapraid_state* state, STREAM* f)
|
|||
/* find the disk for this mapping */
|
||||
disk = find_disk(state, map->name);
|
||||
if (!disk) {
|
||||
fprintf(stderr, "Internal incosistency for unmapped disk '%s'\n", map->name);
|
||||
fprintf(stderr, "Internal inconsistency for unmapped disk '%s'\n", map->name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -2305,7 +2301,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
|
||||
if (rehash && state->prevhash == HASH_UNDEFINED) {
|
||||
decoding_error(path, f);
|
||||
fprintf(stderr, "Internal incosistency for missing previous checksum!\n");
|
||||
fprintf(stderr, "Internal inconsistency for missing previous checksum!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -2322,13 +2318,13 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
if (position_has_any_hash(state, v_pos)) {
|
||||
if (!info) {
|
||||
decoding_error(path, f);
|
||||
fprintf(stderr, "Internal incosistency for missing info!\n");
|
||||
fprintf(stderr, "Internal inconsistency for missing info!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
if (info) {
|
||||
decoding_error(path, f);
|
||||
fprintf(stderr, "Internal incosistency for unexpected info!\n");
|
||||
fprintf(stderr, "Internal inconsistency for unexpected info!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
@ -2689,7 +2685,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
|
||||
/* check that the stored parity size matches the loaded state */
|
||||
if (blockmax != parity_size(state)) {
|
||||
fprintf(stderr, "Internal incosistency in parity size in '%s' at offset %"PRIi64"\n", path, stell(f));
|
||||
fprintf(stderr, "Internal inconsistency in parity size in '%s' at offset %"PRIi64"\n", path, stell(f));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
state->loaded_blockmax = blockmax;
|
||||
|
|
@ -2810,7 +2806,7 @@ static void state_write_binary(struct snapraid_state* state, STREAM* f)
|
|||
/* find the disk for this mapping */
|
||||
disk = find_disk(state, map->name);
|
||||
if (!disk) {
|
||||
fprintf(stderr, "Internal incosistency for unmapped disk '%s'\n", map->name);
|
||||
fprintf(stderr, "Internal inconsistency for unmapped disk '%s'\n", map->name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
|||
48
unix.c
48
unix.c
|
|
@ -129,43 +129,57 @@ int filephy(const char* path, struct stat* st, uint64_t* physical)
|
|||
/* In Linux gets the real physical address of the file */
|
||||
/* Note that FIEMAP doesn't require root permission */
|
||||
int f;
|
||||
|
||||
struct {
|
||||
struct fiemap fiemap;
|
||||
struct fiemap_extent extent;
|
||||
} fm;
|
||||
unsigned int blknum;
|
||||
|
||||
f = open(path, O_RDONLY);
|
||||
if (f == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* first try with FIEMAP */
|
||||
/* if works for ext2, ext3, ext4, xfs */
|
||||
memset(&fm, 0, sizeof(fm));
|
||||
fm.fiemap.fm_start = 0;
|
||||
fm.fiemap.fm_length = ~0ULL;
|
||||
fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */
|
||||
fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
|
||||
|
||||
if (ioctl(f, FS_IOC_FIEMAP, &fm) == -1) {
|
||||
/* if the underline filesystem doesn't support FS_IOC_FIEMAP */
|
||||
/* fallback to use the inode */
|
||||
if (errno == ENOTSUP) {
|
||||
close(f);
|
||||
*physical = st->st_ino;
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(f);
|
||||
return -1;
|
||||
if (ioctl(f, FS_IOC_FIEMAP, &fm) == 0) {
|
||||
*physical = fm.fiemap.fm_extents[0].fe_physical;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*physical = fm.fiemap.fm_extents[0].fe_physical;
|
||||
|
||||
if (close(f) == -1) {
|
||||
return -1;
|
||||
/* if empty, FIBMAP doesn't work */
|
||||
if (st->st_size == 0) {
|
||||
*physical = 0;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void)st; /* not used here */
|
||||
/* then try with FIBMAP */
|
||||
/* it works for jfs, reiserfs, ntfs-3g */
|
||||
/* in exfat it always returns 0, that it's anyway better than the fake inodes */
|
||||
blknum = 0; /* first block */
|
||||
if (ioctl(f, FIBMAP, &blknum) == 0) {
|
||||
*physical = blknum;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* otherwise don't use anything, and keep the existing order */
|
||||
/* at now this should happen only for vfat */
|
||||
/* and it's surely better than using fake inodes */
|
||||
*physical = 0;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
#else
|
||||
/* In a generic Unix uses the inode as fake physical address */
|
||||
*physical = st->st_ino;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue