Autorename disks using UUID for matching

This commit is contained in:
Andrea Mazzoleni 2015-12-28 13:55:22 +01:00
parent 801d01c55b
commit cacc1cb0ce
6 changed files with 95 additions and 13 deletions

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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) {

View 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. */
};
/**

View 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