You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
12 KiB

---
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(&timestamp) == -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", &timestamp, &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);