Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Maintenance:3693
lvm2.openSUSE_13.1_Update
lvmetad_tokent_mismatch_retry.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File lvmetad_tokent_mismatch_retry.patch of Package lvm2.openSUSE_13.1_Update
Index: LVM2.2.02.98/lib/cache/lvmetad.c =================================================================== --- LVM2.2.02.98.orig/lib/cache/lvmetad.c +++ LVM2.2.02.98/lib/cache/lvmetad.c @@ -23,6 +23,9 @@ #include "assert.h" #include "crc.h" +#define SCAN_TIMEOUT_SECONDS 80 +#define MAX_RESCANS 10 /* Maximum number of times to scan all PVs and retry if the daemon returns a token mismatch error */ + static daemon_handle _lvmetad; static int _lvmetad_use = 0; static int _lvmetad_connected = 0; @@ -128,7 +131,10 @@ static daemon_reply _lvmetad_send(const va_list ap; daemon_reply repl; daemon_request req; - int try = 0; + unsigned num_rescans = 0; + unsigned total_usecs_waited = 0; + unsigned max_remaining_sleep_times = 1; + unsigned wait_usecs; retry: req = daemon_request_make(id); @@ -144,15 +150,35 @@ retry: daemon_request_destroy(req); + /** If another process is trying to scan, it might have the + * same future token id and it's better to wait and avoid doing + * the work multiple times. For the case where the future token is + * different, the wait is randomized so that multiple waiting + * processes do not start scanning all at once. + * + * If the token is mismatched because of global_filter changes, + * we re-scan immediately, but if we lose the potential race for + * the update, we back off for a short while (0.05-0.5 seconds) and + * try again. + */ if (!repl.error && !strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") && - try < 2 && !test_mode()) { - if (lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL)) { - ++ try; - daemon_reply_destroy(repl); - goto retry; + num_rescans < MAX_RESCANS && total_usecs_waited < (SCAN_TIMEOUT_SECONDS * 1000000) && !test_mode()) { + if (!strcmp(daemon_reply_str(repl, "expected", ""), "update in progress") || + max_remaining_sleep_times) { + wait_usecs = 50000 + lvm_even_rand(&_lvmetad_cmd->rand_seed, 450000); /* between 0.05s and 0.5s */ + (void) usleep(wait_usecs); + total_usecs_waited += wait_usecs; + if (max_remaining_sleep_times) + max_remaining_sleep_times--; /* Sleep once before rescanning the first time, then 5 times each time after that. */ + } else { + /* If the re-scan fails here, we try again later. */ + (void) lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL); + num_rescans++; + max_remaining_sleep_times = 5; } + daemon_reply_destroy(repl); + goto retry; } - return repl; } Index: LVM2.2.02.98/lib/misc/lvm-wrappers.c =================================================================== --- LVM2.2.02.98.orig/lib/misc/lvm-wrappers.c +++ LVM2.2.02.98/lib/misc/lvm-wrappers.c @@ -117,3 +117,25 @@ int read_urandom(void *buf, size_t len) return 1; } +/* + * Return random integer in [0,max) interval + * + * The loop rejects numbers that come from an "incomplete" slice of the + * RAND_MAX space. Considering the number space [0, RAND_MAX] is divided + * into some "max"-sized slices and at most a single smaller slice, + * between [n*max, RAND_MAX] for suitable n, numbers from this last slice + * are discarded because they could distort the distribution in favour of + * smaller numbers. + */ +unsigned lvm_even_rand(unsigned *seed, unsigned max) +{ + unsigned r, ret; + + do { + r = (unsigned) rand_r(seed); + ret = r % max; + } while (r - ret > RAND_MAX - max); + + return ret; +} +
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor