|
|
|
---
|
|
|
|
libmultipath/defaults.h | 3 -
|
|
|
|
libmultipath/file.c | 89 +++++++++++++++++++++++++++++++++++++++++-
|
|
|
|
libmultipath/file.h | 3 +
|
|
|
|
libmultipath/wwids.c | 7 ++-
|
|
|
|
multipath/main.c | 36 +++++++++++++++-
|
|
|
|
multipath/multipath.rules | 26 +++++++++---
|
|
|
|
multipathd/main.c | 4 +
|
|
|
|
multipathd/multipathd.service | 2
|
|
|
|
multipathd/pidfile.c | 3 +
|
|
|
|
9 files changed, 160 insertions(+), 13 deletions(-)
|
|
|
|
|
|
|
|
Index: multipath-tools-130222/libmultipath/defaults.h
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/defaults.h
|
|
|
|
+++ multipath-tools-130222/libmultipath/defaults.h
|
|
|
|
@@ -24,7 +24,8 @@
|
|
|
|
#define MAX_CHECKINT(a) (a << 2)
|
|
|
|
|
|
|
|
#define MAX_DEV_LOSS_TMO 0x7FFFFFFF
|
|
|
|
-#define DEFAULT_PIDFILE "/var/run/multipathd.pid"
|
|
|
|
+#define DEFAULT_PIDFILE "/var/run/multipathd/multipathd.pid"
|
|
|
|
+#define DEFAULT_TIMESTAMP_FILE "/var/run/multipathd/timestamp"
|
|
|
|
#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
|
|
|
|
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
|
|
|
|
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
|
|
|
|
Index: multipath-tools-130222/libmultipath/file.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/file.c
|
|
|
|
+++ multipath-tools-130222/libmultipath/file.c
|
|
|
|
@@ -12,10 +12,12 @@
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <signal.h>
|
|
|
|
+#include <time.h>
|
|
|
|
|
|
|
|
#include "file.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "uxsock.h"
|
|
|
|
+#include "defaults.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -36,8 +38,8 @@
|
|
|
|
* See the file COPYING included with this distribution for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-ensure_directories_exist(char *str, mode_t dir_mode)
|
|
|
|
+int
|
|
|
|
+ensure_directories_exist(const char *str, mode_t dir_mode)
|
|
|
|
{
|
|
|
|
char *pathname;
|
|
|
|
char *end;
|
|
|
|
@@ -178,3 +180,86 @@ fail:
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+/* If you can't get the timestamp, return equal to just keep using the
|
|
|
|
+ * existing value.
|
|
|
|
+ */
|
|
|
|
+int timestamp_equal(long int chk_timestamp)
|
|
|
|
+{
|
|
|
|
+ char buf[4096];
|
|
|
|
+ FILE *file;
|
|
|
|
+ long int file_timestamp;
|
|
|
|
+ int ret = 1;
|
|
|
|
+
|
|
|
|
+ if ((file = fopen(DEFAULT_TIMESTAMP_FILE, "r")) == NULL) {
|
|
|
|
+ if (errno != ENOENT)
|
|
|
|
+ condlog(2, "Cannot open timestamp file [%s]: %s",
|
|
|
|
+ DEFAULT_TIMESTAMP_FILE, strerror(errno));
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ errno = 0;
|
|
|
|
+ if (fgets(buf, sizeof(buf), file) == NULL) {
|
|
|
|
+ if (errno)
|
|
|
|
+ condlog(2, "Cannot read from timestamp file: %s",
|
|
|
|
+ strerror(errno));
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ if (sscanf(buf, "DM_MULTIPATH_TIMESTAMP=%ld", &file_timestamp) != 1) {
|
|
|
|
+ if (errno)
|
|
|
|
+ condlog(0, "Cannot get timestamp: %s", strerror(errno));
|
|
|
|
+ else
|
|
|
|
+ condlog(0, "invalid timestamp file [%s]: %s",
|
|
|
|
+ DEFAULT_TIMESTAMP_FILE, strerror(errno));
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ if (file_timestamp != chk_timestamp) {
|
|
|
|
+ condlog(3, "timestamp has changed");
|
|
|
|
+ ret = 0;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ condlog(3, "timestamp has not changed");
|
|
|
|
+out:
|
|
|
|
+ if (file)
|
|
|
|
+ fclose(file);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int update_timestamp(int create)
|
|
|
|
+{
|
|
|
|
+ char buf[44];
|
|
|
|
+ time_t timestamp;
|
|
|
|
+ int fd;
|
|
|
|
+ int flags = O_WRONLY;
|
|
|
|
+ if (create)
|
|
|
|
+ flags |= O_CREAT;
|
|
|
|
+ if((fd = open(DEFAULT_TIMESTAMP_FILE, flags,
|
|
|
|
+ (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
|
|
|
|
+ if (errno == ENOENT)
|
|
|
|
+ return 0;
|
|
|
|
+ condlog(0, "Cannot open timestamp file [%s]: %s",
|
|
|
|
+ DEFAULT_TIMESTAMP_FILE, strerror(errno));
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ if (ftruncate(fd, 0) < 0) {
|
|
|
|
+ condlog(0, "Cannot truncate timestamp file [%s]: %s",
|
|
|
|
+ DEFAULT_TIMESTAMP_FILE, strerror(errno));
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ if (time(×tamp) == -1) {
|
|
|
|
+ condlog(0, "Cannot get current time: %s", strerror(errno));
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
|
+ snprintf(buf, sizeof(buf)-1, "DM_MULTIPATH_TIMESTAMP=%ld\n",
|
|
|
|
+ timestamp);
|
|
|
|
+ if (write(fd, buf, strlen(buf)) != strlen(buf)) {
|
|
|
|
+ condlog(0, "Cannot write out timestamp to %s: %s",
|
|
|
|
+ DEFAULT_TIMESTAMP_FILE, strerror(errno));
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ close(fd);
|
|
|
|
+ return 0;
|
|
|
|
+fail:
|
|
|
|
+ close(fd);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
Index: multipath-tools-130222/libmultipath/file.h
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/file.h
|
|
|
|
+++ multipath-tools-130222/libmultipath/file.h
|
|
|
|
@@ -7,5 +7,8 @@
|
|
|
|
|
|
|
|
#define FILE_TIMEOUT 30
|
|
|
|
int open_file(char *file, int *can_write, char *header);
|
|
|
|
+int ensure_directories_exist(const char *str, mode_t dir_mode);
|
|
|
|
+int update_timestamp(int create);
|
|
|
|
+int timestamp_equal(long int chk_timestamp);
|
|
|
|
|
|
|
|
#endif /* _FILE_H */
|
|
|
|
Index: multipath-tools-130222/multipathd/pidfile.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/multipathd/pidfile.c
|
|
|
|
+++ multipath-tools-130222/multipathd/pidfile.c
|
|
|
|
@@ -9,6 +9,7 @@
|
|
|
|
#include <fcntl.h> /* for fcntl() */
|
|
|
|
|
|
|
|
#include <debug.h>
|
|
|
|
+#include <file.h>
|
|
|
|
|
|
|
|
#include "pidfile.h"
|
|
|
|
|
|
|
|
@@ -18,6 +19,8 @@ int pidfile_create(const char *pidFile,
|
|
|
|
struct flock lock;
|
|
|
|
int fd, value;
|
|
|
|
|
|
|
|
+ if (ensure_directories_exist(pidFile, 0700))
|
|
|
|
+ return 1;
|
|
|
|
if((fd = open(pidFile, O_WRONLY | O_CREAT,
|
|
|
|
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
|
|
|
|
condlog(0, "Cannot open pidfile [%s], error was [%s]",
|
|
|
|
Index: multipath-tools-130222/libmultipath/wwids.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/libmultipath/wwids.c
|
|
|
|
+++ multipath-tools-130222/libmultipath/wwids.c
|
|
|
|
@@ -125,6 +125,7 @@ replace_wwids(vector mp)
|
|
|
|
goto out_file;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
+ update_timestamp(0);
|
|
|
|
out_file:
|
|
|
|
close(fd);
|
|
|
|
out:
|
|
|
|
@@ -209,6 +210,8 @@ remove_wwid(char *wwid) {
|
|
|
|
goto out_file;
|
|
|
|
}
|
|
|
|
ret = do_remove_wwid(fd, str);
|
|
|
|
+ if (!ret)
|
|
|
|
+ update_timestamp(0);
|
|
|
|
|
|
|
|
out_file:
|
|
|
|
close(fd);
|
|
|
|
@@ -294,8 +297,10 @@ remember_wwid(char *wwid)
|
|
|
|
condlog(3, "failed writing wwid %s to wwids file", wwid);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
- if (ret == 1)
|
|
|
|
+ if (ret == 1) {
|
|
|
|
condlog(3, "wrote wwid %s to wwids file", wwid);
|
|
|
|
+ update_timestamp(0);
|
|
|
|
+ }
|
|
|
|
else
|
|
|
|
condlog(4, "wwid %s already in wwids file", wwid);
|
|
|
|
return 0;
|
|
|
|
Index: multipath-tools-130222/multipath/multipath.rules
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/multipath/multipath.rules
|
|
|
|
+++ multipath-tools-130222/multipath/multipath.rules
|
|
|
|
@@ -4,18 +4,34 @@ SUBSYSTEM!="block", GOTO="end_mpath"
|
|
|
|
|
|
|
|
IMPORT{cmdline}="nompath"
|
|
|
|
ENV{nompath}=="?*", GOTO="end_mpath"
|
|
|
|
+ENV{DEVTYPE}=="partition", GOTO="end_mpath"
|
|
|
|
ENV{MPATH_SBIN_PATH}="/sbin"
|
|
|
|
TEST!="$env{MPATH_SBIN_PATH}/multipath", ENV{MPATH_SBIN_PATH}="/usr/sbin"
|
|
|
|
+TEST!="/etc/multipath.conf", GOTO="check_kpartx"
|
|
|
|
|
|
|
|
-ACTION=="add", ENV{DEVTYPE}!="partition", \
|
|
|
|
- ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \
|
|
|
|
- TEST=="/etc/multipath.conf", \
|
|
|
|
+ACTION=="add", ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \
|
|
|
|
PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \
|
|
|
|
- ENV{DM_MULTIPATH_DEVICE_PATH}="1" ENV{ID_FS_TYPE}="mpath_member"
|
|
|
|
+ ENV{DM_MULTIPATH_DEVICE_PATH}="1", ENV{ID_FS_TYPE}="mpath_member"
|
|
|
|
|
|
|
|
-ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DEVTYPE}!="partition", \
|
|
|
|
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", \
|
|
|
|
RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}"
|
|
|
|
|
|
|
|
+ACTION!="change", GOTO="update_timestamp"
|
|
|
|
+IMPORT{db}="DM_MULTIPATH_TIMESTAMP"
|
|
|
|
+IMPORT{db}="DM_MULTIPATH_DEVICE_PATH"
|
|
|
|
+# Check if the device is part of a multipath device. the -T option just keeps
|
|
|
|
+# the old result if the timestamp hasn't changed.
|
|
|
|
+PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -T $env{DM_MULTIPATH_TIMESTAMP}:$env{DM_MULTIPATH_DEVICE_PATH} -c $env{DEVNAME}", \
|
|
|
|
+ ENV{DM_MULTIPATH_DEVICE_PATH}="1", ENV{ID_FS_TYPE}="mpath_member", \
|
|
|
|
+ GOTO="update_timestamp"
|
|
|
|
+
|
|
|
|
+# If the device isn't part of a multipath device, clear this
|
|
|
|
+ENV{DM_MULTIPATH_DEVICE_PATH}=""
|
|
|
|
+
|
|
|
|
+LABEL="update_timestamp"
|
|
|
|
+IMPORT{file}="/run/multipathd/timestamp"
|
|
|
|
+
|
|
|
|
+LABEL="check_kpartx"
|
|
|
|
KERNEL!="dm-*", GOTO="end_mpath"
|
|
|
|
ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10"
|
|
|
|
ACTION!="change", GOTO="end_mpath"
|
|
|
|
Index: multipath-tools-130222/multipathd/main.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/multipathd/main.c
|
|
|
|
+++ multipath-tools-130222/multipathd/main.c
|
|
|
|
@@ -54,6 +54,7 @@
|
|
|
|
#include <pgpolicies.h>
|
|
|
|
#include <uevent.h>
|
|
|
|
#include <log.h>
|
|
|
|
+#include <file.h>
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "pidfile.h"
|
|
|
|
@@ -1417,6 +1418,7 @@ reconfigure (struct vectors * vecs)
|
|
|
|
free_config(old);
|
|
|
|
retval = 0;
|
|
|
|
}
|
|
|
|
+ update_timestamp(0);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
@@ -1709,6 +1711,7 @@ child (void * param)
|
|
|
|
|
|
|
|
/* Startup complete, create logfile */
|
|
|
|
pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid);
|
|
|
|
+ update_timestamp(1);
|
|
|
|
/* Ignore errors, we can live without */
|
|
|
|
|
|
|
|
running_state = DAEMON_RUNNING;
|
|
|
|
@@ -1758,6 +1761,7 @@ child (void * param)
|
|
|
|
if (!pid_rc) {
|
|
|
|
condlog(3, "unlink pidfile");
|
|
|
|
unlink(DEFAULT_PIDFILE);
|
|
|
|
+ unlink(DEFAULT_TIMESTAMP_FILE);
|
|
|
|
}
|
|
|
|
|
|
|
|
condlog(2, "--------shut down-------");
|
|
|
|
Index: multipath-tools-130222/multipathd/multipathd.service
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/multipathd/multipathd.service
|
|
|
|
+++ multipath-tools-130222/multipathd/multipathd.service
|
|
|
|
@@ -9,7 +9,7 @@ Conflicts=shutdown.target
|
|
|
|
|
|
|
|
[Service]
|
|
|
|
Type=forking
|
|
|
|
-PIDFile=/var/run/multipathd.pid
|
|
|
|
+PIDFile=/var/run/multipathd/multipathd.pid
|
|
|
|
ExecStartPre=/sbin/modprobe dm-multipath
|
|
|
|
ExecStart=/sbin/multipathd
|
|
|
|
ExecReload=/sbin/multipathd reconfigure
|
|
|
|
Index: multipath-tools-130222/multipath/main.c
|
|
|
|
===================================================================
|
|
|
|
--- multipath-tools-130222.orig/multipath/main.c
|
|
|
|
+++ multipath-tools-130222/multipath/main.c
|
|
|
|
@@ -55,6 +55,7 @@
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <wwids.h>
|
|
|
|
+#include <file.h>
|
|
|
|
#include "dev_t.h"
|
|
|
|
|
|
|
|
int logsink;
|
|
|
|
@@ -84,7 +85,7 @@ usage (char * progname)
|
|
|
|
{
|
|
|
|
fprintf (stderr, VERSION_STRING);
|
|
|
|
fprintf (stderr, "Usage:\n");
|
|
|
|
- fprintf (stderr, " %s [-c|-w|-W] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
|
|
|
|
+ fprintf (stderr, " %s [-c|-w|-W] [-d] [-T tm:val] [-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);
|
|
|
|
@@ -98,6 +99,9 @@ usage (char * progname)
|
|
|
|
" -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" \
|
|
|
|
+ " -T tm:val\n" \
|
|
|
|
+ " check if tm matches the multipathd timestamp. If so val is\n" \
|
|
|
|
+ " whether or not the device is 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" \
|
|
|
|
@@ -441,7 +445,31 @@ main (int argc, char *argv[])
|
|
|
|
extern char *optarg;
|
|
|
|
extern int optind;
|
|
|
|
int r = 1;
|
|
|
|
-
|
|
|
|
+ long int timestamp = -1;
|
|
|
|
+ int valid = -1;
|
|
|
|
+ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtT:qwW")) != EOF ) {
|
|
|
|
+ switch(arg) {
|
|
|
|
+ case 'T':
|
|
|
|
+ if (optarg[0] == ':')
|
|
|
|
+ sscanf(optarg, ":%d", &valid);
|
|
|
|
+ else
|
|
|
|
+ sscanf(optarg, "%ld:%d", ×tamp, &valid);
|
|
|
|
+ if (timestamp_equal(timestamp))
|
|
|
|
+ return (valid != 1);
|
|
|
|
+ break;
|
|
|
|
+ case ':':
|
|
|
|
+ fprintf(stderr, "Missing option argument\n");
|
|
|
|
+ usage(argv[0]);
|
|
|
|
+ exit(1);
|
|
|
|
+ case '?':
|
|
|
|
+ fprintf(stderr, "Unknown switch: %s\n", optarg);
|
|
|
|
+ usage(argv[0]);
|
|
|
|
+ exit(1);
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ optind = 1;
|
|
|
|
if (getuid() != 0) {
|
|
|
|
fprintf(stderr, "need to be root\n");
|
|
|
|
exit(1);
|
|
|
|
@@ -455,7 +483,7 @@ main (int argc, char *argv[])
|
|
|
|
if (dm_prereq())
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
- while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtqwW")) != EOF ) {
|
|
|
|
+ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtT:qwW")) != EOF ) {
|
|
|
|
switch(arg) {
|
|
|
|
case 1: printf("optarg : %s\n",optarg);
|
|
|
|
break;
|
|
|
|
@@ -517,6 +545,8 @@ main (int argc, char *argv[])
|
|
|
|
case 't':
|
|
|
|
r = dump_config();
|
|
|
|
goto out;
|
|
|
|
+ case 'T':
|
|
|
|
+ break;
|
|
|
|
case 'h':
|
|
|
|
usage(argv[0]);
|
|
|
|
exit(0);
|