]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blob - multipath-tools/patches/0021-RHBZ-548874-add-find-multipaths.patch
Change file layout of the makefiles.
[people/ms/ipfire-3.x.git] / multipath-tools / patches / 0021-RHBZ-548874-add-find-multipaths.patch
1 ---
2 libmultipath/Makefile | 2
3 libmultipath/alias.c | 152 ------------------------------
4 libmultipath/alias.h | 1
5 libmultipath/config.c | 5 -
6 libmultipath/config.h | 1
7 libmultipath/configure.c | 23 ++++
8 libmultipath/defaults.h | 2
9 libmultipath/dict.c | 34 ++++++
10 libmultipath/file.c | 178 +++++++++++++++++++++++++++++++++++
11 libmultipath/file.h | 11 ++
12 libmultipath/finder.c | 150 ++++++++++++++++++++++++++++++
13 libmultipath/finder.h | 18 +++
14 multipath/Makefile | 2
15 multipath/main.c | 2
16 multipath/mpathconf | 234 +++++++++++++++++++++++++++++++++++++++++++++++
17 multipathd/main.c | 27 +++--
18 16 files changed, 679 insertions(+), 163 deletions(-)
19
20 Index: multipath-tools/libmultipath/alias.c
21 ===================================================================
22 --- multipath-tools.orig/libmultipath/alias.c
23 +++ multipath-tools/libmultipath/alias.c
24 @@ -3,19 +3,16 @@
25 * Copyright (c) 2005 Benjamin Marzinski, Redhat
26 */
27 #include <stdlib.h>
28 -#include <sys/types.h>
29 -#include <sys/stat.h>
30 -#include <fcntl.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <limits.h>
35 #include <stdio.h>
36 -#include <signal.h>
37
38 #include "debug.h"
39 #include "uxsock.h"
40 #include "alias.h"
41 +#include "file.h"
42
43
44 /*
45 @@ -37,149 +34,6 @@
46 */
47
48 static int
49 -ensure_directories_exist(char *str, mode_t dir_mode)
50 -{
51 - char *pathname;
52 - char *end;
53 - int err;
54 -
55 - pathname = strdup(str);
56 - if (!pathname){
57 - condlog(0, "Cannot copy bindings file pathname : %s",
58 - strerror(errno));
59 - return -1;
60 - }
61 - end = pathname;
62 - /* skip leading slashes */
63 - while (end && *end && (*end == '/'))
64 - end++;
65 -
66 - while ((end = strchr(end, '/'))) {
67 - /* if there is another slash, make the dir. */
68 - *end = '\0';
69 - err = mkdir(pathname, dir_mode);
70 - if (err && errno != EEXIST) {
71 - condlog(0, "Cannot make directory [%s] : %s",
72 - pathname, strerror(errno));
73 - free(pathname);
74 - return -1;
75 - }
76 - if (!err)
77 - condlog(3, "Created dir [%s]", pathname);
78 - *end = '/';
79 - end++;
80 - }
81 - free(pathname);
82 - return 0;
83 -}
84 -
85 -static void
86 -sigalrm(int sig)
87 -{
88 - /* do nothing */
89 -}
90 -
91 -static int
92 -lock_bindings_file(int fd)
93 -{
94 - struct sigaction act, oldact;
95 - sigset_t set, oldset;
96 - struct flock lock;
97 - int err;
98 -
99 - memset(&lock, 0, sizeof(lock));
100 - lock.l_type = F_WRLCK;
101 - lock.l_whence = SEEK_SET;
102 -
103 - act.sa_handler = sigalrm;
104 - sigemptyset(&act.sa_mask);
105 - act.sa_flags = 0;
106 - sigemptyset(&set);
107 - sigaddset(&set, SIGALRM);
108 -
109 - sigaction(SIGALRM, &act, &oldact);
110 - sigprocmask(SIG_UNBLOCK, &set, &oldset);
111 -
112 - alarm(BINDINGS_FILE_TIMEOUT);
113 - err = fcntl(fd, F_SETLKW, &lock);
114 - alarm(0);
115 -
116 - if (err) {
117 - if (errno != EINTR)
118 - condlog(0, "Cannot lock bindings file : %s",
119 - strerror(errno));
120 - else
121 - condlog(0, "Bindings file is locked. Giving up.");
122 - }
123 -
124 - sigprocmask(SIG_SETMASK, &oldset, NULL);
125 - sigaction(SIGALRM, &oldact, NULL);
126 - return err;
127 -
128 -}
129 -
130 -
131 -static int
132 -open_bindings_file(char *file, int *can_write)
133 -{
134 - int fd;
135 - struct stat s;
136 -
137 - if (ensure_directories_exist(file, 0700))
138 - return -1;
139 - *can_write = 1;
140 - fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
141 - if (fd < 0) {
142 - if (errno == EROFS) {
143 - *can_write = 0;
144 - condlog(3, "Cannot open bindings file [%s] read/write. "
145 - " trying readonly", file);
146 - fd = open(file, O_RDONLY);
147 - if (fd < 0) {
148 - condlog(0, "Cannot open bindings file [%s] "
149 - "readonly : %s", file, strerror(errno));
150 - return -1;
151 - }
152 - }
153 - else {
154 - condlog(0, "Cannot open bindings file [%s] : %s", file,
155 - strerror(errno));
156 - return -1;
157 - }
158 - }
159 - if (*can_write && lock_bindings_file(fd) < 0)
160 - goto fail;
161 -
162 - memset(&s, 0, sizeof(s));
163 - if (fstat(fd, &s) < 0){
164 - condlog(0, "Cannot stat bindings file : %s", strerror(errno));
165 - goto fail;
166 - }
167 - if (s.st_size == 0) {
168 - if (*can_write == 0)
169 - goto fail;
170 - /* If bindings file is empty, write the header */
171 - size_t len = strlen(BINDINGS_FILE_HEADER);
172 - if (write_all(fd, BINDINGS_FILE_HEADER, len) != len) {
173 - condlog(0,
174 - "Cannot write header to bindings file : %s",
175 - strerror(errno));
176 - /* cleanup partially written header */
177 - ftruncate(fd, 0);
178 - goto fail;
179 - }
180 - fsync(fd);
181 - condlog(3, "Initialized new bindings file [%s]", file);
182 - }
183 -
184 - return fd;
185 -
186 -fail:
187 - close(fd);
188 - return -1;
189 -}
190 -
191 -static int
192 format_devname(char *name, int id, int len)
193 {
194 int pos;
195 @@ -364,7 +218,7 @@ get_user_friendly_alias(char *wwid, char
196 return NULL;
197 }
198
199 - fd = open_bindings_file(file, &can_write);
200 + fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
201 if (fd < 0)
202 return NULL;
203
204 @@ -414,7 +268,7 @@ get_user_friendly_wwid(char *alias, char
205 return NULL;
206 }
207
208 - fd = open_bindings_file(file, &unused);
209 + fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
210 if (fd < 0)
211 return NULL;
212
213 Index: multipath-tools/libmultipath/alias.h
214 ===================================================================
215 --- multipath-tools.orig/libmultipath/alias.h
216 +++ multipath-tools/libmultipath/alias.h
217 @@ -1,4 +1,3 @@
218 -#define BINDINGS_FILE_TIMEOUT 30
219 #define BINDINGS_FILE_HEADER \
220 "# Multipath bindings, Version : 1.0\n" \
221 "# NOTE: this file is automatically maintained by the multipath program.\n" \
222 Index: multipath-tools/libmultipath/config.c
223 ===================================================================
224 --- multipath-tools.orig/libmultipath/config.c
225 +++ multipath-tools/libmultipath/config.c
226 @@ -452,6 +452,7 @@ load_config (char * file)
227 conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
228 conf->flush_on_last_del = 0;
229 conf->attribute_flags = 0;
230 + conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
231
232 /*
233 * preload default hwtable
234 @@ -476,10 +477,12 @@ load_config (char * file)
235 }
236 } else {
237 condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
238 - condlog(0, "A default multipath.conf file is located at");
239 + condlog(0, "A sample multipath.conf file is located at");
240 condlog(0,
241 "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf",
242 MULTIPATH_VERSION(VERSION_CODE));
243 + condlog(0,
244 +"You can run /sbin/mpathconf to create or modify /etc/multipath.conf");
245 conf->blist_devnode = vector_alloc();
246 if (!conf->blist_devnode) {
247 condlog(0, "cannot allocate blacklist\n");
248 Index: multipath-tools/libmultipath/config.h
249 ===================================================================
250 --- multipath-tools.orig/libmultipath/config.h
251 +++ multipath-tools/libmultipath/config.h
252 @@ -85,6 +85,7 @@ struct config {
253 int attribute_flags;
254 int fast_io_fail;
255 unsigned int dev_loss;
256 + int find_multipaths;
257 uid_t uid;
258 gid_t gid;
259 mode_t mode;
260 Index: multipath-tools/libmultipath/configure.c
261 ===================================================================
262 --- multipath-tools.orig/libmultipath/configure.c
263 +++ multipath-tools/libmultipath/configure.c
264 @@ -35,6 +35,7 @@
265 #include "alias.h"
266 #include "prio.h"
267 #include "util.h"
268 +#include "finder.h"
269
270 extern int
271 setup_map (struct multipath * mpp)
272 @@ -462,6 +463,10 @@ coalesce_paths (struct vectors * vecs, v
273
274 memset(empty_buff, 0, WWID_SIZE);
275
276 + /* ignore refwwid if it's empty */
277 + if (refwwid && !strlen(refwwid))
278 + refwwid = NULL;
279 +
280 if (force_reload) {
281 vector_foreach_slot (pathvec, pp1, k) {
282 pp1->mpp = NULL;
283 @@ -472,21 +477,35 @@ coalesce_paths (struct vectors * vecs, v
284
285 /* 1. if path has no unique id or wwid blacklisted */
286 if (memcmp(empty_buff, pp1->wwid, WWID_SIZE) == 0 ||
287 - filter_path(conf, pp1) > 0)
288 + filter_path(conf, pp1) > 0) {
289 + orphan_path(pp1);
290 continue;
291 + }
292
293 /* 2. if path already coalesced */
294 if (pp1->mpp)
295 continue;
296
297 /* 3. if path has disappeared */
298 - if (!pp1->size)
299 + if (!pp1->size) {
300 + orphan_path(pp1);
301 continue;
302 + }
303
304 /* 4. path is out of scope */
305 if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
306 continue;
307
308 + /* If find_multipaths was selected check if the path is valid */
309 + if (conf->find_multipaths){
310 + if (refwwid || should_multipath(pp1, pathvec))
311 + remember_wwid(pp1->wwid);
312 + else {
313 + orphan_path(pp1);
314 + continue;
315 + }
316 + }
317 +
318 /*
319 * at this point, we know we really got a new mp
320 */
321 Index: multipath-tools/libmultipath/defaults.h
322 ===================================================================
323 --- multipath-tools.orig/libmultipath/defaults.h
324 +++ multipath-tools/libmultipath/defaults.h
325 @@ -12,6 +12,7 @@
326 #define DEFAULT_PGTIMEOUT -PGTIMEOUT_NONE
327 #define DEFAULT_USER_FRIENDLY_NAMES 0
328 #define DEFAULT_VERBOSITY 2
329 +#define DEFAULT_FIND_MULTIPATHS 0
330
331 #define DEFAULT_CHECKINT 5
332 #define MAX_CHECKINT(a) (a << 2)
333 @@ -20,5 +21,6 @@
334 #define DEFAULT_SOCKET "/var/run/multipathd.sock"
335 #define DEFAULT_CONFIGFILE "/etc/multipath.conf"
336 #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
337 +#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
338
339 char * set_default (char * str);
340 Index: multipath-tools/libmultipath/dict.c
341 ===================================================================
342 --- multipath-tools.orig/libmultipath/dict.c
343 +++ multipath-tools/libmultipath/dict.c
344 @@ -444,6 +444,27 @@ def_flush_on_last_del_handler(vector str
345 }
346
347 static int
348 +def_find_multipaths_handler(vector strvec)
349 +{
350 + char * buff;
351 +
352 + buff = set_value(strvec);
353 +
354 + if (!buff)
355 + return 1;
356 +
357 + if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
358 + (strlen(buff) == 1 && !strcmp(buff, "0")))
359 + conf->find_multipaths = 0;
360 + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
361 + (strlen(buff) == 1 && !strcmp(buff, "1")))
362 + conf->find_multipaths = 1;
363 +
364 + FREE(buff);
365 + return 0;
366 +}
367 +
368 +static int
369 names_handler(vector strvec)
370 {
371 char * buff;
372 @@ -2076,6 +2097,18 @@ snprint_def_flush_on_last_del (char * bu
373 }
374
375 static int
376 +snprint_def_find_multipaths (char * buff, int len, void * data)
377 +{
378 + if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS)
379 + return 0;
380 + if (!conf->find_multipaths)
381 + return snprintf(buff, len, "no");
382 +
383 + return snprintf(buff, len, "yes");
384 +}
385 +
386 +
387 +static int
388 snprint_def_user_friendly_names (char * buff, int len, void * data)
389 {
390 if (conf->user_friendly_names == DEFAULT_USER_FRIENDLY_NAMES)
391 @@ -2141,6 +2174,7 @@ init_keywords(void)
392 install_keyword("gid", &def_gid_handler, &snprint_def_gid);
393 install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
394 install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
395 + install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
396 __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
397 __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
398 __deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
399 Index: multipath-tools/libmultipath/file.c
400 ===================================================================
401 --- /dev/null
402 +++ multipath-tools/libmultipath/file.c
403 @@ -0,0 +1,178 @@
404 +/*
405 + * Copyright (c) 2005 Christophe Varoqui
406 + * Copyright (c) 2005 Benjamin Marzinski, Redhat
407 + */
408 +#include <stdlib.h>
409 +#include <sys/types.h>
410 +#include <sys/stat.h>
411 +#include <fcntl.h>
412 +#include <errno.h>
413 +#include <unistd.h>
414 +#include <string.h>
415 +#include <limits.h>
416 +#include <stdio.h>
417 +#include <signal.h>
418 +
419 +#include "file.h"
420 +#include "debug.h"
421 +#include "uxsock.h"
422 +
423 +
424 +/*
425 + * significant parts of this file were taken from iscsi-bindings.c of the
426 + * linux-iscsi project.
427 + * Copyright (C) 2002 Cisco Systems, Inc.
428 + *
429 + * This program is free software; you can redistribute it and/or modify
430 + * it under the terms of the GNU General Public License as published
431 + * by the Free Software Foundation; either version 2 of the License, or
432 + * (at your option) any later version.
433 + *
434 + * This program is distributed in the hope that it will be useful, but
435 + * WITHOUT ANY WARRANTY; without even the implied warranty of
436 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
437 + * General Public License for more details.
438 + *
439 + * See the file COPYING included with this distribution for more details.
440 + */
441 +
442 +static int
443 +ensure_directories_exist(char *str, mode_t dir_mode)
444 +{
445 + char *pathname;
446 + char *end;
447 + int err;
448 +
449 + pathname = strdup(str);
450 + if (!pathname){
451 + condlog(0, "Cannot copy file pathname %s : %s",
452 + str, strerror(errno));
453 + return -1;
454 + }
455 + end = pathname;
456 + /* skip leading slashes */
457 + while (end && *end && (*end == '/'))
458 + end++;
459 +
460 + while ((end = strchr(end, '/'))) {
461 + /* if there is another slash, make the dir. */
462 + *end = '\0';
463 + err = mkdir(pathname, dir_mode);
464 + if (err && errno != EEXIST) {
465 + condlog(0, "Cannot make directory [%s] : %s",
466 + pathname, strerror(errno));
467 + free(pathname);
468 + return -1;
469 + }
470 + if (!err)
471 + condlog(3, "Created dir [%s]", pathname);
472 + *end = '/';
473 + end++;
474 + }
475 + free(pathname);
476 + return 0;
477 +}
478 +
479 +static void
480 +sigalrm(int sig)
481 +{
482 + /* do nothing */
483 +}
484 +
485 +static int
486 +lock_file(int fd, char *file_name)
487 +{
488 + struct sigaction act, oldact;
489 + sigset_t set, oldset;
490 + struct flock lock;
491 + int err;
492 +
493 + memset(&lock, 0, sizeof(lock));
494 + lock.l_type = F_WRLCK;
495 + lock.l_whence = SEEK_SET;
496 +
497 + act.sa_handler = sigalrm;
498 + sigemptyset(&act.sa_mask);
499 + act.sa_flags = 0;
500 + sigemptyset(&set);
501 + sigaddset(&set, SIGALRM);
502 +
503 + sigaction(SIGALRM, &act, &oldact);
504 + sigprocmask(SIG_UNBLOCK, &set, &oldset);
505 +
506 + alarm(FILE_TIMEOUT);
507 + err = fcntl(fd, F_SETLKW, &lock);
508 + alarm(0);
509 +
510 + if (err) {
511 + if (errno != EINTR)
512 + condlog(0, "Cannot lock %s : %s", file_name,
513 + strerror(errno));
514 + else
515 + condlog(0, "%s is locked. Giving up.", file_name);
516 + }
517 +
518 + sigprocmask(SIG_SETMASK, &oldset, NULL);
519 + sigaction(SIGALRM, &oldact, NULL);
520 + return err;
521 +}
522 +
523 +int
524 +open_file(char *file, int *can_write, char *header)
525 +{
526 + int fd;
527 + struct stat s;
528 +
529 + if (ensure_directories_exist(file, 0700))
530 + return -1;
531 + *can_write = 1;
532 + fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
533 + if (fd < 0) {
534 + if (errno == EROFS) {
535 + *can_write = 0;
536 + condlog(3, "Cannot open file [%s] read/write. "
537 + " trying readonly", file);
538 + fd = open(file, O_RDONLY);
539 + if (fd < 0) {
540 + condlog(0, "Cannot open file [%s] "
541 + "readonly : %s", file, strerror(errno));
542 + return -1;
543 + }
544 + }
545 + else {
546 + condlog(0, "Cannot open file [%s] : %s", file,
547 + strerror(errno));
548 + return -1;
549 + }
550 + }
551 + if (*can_write && lock_file(fd, file) < 0)
552 + goto fail;
553 +
554 + memset(&s, 0, sizeof(s));
555 + if (fstat(fd, &s) < 0){
556 + condlog(0, "Cannot stat file %s : %s", file, strerror(errno));
557 + goto fail;
558 + }
559 + if (s.st_size == 0) {
560 + if (*can_write == 0)
561 + goto fail;
562 + /* If file is empty, write the header */
563 + size_t len = strlen(header);
564 + if (write_all(fd, header, len) != len) {
565 + condlog(0,
566 + "Cannot write header to file %s : %s", file,
567 + strerror(errno));
568 + /* cleanup partially written header */
569 + ftruncate(fd, 0);
570 + goto fail;
571 + }
572 + fsync(fd);
573 + condlog(3, "Initialized new file [%s]", file);
574 + }
575 +
576 + return fd;
577 +
578 +fail:
579 + close(fd);
580 + return -1;
581 +}
582 Index: multipath-tools/libmultipath/file.h
583 ===================================================================
584 --- /dev/null
585 +++ multipath-tools/libmultipath/file.h
586 @@ -0,0 +1,11 @@
587 +/*
588 + * Copyright (c) 2010 Benjamin Marzinski, Redhat
589 + */
590 +
591 +#ifndef _FILE_H
592 +#define _FILE_H
593 +
594 +#define FILE_TIMEOUT 30
595 +int open_file(char *file, int *can_write, char *header);
596 +
597 +#endif /* _FILE_H */
598 Index: multipath-tools/libmultipath/finder.c
599 ===================================================================
600 --- /dev/null
601 +++ multipath-tools/libmultipath/finder.c
602 @@ -0,0 +1,150 @@
603 +#include <stdlib.h>
604 +#include <errno.h>
605 +#include <unistd.h>
606 +#include <string.h>
607 +#include <limits.h>
608 +#include <stdio.h>
609 +
610 +#include "checkers.h"
611 +#include "vector.h"
612 +#include "structs.h"
613 +#include "debug.h"
614 +#include "uxsock.h"
615 +#include "file.h"
616 +#include "finder.h"
617 +#include "defaults.h"
618 +
619 +/*
620 + * Copyright (c) 2010 Benjamin Marzinski, Redhat
621 + */
622 +
623 +static int
624 +lookup_wwid(FILE *f, char *wwid) {
625 + char buf[LINE_MAX];
626 +
627 + while (fgets(buf, LINE_MAX, f)) {
628 + char *c;
629 +
630 + c = strpbrk(buf, "#\n\r");
631 + if (c)
632 + *c = '\0';
633 + if (*buf == '\0')
634 + continue;
635 + if (strncmp(wwid, buf, WWID_SIZE) == 0)
636 + return 1;
637 + }
638 + return 0;
639 +}
640 +
641 +static int
642 +write_out_wwid(int fd, char *wwid) {
643 + int ret;
644 + off_t offset;
645 + char buf[WWID_SIZE + 1];
646 +
647 + ret = snprintf(buf, WWID_SIZE + 1, "%s\n", wwid);
648 + if (ret > WWID_SIZE || ret < 0){
649 + condlog(0, "can't format wwid for writing (%d) : %s",
650 + ret, strerror(errno));
651 + return -1;
652 + }
653 + offset = lseek(fd, 0, SEEK_END);
654 + if (offset < 0) {
655 + condlog(0, "can't seek to the end of wwids file : %s",
656 + strerror(errno));
657 + return -1;
658 + }
659 + if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
660 + condlog(0, "cannot write wwid to wwids file : %s",
661 + strerror(errno));
662 + ftruncate(fd, offset);
663 + return -1;
664 + }
665 + return 1;
666 +}
667 +
668 +static int
669 +check_wwids_file(char *wwid, int write_wwid)
670 +{
671 + int scan_fd, fd, can_write, found, ret;
672 + FILE *f;
673 + fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
674 + if (fd < 0)
675 + return -1;
676 +
677 + scan_fd = dup(fd);
678 + if (scan_fd < 0) {
679 + condlog(0, "can't dup wwids file descriptor : %s",
680 + strerror(errno));
681 + close(fd);
682 + return -1;
683 + }
684 + f = fdopen(scan_fd, "r");
685 + if (!f) {
686 + condlog(0,"can't fdopen wwids file : %s", strerror(errno));
687 + close(fd);
688 + close(scan_fd);
689 + return -1;
690 + }
691 + found = lookup_wwid(f, wwid);
692 + if (found) {
693 + ret = 0;
694 + goto out;
695 + }
696 + if (!write_wwid) {
697 + ret = -1;
698 + goto out;
699 + }
700 + if (!can_write) {
701 + condlog(0, "wwids file is read-only. Can't write wwid");
702 + ret = -1;
703 + goto out;
704 + }
705 + ret = write_out_wwid(fd, wwid);
706 +out:
707 + fclose(f);
708 + close(scan_fd);
709 + close(fd);
710 + return ret;
711 +}
712 +
713 +int
714 +should_multipath(struct path *pp1, vector pathvec)
715 +{
716 + int i;
717 + struct path *pp2;
718 +
719 + condlog(4, "checking if %s should be multipathed", pp1->dev);
720 + vector_foreach_slot(pathvec, pp2, i) {
721 + if (pp1->dev == pp2->dev)
722 + continue;
723 + if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
724 + condlog(3, "found multiple paths with wwid %s, "
725 + "multipathing %s", pp1->wwid, pp1->dev);
726 + return 1;
727 + }
728 + }
729 + if (check_wwids_file(pp1->wwid, 0) < 0) {
730 + condlog(3, "wwid %s not in wwids file, skipping %s",
731 + pp1->wwid, pp1->dev);
732 + return 0;
733 + }
734 + condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid,
735 + pp1->dev);
736 + return 1;
737 +}
738 +
739 +int
740 +remember_wwid(char *wwid)
741 +{
742 + int ret = check_wwids_file(wwid, 1);
743 + if (ret < 0){
744 + condlog(3, "failed writing wwid %s to wwids file", wwid);
745 + return -1;
746 + }
747 + if (ret == 1)
748 + condlog(3, "wrote wwid %s to wwids file", wwid);
749 + else
750 + condlog(4, "wwid %s already in wwids file", wwid);
751 + return 0;
752 +}
753 Index: multipath-tools/libmultipath/finder.h
754 ===================================================================
755 --- /dev/null
756 +++ multipath-tools/libmultipath/finder.h
757 @@ -0,0 +1,18 @@
758 +/*
759 + * Copyright (c) 2010 Benjamin Marzinski, Redhat
760 + */
761 +
762 +#ifndef _FINDER_H
763 +#define _FINDER_H
764 +
765 +#define WWIDS_FILE_HEADER \
766 +"# Multipath wwids, Version : 1.0\n" \
767 +"# NOTE: This file is automatically maintained by multipath and multipathd.\n" \
768 +"# You should not need to edit this file in normal circumstances.\n" \
769 +"#\n" \
770 +"# Valid WWIDs:\n"
771 +
772 +int should_multipath(struct path *pp, vector pathvec);
773 +int remember_wwid(char *wwid);
774 +
775 +#endif /* _FINDER_H */
776 Index: multipath-tools/multipath/main.c
777 ===================================================================
778 --- multipath-tools.orig/multipath/main.c
779 +++ multipath-tools/multipath/main.c
780 @@ -307,7 +307,7 @@ configure (void)
781 /*
782 * core logic entry point
783 */
784 - r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
785 + r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload);
786
787 out:
788 if (refwwid)
789 Index: multipath-tools/multipathd/main.c
790 ===================================================================
791 --- multipath-tools.orig/multipathd/main.c
792 +++ multipath-tools/multipathd/main.c
793 @@ -47,6 +47,7 @@
794 #include <print.h>
795 #include <configure.h>
796 #include <prio.h>
797 +#include <finder.h>
798
799 #include "main.h"
800 #include "pidfile.h"
801 @@ -397,7 +398,7 @@ ev_add_path (char * devname, struct vect
802 */
803 if (memcmp(empty_buff, pp->wwid, WWID_SIZE) == 0) {
804 condlog(0, "%s: failed to get path uid", devname);
805 - return 1; /* leave path added to pathvec */
806 + goto fail; /* leave path added to pathvec */
807 }
808 if (filter_path(conf, pp) > 0){
809 int i = find_slot(vecs->pathvec, (void *)pp);
810 @@ -412,18 +413,26 @@ rescan:
811 condlog(4,"%s: adopting all paths for path %s",
812 mpp->alias, pp->dev);
813 if (adopt_paths(vecs->pathvec, mpp))
814 - return 1; /* leave path added to pathvec */
815 + goto fail; /* leave path added to pathvec */
816
817 verify_paths(mpp, vecs, NULL);
818 mpp->flush_on_last_del = FLUSH_UNDEF;
819 mpp->action = ACT_RELOAD;
820 }
821 else {
822 + if (conf->find_multipaths) {
823 + if (should_multipath(pp, vecs->pathvec))
824 + remember_wwid(pp->wwid);
825 + else {
826 + orphan_path(pp);
827 + return 0;
828 + }
829 + }
830 condlog(4,"%s: creating new map", pp->dev);
831 if ((mpp = add_map_with_path(vecs, pp, 1)))
832 mpp->action = ACT_CREATE;
833 else
834 - return 1; /* leave path added to pathvec */
835 + goto fail; /* leave path added to pathvec */
836 }
837
838 /*
839 @@ -432,7 +441,7 @@ rescan:
840 if (setup_map(mpp)) {
841 condlog(0, "%s: failed to setup map for addition of new "
842 "path %s", mpp->alias, devname);
843 - goto out;
844 + goto fail_map;
845 }
846 /*
847 * reload the map for the multipath mapped device
848 @@ -450,7 +459,7 @@ rescan:
849 goto rescan;
850 }
851 else
852 - goto out;
853 + goto fail_map;
854 }
855 dm_lib_release();
856
857 @@ -458,19 +467,21 @@ rescan:
858 * update our state from kernel regardless of create or reload
859 */
860 if (setup_multipath(vecs, mpp))
861 - goto out;
862 + goto fail_map;
863
864 sync_map_state(mpp);
865
866 if (mpp->action == ACT_CREATE &&
867 start_waiter_thread(mpp, vecs))
868 - goto out;
869 + goto fail_map;
870
871 condlog(2, "%s path added to devmap %s", devname, mpp->alias);
872 return 0;
873
874 -out:
875 +fail_map:
876 remove_map(mpp, vecs, 1);
877 +fail:
878 + orphan_path(pp);
879 return 1;
880 }
881
882 Index: multipath-tools/libmultipath/Makefile
883 ===================================================================
884 --- multipath-tools.orig/libmultipath/Makefile
885 +++ multipath-tools/libmultipath/Makefile
886 @@ -12,7 +12,7 @@ OBJS = memory.o parser.o vector.o devmap
887 pgpolicies.o debug.o regex.o defaults.o uevent.o \
888 switchgroup.o uxsock.o print.o alias.o log_pthread.o \
889 log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
890 - lock.o waiter.o
891 + lock.o waiter.o file.o finder.o
892
893 LIBDM_API_FLUSH = $(shell if test -d /lib64 ; then objdump -T /lib64/libdevmapper.so* ; else objdump -T /lib/libdevmapper.so.* ; fi | grep -c dm_task_no_flush)
894
895 Index: multipath-tools/multipath/mpathconf
896 ===================================================================
897 --- /dev/null
898 +++ multipath-tools/multipath/mpathconf
899 @@ -0,0 +1,234 @@
900 +#!/bin/sh
901 +#
902 +# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
903 +#
904 +# This file is part of the device-mapper-multipath package.
905 +#
906 +# This copyrighted material is made available to anyone wishing to use,
907 +# modify, copy, or redistribute it subject to the terms and conditions
908 +# of the GNU General Public License v.2.
909 +#
910 +# You should have received a copy of the GNU General Public License
911 +# along with this program; if not, write to the Free Software Foundation,
912 +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
913 +
914 +#
915 +# Simple editting of /etc/multipath.conf
916 +# This program was largely ripped off from lvmconf
917 +#
918 +
919 +DEFAULT_CONFIGFILE="/usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf"
920 +CONFIGFILE="/etc/multipath.conf"
921 +MULTIPATHDIR="/etc/multipath"
922 +TMPFILE=/etc/multipath/.multipath.conf.tmp
923 +
924 +function usage
925 +{
926 + echo "usage: $0 <command>"
927 + echo ""
928 + echo "Commands:"
929 + echo "Enable: --enable [--user_friendly_names <y|n>] [--find_multipaths <y|n>"
930 + echo "Disable: --disable"
931 + echo "Set user_friendly_names: --user_friendly_names <y|n>"
932 + echo "Set find_multipaths: --find_multipaths <y|n>"
933 + echo ""
934 +}
935 +
936 +function parse_args
937 +{
938 + while [ -n "$1" ]; do
939 + case $1 in
940 + --enable)
941 + ENABLE=1
942 + shift
943 + ;;
944 + --disable)
945 + ENABLE=0
946 + shift
947 + ;;
948 + --user_friendly_names)
949 + if [ -n "$2" ]; then
950 + FRIENDLY=$2
951 + shift 2
952 + else
953 + usage
954 + exit 1
955 + fi
956 + ;;
957 + --find_multipaths)
958 + if [ -n "$2" ]; then
959 + FIND=$2
960 + shift 2
961 + else
962 + usage
963 + exit 1
964 + fi
965 + ;;
966 + *)
967 + usage
968 + exit
969 + esac
970 + done
971 +}
972 +
973 +function validate_args
974 +{
975 + if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" ]; then
976 + echo "ignoring extra parameters on disable"
977 + FRIENDLY=""
978 + FIND=""
979 + fi
980 + if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
981 + echo "--user_friendly_names must be either 'y' or 'n'"
982 + exit 1
983 + fi
984 + if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
985 + echo "--find_multipaths must be either 'y' or 'n'"
986 + exit 1
987 + fi
988 + if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then
989 + DISPLAY=1
990 + fi
991 +}
992 +
993 +umask 0077
994 +
995 +parse_args "$@"
996 +
997 +validate_args
998 +
999 +if [ ! -d "$MULTIPATHDIR" ]; then
1000 + echo "/etc/multipath/ does not exist. failing"
1001 + exit 1
1002 +fi
1003 +
1004 +rm $TMPFILE 2> /dev/null
1005 +if [ -f "$CONFIGFILE" ]; then
1006 + cp $CONFIGFILE $TMPFILE
1007 +elif [ -f "$DEFAULT_CONFIGFILE" ]; then
1008 + cp $DEFAULT_CONFIGFILE $TMPFILE
1009 +else
1010 + touch $TMPFILE
1011 +fi
1012 +
1013 +if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then
1014 + HAVE_BLACKLIST=1
1015 +fi
1016 +
1017 +if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then
1018 + HAVE_DEFAULTS=1
1019 +fi
1020 +
1021 +if [ "$HAVE_BLACKLIST" = "1" ]; then
1022 + if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
1023 + HAVE_DISABLE=1
1024 + elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[#[:space:]]*devnode \"\.\?\*\"" ; then
1025 + HAVE_DISABLE=0
1026 + fi
1027 +fi
1028 +
1029 +if [ "$HAVE_DEFAULTS" = "1" ]; then
1030 + if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then
1031 + HAVE_FIND=1
1032 + elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then
1033 + HAVE_FIND=0
1034 + fi
1035 + if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
1036 + HAVE_FRIENDLY=1
1037 + elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
1038 + HAVE_FRIENDLY=0
1039 + fi
1040 +fi
1041 +
1042 +if [ -n "$DISPLAY" ]; then
1043 + if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then
1044 + echo "multipath is enabled"
1045 + else
1046 + echo "multipath is disabled"
1047 + fi
1048 + if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
1049 + echo "find_multipaths is disabled"
1050 + else
1051 + echo "find_multipaths is enabled"
1052 + fi
1053 + if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
1054 + echo "user_friendly_names is disabled"
1055 + else
1056 + echo "user_friendly_names is enabled"
1057 + fi
1058 + exit 0
1059 +fi
1060 +
1061 +if [ -z "$HAVE_BLACKLIST" ]; then
1062 + cat >> $TMPFILE <<- _EOF_
1063 +
1064 +blacklist {
1065 +}
1066 +_EOF_
1067 +fi
1068 +
1069 +if [ -z "$HAVE_DEFAULTS" ]; then
1070 + cat >> $TMPFILE <<- _EOF_
1071 +
1072 +defaults {
1073 +}
1074 +_EOF_
1075 +fi
1076 +
1077 +if [ "$ENABLE" = 1 ]; then
1078 + if [ "$HAVE_DISABLE" = 1 ]; then
1079 + sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
1080 + fi
1081 +elif [ "$ENABLE" = 0 ]; then
1082 + if [ -z "$HAVE_DISABLE" ]; then
1083 + sed -i '/^blacklist[[:space:]]*{/ a\
1084 + devnode "*"
1085 +' $TMPFILE
1086 + elif [ "$HAVE_DISABLE" = 0 ]; then
1087 + sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[#[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
1088 + fi
1089 +fi
1090 +
1091 +if [ "$FIND" = "n" ]; then
1092 + if [ "$HAVE_FIND" = 1 ]; then
1093 + sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE
1094 + fi
1095 +elif [ "$FIND" = "y" ]; then
1096 + if [ -z "$HAVE_FIND" ]; then
1097 + sed -i '/^defaults[[:space:]]*{/ a\
1098 + find_multipaths yes
1099 +' $TMPFILE
1100 + elif [ "$HAVE_FIND" = 0 ]; then
1101 + sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE
1102 + fi
1103 +fi
1104 +
1105 +if [ "$FRIENDLY" = "n" ]; then
1106 + if [ "$HAVE_FRIENDLY" = 1 ]; then
1107 + sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
1108 + fi
1109 +elif [ "$FRIENDLY" = "y" ]; then
1110 + if [ -z "$HAVE_FRIENDLY" ]; then
1111 + sed -i '/^defaults[[:space:]]*{/ a\
1112 + user_friendly_names yes
1113 +' $TMPFILE
1114 + elif [ "$HAVE_FRIENDLY" = 0 ]; then
1115 + sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
1116 + fi
1117 +fi
1118 +
1119 +if [ -f "$CONFIGFILE" ]; then
1120 + cp $CONFIGFILE $CONFIGFILE.old
1121 + if [ $? != 0 ]; then
1122 + echo "failed to backup old config file, $CONFIGFILE not updated"
1123 + exit 1
1124 + fi
1125 +fi
1126 +
1127 +cp $TMPFILE $CONFIGFILE
1128 +if [ $? != 0 ]; then
1129 + echo "failed to copy new config file into place, check $CONFIGFILE is still OK"
1130 + exit 1
1131 +fi
1132 +
1133 +rm -f $TMPFILE
1134 Index: multipath-tools/multipath/Makefile
1135 ===================================================================
1136 --- multipath-tools.orig/multipath/Makefile
1137 +++ multipath-tools/multipath/Makefile
1138 @@ -21,6 +21,7 @@ $(EXEC): $(OBJS)
1139 install:
1140 $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
1141 $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
1142 + $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
1143 $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/udev/rules.d
1144 $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/lib/udev/rules.d/40-multipath.rules
1145 $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
1146 @@ -31,6 +32,7 @@ install:
1147 uninstall:
1148 rm $(DESTDIR)/lib/udev/rules.d/multipath.rules
1149 rm $(DESTDIR)$(bindir)/$(EXEC)
1150 + rm $(DESTDIR)$(bindir)/mpathconf
1151 rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
1152 rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
1153