blob: b98d310a1377d210d1b6031f52dcbb53f566cd5c [file] [log] [blame]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Benjamin Marzinski <bmarzins@redhat.com>
3Date: Mon, 4 Jun 2018 22:04:44 -0500
4Subject: [PATCH] mpathpersist: fix aptpl support
5
6The "Active Persist Through Power Loss" flag must be set whenever a key
7is registered. However, there is no way for multipathd to know if this
8was set by mpathpersist. The result is that if a path goes down and
9comes back up (or if it wasn't up when mpathpersist was first run)
10multipathd will clear the aptpl flag when it reregisters the key on it.
11
12To fix this, multipath.conf now accepts an optional ":aptpl" appended
13on the reservation_key value. If this is added to the reservation_key
14multipathd will set the aptpl flag when it reregisters the key. If
15reservation_key is set to "file", this will automatically be tracked
16in the /etc/multipath/prkeys file.
17
18To track this flag in the prkeys file, without changing the format
19I've made "0x<key>" stand for non-aptpl keys, and "0X<key>" stand
20for aptpl keys. Since previously, all keys used a lower-case x, this
21will default to the current behavior for existing keys. Obviously, the
22next time mpathpersist is run, this will be changed if --param-aptpl
23is used. Since there are no more flags that are in sg_persist that
24multipathd needs to care about in mpathpersist, there shouldn't need
25to be any more flags added to the prkeys file.
26
27Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
28---
29 libmpathpersist/mpath_persist.c | 3 ++-
30 libmpathpersist/mpath_updatepr.c | 11 +++++++----
31 libmpathpersist/mpathpr.h | 3 ++-
32 libmultipath/Makefile | 2 +-
33 libmultipath/config.h | 2 ++
34 libmultipath/dict.c | 23 +++++++++++++++++++----
35 libmultipath/dict.h | 3 ++-
36 libmultipath/prkey.c | 27 ++++++++++++++++++++++++---
37 libmultipath/prkey.h | 6 ++++--
38 libmultipath/propsel.c | 6 ++++--
39 libmultipath/structs.h | 1 +
40 libmultipath/util.c | 16 ++++++++++++++++
41 libmultipath/util.h | 1 +
42 multipath/multipath.conf.5 | 7 +++++--
43 multipathd/cli_handlers.c | 15 ++++++++++-----
44 multipathd/main.c | 1 +
45 16 files changed, 101 insertions(+), 26 deletions(-)
46
47diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
48index ca91c55..6e9e67f 100644
49--- a/libmpathpersist/mpath_persist.c
50+++ b/libmpathpersist/mpath_persist.c
51@@ -344,7 +344,8 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
52 rq_servact == MPATH_PROUT_REG_SA) ||
53 rq_servact == MPATH_PROUT_REG_IGN_SA)) {
54 memcpy(&mpp->reservation_key, paramp->sa_key, 8);
55- if (update_prkey(alias, get_be64(mpp->reservation_key))) {
56+ if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
57+ paramp->sa_flags)) {
58 condlog(0, "%s: failed to set prkey for multipathd.",
59 alias);
60 ret = MPATH_PR_DMMP_ERROR;
61diff --git a/libmpathpersist/mpath_updatepr.c b/libmpathpersist/mpath_updatepr.c
62index 8063e90..0aca28e 100644
63--- a/libmpathpersist/mpath_updatepr.c
64+++ b/libmpathpersist/mpath_updatepr.c
65@@ -1,7 +1,5 @@
66 #include <stdio.h>
67 #include <unistd.h>
68-#include <errno.h>
69-
70 #include <stdlib.h>
71 #include <stdarg.h>
72 #include <fcntl.h>
73@@ -11,6 +9,8 @@
74 #include <sys/un.h>
75 #include <poll.h>
76 #include <errno.h>
77+#include <libudev.h>
78+#include <mpath_persist.h>
79 #include "debug.h"
80 #include "mpath_cmd.h"
81 #include "uxsock.h"
82@@ -59,11 +59,14 @@ int update_prflag(char *mapname, int set) {
83 return do_update_pr(mapname, (set)? "setprstatus" : "unsetprstatus");
84 }
85
86-int update_prkey(char *mapname, uint64_t prkey) {
87+int update_prkey_flags(char *mapname, uint64_t prkey, uint8_t sa_flags) {
88 char str[256];
89+ char *flagstr = "";
90
91+ if (sa_flags & MPATH_F_APTPL_MASK)
92+ flagstr = ":aptpl";
93 if (prkey)
94- sprintf(str, "setprkey key %" PRIx64, prkey);
95+ sprintf(str, "setprkey key %" PRIx64 "%s", prkey, flagstr);
96 else
97 sprintf(str, "unsetprkey");
98 return do_update_pr(mapname, str);
99diff --git a/libmpathpersist/mpathpr.h b/libmpathpersist/mpathpr.h
100index 72feb60..5ea8cd6 100644
101--- a/libmpathpersist/mpathpr.h
102+++ b/libmpathpersist/mpathpr.h
103@@ -46,7 +46,8 @@ int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
104 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
105
106 int update_prflag(char *mapname, int set);
107-int update_prkey(char *mapname, uint64_t prkey);
108+int update_prkey_flags(char *mapname, uint64_t prkey, uint8_t sa_flags);
109+#define update_prkey(mapname, prkey) update_prkey_flags(mapname, prkey, 0)
110 void * mpath_alloc_prin_response(int prin_sa);
111 int update_map_pr(struct multipath *mpp);
112
113diff --git a/libmultipath/Makefile b/libmultipath/Makefile
114index f51786d..33f5269 100644
115--- a/libmultipath/Makefile
116+++ b/libmultipath/Makefile
117@@ -7,7 +7,7 @@ SONAME = 0
118 DEVLIB = libmultipath.so
119 LIBS = $(DEVLIB).$(SONAME)
120
121-CFLAGS += $(LIB_CFLAGS) -I$(mpathcmddir)
122+CFLAGS += $(LIB_CFLAGS) -I$(mpathcmddir) -I$(mpathpersistdir)
123
124 LIBDEPS += -lpthread -ldl -ldevmapper -ludev -L$(mpathcmddir) -lmpathcmd -lurcu -laio
125
126diff --git a/libmultipath/config.h b/libmultipath/config.h
127index 1bf708a..fcbe3fc 100644
128--- a/libmultipath/config.h
129+++ b/libmultipath/config.h
130@@ -98,6 +98,7 @@ struct mpentry {
131 char * prio_args;
132 int prkey_source;
133 struct be64 reservation_key;
134+ uint8_t sa_flags;
135 int pgpolicy;
136 int pgfailback;
137 int rr_weight;
138@@ -197,6 +198,7 @@ struct config {
139 int prkey_source;
140 int all_tg_pt;
141 struct be64 reservation_key;
142+ uint8_t sa_flags;
143
144 vector keywords;
145 vector mptable;
146diff --git a/libmultipath/dict.c b/libmultipath/dict.c
147index 2557b8a..7ad0f5a 100644
148--- a/libmultipath/dict.c
149+++ b/libmultipath/dict.c
150@@ -22,6 +22,8 @@
151 #include "util.h"
152 #include <errno.h>
153 #include <inttypes.h>
154+#include <libudev.h>
155+#include <mpath_persist.h>
156 #include "mpath_cmd.h"
157 #include "dict.h"
158
159@@ -1012,10 +1014,12 @@ snprint_def_log_checker_err (struct config *conf, char * buff, int len,
160 }
161
162 static int
163-set_reservation_key(vector strvec, struct be64 *be64_ptr, int *source_ptr)
164+set_reservation_key(vector strvec, struct be64 *be64_ptr, uint8_t *flags_ptr,
165+ int *source_ptr)
166 {
167 char *buff;
168 uint64_t prkey;
169+ uint8_t sa_flags;
170
171 buff = set_value(strvec);
172 if (!buff)
173@@ -1023,35 +1027,43 @@ set_reservation_key(vector strvec, struct be64 *be64_ptr, int *source_ptr)
174
175 if (strcmp(buff, "file") == 0) {
176 *source_ptr = PRKEY_SOURCE_FILE;
177+ *flags_ptr = 0;
178 put_be64(*be64_ptr, 0);
179 FREE(buff);
180 return 0;
181 }
182
183- if (parse_prkey(buff, &prkey) != 0) {
184+ if (parse_prkey_flags(buff, &prkey, &sa_flags) != 0) {
185 FREE(buff);
186 return 1;
187 }
188 *source_ptr = PRKEY_SOURCE_CONF;
189+ *flags_ptr = sa_flags;
190 put_be64(*be64_ptr, prkey);
191 FREE(buff);
192 return 0;
193 }
194
195 int
196-print_reservation_key(char * buff, int len, struct be64 key, int source)
197+print_reservation_key(char * buff, int len, struct be64 key, uint8_t flags,
198+ int source)
199 {
200+ char *flagstr = "";
201 if (source == PRKEY_SOURCE_NONE)
202 return 0;
203 if (source == PRKEY_SOURCE_FILE)
204 return snprintf(buff, len, "file");
205- return snprintf(buff, len, "0x%" PRIx64, get_be64(key));
206+ if (flags & MPATH_F_APTPL_MASK)
207+ flagstr = ":aptpl";
208+ return snprintf(buff, len, "0x%" PRIx64 "%s", get_be64(key),
209+ flagstr);
210 }
211
212 static int
213 def_reservation_key_handler(struct config *conf, vector strvec)
214 {
215 return set_reservation_key(strvec, &conf->reservation_key,
216+ &conf->sa_flags,
217 &conf->prkey_source);
218 }
219
220@@ -1060,6 +1072,7 @@ snprint_def_reservation_key (struct config *conf, char * buff, int len,
221 const void * data)
222 {
223 return print_reservation_key(buff, len, conf->reservation_key,
224+ conf->sa_flags,
225 conf->prkey_source);
226 }
227
228@@ -1070,6 +1083,7 @@ mp_reservation_key_handler(struct config *conf, vector strvec)
229 if (!mpe)
230 return 1;
231 return set_reservation_key(strvec, &mpe->reservation_key,
232+ &mpe->sa_flags,
233 &mpe->prkey_source);
234 }
235
236@@ -1079,6 +1093,7 @@ snprint_mp_reservation_key (struct config *conf, char * buff, int len,
237 {
238 const struct mpentry * mpe = (const struct mpentry *)data;
239 return print_reservation_key(buff, len, mpe->reservation_key,
240+ mpe->sa_flags,
241 mpe->prkey_source);
242 }
243
244diff --git a/libmultipath/dict.h b/libmultipath/dict.h
245index 7564892..a40ac66 100644
246--- a/libmultipath/dict.h
247+++ b/libmultipath/dict.h
248@@ -15,6 +15,7 @@ int print_pgpolicy(char *buff, int len, long v);
249 int print_no_path_retry(char *buff, int len, long v);
250 int print_fast_io_fail(char *buff, int len, long v);
251 int print_dev_loss(char *buff, int len, unsigned long v);
252-int print_reservation_key(char * buff, int len, struct be64 key, int source);
253+int print_reservation_key(char * buff, int len, struct be64 key, uint8_t
254+ flags, int source);
255 int print_off_int_undef(char *buff, int len, long v);
256 #endif /* _DICT_H */
257diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c
258index 89b90ed..d645f81 100644
259--- a/libmultipath/prkey.c
260+++ b/libmultipath/prkey.c
261@@ -11,6 +11,8 @@
262 #include <string.h>
263 #include <inttypes.h>
264 #include <errno.h>
265+#include <libudev.h>
266+#include <mpath_persist.h>
267
268 #define PRKEY_READ 0
269 #define PRKEY_WRITE 1
270@@ -108,7 +110,8 @@ static int do_prkey(int fd, char *wwid, char *keystr, int cmd)
271 return 0;
272 }
273
274-int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey)
275+int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
276+ uint8_t *sa_flags)
277 {
278 int fd;
279 int unused;
280@@ -124,6 +127,9 @@ int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey)
281 ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ);
282 if (ret)
283 goto out_file;
284+ *sa_flags = 0;
285+ if (strchr(keystr, 'X'))
286+ *sa_flags = MPATH_F_APTPL_MASK;
287 ret = !!parse_prkey(keystr, prkey);
288 out_file:
289 close(fd);
290@@ -131,7 +137,8 @@ out:
291 return ret;
292 }
293
294-int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey)
295+int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey,
296+ uint8_t sa_flags)
297 {
298 int fd;
299 int can_write = 1;
300@@ -141,6 +148,12 @@ int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey)
301 if (!strlen(mpp->wwid))
302 goto out;
303
304+ if (sa_flags & ~MPATH_F_APTPL_MASK) {
305+ condlog(0, "unsupported pr flags, 0x%x",
306+ sa_flags & ~MPATH_F_APTPL_MASK);
307+ sa_flags &= MPATH_F_APTPL_MASK;
308+ }
309+
310 fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER);
311 if (fd < 0)
312 goto out;
313@@ -149,7 +162,15 @@ int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey)
314 goto out_file;
315 }
316 if (prkey) {
317- snprintf(keystr, PRKEY_SIZE, "0x%016" PRIx64, prkey);
318+ /* using the capitalization of the 'x' is a hack, but
319+ * it's unlikely that mpath_persist will support more options
320+ * since sg_persist doesn't, and this lets us keep the
321+ * same file format as before instead of needing to change
322+ * the format of the prkeys file */
323+ if (sa_flags)
324+ snprintf(keystr, PRKEY_SIZE, "0X%016" PRIx64, prkey);
325+ else
326+ snprintf(keystr, PRKEY_SIZE, "0x%016" PRIx64, prkey);
327 keystr[PRKEY_SIZE - 1] = '\0';
328 ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_WRITE);
329 }
330diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h
331index 4028e70..6739191 100644
332--- a/libmultipath/prkey.h
333+++ b/libmultipath/prkey.h
334@@ -13,7 +13,9 @@
335 "# prkey wwid\n" \
336 "#\n"
337
338-int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey);
339-int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey);
340+int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey,
341+ uint8_t sa_flags);
342+int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
343+ uint8_t *sa_flags);
344
345 #endif /* _PRKEY_H */
346diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
347index 9ca1355..62a6893 100644
348--- a/libmultipath/propsel.c
349+++ b/libmultipath/propsel.c
350@@ -106,6 +106,7 @@ do { \
351 if (src && src->prkey_source != PRKEY_SOURCE_NONE) { \
352 mp->prkey_source = src->prkey_source; \
353 mp->reservation_key = src->reservation_key; \
354+ mp->sa_flags = src->sa_flags; \
355 origin = msg; \
356 goto out; \
357 } \
358@@ -703,18 +704,19 @@ int select_reservation_key(struct config *conf, struct multipath *mp)
359 do_prkey_set(mp->mpe, multipaths_origin);
360 do_prkey_set(conf, conf_origin);
361 put_be64(mp->reservation_key, 0);
362+ mp->sa_flags = 0;
363 mp->prkey_source = PRKEY_SOURCE_NONE;
364 return 0;
365 out:
366 if (mp->prkey_source == PRKEY_SOURCE_FILE) {
367 from_file = " (from prkeys file)";
368- if (get_prkey(conf, mp, &prkey) != 0)
369+ if (get_prkey(conf, mp, &prkey, &mp->sa_flags) != 0)
370 put_be64(mp->reservation_key, 0);
371 else
372 put_be64(mp->reservation_key, prkey);
373 }
374 print_reservation_key(buff, PRKEY_SIZE, mp->reservation_key,
375- mp->prkey_source);
376+ mp->sa_flags, mp->prkey_source);
377 condlog(3, "%s: reservation_key = %s %s%s", mp->alias, buff, origin,
378 from_file);
379 return 0;
380diff --git a/libmultipath/structs.h b/libmultipath/structs.h
381index 0194b1e..987479f 100644
382--- a/libmultipath/structs.h
383+++ b/libmultipath/structs.h
384@@ -367,6 +367,7 @@ struct multipath {
385 /* persistent management data*/
386 int prkey_source;
387 struct be64 reservation_key;
388+ uint8_t sa_flags;
389 unsigned char prflag;
390 int all_tg_pt;
391 struct gen_multipath generic_mp;
392diff --git a/libmultipath/util.c b/libmultipath/util.c
393index 7251ad0..8d8fcc8 100644
394--- a/libmultipath/util.c
395+++ b/libmultipath/util.c
396@@ -10,6 +10,8 @@
397 #include <dirent.h>
398 #include <unistd.h>
399 #include <errno.h>
400+#include <libudev.h>
401+#include <mpath_persist.h>
402
403 #include "util.h"
404 #include "debug.h"
405@@ -435,6 +437,20 @@ int parse_prkey(char *ptr, uint64_t *prkey)
406 return 0;
407 }
408
409+int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags)
410+{
411+ char *flagstr;
412+
413+ flagstr = strchr(ptr, ':');
414+ *flags = 0;
415+ if (flagstr) {
416+ *flagstr++ = '\0';
417+ if (strlen(flagstr) == 5 && strcmp(flagstr, "aptpl") == 0)
418+ *flags = MPATH_F_APTPL_MASK;
419+ }
420+ return parse_prkey(ptr, prkey);
421+}
422+
423 int safe_write(int fd, const void *buf, size_t count)
424 {
425 while (count > 0) {
426diff --git a/libmultipath/util.h b/libmultipath/util.h
427index a3ab894..56cec76 100644
428--- a/libmultipath/util.h
429+++ b/libmultipath/util.h
430@@ -19,6 +19,7 @@ void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached);
431 int systemd_service_enabled(const char *dev);
432 int get_linux_version_code(void);
433 int parse_prkey(char *ptr, uint64_t *prkey);
434+int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags);
435 int safe_write(int fd, const void *buf, size_t count);
436
437 #define KERNEL_VERSION(maj, min, ptc) ((((maj) * 256) + (min)) * 256 + (ptc))
438diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
439index 31f4585..30d8598 100644
440--- a/multipath/multipath.conf.5
441+++ b/multipath/multipath.conf.5
442@@ -726,14 +726,17 @@ This is the service action reservation key used by mpathpersist. It must be
443 set for all multipath devices using persistent reservations, and it must be
444 the same as the RESERVATION KEY field of the PERSISTENT RESERVE OUT parameter
445 list which contains an 8-byte value provided by the application client to the
446-device server to identify the I_T nexus.
447+device server to identify the I_T nexus. If the \fI--param-aptpl\fR option is
448+used when registering the key with mpathpersist, \fB:aptpl\fR must be appended
449+to the end of the reservation key.
450 .RS
451 .PP
452 Alternatively, this can be set to \fBfile\fR, which will store the RESERVATION
453 KEY registered by mpathpersist in the \fIprkeys_file\fR. multipathd will then
454 use this key to register additional paths as they appear. When the
455 registration is removed, the RESERVATION KEY is removed from the
456-\fIprkeys_file\fR.
457+\fIprkeys_file\fR. The prkeys file will automatically keep track of whether
458+the key was registered with \fI--param-aptpl\fR.
459 .TP
460 The default is: \fB<unset>\fR
461 .RE
462diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
463index ba50fb8..6452796 100644
464--- a/multipathd/cli_handlers.c
465+++ b/multipathd/cli_handlers.c
466@@ -21,6 +21,7 @@
467 #include "sysfs.h"
468 #include <errno.h>
469 #include <libudev.h>
470+#include <mpath_persist.h>
471 #include "util.h"
472 #include "prkey.h"
473 #include "propsel.h"
474@@ -1463,6 +1464,7 @@ cli_getprkey(void * v, char ** reply, int * len, void * data)
475 struct multipath * mpp;
476 struct vectors * vecs = (struct vectors *)data;
477 char *mapname = get_keyparam(v, MAP);
478+ char *flagstr = "";
479
480 mapname = convert_dev(mapname, 0);
481 condlog(3, "%s: get persistent reservation key (operator)", mapname);
482@@ -1478,8 +1480,10 @@ cli_getprkey(void * v, char ** reply, int * len, void * data)
483 *len = strlen(*reply) + 1;
484 return 0;
485 }
486- snprintf(*reply, 20, "0x%" PRIx64 "\n",
487- get_be64(mpp->reservation_key));
488+ if (mpp->sa_flags & MPATH_F_APTPL_MASK)
489+ flagstr = ":aptpl";
490+ snprintf(*reply, 20, "0x%" PRIx64 "%s\n",
491+ get_be64(mpp->reservation_key), flagstr);
492 (*reply)[19] = '\0';
493 *len = strlen(*reply) + 1;
494 return 0;
495@@ -1503,7 +1507,7 @@ cli_unsetprkey(void * v, char ** reply, int * len, void * data)
496
497 conf = get_multipath_config();
498 pthread_cleanup_push(put_multipath_config, conf);
499- ret = set_prkey(conf, mpp, 0);
500+ ret = set_prkey(conf, mpp, 0, 0);
501 pthread_cleanup_pop(1);
502
503 return ret;
504@@ -1517,6 +1521,7 @@ cli_setprkey(void * v, char ** reply, int * len, void * data)
505 char *mapname = get_keyparam(v, MAP);
506 char *keyparam = get_keyparam(v, KEY);
507 uint64_t prkey;
508+ uint8_t flags;
509 int ret;
510 struct config *conf;
511
512@@ -1527,14 +1532,14 @@ cli_setprkey(void * v, char ** reply, int * len, void * data)
513 if (!mpp)
514 return 1;
515
516- if (parse_prkey(keyparam, &prkey) != 0) {
517+ if (parse_prkey_flags(keyparam, &prkey, &flags) != 0) {
518 condlog(0, "%s: invalid prkey : '%s'", mapname, keyparam);
519 return 1;
520 }
521
522 conf = get_multipath_config();
523 pthread_cleanup_push(put_multipath_config, conf);
524- ret = set_prkey(conf, mpp, prkey);
525+ ret = set_prkey(conf, mpp, prkey, flags);
526 pthread_cleanup_pop(1);
527
528 return ret;
529diff --git a/multipathd/main.c b/multipathd/main.c
530index d40c416..6b1e782 100644
531--- a/multipathd/main.c
532+++ b/multipathd/main.c
533@@ -3089,6 +3089,7 @@ void * mpath_pr_event_handler_fn (void * pathp )
534
535 param= malloc(sizeof(struct prout_param_descriptor));
536 memset(param, 0 , sizeof(struct prout_param_descriptor));
537+ param->sa_flags = mpp->sa_flags;
538 memcpy(param->sa_key, &mpp->reservation_key, 8);
539 param->num_transportid = 0;
540
541--
5422.7.4
543