FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Device-mapper Development

 
 
LinkBack Thread Tools
 
Old 08-17-2012, 08:13 PM
Christophe Varoqui
 
Default multipath: check if a device belongs to multipath

On ven., 2012-07-27 at 15:55 -0500, Benjamin Marzinski wrote:
> This patch adds a new multipath option "-c", which checks if a device
> belongs to multipath. This can be done during the add uevent for the
> device, before the multipath device has even been created. This allows
> udev to be able to handle multipath path devices differently. To do
> this multipath now keeps track of the wwids of all previously created
> multipath devices in /etc/multipath/wwids. The file creating and
> editting code from alias.[ch] has been split out into file.[ch]. When a
> device is checked to see if it's a multipath path, it's wwid is
> compared against the ones in the wwids file. Also, since the
> uid_attribute may not have been added to the udev database entry for
> the device if this is called in a udev rule, when using the "-c" option,
> get_uid will now also check the process' envirionment variables for the
> uid_attribute.
>
I'd like other distribution maintainers' comments on this one, as it
impacts the multipath-tools intregration with udev.

Hannes ? Did you face the same issue with SuSE ? Did you solve it
differently ?

Ben, does this approach supersedes/extends the "complicated blacklisting
scheme" you proposed earlier ?

Thanks.

> Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
> libmultipath/Makefile | 2
> libmultipath/alias.c | 153 ---------------------------------------
> libmultipath/alias.h | 1
> libmultipath/configure.c | 3
> libmultipath/defaults.h | 1
> libmultipath/discovery.c | 2
> libmultipath/file.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++
> libmultipath/file.h | 11 ++
> libmultipath/wwids.c | 139 ++++++++++++++++++++++++++++++++++++
> libmultipath/wwids.h | 18 ++++
> multipath/main.c | 37 ++++++++-
> 11 files changed, 389 insertions(+), 158 deletions(-)
>
> Index: multipath-tools-120518/libmultipath/alias.c
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/alias.c
> +++ multipath-tools-120518/libmultipath/alias.c
> @@ -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"
>
>
> /*
> @@ -36,150 +33,6 @@
> * 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 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 = '';
> - 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 */
> - if (ftruncate(fd, 0))
> - condlog(0, "Cannot truncate the header : %s",
> - strerror(errno));
> - goto fail;
> - }
> - fsync(fd);
> - condlog(3, "Initialized new bindings file [%s]", file);
> - }
> -
> - return fd;
> -
> -fail:
> - close(fd);
> - return -1;
> -}
>
> static int
> format_devname(char *name, int id, int len, char *prefix)
> @@ -370,7 +223,7 @@ get_user_friendly_alias(char *wwid, char
> return NULL;
> }
>
> - fd = open_bindings_file(file, &can_write);
> + fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
> if (fd < 0)
> return NULL;
>
> @@ -414,7 +267,7 @@ get_user_friendly_wwid(char *alias, char
> return NULL;
> }
>
> - fd = open_bindings_file(file, &unused);
> + fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
> if (fd < 0)
> return NULL;
>
> Index: multipath-tools-120518/libmultipath/alias.h
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/alias.h
> +++ multipath-tools-120518/libmultipath/alias.h
> @@ -1,4 +1,3 @@
> -#define BINDINGS_FILE_TIMEOUT 30
> #define BINDINGS_FILE_HEADER
> "# Multipath bindings, Version : 1.0
"
> "# NOTE: this file is automatically maintained by the multipath program.
"
> Index: multipath-tools-120518/libmultipath/configure.c
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/configure.c
> +++ multipath-tools-120518/libmultipath/configure.c
> @@ -37,6 +37,7 @@
> #include "prio.h"
> #include "util.h"
> #include "uxsock.h"
> +#include "wwids.h"
>
> extern int
> setup_map (struct multipath * mpp, char * params, int params_size)
> @@ -407,6 +408,8 @@ domap (struct multipath * mpp, char * pa
> * 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);
> Index: multipath-tools-120518/libmultipath/defaults.h
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/defaults.h
> +++ multipath-tools-120518/libmultipath/defaults.h
> @@ -24,5 +24,6 @@
> #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);
> Index: multipath-tools-120518/libmultipath/file.c
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/file.c
> @@ -0,0 +1,180 @@
> +/*
> + * 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 = '';
> + 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 */
> + if (ftruncate(fd, 0))
> + condlog(0, "Cannot truncate header : %s",
> + strerror(errno));
> + goto fail;
> + }
> + fsync(fd);
> + condlog(3, "Initialized new file [%s]", file);
> + }
> +
> + return fd;
> +
> +fail:
> + close(fd);
> + return -1;
> +}
> Index: multipath-tools-120518/libmultipath/file.h
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/file.h
> @@ -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 */
> 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:
");
> - fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]
", progname);
> + fprintf (stderr, " %s [-c] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]
", progname);
> fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]
", progname);
> fprintf (stderr, " %s -F [-v lvl]
", progname);
> fprintf (stderr, " %s -t
", progname);
> @@ -95,6 +96,7 @@ usage (char * progname)
> " -ll show multipath topology (maximum info)
"
> " -f flush a multipath device map
"
> " -F flush all multipath device maps
"
> + " -c check if a device should be a path in a multipath device
"
> " -q allow queue_if_no_path when multipathd is not running
"
> " -d dry run, do not create or update devmaps
"
> " -t dump internal hardware table
"
> @@ -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
",
> + 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
", conf->dev);
> + r = 0;
> + }
> + else
> + printf("%s is not a valid multipath device path
", 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:b:Brtq")) != EOF ) {
> + while ((arg = getopt(argc, argv, ":dchl::FfM:v:b:Brtq")) != EOF ) {
> switch(arg) {
> case 1: printf("optarg : %s
",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
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/wwids.c
> @@ -0,0 +1,139 @@
> +#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"
> +#include "wwids.h"
> +#include "defaults.h"
> +
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +static int
> +lookup_wwid(FILE *f, char *wwid) {
> + int c;
> + char buf[LINE_MAX];
> + int count;
> +
> + 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] == '')
> + goto next;
> + if (c != wwid[count++])
> + goto next;
> + }
> + if (wwid[count] == '')
> + return 1;
> +next:
> + if (fgets(buf, LINE_MAX, f) == NULL)
> + return 0;
> + }
> + return 0;
> +}
> +
> +static int
> +write_out_wwid(int fd, char *wwid) {
> + int ret;
> + off_t offset;
> + char buf[WWID_SIZE + 3];
> +
> + ret = snprintf(buf, WWID_SIZE + 3, "/%s/
", wwid);
> + if (ret >= (WWID_SIZE + 3) || ret < 0){
> + 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));
> + if (ftruncate(fd, offset))
> + condlog(0, "cannot truncate failed wwid write : %s",
> + strerror(errno));
> + return -1;
> + }
> + return 1;
> +}
> +
> +int
> +check_wwids_file(char *wwid, int write_wwid)
> +{
> + int fd, can_write, found, ret;
> + FILE *f;
> + fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
> + if (fd < 0)
> + return -1;
> +
> + f = fdopen(fd, "r");
> + 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;
> + }
> +
> + if (fflush(f) != 0) {
> + condlog(0, "cannot fflush wwids file stream : %s",
> + strerror(errno));
> + ret = -1;
> + goto out;
> + }
> +
> + 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;
> +}
> Index: multipath-tools-120518/libmultipath/wwids.h
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/wwids.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +#ifndef _WWIDS_H
> +#define _WWIDS_H
> +
> +#define WWIDS_FILE_HEADER
> +"# Multipath wwids, Version : 1.0
"
> +"# NOTE: This file is automatically maintained by multipath and multipathd.
"
> +"# You should not need to edit this file in normal circumstances.
"
> +"#
"
> +"# Valid WWIDs:
"
> +
> +int remember_wwid(char *wwid);
> +int check_wwids_file(char *wwid, int write_wwid);
> +
> +#endif /* _WWIDS_H */
> Index: multipath-tools-120518/libmultipath/discovery.c
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/discovery.c
> +++ multipath-tools-120518/libmultipath/discovery.c
> @@ -810,6 +810,8 @@ get_uid (struct path * pp)
>
> 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;
>



