mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Autorename disks using UUID for matching
This commit is contained in:
parent
801d01c55b
commit
cacc1cb0ce
6 changed files with 95 additions and 13 deletions
2
HISTORY
2
HISTORY
|
|
@ -6,6 +6,8 @@ SnapRAID HISTORY
|
|||
* Fixes support for symlinks pointing to an empty target. Before they
|
||||
were only partially supported, and their presence could result in
|
||||
a content file not readable.
|
||||
* Autorename disks using the matching UUID. To rename a disk you can
|
||||
now change directly the name in the configuration file.
|
||||
* Improves the physical offset ordering for the Btrfs filesystem,
|
||||
correctly detecting files that have not a physical offset, for
|
||||
whatever reason.
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ EXTRA_DIST = \
|
|||
test/test-par6.conf \
|
||||
test/test-par6-hole.conf \
|
||||
test/test-par6-noaccess.conf \
|
||||
test/test-par6-rename.conf \
|
||||
snapraid.conf.example \
|
||||
configure.windows-x86 configure.windows-x64 snapraid.conf.example.windows \
|
||||
acinclude.m4 \
|
||||
|
|
@ -185,6 +186,7 @@ endif
|
|||
CONF = $(srcdir)/test/test-par6.conf
|
||||
HOLE = $(srcdir)/test/test-par6-hole.conf
|
||||
NOACCESS = $(srcdir)/test/test-par6-noaccess.conf
|
||||
RENAME = $(srcdir)/test/test-par6-rename.conf
|
||||
PAR1 = $(srcdir)/test/test-par1.conf
|
||||
PAR2 = $(srcdir)/test/test-par2.conf
|
||||
PAR3 = $(srcdir)/test/test-par3.conf
|
||||
|
|
@ -425,6 +427,9 @@ endif
|
|||
echo --- Fix with unaccessible parity and disk
|
||||
$(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(NOACCESS) fix --test-expect-failure
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(NOACCESS) fix --force-device --test-expect-recoverable -l test.log
|
||||
echo -- Rename a disk
|
||||
$(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RENAME) --test-match-first-uuid sync
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-match-first-uuid sync
|
||||
#### SCRUB ####
|
||||
echo --- Scrub some times
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 100 scrub
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ void config(char* conf, size_t conf_size, const char* argv0)
|
|||
#define OPT_TEST_EXPECT_NEED_SYNC 285
|
||||
#define OPT_NO_WARNINGS 286
|
||||
#define OPT_TEST_FAKE_UUID 287
|
||||
#define OPT_TEST_MATCH_FIRST_UUID 288
|
||||
|
||||
#if HAVE_GETOPT_LONG
|
||||
struct option long_options[] = {
|
||||
|
|
@ -368,6 +369,9 @@ struct option long_options[] = {
|
|||
/* Fake UUID */
|
||||
{ "test-fake-uuid", 0, 0, OPT_TEST_FAKE_UUID },
|
||||
|
||||
/* Match first UUID */
|
||||
{ "test-match-first-uuid", 0, 0, OPT_TEST_MATCH_FIRST_UUID },
|
||||
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
#endif
|
||||
|
|
@ -740,6 +744,9 @@ int main(int argc, char* argv[])
|
|||
case OPT_TEST_FAKE_UUID :
|
||||
opt.fake_uuid = 2;
|
||||
break;
|
||||
case OPT_TEST_MATCH_FIRST_UUID :
|
||||
opt.match_first_uuid = 1;
|
||||
break;
|
||||
default :
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Unknown option '%c'\n", (char)c);
|
||||
|
|
|
|||
|
|
@ -1155,7 +1155,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/**
|
||||
* Find a disk by name.
|
||||
*/
|
||||
static struct snapraid_disk* find_disk(struct snapraid_state* state, const char* name)
|
||||
static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name)
|
||||
{
|
||||
tommy_node* i;
|
||||
|
||||
|
|
@ -1179,6 +1179,39 @@ static struct snapraid_disk* find_disk(struct snapraid_state* state, const char*
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a disk by UUID.
|
||||
*/
|
||||
static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid)
|
||||
{
|
||||
tommy_node* i;
|
||||
struct snapraid_disk* found = 0;
|
||||
|
||||
/* special test case to find the first macthing UUID */
|
||||
/* when testing UUID are all equal or not supported */
|
||||
/* and we should handle this case specifically */
|
||||
if (state->opt.match_first_uuid)
|
||||
return state->disklist->data;
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
/* never find an empty uuid */
|
||||
if (!*uuid)
|
||||
return 0;
|
||||
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
if (strcmp(disk->uuid, uuid) == 0) {
|
||||
/* never match duplicate UUID */
|
||||
if (found)
|
||||
return 0;
|
||||
found = disk;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the disk mapping if required.
|
||||
*/
|
||||
|
|
@ -1198,7 +1231,7 @@ static void state_map(struct snapraid_state* state)
|
|||
struct snapraid_map* map = i->data;
|
||||
struct snapraid_disk* disk;
|
||||
|
||||
disk = find_disk(state, map->name);
|
||||
disk = find_disk_by_name(state, map->name);
|
||||
|
||||
/* go to the next mapping before removing */
|
||||
i = i->next;
|
||||
|
|
@ -1270,7 +1303,7 @@ static void state_map(struct snapraid_state* state)
|
|||
struct snapraid_map* map = i->data;
|
||||
struct snapraid_disk* disk;
|
||||
|
||||
disk = find_disk(state, map->name);
|
||||
disk = find_disk_by_name(state, map->name);
|
||||
if (disk == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
|
||||
|
|
@ -1398,7 +1431,7 @@ void state_refresh(struct snapraid_state* state)
|
|||
uint64_t free_space;
|
||||
int ret;
|
||||
|
||||
disk = find_disk(state, map->name);
|
||||
disk = find_disk_by_name(state, map->name);
|
||||
if (disk == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
|
||||
|
|
@ -2375,21 +2408,31 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
map = map_alloc(buffer, v_pos, v_total_blocks, v_free_blocks, uuid);
|
||||
|
||||
tommy_list_insert_tail(&state->maplist, &map->node, map);
|
||||
|
||||
/* find the disk */
|
||||
disk = find_disk(state, buffer);
|
||||
disk = find_disk_by_name(state, buffer);
|
||||
if (!disk) {
|
||||
/* search by UUID if renamed */
|
||||
disk = find_disk_by_uuid(state, uuid);
|
||||
if (disk) {
|
||||
log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name);
|
||||
|
||||
/* write the new state with the new name */
|
||||
state->need_write = 1;
|
||||
}
|
||||
}
|
||||
if (!disk) {
|
||||
/* LCOV_EXCL_START */
|
||||
decoding_error(path, f);
|
||||
log_fatal("Disk named '%s' not present in the configuration file!\n", buffer);
|
||||
log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid);
|
||||
log_fatal("If you have removed it from the configuration file, please restore it\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid);
|
||||
|
||||
tommy_list_insert_tail(&state->maplist, &map->node, map);
|
||||
|
||||
/* insert in the mapping vector */
|
||||
tommy_array_grow(&disk_mapping, mapping_max + 1);
|
||||
tommy_array_set(&disk_mapping, mapping_max, disk);
|
||||
|
|
@ -2638,7 +2681,7 @@ static void* state_write_thread(void* arg)
|
|||
struct snapraid_disk* disk;
|
||||
|
||||
/* find the disk for this mapping */
|
||||
disk = find_disk(state, map->name);
|
||||
disk = find_disk_by_name(state, map->name);
|
||||
if (!disk) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
|
||||
|
|
@ -3072,7 +3115,7 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
|
|||
struct snapraid_disk* disk;
|
||||
|
||||
/* find the disk for this mapping */
|
||||
disk = find_disk(state, map->name);
|
||||
disk = find_disk_by_name(state, map->name);
|
||||
if (!disk) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
|
||||
|
|
@ -3982,7 +4025,7 @@ void generate_configuration(const char* path)
|
|||
printf("# Set the correct dir for disk '%s'\n", map->name);
|
||||
if (map->uuid[0])
|
||||
printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid);
|
||||
disk = find_disk(&state, map->name);
|
||||
disk = find_disk_by_name(&state, map->name);
|
||||
if (disk && disk->filelist) {
|
||||
struct snapraid_file* file = disk->filelist->data;
|
||||
if (file) {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ struct snapraid_option {
|
|||
int no_warnings; /**< Remove some warning messages. */
|
||||
int expected_missing; /**< If missing files are expected and should not be reported. */
|
||||
int fake_uuid; /**< Set fakes UUID for testing. */
|
||||
int match_first_uuid; /**< Force the matching of the first UUID. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
24
test/test-par6-rename.conf
Normal file
24
test/test-par6-rename.conf
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
blocksize 1
|
||||
parity bench/parity
|
||||
2-parity bench/2-parity
|
||||
3-parity bench/3-parity
|
||||
4-parity bench/4-parity
|
||||
5-parity bench/5-parity
|
||||
6-parity bench/6-parity
|
||||
content bench/content
|
||||
content bench/1-content
|
||||
content bench/2-content
|
||||
content bench/3-content
|
||||
content bench/4-content
|
||||
content bench/5-content
|
||||
content bench/6-content
|
||||
disk disk1-rename bench/disk1/
|
||||
disk disk2 bench/disk2/
|
||||
disk disk3 bench/disk3/
|
||||
disk disk4 bench/disk4/
|
||||
disk disk5 bench/disk5/
|
||||
disk disk6 bench/disk6/
|
||||
include *.hidden
|
||||
exclude *.unrecoverable
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue