Commit 7ec23d50949d5062b5b749638dd9380ed75e58e5

Authored by Jonathan Brassow
Committed by Alasdair G Kergon
1 parent d2b698644c

dm log: userspace add luid to distinguish between concurrent log instances

Device-mapper userspace logs (like the clustered log) are
identified by a universally unique identifier (UUID).  This
identifier is used to associate requests from the kernel to
a specific log in userspace.  The UUID must be unique everywhere,
since multiple machines may use this identifier when communicating
about a particular log, as is the case for cluster logs.

Sometimes, device-mapper/LVM may re-use a UUID.  This is the
case during pvmoves, when moving from one segment of an LV
to another, or when resizing a mirror, etc.  In these cases,
a new log is created with the same UUID and loaded in the
"inactive" slot.  When a device-mapper "resume" is issued,
the "live" table is deactivated and the new "inactive" table
becomes "live".  (The "inactive" table can also be removed
via a device-mapper 'clear' command.)

The above two issues were colliding.  More than one log was being
created with the same UUID, and there was no way to distinguish
between them.  So, sometimes the wrong log would be swapped
out during the exchange.

The solution is to create a locally unique identifier,
'luid', to go along with the UUID.  This new identifier is used
to determine exactly which log is being referenced by the kernel
when the log exchange is made.  The identifier is not
universally safe, but it does not need to be, since
create/destroy/suspend/resume operations are bound to a specific
machine; and these are the operations that make up the exchange.

Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 4 changed files with 31 additions and 13 deletions Side-by-side Diff

drivers/md/dm-log-userspace-base.c
... ... @@ -21,6 +21,7 @@
21 21 struct dm_target *ti;
22 22 uint32_t region_size;
23 23 region_t region_count;
  24 + uint64_t luid;
24 25 char uuid[DM_UUID_LEN];
25 26  
26 27 char *usr_argv_str;
... ... @@ -63,7 +64,7 @@
63 64 * restored.
64 65 */
65 66 retry:
66   - r = dm_consult_userspace(uuid, request_type, data,
  67 + r = dm_consult_userspace(uuid, lc->luid, request_type, data,
67 68 data_size, rdata, rdata_size);
68 69  
69 70 if (r != -ESRCH)
70 71  
... ... @@ -74,14 +75,15 @@
74 75 set_current_state(TASK_INTERRUPTIBLE);
75 76 schedule_timeout(2*HZ);
76 77 DMWARN("Attempting to contact userspace log server...");
77   - r = dm_consult_userspace(uuid, DM_ULOG_CTR, lc->usr_argv_str,
  78 + r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_CTR,
  79 + lc->usr_argv_str,
78 80 strlen(lc->usr_argv_str) + 1,
79 81 NULL, NULL);
80 82 if (!r)
81 83 break;
82 84 }
83 85 DMINFO("Reconnected to userspace log server... DM_ULOG_CTR complete");
84   - r = dm_consult_userspace(uuid, DM_ULOG_RESUME, NULL,
  86 + r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_RESUME, NULL,
85 87 0, NULL, NULL);
86 88 if (!r)
87 89 goto retry;
... ... @@ -153,6 +155,9 @@
153 155 return -ENOMEM;
154 156 }
155 157  
  158 + /* The ptr value is sufficient for local unique id */
  159 + lc->luid = (uint64_t)lc;
  160 +
156 161 lc->ti = ti;
157 162  
158 163 if (strlen(argv[0]) > (DM_UUID_LEN - 1)) {
... ... @@ -172,7 +177,7 @@
172 177 }
173 178  
174 179 /* Send table string */
175   - r = dm_consult_userspace(lc->uuid, DM_ULOG_CTR,
  180 + r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
176 181 ctr_str, str_size, NULL, NULL);
177 182  
178 183 if (r == -ESRCH) {
... ... @@ -182,7 +187,7 @@
182 187  
183 188 /* Since the region size does not change, get it now */
184 189 rdata_size = sizeof(rdata);
185   - r = dm_consult_userspace(lc->uuid, DM_ULOG_GET_REGION_SIZE,
  190 + r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_GET_REGION_SIZE,
186 191 NULL, 0, (char *)&rdata, &rdata_size);
187 192  
188 193 if (r) {
... ... @@ -211,7 +216,7 @@
211 216 int r;
212 217 struct log_c *lc = log->context;
213 218  
214   - r = dm_consult_userspace(lc->uuid, DM_ULOG_DTR,
  219 + r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR,
215 220 NULL, 0,
216 221 NULL, NULL);
217 222  
... ... @@ -226,7 +231,7 @@
226 231 int r;
227 232 struct log_c *lc = log->context;
228 233  
229   - r = dm_consult_userspace(lc->uuid, DM_ULOG_PRESUSPEND,
  234 + r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_PRESUSPEND,
230 235 NULL, 0,
231 236 NULL, NULL);
232 237  
... ... @@ -238,7 +243,7 @@
238 243 int r;
239 244 struct log_c *lc = log->context;
240 245  
241   - r = dm_consult_userspace(lc->uuid, DM_ULOG_POSTSUSPEND,
  246 + r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_POSTSUSPEND,
242 247 NULL, 0,
243 248 NULL, NULL);
244 249  
... ... @@ -251,7 +256,7 @@
251 256 struct log_c *lc = log->context;
252 257  
253 258 lc->in_sync_hint = 0;
254   - r = dm_consult_userspace(lc->uuid, DM_ULOG_RESUME,
  259 + r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_RESUME,
255 260 NULL, 0,
256 261 NULL, NULL);
257 262  
drivers/md/dm-log-userspace-transfer.c
... ... @@ -147,7 +147,8 @@
147 147  
148 148 /**
149 149 * dm_consult_userspace
150   - * @uuid: log's uuid (must be DM_UUID_LEN in size)
  150 + * @uuid: log's universal unique identifier (must be DM_UUID_LEN in size)
  151 + * @luid: log's local unique identifier
151 152 * @request_type: found in include/linux/dm-log-userspace.h
152 153 * @data: data to tx to the server
153 154 * @data_size: size of data in bytes
... ... @@ -163,7 +164,7 @@
163 164 *
164 165 * Returns: 0 on success, -EXXX on failure
165 166 **/
166   -int dm_consult_userspace(const char *uuid, int request_type,
  167 +int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
167 168 char *data, size_t data_size,
168 169 char *rdata, size_t *rdata_size)
169 170 {
... ... @@ -190,6 +191,7 @@
190 191  
191 192 memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size);
192 193 memcpy(tfr->uuid, uuid, DM_UUID_LEN);
  194 + tfr->luid = luid;
193 195 tfr->seq = dm_ulog_seq++;
194 196  
195 197 /*
drivers/md/dm-log-userspace-transfer.h
... ... @@ -11,7 +11,7 @@
11 11  
12 12 int dm_ulog_tfr_init(void);
13 13 void dm_ulog_tfr_exit(void);
14   -int dm_consult_userspace(const char *uuid, int request_type,
  14 +int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
15 15 char *data, size_t data_size,
16 16 char *rdata, size_t *rdata_size);
17 17  
include/linux/dm-log-userspace.h
... ... @@ -371,7 +371,18 @@
371 371 (DM_ULOG_REQUEST_MASK & (request_type))
372 372  
373 373 struct dm_ulog_request {
374   - char uuid[DM_UUID_LEN]; /* Ties a request to a specific mirror log */
  374 + /*
  375 + * The local unique identifier (luid) and the universally unique
  376 + * identifier (uuid) are used to tie a request to a specific
  377 + * mirror log. A single machine log could probably make due with
  378 + * just the 'luid', but a cluster-aware log must use the 'uuid' and
  379 + * the 'luid'. The uuid is what is required for node to node
  380 + * communication concerning a particular log, but the 'luid' helps
  381 + * differentiate between logs that are being swapped and have the
  382 + * same 'uuid'. (Think "live" and "inactive" device-mapper tables.)
  383 + */
  384 + uint64_t luid;
  385 + char uuid[DM_UUID_LEN];
375 386 char padding[7]; /* Padding because DM_UUID_LEN = 129 */
376 387  
377 388 int32_t error; /* Used to report back processing errors */