--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 08-20-2012, 12:15 PM
Hannes Reinecke
 
Default multipath: check if a device belongs to multipath

On 08/17/2012 10:13 PM, Christophe Varoqui wrote:
> On ven., 2012-07-27 at 15:55 -0500, Benjamin Marzinski wrote:
>> This patch adds a new multipath option "-c", which checks if a device
>> belongs to multipath. This can be done during the add uevent for the
>> device, before the multipath device has even been created. This allows
>> udev to be able to handle multipath path devices differently. To do
>> this multipath now keeps track of the wwids of all previously created
>> multipath devices in /etc/multipath/wwids. The file creating and
>> editting code from alias.[ch] has been split out into file.[ch]. When a
>> device is checked to see if it's a multipath path, it's wwid is
>> compared against the ones in the wwids file. Also, since the
>> uid_attribute may not have been added to the udev database entry for
>> the device if this is called in a udev rule, when using the "-c" option,
>> get_uid will now also check the process' envirionment variables for the
>> uid_attribute.
>>
> I'd like other distribution maintainers' comments on this one, as it
> impacts the multipath-tools intregration with udev.
>
> Hannes ? Did you face the same issue with SuSE ? Did you solve it
> differently ?
>
No; currently I didn't solve it at all, what with me being tied up
with customer issues :-(

But this is basically the approach I've discussed with Harald Hoyer
and Kay Sievers on how we should facilitate proper systemd integration.

The idea here is to have a udev rule calling 'multipath -c' via
PROGRAM, so that udev can detect if a device should've been handled
via multipath.
Which would allow any rules following that one to evaluate this
status and possibly skip the device.

So from that perspective the patch should be okay.

However, the one thing to note is this patch _again_ is using
hard-coded filenames under /etc, which really shouldn't happen.
We should be introducing a configuration file variable to set it.

> Ben, does this approach supersedes/extends the "complicated blacklisting
> scheme" you proposed earlier ?
>
I sincerely hope so ...

Cheers,

Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 08-20-2012, 05:50 PM
Christophe Varoqui
 
Default multipath: check if a device belongs to multipath

On lun., 2012-08-20 at 12:43 -0500, Benjamin Marzinski wrote:
> On Mon, Aug 20, 2012 at 02:15:21PM +0200, Hannes Reinecke wrote:
> > On 08/17/2012 10:13 PM, Christophe Varoqui wrote:
> > > On ven., 2012-07-27 at 15:55 -0500, Benjamin Marzinski wrote:
> > >> This patch adds a new multipath option "-c", which checks if a device
> > >> belongs to multipath. This can be done during the add uevent for the
> > >> device, before the multipath device has even been created. This allows
> > >> udev to be able to handle multipath path devices differently. To do
> > >> this multipath now keeps track of the wwids of all previously created
> > >> multipath devices in /etc/multipath/wwids. The file creating and
> > >> editting code from alias.[ch] has been split out into file.[ch]. When a
> > >> device is checked to see if it's a multipath path, it's wwid is
> > >> compared against the ones in the wwids file. Also, since the
> > >> uid_attribute may not have been added to the udev database entry for
> > >> the device if this is called in a udev rule, when using the "-c" option,
> > >> get_uid will now also check the process' envirionment variables for the
> > >> uid_attribute.
> > >>
> > > I'd like other distribution maintainers' comments on this one, as it
> > > impacts the multipath-tools intregration with udev.
> > >
> > > Hannes ? Did you face the same issue with SuSE ? Did you solve it
> > > differently ?
> > >
> > No; currently I didn't solve it at all, what with me being tied up
> > with customer issues :-(
> >
> > But this is basically the approach I've discussed with Harald Hoyer
> > and Kay Sievers on how we should facilitate proper systemd integration.
> >
> > The idea here is to have a udev rule calling 'multipath -c' via
> > PROGRAM, so that udev can detect if a device should've been handled
> > via multipath.
> > Which would allow any rules following that one to evaluate this
> > status and possibly skip the device.
> >
> > So from that perspective the patch should be okay.
> >
> > However, the one thing to note is this patch _again_ is using
> > hard-coded filenames under /etc, which really shouldn't happen.
> > We should be introducing a configuration file variable to set it.
>
> I'll post a patch that adds a configuration parameter soon.
>
> >
> > > Ben, does this approach supersedes/extends the "complicated blacklisting
> > > scheme" you proposed earlier ?
> > >
> > I sincerely hope so ...
>
> actually, this is patch is what I though were the non-objectional parts
> to that patch. I still think it's useful to be able to setup multipath
> so that instead of defaulting to use all the non-blacklisted LUNs, it
> just defaults to using the LUNs which actually have multiple paths. That
> patch didn't effect how the blacklisting code worked. Nor did it keep you
> from setting up multipath on single pathed LUNs. It just didn't default
> to setting up multipath devices on single pathed LUNs, if you had never
> set up a multipath device on that LUN before.
>
Ok fine. Do you prefer I merge the already submitted patch so that you
can submit an incremental patch for the cache file location or I wait
for your submitting a feature-complete patch ?

Thanks for the clarification.

cvaroqui,
OpenSVC

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 08-21-2012, 05:40 PM
Christophe Varoqui
 
Default multipath: check if a device belongs to multipath

On ven., 2012-07-27 at 15:55 -0500, Benjamin Marzinski wrote:
> This patch adds a new multipath option "-c", which checks if a device
> belongs to multipath. This can be done during the add uevent for the
> device, before the multipath device has even been created. This allows
> udev to be able to handle multipath path devices differently. To do
> this multipath now keeps track of the wwids of all previously created
> multipath devices in /etc/multipath/wwids. The file creating and
> editting code from alias.[ch] has been split out into file.[ch]. When a
> device is checked to see if it's a multipath path, it's wwid is
> compared against the ones in the wwids file. Also, since the
> uid_attribute may not have been added to the udev database entry for
> the device if this is called in a udev rule, when using the "-c" option,
> get_uid will now also check the process' envirionment variables for the
> uid_attribute.
>
Applied.

Thanks.

> Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
> libmultipath/Makefile | 2
> libmultipath/alias.c | 153 ---------------------------------------
> libmultipath/alias.h | 1
> libmultipath/configure.c | 3
> libmultipath/defaults.h | 1
> libmultipath/discovery.c | 2
> libmultipath/file.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++
> libmultipath/file.h | 11 ++
> libmultipath/wwids.c | 139 ++++++++++++++++++++++++++++++++++++
> libmultipath/wwids.h | 18 ++++
> multipath/main.c | 37 ++++++++-
> 11 files changed, 389 insertions(+), 158 deletions(-)
>
> Index: multipath-tools-120518/libmultipath/alias.c
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/alias.c
> +++ multipath-tools-120518/libmultipath/alias.c
> @@ -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"
>
>
> /*
> @@ -36,150 +33,6 @@
> * 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 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 = '';
> - 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 */
> - if (ftruncate(fd, 0))
> - condlog(0, "Cannot truncate the header : %s",
> - strerror(errno));
> - goto fail;
> - }
> - fsync(fd);
> - condlog(3, "Initialized new bindings file [%s]", file);
> - }
> -
> - return fd;
> -
> -fail:
> - close(fd);
> - return -1;
> -}
>
> static int
> format_devname(char *name, int id, int len, char *prefix)
> @@ -370,7 +223,7 @@ get_user_friendly_alias(char *wwid, char
> return NULL;
> }
>
> - fd = open_bindings_file(file, &can_write);
> + fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
> if (fd < 0)
> return NULL;
>
> @@ -414,7 +267,7 @@ get_user_friendly_wwid(char *alias, char
> return NULL;
> }
>
> - fd = open_bindings_file(file, &unused);
> + fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
> if (fd < 0)
> return NULL;
>
> Index: multipath-tools-120518/libmultipath/alias.h
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/alias.h
> +++ multipath-tools-120518/libmultipath/alias.h
> @@ -1,4 +1,3 @@
> -#define BINDINGS_FILE_TIMEOUT 30
> #define BINDINGS_FILE_HEADER
> "# Multipath bindings, Version : 1.0
"
> "# NOTE: this file is automatically maintained by the multipath program.
"
> Index: multipath-tools-120518/libmultipath/configure.c
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/configure.c
> +++ multipath-tools-120518/libmultipath/configure.c
> @@ -37,6 +37,7 @@
> #include "prio.h"
> #include "util.h"
> #include "uxsock.h"
> +#include "wwids.h"
>
> extern int
> setup_map (struct multipath * mpp, char * params, int params_size)
> @@ -407,6 +408,8 @@ domap (struct multipath * mpp, char * pa
> * 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);
> Index: multipath-tools-120518/libmultipath/defaults.h
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/defaults.h
> +++ multipath-tools-120518/libmultipath/defaults.h
> @@ -24,5 +24,6 @@
> #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);
> Index: multipath-tools-120518/libmultipath/file.c
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/file.c
> @@ -0,0 +1,180 @@
> +/*
> + * 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 = '';
> + 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 */
> + if (ftruncate(fd, 0))
> + condlog(0, "Cannot truncate header : %s",
> + strerror(errno));
> + goto fail;
> + }
> + fsync(fd);
> + condlog(3, "Initialized new file [%s]", file);
> + }
> +
> + return fd;
> +
> +fail:
> + close(fd);
> + return -1;
> +}
> Index: multipath-tools-120518/libmultipath/file.h
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/file.h
> @@ -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 */
> 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:
");
> - fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]
", progname);
> + fprintf (stderr, " %s [-c] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]
", progname);
> fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]
", progname);
> fprintf (stderr, " %s -F [-v lvl]
", progname);
> fprintf (stderr, " %s -t
", progname);
> @@ -95,6 +96,7 @@ usage (char * progname)
> " -ll show multipath topology (maximum info)
"
> " -f flush a multipath device map
"
> " -F flush all multipath device maps
"
> + " -c check if a device should be a path in a multipath device
"
> " -q allow queue_if_no_path when multipathd is not running
"
> " -d dry run, do not create or update devmaps
"
> " -t dump internal hardware table
"
> @@ -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
",
> + 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
", conf->dev);
> + r = 0;
> + }
> + else
> + printf("%s is not a valid multipath device path
", 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:b:Brtq")) != EOF ) {
> + while ((arg = getopt(argc, argv, ":dchl::FfM:v:b:Brtq")) != EOF ) {
> switch(arg) {
> case 1: printf("optarg : %s
",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
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/wwids.c
> @@ -0,0 +1,139 @@
> +#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"
> +#include "wwids.h"
> +#include "defaults.h"
> +
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +static int
> +lookup_wwid(FILE *f, char *wwid) {
> + int c;
> + char buf[LINE_MAX];
> + int count;
> +
> + 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] == '')
> + goto next;
> + if (c != wwid[count++])
> + goto next;
> + }
> + if (wwid[count] == '')
> + return 1;
> +next:
> + if (fgets(buf, LINE_MAX, f) == NULL)
> + return 0;
> + }
> + return 0;
> +}
> +
> +static int
> +write_out_wwid(int fd, char *wwid) {
> + int ret;
> + off_t offset;
> + char buf[WWID_SIZE + 3];
> +
> + ret = snprintf(buf, WWID_SIZE + 3, "/%s/
", wwid);
> + if (ret >= (WWID_SIZE + 3) || ret < 0){
> + 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));
> + if (ftruncate(fd, offset))
> + condlog(0, "cannot truncate failed wwid write : %s",
> + strerror(errno));
> + return -1;
> + }
> + return 1;
> +}
> +
> +int
> +check_wwids_file(char *wwid, int write_wwid)
> +{
> + int fd, can_write, found, ret;
> + FILE *f;
> + fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
> + if (fd < 0)
> + return -1;
> +
> + f = fdopen(fd, "r");
> + 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;
> + }
> +
> + if (fflush(f) != 0) {
> + condlog(0, "cannot fflush wwids file stream : %s",
> + strerror(errno));
> + ret = -1;
> + goto out;
> + }
> +
> + 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;
> +}
> Index: multipath-tools-120518/libmultipath/wwids.h
> ================================================== =================
> --- /dev/null
> +++ multipath-tools-120518/libmultipath/wwids.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +#ifndef _WWIDS_H
> +#define _WWIDS_H
> +
> +#define WWIDS_FILE_HEADER
> +"# Multipath wwids, Version : 1.0
"
> +"# NOTE: This file is automatically maintained by multipath and multipathd.
"
> +"# You should not need to edit this file in normal circumstances.
"
> +"#
"
> +"# Valid WWIDs:
"
> +
> +int remember_wwid(char *wwid);
> +int check_wwids_file(char *wwid, int write_wwid);
> +
> +#endif /* _WWIDS_H */
> Index: multipath-tools-120518/libmultipath/discovery.c
> ================================================== =================
> --- multipath-tools-120518.orig/libmultipath/discovery.c
> +++ multipath-tools-120518/libmultipath/discovery.c
> @@ -810,6 +810,8 @@ get_uid (struct path * pp)
>
> 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;
>



--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 

Thread Tools




All times are GMT. The time now is 09:38 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright ©2007 - 2008, www.linux-archive.org