2010-01-23 01:39:39 +00:00
|
|
|
---
|
|
|
|
libmultipath/Makefile | 2
|
2012-06-28 17:41:03 +00:00
|
|
|
libmultipath/alias.c | 153 ---------------------------------------
|
2010-01-23 01:39:39 +00:00
|
|
|
libmultipath/alias.h | 1
|
2012-06-28 17:41:03 +00:00
|
|
|
libmultipath/configure.c | 3
|
|
|
|
libmultipath/defaults.h | 1
|
|
|
|
libmultipath/discovery.c | 2
|
|
|
|
libmultipath/file.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++
|
2010-01-23 01:39:39 +00:00
|
|
|
libmultipath/file.h | 11 ++
|
2012-06-28 17:41:03 +00:00
|
|
|
libmultipath/wwids.c | 139 ++++++++++++++++++++++++++++++++++++
|
|
|
|
libmultipath/wwids.h | 18 ++++
|
|
|
|
multipath/main.c | 37 ++++++++-
|
|
|
|
11 files changed, 389 insertions(+), 158 deletions(-)
|
2010-01-23 01:39:39 +00:00
|
|
|
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/alias.c
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
2012-06-28 17:41:03 +00:00
|
|
|
--- multipath-tools-120518.orig/libmultipath/alias.c
|
|
|
|
+++ multipath-tools-120518/libmultipath/alias.c
|
2010-01-23 01:39:39 +00:00
|
|
|
@@ -3,19 +3,16 @@
|
|
|
|
* Copyright (c) 2005 Benjamin Marzinski, Redhat
|
|
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
-#include <sys/types.h>
|
|
|
|
-#include <sys/stat.h>
|
|
|
|
-#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
-#include <signal.h>
|
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
#include "uxsock.h"
|
|
|
|
#include "alias.h"
|
|
|
|
+#include "file.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2012-06-28 17:41:03 +00:00
|
|
|
@@ -36,150 +33,6 @@
|
2012-01-24 16:35:54 +00:00
|
|
|
* See the file COPYING included with this distribution for more details.
|
2010-01-23 01:39:39 +00:00
|
|
|
*/
|
|
|
|
|
2012-01-24 16:35:54 +00:00
|
|
|
-static int
|
2010-01-23 01:39:39 +00:00
|
|
|
-ensure_directories_exist(char *str, mode_t dir_mode)
|
|
|
|
-{
|
|
|
|
- char *pathname;
|
|
|
|
- char *end;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- pathname = strdup(str);
|
|
|
|
- if (!pathname){
|
|
|
|
- condlog(0, "Cannot copy bindings file pathname : %s",
|
|
|
|
- strerror(errno));
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
- end = pathname;
|
|
|
|
- /* skip leading slashes */
|
|
|
|
- while (end && *end && (*end == '/'))
|
|
|
|
- end++;
|
|
|
|
-
|
|
|
|
- while ((end = strchr(end, '/'))) {
|
|
|
|
- /* if there is another slash, make the dir. */
|
|
|
|
- *end = '\0';
|
|
|
|
- err = mkdir(pathname, dir_mode);
|
|
|
|
- if (err && errno != EEXIST) {
|
|
|
|
- condlog(0, "Cannot make directory [%s] : %s",
|
|
|
|
- pathname, strerror(errno));
|
|
|
|
- free(pathname);
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
- if (!err)
|
|
|
|
- condlog(3, "Created dir [%s]", pathname);
|
|
|
|
- *end = '/';
|
|
|
|
- end++;
|
|
|
|
- }
|
|
|
|
- free(pathname);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void
|
|
|
|
-sigalrm(int sig)
|
|
|
|
-{
|
|
|
|
- /* do nothing */
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int
|
|
|
|
-lock_bindings_file(int fd)
|
|
|
|
-{
|
|
|
|
- struct sigaction act, oldact;
|
|
|
|
- sigset_t set, oldset;
|
|
|
|
- struct flock lock;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- memset(&lock, 0, sizeof(lock));
|
|
|
|
- lock.l_type = F_WRLCK;
|
|
|
|
- lock.l_whence = SEEK_SET;
|
|
|
|
-
|
|
|
|
- act.sa_handler = sigalrm;
|
|
|
|
- sigemptyset(&act.sa_mask);
|
|
|
|
- act.sa_flags = 0;
|
|
|
|
- sigemptyset(&set);
|
|
|
|
- sigaddset(&set, SIGALRM);
|
|
|
|
-
|
|
|
|
- sigaction(SIGALRM, &act, &oldact);
|
|
|
|
- sigprocmask(SIG_UNBLOCK, &set, &oldset);
|
|
|
|
-
|
|
|
|
- alarm(BINDINGS_FILE_TIMEOUT);
|
|
|
|
- err = fcntl(fd, F_SETLKW, &lock);
|
|
|
|
- alarm(0);
|
|
|
|
-
|
|
|
|
- if (err) {
|
|
|
|
- if (errno != EINTR)
|
|
|
|
- condlog(0, "Cannot lock bindings file : %s",
|
|
|
|
- strerror(errno));
|
|
|
|
- else
|
|
|
|
- condlog(0, "Bindings file is locked. Giving up.");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
|
|
- sigaction(SIGALRM, &oldact, NULL);
|
|
|
|
- return err;
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static int
|
|
|
|
-open_bindings_file(char *file, int *can_write)
|
|
|
|
-{
|
|
|
|
- int fd;
|
|
|
|
- struct stat s;
|
|
|
|
-
|
|
|
|
- if (ensure_directories_exist(file, 0700))
|
|
|
|
- return -1;
|
|
|
|
- *can_write = 1;
|
|
|
|
- fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
|
|
|
- if (fd < 0) {
|
|
|
|
- if (errno == EROFS) {
|
|
|
|
- *can_write = 0;
|
|
|
|
- condlog(3, "Cannot open bindings file [%s] read/write. "
|
|
|
|
- " trying readonly", file);
|
|
|
|
- fd = open(file, O_RDONLY);
|
|
|
|
- if (fd < 0) {
|
|
|
|
- condlog(0, "Cannot open bindings file [%s] "
|
|
|
|
- "readonly : %s", file, strerror(errno));
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- condlog(0, "Cannot open bindings file [%s] : %s", file,
|
|
|
|
- strerror(errno));
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (*can_write && lock_bindings_file(fd) < 0)
|
|
|
|
- goto fail;
|
|
|
|
-
|
|
|
|
- memset(&s, 0, sizeof(s));
|
|
|
|
- if (fstat(fd, &s) < 0){
|
|
|
|
- condlog(0, "Cannot stat bindings file : %s", strerror(errno));
|
|
|
|
- goto fail;
|
|
|
|
- }
|
|
|
|
- if (s.st_size == 0) {
|
|
|
|
- if (*can_write == 0)
|
|
|
|
- goto fail;
|
|
|
|
- /* If bindings file is empty, write the header */
|
|
|
|
- size_t len = strlen(BINDINGS_FILE_HEADER);
|
|
|
|
- if (write_all(fd, BINDINGS_FILE_HEADER, len) != len) {
|
|
|
|
- condlog(0,
|
|
|
|
- "Cannot write header to bindings file : %s",
|
|
|
|
- strerror(errno));
|
|
|
|
- /* cleanup partially written header */
|
2012-06-28 17:41:03 +00:00
|
|
|
- if (ftruncate(fd, 0))
|
|
|
|
- condlog(0, "Cannot truncate the header : %s",
|
|
|
|
- strerror(errno));
|
2010-01-23 01:39:39 +00:00
|
|
|
- goto fail;
|
|
|
|
- }
|
|
|
|
- fsync(fd);
|
|
|
|
- condlog(3, "Initialized new bindings file [%s]", file);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return fd;
|
|
|
|
-
|
|
|
|
-fail:
|
|
|
|
- close(fd);
|
|
|
|
- return -1;
|
|
|
|
-}
|
2012-01-24 16:35:54 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
format_devname(char *name, int id, int len, char *prefix)
|
2012-06-28 17:41:03 +00:00
|
|
|
@@ -370,7 +223,7 @@ get_user_friendly_alias(char *wwid, char
|
2010-01-23 01:39:39 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
- fd = open_bindings_file(file, &can_write);
|
|
|
|
+ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
|
|
|
|
if (fd < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2012-06-28 17:41:03 +00:00
|
|
|
@@ -414,7 +267,7 @@ get_user_friendly_wwid(char *alias, char
|
2010-01-23 01:39:39 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
- fd = open_bindings_file(file, &unused);
|
|
|
|
+ fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
|
|
|
|
if (fd < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/alias.h
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
2012-06-28 17:41:03 +00:00
|
|
|
--- multipath-tools-120518.orig/libmultipath/alias.h
|
|
|
|
+++ multipath-tools-120518/libmultipath/alias.h
|
2010-01-23 01:39:39 +00:00
|
|
|
@@ -1,4 +1,3 @@
|
|
|
|
-#define BINDINGS_FILE_TIMEOUT 30
|
|
|
|
#define BINDINGS_FILE_HEADER \
|
|
|
|
"# Multipath bindings, Version : 1.0\n" \
|
|
|
|
"# NOTE: this file is automatically maintained by the multipath program.\n" \
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/configure.c
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
2012-06-28 17:41:03 +00:00
|
|
|
--- multipath-tools-120518.orig/libmultipath/configure.c
|
|
|
|
+++ multipath-tools-120518/libmultipath/configure.c
|
|
|
|
@@ -37,6 +37,7 @@
|
2010-01-23 01:39:39 +00:00
|
|
|
#include "prio.h"
|
|
|
|
#include "util.h"
|
2012-01-24 16:35:54 +00:00
|
|
|
#include "uxsock.h"
|
2012-06-28 17:41:03 +00:00
|
|
|
+#include "wwids.h"
|
2010-01-23 01:39:39 +00:00
|
|
|
|
|
|
|
extern int
|
2012-01-24 16:35:54 +00:00
|
|
|
setup_map (struct multipath * mpp, char * params, int params_size)
|
2012-06-28 17:41:03 +00:00
|
|
|
@@ -407,6 +408,8 @@ domap (struct multipath * mpp, char * pa
|
2011-07-15 17:25:48 +00:00
|
|
|
* DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
|
|
|
|
* succeeded
|
|
|
|
*/
|
|
|
|
+ if (mpp->action == ACT_CREATE)
|
|
|
|
+ remember_wwid(mpp->wwid);
|
|
|
|
if (!conf->daemon) {
|
|
|
|
/* multipath client mode */
|
|
|
|
dm_switchgroup(mpp->alias, mpp->bestpg);
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/defaults.h
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
2012-06-28 17:41:03 +00:00
|
|
|
--- multipath-tools-120518.orig/libmultipath/defaults.h
|
|
|
|
+++ multipath-tools-120518/libmultipath/defaults.h
|
|
|
|
@@ -24,5 +24,6 @@
|
2010-01-23 01:39:39 +00:00
|
|
|
#define DEFAULT_SOCKET "/var/run/multipathd.sock"
|
|
|
|
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
|
|
|
|
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
|
|
|
|
+#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
|
|
|
|
|
|
|
|
char * set_default (char * str);
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/file.c
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
|
|
|
--- /dev/null
|
2012-06-28 17:41:03 +00:00
|
|
|
+++ multipath-tools-120518/libmultipath/file.c
|
|
|
|
@@ -0,0 +1,180 @@
|
2010-01-23 01:39:39 +00:00
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2005 Christophe Varoqui
|
|
|
|
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
|
|
|
|
+ */
|
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <sys/types.h>
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
+#include <fcntl.h>
|
|
|
|
+#include <errno.h>
|
|
|
|
+#include <unistd.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <limits.h>
|
|
|
|
+#include <stdio.h>
|
|
|
|
+#include <signal.h>
|
|
|
|
+
|
|
|
|
+#include "file.h"
|
|
|
|
+#include "debug.h"
|
|
|
|
+#include "uxsock.h"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * significant parts of this file were taken from iscsi-bindings.c of the
|
|
|
|
+ * linux-iscsi project.
|
|
|
|
+ * Copyright (C) 2002 Cisco Systems, Inc.
|
|
|
|
+ *
|
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
|
+ * it under the terms of the GNU General Public License as published
|
|
|
|
+ * by the Free Software Foundation; either version 2 of the License, or
|
|
|
|
+ * (at your option) any later version.
|
|
|
|
+ *
|
|
|
|
+ * This program is distributed in the hope that it will be useful, but
|
|
|
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
+ * General Public License for more details.
|
|
|
|
+ *
|
|
|
|
+ * See the file COPYING included with this distribution for more details.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+ensure_directories_exist(char *str, mode_t dir_mode)
|
|
|
|
+{
|
|
|
|
+ char *pathname;
|
|
|
|
+ char *end;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ pathname = strdup(str);
|
|
|
|
+ if (!pathname){
|
|
|
|
+ condlog(0, "Cannot copy file pathname %s : %s",
|
|
|
|
+ str, strerror(errno));
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ end = pathname;
|
|
|
|
+ /* skip leading slashes */
|
|
|
|
+ while (end && *end && (*end == '/'))
|
|
|
|
+ end++;
|
|
|
|
+
|
|
|
|
+ while ((end = strchr(end, '/'))) {
|
|
|
|
+ /* if there is another slash, make the dir. */
|
|
|
|
+ *end = '\0';
|
|
|
|
+ err = mkdir(pathname, dir_mode);
|
|
|
|
+ if (err && errno != EEXIST) {
|
|
|
|
+ condlog(0, "Cannot make directory [%s] : %s",
|
|
|
|
+ pathname, strerror(errno));
|
|
|
|
+ free(pathname);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ if (!err)
|
|
|
|
+ condlog(3, "Created dir [%s]", pathname);
|
|
|
|
+ *end = '/';
|
|
|
|
+ end++;
|
|
|
|
+ }
|
|
|
|
+ free(pathname);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+sigalrm(int sig)
|
|
|
|
+{
|
|
|
|
+ /* do nothing */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+lock_file(int fd, char *file_name)
|
|
|
|
+{
|
|
|
|
+ struct sigaction act, oldact;
|
|
|
|
+ sigset_t set, oldset;
|
|
|
|
+ struct flock lock;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ memset(&lock, 0, sizeof(lock));
|
|
|
|
+ lock.l_type = F_WRLCK;
|
|
|
|
+ lock.l_whence = SEEK_SET;
|
|
|
|
+
|
|
|
|
+ act.sa_handler = sigalrm;
|
|
|
|
+ sigemptyset(&act.sa_mask);
|
|
|
|
+ act.sa_flags = 0;
|
|
|
|
+ sigemptyset(&set);
|
|
|
|
+ sigaddset(&set, SIGALRM);
|
|
|
|
+
|
|
|
|
+ sigaction(SIGALRM, &act, &oldact);
|
|
|
|
+ sigprocmask(SIG_UNBLOCK, &set, &oldset);
|
|
|
|
+
|
|
|
|
+ alarm(FILE_TIMEOUT);
|
|
|
|
+ err = fcntl(fd, F_SETLKW, &lock);
|
|
|
|
+ alarm(0);
|
|
|
|
+
|
|
|
|
+ if (err) {
|
|
|
|
+ if (errno != EINTR)
|
|
|
|
+ condlog(0, "Cannot lock %s : %s", file_name,
|
|
|
|
+ strerror(errno));
|
|
|
|
+ else
|
|
|
|
+ condlog(0, "%s is locked. Giving up.", file_name);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
|
|
+ sigaction(SIGALRM, &oldact, NULL);
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+open_file(char *file, int *can_write, char *header)
|
|
|
|
+{
|
|
|
|
+ int fd;
|
|
|
|
+ struct stat s;
|
|
|
|
+
|
|
|
|
+ if (ensure_directories_exist(file, 0700))
|
|
|
|
+ return -1;
|
|
|
|
+ *can_write = 1;
|
|
|
|
+ fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
|
|
|
+ if (fd < 0) {
|
|
|
|
+ if (errno == EROFS) {
|
|
|
|
+ *can_write = 0;
|
|
|
|
+ condlog(3, "Cannot open file [%s] read/write. "
|
|
|
|
+ " trying readonly", file);
|
|
|
|
+ fd = open(file, O_RDONLY);
|
|
|
|
+ if (fd < 0) {
|
|
|
|
+ condlog(0, "Cannot open file [%s] "
|
|
|
|
+ "readonly : %s", file, strerror(errno));
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ condlog(0, "Cannot open file [%s] : %s", file,
|
|
|
|
+ strerror(errno));
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (*can_write && lock_file(fd, file) < 0)
|
|
|
|
+ goto fail;
|
|
|
|
+
|
|
|
|
+ memset(&s, 0, sizeof(s));
|
|
|
|
+ if (fstat(fd, &s) < 0){
|
|
|
|
+ condlog(0, "Cannot stat file %s : %s", file, strerror(errno));
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ if (s.st_size == 0) {
|
|
|
|
+ if (*can_write == 0)
|
|
|
|
+ goto fail;
|
|
|
|
+ /* If file is empty, write the header */
|
|
|
|
+ size_t len = strlen(header);
|
|
|
|
+ if (write_all(fd, header, len) != len) {
|
|
|
|
+ condlog(0,
|
|
|
|
+ "Cannot write header to file %s : %s", file,
|
|
|
|
+ strerror(errno));
|
|
|
|
+ /* cleanup partially written header */
|
2012-06-28 17:41:03 +00:00
|
|
|
+ if (ftruncate(fd, 0))
|
|
|
|
+ condlog(0, "Cannot truncate header : %s",
|
|
|
|
+ strerror(errno));
|
2010-01-23 01:39:39 +00:00
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ fsync(fd);
|
|
|
|
+ condlog(3, "Initialized new file [%s]", file);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return fd;
|
|
|
|
+
|
|
|
|
+fail:
|
|
|
|
+ close(fd);
|
|
|
|
+ return -1;
|
|
|
|
+}
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/file.h
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
|
|
|
--- /dev/null
|
2012-06-28 17:41:03 +00:00
|
|
|
+++ multipath-tools-120518/libmultipath/file.h
|
2010-01-23 01:39:39 +00:00
|
|
|
@@ -0,0 +1,11 @@
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#ifndef _FILE_H
|
|
|
|
+#define _FILE_H
|
|
|
|
+
|
|
|
|
+#define FILE_TIMEOUT 30
|
|
|
|
+int open_file(char *file, int *can_write, char *header);
|
|
|
|
+
|
|
|
|
+#endif /* _FILE_H */
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/multipath/main.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-120518.orig/multipath/main.c
|
|
|
|
+++ multipath-tools-120518/multipath/main.c
|
|
|
|
@@ -53,6 +53,7 @@
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
+#include <wwids.h>
|
|
|
|
#include "dev_t.h"
|
|
|
|
|
|
|
|
int logsink;
|
|
|
|
@@ -82,7 +83,7 @@ usage (char * progname)
|
|
|
|
{
|
|
|
|
fprintf (stderr, VERSION_STRING);
|
|
|
|
fprintf (stderr, "Usage:\n");
|
|
|
|
- fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
|
|
|
|
+ fprintf (stderr, " %s [-c] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
|
|
|
|
fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname);
|
|
|
|
fprintf (stderr, " %s -F [-v lvl]\n", progname);
|
|
|
|
fprintf (stderr, " %s -t\n", progname);
|
|
|
|
@@ -95,6 +96,7 @@ usage (char * progname)
|
|
|
|
" -ll show multipath topology (maximum info)\n" \
|
|
|
|
" -f flush a multipath device map\n" \
|
|
|
|
" -F flush all multipath device maps\n" \
|
|
|
|
+ " -c check if a device should be a path in a multipath device\n" \
|
|
|
|
" -q allow queue_if_no_path when multipathd is not running\n"\
|
|
|
|
" -d dry run, do not create or update devmaps\n" \
|
|
|
|
" -t dump internal hardware table\n" \
|
|
|
|
@@ -209,6 +211,7 @@ get_dm_mpvec (vector curmp, vector pathv
|
|
|
|
|
|
|
|
if (!conf->dry_run)
|
|
|
|
reinstate_paths(mpp);
|
|
|
|
+ remember_wwid(mpp->wwid);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
@@ -259,9 +262,13 @@ configure (void)
|
|
|
|
* if we have a blacklisted device parameter, exit early
|
|
|
|
*/
|
|
|
|
if (dev &&
|
|
|
|
- (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0))
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
+ (filter_devnode(conf->blist_devnode,
|
|
|
|
+ conf->elist_devnode, dev) > 0)) {
|
|
|
|
+ if (conf->dry_run == 2)
|
|
|
|
+ printf("%s is not a valid multipath device path\n",
|
|
|
|
+ conf->dev);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
/*
|
|
|
|
* scope limiting must be translated into a wwid
|
|
|
|
* failing the translation is fatal (by policy)
|
|
|
|
@@ -277,6 +284,15 @@ configure (void)
|
|
|
|
if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
|
|
|
|
refwwid) > 0)
|
|
|
|
goto out;
|
|
|
|
+ if (conf->dry_run == 2) {
|
|
|
|
+ if (check_wwids_file(refwwid, 0) == 0){
|
|
|
|
+ printf("%s is a valid multipath device path\n", conf->dev);
|
|
|
|
+ r = 0;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ printf("%s is not a valid multipath device path\n", conf->dev);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -412,7 +428,7 @@ main (int argc, char *argv[])
|
|
|
|
if (load_config(DEFAULT_CONFIGFILE))
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
- while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:Brtq")) != EOF ) {
|
|
|
|
+ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brtq")) != EOF ) {
|
|
|
|
switch(arg) {
|
|
|
|
case 1: printf("optarg : %s\n",optarg);
|
|
|
|
break;
|
|
|
|
@@ -434,8 +450,12 @@ main (int argc, char *argv[])
|
|
|
|
case 'q':
|
|
|
|
conf->allow_queueing = 1;
|
|
|
|
break;
|
|
|
|
+ case 'c':
|
|
|
|
+ conf->dry_run = 2;
|
|
|
|
+ break;
|
|
|
|
case 'd':
|
|
|
|
- conf->dry_run = 1;
|
|
|
|
+ if (!conf->dry_run)
|
|
|
|
+ conf->dry_run = 1;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
conf->remove = FLUSH_ONE;
|
|
|
|
@@ -517,6 +537,11 @@ main (int argc, char *argv[])
|
|
|
|
}
|
|
|
|
dm_init();
|
|
|
|
|
|
|
|
+ if (conf->dry_run == 2 &&
|
|
|
|
+ (!conf->dev || conf->dev_type == DEV_DEVMAP)) {
|
|
|
|
+ condlog(0, "the -c option requires a path to check");
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
if (conf->remove == FLUSH_ONE) {
|
|
|
|
if (conf->dev_type == DEV_DEVMAP)
|
|
|
|
r = dm_flush_map(conf->dev);
|
|
|
|
Index: multipath-tools-120518/libmultipath/Makefile
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-120518.orig/libmultipath/Makefile
|
|
|
|
+++ multipath-tools-120518/libmultipath/Makefile
|
|
|
|
@@ -15,7 +15,7 @@ OBJS = memory.o parser.o vector.o devmap
|
|
|
|
pgpolicies.o debug.o regex.o defaults.o uevent.o \
|
|
|
|
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
|
|
|
|
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
|
|
|
|
- lock.o waiter.o
|
|
|
|
+ lock.o waiter.o file.o wwids.o
|
|
|
|
|
|
|
|
LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
|
|
|
|
|
|
|
|
Index: multipath-tools-120518/libmultipath/wwids.c
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
|
|
|
--- /dev/null
|
2012-06-28 17:41:03 +00:00
|
|
|
+++ multipath-tools-120518/libmultipath/wwids.c
|
|
|
|
@@ -0,0 +1,139 @@
|
2010-01-23 01:39:39 +00:00
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <errno.h>
|
|
|
|
+#include <unistd.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <limits.h>
|
|
|
|
+#include <stdio.h>
|
|
|
|
+
|
|
|
|
+#include "checkers.h"
|
|
|
|
+#include "vector.h"
|
|
|
|
+#include "structs.h"
|
|
|
|
+#include "debug.h"
|
|
|
|
+#include "uxsock.h"
|
|
|
|
+#include "file.h"
|
2012-06-28 17:41:03 +00:00
|
|
|
+#include "wwids.h"
|
2010-01-23 01:39:39 +00:00
|
|
|
+#include "defaults.h"
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+lookup_wwid(FILE *f, char *wwid) {
|
2011-07-15 17:25:48 +00:00
|
|
|
+ int c;
|
2010-01-23 01:39:39 +00:00
|
|
|
+ char buf[LINE_MAX];
|
2011-07-15 17:25:48 +00:00
|
|
|
+ int count;
|
2010-01-23 01:39:39 +00:00
|
|
|
+
|
2011-07-15 17:25:48 +00:00
|
|
|
+ while ((c = fgetc(f)) != EOF){
|
|
|
|
+ if (c != '/') {
|
|
|
|
+ if (fgets(buf, LINE_MAX, f) == NULL)
|
|
|
|
+ return 0;
|
|
|
|
+ else
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ count = 0;
|
|
|
|
+ while ((c = fgetc(f)) != '/') {
|
|
|
|
+ if (c == EOF)
|
|
|
|
+ return 0;
|
|
|
|
+ if (count >= WWID_SIZE - 1)
|
|
|
|
+ goto next;
|
|
|
|
+ if (wwid[count] == '\0')
|
|
|
|
+ goto next;
|
|
|
|
+ if (c != wwid[count++])
|
|
|
|
+ goto next;
|
|
|
|
+ }
|
|
|
|
+ if (wwid[count] == '\0')
|
2010-01-23 01:39:39 +00:00
|
|
|
+ return 1;
|
2011-07-15 17:25:48 +00:00
|
|
|
+next:
|
|
|
|
+ if (fgets(buf, LINE_MAX, f) == NULL)
|
|
|
|
+ return 0;
|
2010-01-23 01:39:39 +00:00
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+write_out_wwid(int fd, char *wwid) {
|
|
|
|
+ int ret;
|
|
|
|
+ off_t offset;
|
2011-07-15 17:25:48 +00:00
|
|
|
+ char buf[WWID_SIZE + 3];
|
2010-01-23 01:39:39 +00:00
|
|
|
+
|
2011-07-15 17:25:48 +00:00
|
|
|
+ ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
|
|
|
|
+ if (ret >= (WWID_SIZE + 3) || ret < 0){
|
2010-01-23 01:39:39 +00:00
|
|
|
+ condlog(0, "can't format wwid for writing (%d) : %s",
|
|
|
|
+ ret, strerror(errno));
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ offset = lseek(fd, 0, SEEK_END);
|
|
|
|
+ if (offset < 0) {
|
|
|
|
+ condlog(0, "can't seek to the end of wwids file : %s",
|
|
|
|
+ strerror(errno));
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
|
|
|
|
+ condlog(0, "cannot write wwid to wwids file : %s",
|
|
|
|
+ strerror(errno));
|
2012-06-28 17:41:03 +00:00
|
|
|
+ if (ftruncate(fd, offset))
|
|
|
|
+ condlog(0, "cannot truncate failed wwid write : %s",
|
|
|
|
+ strerror(errno));
|
2010-01-23 01:39:39 +00:00
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
2012-06-28 17:41:03 +00:00
|
|
|
+int
|
2010-01-23 01:39:39 +00:00
|
|
|
+check_wwids_file(char *wwid, int write_wwid)
|
|
|
|
+{
|
2012-06-28 17:41:03 +00:00
|
|
|
+ int fd, can_write, found, ret;
|
2010-01-23 01:39:39 +00:00
|
|
|
+ FILE *f;
|
|
|
|
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
|
|
|
|
+ if (fd < 0)
|
|
|
|
+ return -1;
|
|
|
|
+
|
2012-06-28 17:41:03 +00:00
|
|
|
+ f = fdopen(fd, "r");
|
2010-01-23 01:39:39 +00:00
|
|
|
+ if (!f) {
|
|
|
|
+ condlog(0,"can't fdopen wwids file : %s", strerror(errno));
|
|
|
|
+ close(fd);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ found = lookup_wwid(f, wwid);
|
|
|
|
+ if (found) {
|
|
|
|
+ ret = 0;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ if (!write_wwid) {
|
|
|
|
+ ret = -1;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ if (!can_write) {
|
|
|
|
+ condlog(0, "wwids file is read-only. Can't write wwid");
|
|
|
|
+ ret = -1;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
2012-06-28 17:41:03 +00:00
|
|
|
+
|
|
|
|
+ if (fflush(f) != 0) {
|
|
|
|
+ condlog(0, "cannot fflush wwids file stream : %s",
|
|
|
|
+ strerror(errno));
|
|
|
|
+ ret = -1;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
2010-01-23 01:39:39 +00:00
|
|
|
+ ret = write_out_wwid(fd, wwid);
|
|
|
|
+out:
|
|
|
|
+ fclose(f);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+remember_wwid(char *wwid)
|
|
|
|
+{
|
|
|
|
+ int ret = check_wwids_file(wwid, 1);
|
|
|
|
+ if (ret < 0){
|
|
|
|
+ condlog(3, "failed writing wwid %s to wwids file", wwid);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ if (ret == 1)
|
|
|
|
+ condlog(3, "wrote wwid %s to wwids file", wwid);
|
|
|
|
+ else
|
|
|
|
+ condlog(4, "wwid %s already in wwids file", wwid);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
2012-06-28 17:41:03 +00:00
|
|
|
Index: multipath-tools-120518/libmultipath/wwids.h
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
|
|
|
--- /dev/null
|
2012-06-28 17:41:03 +00:00
|
|
|
+++ multipath-tools-120518/libmultipath/wwids.h
|
2010-01-23 01:39:39 +00:00
|
|
|
@@ -0,0 +1,18 @@
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
|
|
|
|
+ */
|
|
|
|
+
|
2012-06-28 17:41:03 +00:00
|
|
|
+#ifndef _WWIDS_H
|
|
|
|
+#define _WWIDS_H
|
2010-01-23 01:39:39 +00:00
|
|
|
+
|
|
|
|
+#define WWIDS_FILE_HEADER \
|
|
|
|
+"# Multipath wwids, Version : 1.0\n" \
|
|
|
|
+"# NOTE: This file is automatically maintained by multipath and multipathd.\n" \
|
|
|
|
+"# You should not need to edit this file in normal circumstances.\n" \
|
|
|
|
+"#\n" \
|
|
|
|
+"# Valid WWIDs:\n"
|
|
|
|
+
|
|
|
|
+int remember_wwid(char *wwid);
|
2012-06-28 17:41:03 +00:00
|
|
|
+int check_wwids_file(char *wwid, int write_wwid);
|
2010-01-23 01:39:39 +00:00
|
|
|
+
|
2012-06-28 17:41:03 +00:00
|
|
|
+#endif /* _WWIDS_H */
|
|
|
|
Index: multipath-tools-120518/libmultipath/discovery.c
|
2010-01-23 01:39:39 +00:00
|
|
|
===================================================================
|
2012-06-28 17:41:03 +00:00
|
|
|
--- multipath-tools-120518.orig/libmultipath/discovery.c
|
|
|
|
+++ multipath-tools-120518/libmultipath/discovery.c
|
|
|
|
@@ -810,6 +810,8 @@ get_uid (struct path * pp)
|
2010-01-23 01:39:39 +00:00
|
|
|
|
2012-06-28 17:41:03 +00:00
|
|
|
memset(pp->wwid, 0, WWID_SIZE);
|
|
|
|
value = udev_device_get_property_value(pp->udev, pp->uid_attribute);
|
|
|
|
+ if ((!value || strlen(value) == 0) && conf->dry_run == 2)
|
|
|
|
+ value = getenv(pp->uid_attribute);
|
|
|
|
if (value && strlen(value)) {
|
|
|
|
size_t len = WWID_SIZE;
|
2010-01-23 01:39:39 +00:00
|
|
|
|