mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
[PATCH] more udev-016/extras/multipath
incremental to udev-016/extras/multipath-0.0.16.3, * add a GROUP_BY_SERIAL flag. This should be useful for controlers that activate their spare paths on simple IO submition with a penalty. The StorageWorks HW defaults to this mode, even if the MULTIBUS mode is OK. * remove unused sg_err.c * big restructuring : split devinfo.c from main.c. Export : * void basename (char *, char *); * int get_serial (int, char *); * int get_lun_strings (char *, char *, char *, char *); * int get_evpd_wwid(char *, char *); * long get_disk_size (char *); Now we see clearly what is expected from an external package like scsi_id. * stop passing struct env as param
This commit is contained in:
parent
cbb576b91d
commit
09b7985cf6
@ -1,4 +1,16 @@
|
||||
2004-02-04 multipath-016
|
||||
* add a GROUP_BY_SERIAL flag. This should be useful for
|
||||
controlers that activate they spare paths on simple IO
|
||||
submition with a penalty. The StorageWorks HW defaults to
|
||||
this mode, even if the MULTIBUS mode is OK.
|
||||
* remove unused sg_err.c
|
||||
* big restructuring : split devinfo.c from main.c. Export :
|
||||
* void basename (char *, char *);
|
||||
* int get_serial (int, char *);
|
||||
* int get_lun_strings (char *, char *, char *, char *);
|
||||
* int get_evpd_wwid(char *, char *);
|
||||
* long get_disk_size (char *);
|
||||
* stop passing struct env as param
|
||||
* add devmap_name proggy for udev to name devmaps as per their
|
||||
internal DM name and not only by their sysfs enum name (dm-*)
|
||||
The corresponding udev.rules line is :
|
||||
|
@ -18,7 +18,7 @@ CFLAGS = -pipe -g -O2 -Wall -Wunused -Wstrict-prototypes -nostdinc \
|
||||
-I$(klibcdir)/klibc/include -I$(klibcdir)/klibc/include/bits32 \
|
||||
-I$(GCCINCDIR) -I$(KERNEL_DIR)/include -I$(sysfsdir) -I.
|
||||
|
||||
OBJS = main.o
|
||||
OBJS = devinfo.o main.o
|
||||
CRT0 = ../../klibc/klibc/crt0.o
|
||||
LIB = ../../klibc/klibc/libc.a
|
||||
LIBGCC := $(shell $(CC) -print-libgcc-file-name )
|
||||
@ -67,4 +67,4 @@ uninstall:
|
||||
rm $(bindir)/devmap_name
|
||||
|
||||
# Code dependencies
|
||||
main.o: main.c main.h sg_include.h
|
||||
main.o: main.c main.h sg_include.h devinfo.h
|
||||
|
204
extras/multipath/devinfo.c
Normal file
204
extras/multipath/devinfo.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <libsysfs.h>
|
||||
#include "devinfo.h"
|
||||
#include "sg_include.h"
|
||||
|
||||
#define FILE_NAME_SIZE 255
|
||||
|
||||
void
|
||||
basename(char * str1, char * str2)
|
||||
{
|
||||
char *p = str1 + (strlen(str1) - 1);
|
||||
|
||||
while (*--p != '/')
|
||||
continue;
|
||||
strcpy(str2, ++p);
|
||||
}
|
||||
|
||||
static int
|
||||
do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
|
||||
void *resp, int mx_resp_len, int noisy)
|
||||
{
|
||||
unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
|
||||
{ INQUIRY_CMD, 0, 0, 0, 0, 0 };
|
||||
unsigned char sense_b[SENSE_BUFF_LEN];
|
||||
struct sg_io_hdr io_hdr;
|
||||
|
||||
if (cmddt)
|
||||
inqCmdBlk[1] |= 2;
|
||||
if (evpd)
|
||||
inqCmdBlk[1] |= 1;
|
||||
inqCmdBlk[2] = (unsigned char) pg_op;
|
||||
inqCmdBlk[4] = (unsigned char) mx_resp_len;
|
||||
memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = sizeof (inqCmdBlk);
|
||||
io_hdr.mx_sb_len = sizeof (sense_b);
|
||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
io_hdr.dxfer_len = mx_resp_len;
|
||||
io_hdr.dxferp = resp;
|
||||
io_hdr.cmdp = inqCmdBlk;
|
||||
io_hdr.sbp = sense_b;
|
||||
io_hdr.timeout = DEF_TIMEOUT;
|
||||
|
||||
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
|
||||
perror("SG_IO (inquiry) error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* treat SG_ERR here to get rid of sg_err.[ch] */
|
||||
io_hdr.status &= 0x7e;
|
||||
if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
|
||||
(0 == io_hdr.driver_status))
|
||||
return 0;
|
||||
if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
|
||||
(SCSI_COMMAND_TERMINATED == io_hdr.status) ||
|
||||
(SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
|
||||
if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
|
||||
int sense_key;
|
||||
unsigned char * sense_buffer = io_hdr.sbp;
|
||||
if (sense_buffer[0] & 0x2)
|
||||
sense_key = sense_buffer[1] & 0xf;
|
||||
else
|
||||
sense_key = sense_buffer[2] & 0xf;
|
||||
if(RECOVERED_ERROR == sense_key)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
get_serial (char * str, char * devname)
|
||||
{
|
||||
int fd;
|
||||
int len;
|
||||
char buff[MX_ALLOC_LEN + 1];
|
||||
|
||||
if ((fd = open(devname, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
|
||||
if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
|
||||
len = buff[3];
|
||||
if (len > 0) {
|
||||
memcpy(str, buff + 4, len);
|
||||
buff[len] = '\0';
|
||||
}
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
get_lun_strings(char * vendor_id, char * product_id, char * rev, char * devname)
|
||||
{
|
||||
int fd;
|
||||
char buff[36];
|
||||
char attr_path[FILE_NAME_SIZE];
|
||||
char sysfs_path[FILE_NAME_SIZE];
|
||||
char basedev[FILE_NAME_SIZE];
|
||||
|
||||
if (0 == sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
|
||||
/* sysfs style */
|
||||
basename(devname, basedev);
|
||||
|
||||
sprintf(attr_path, "%s/block/%s/device/vendor",
|
||||
sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path,
|
||||
vendor_id, 8)) return 0;
|
||||
|
||||
sprintf(attr_path, "%s/block/%s/device/model",
|
||||
sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path,
|
||||
product_id, 16)) return 0;
|
||||
|
||||
sprintf(attr_path, "%s/block/%s/device/rev",
|
||||
sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path,
|
||||
rev, 4)) return 0;
|
||||
} else {
|
||||
/* ioctl style */
|
||||
if ((fd = open(devname, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
if (0 != do_inq(fd, 0, 0, 0, buff, 36, 1))
|
||||
return 0;
|
||||
memcpy(vendor_id, &buff[8], 8);
|
||||
memcpy(product_id, &buff[16], 16);
|
||||
memcpy(rev, &buff[32], 4);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sprint_wwid(char * buff, const char * str)
|
||||
{
|
||||
int i;
|
||||
const char *p;
|
||||
char *cursor;
|
||||
unsigned char c;
|
||||
|
||||
p = str;
|
||||
cursor = buff;
|
||||
for (i = 0; i <= WWID_SIZE / 2 - 1; i++) {
|
||||
c = *p++;
|
||||
sprintf(cursor, "%.2x", (int) (unsigned char) c);
|
||||
cursor += 2;
|
||||
}
|
||||
buff[WWID_SIZE - 1] = '\0';
|
||||
}
|
||||
|
||||
/* get EVPD page 0x83 off 8 */
|
||||
/* tested ok with StorageWorks */
|
||||
int
|
||||
get_evpd_wwid(char * devname, char * wwid)
|
||||
{
|
||||
int fd;
|
||||
char buff[64];
|
||||
|
||||
if ((fd = open(devname, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
|
||||
if (0 == do_inq(fd, 0, 1, 0x83, buff, sizeof (buff), 1)) {
|
||||
sprint_wwid(wwid, &buff[8]);
|
||||
close(fd);
|
||||
return 1; /* success */
|
||||
}
|
||||
close(fd);
|
||||
return 0; /* not good */
|
||||
}
|
||||
|
||||
long
|
||||
get_disk_size (char * devname) {
|
||||
long size;
|
||||
int fd;
|
||||
char attr_path[FILE_NAME_SIZE];
|
||||
char sysfs_path[FILE_NAME_SIZE];
|
||||
char buff[FILE_NAME_SIZE];
|
||||
char basedev[FILE_NAME_SIZE];
|
||||
|
||||
if (0 == sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
|
||||
basename(devname, basedev);
|
||||
sprintf(attr_path, "%s/block/%s/size",
|
||||
sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path, buff,
|
||||
FILE_NAME_SIZE * sizeof(char)))
|
||||
return -1;
|
||||
size = atoi(buff);
|
||||
return size;
|
||||
} else {
|
||||
if ((fd = open(devname, O_RDONLY)) < 0)
|
||||
return -1;
|
||||
if(!ioctl(fd, BLKGETSIZE, &size))
|
||||
return size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
19
extras/multipath/devinfo.h
Normal file
19
extras/multipath/devinfo.h
Normal file
@ -0,0 +1,19 @@
|
||||
#define INQUIRY_CMDLEN 6
|
||||
#define INQUIRY_CMD 0x12
|
||||
#define SENSE_BUFF_LEN 32
|
||||
#define DEF_TIMEOUT 60000
|
||||
#define RECOVERED_ERROR 0x01
|
||||
#define MX_ALLOC_LEN 255
|
||||
#define WWID_SIZE 33
|
||||
#define BLKGETSIZE _IO(0x12,96)
|
||||
|
||||
/* exerpt from "sg_err.h" */
|
||||
#define SCSI_CHECK_CONDITION 0x2
|
||||
#define SCSI_COMMAND_TERMINATED 0x22
|
||||
#define SG_ERR_DRIVER_SENSE 0x08
|
||||
|
||||
void basename (char *, char *);
|
||||
int get_serial (char *, char *);
|
||||
int get_lun_strings (char *, char *, char *, char *);
|
||||
int get_evpd_wwid(char *, char *);
|
||||
long get_disk_size (char *);
|
@ -28,150 +28,7 @@
|
||||
#include <libsysfs.h>
|
||||
#include "libdevmapper/libdevmapper.h"
|
||||
#include "main.h"
|
||||
|
||||
static int
|
||||
do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
|
||||
void *resp, int mx_resp_len, int noisy)
|
||||
{
|
||||
unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
|
||||
{ INQUIRY_CMD, 0, 0, 0, 0, 0 };
|
||||
unsigned char sense_b[SENSE_BUFF_LEN];
|
||||
struct sg_io_hdr io_hdr;
|
||||
|
||||
if (cmddt)
|
||||
inqCmdBlk[1] |= 2;
|
||||
if (evpd)
|
||||
inqCmdBlk[1] |= 1;
|
||||
inqCmdBlk[2] = (unsigned char) pg_op;
|
||||
inqCmdBlk[4] = (unsigned char) mx_resp_len;
|
||||
memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = sizeof (inqCmdBlk);
|
||||
io_hdr.mx_sb_len = sizeof (sense_b);
|
||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
io_hdr.dxfer_len = mx_resp_len;
|
||||
io_hdr.dxferp = resp;
|
||||
io_hdr.cmdp = inqCmdBlk;
|
||||
io_hdr.sbp = sense_b;
|
||||
io_hdr.timeout = DEF_TIMEOUT;
|
||||
|
||||
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
|
||||
perror("SG_IO (inquiry) error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* treat SG_ERR here to get rid of sg_err.[ch] */
|
||||
io_hdr.status &= 0x7e;
|
||||
if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
|
||||
(0 == io_hdr.driver_status))
|
||||
return 0;
|
||||
if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
|
||||
(SCSI_COMMAND_TERMINATED == io_hdr.status) ||
|
||||
(SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
|
||||
if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
|
||||
int sense_key;
|
||||
unsigned char * sense_buffer = io_hdr.sbp;
|
||||
if (sense_buffer[0] & 0x2)
|
||||
sense_key = sense_buffer[1] & 0xf;
|
||||
else
|
||||
sense_key = sense_buffer[2] & 0xf;
|
||||
if(RECOVERED_ERROR == sense_key)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
sprint_wwid(char * buff, const char * str)
|
||||
{
|
||||
int i;
|
||||
const char *p;
|
||||
char *cursor;
|
||||
unsigned char c;
|
||||
|
||||
p = str;
|
||||
cursor = buff;
|
||||
for (i = 0; i <= WWID_SIZE / 2 - 1; i++) {
|
||||
c = *p++;
|
||||
sprintf(cursor, "%.2x", (int) (unsigned char) c);
|
||||
cursor += 2;
|
||||
}
|
||||
buff[WWID_SIZE - 1] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
basename(char * str1, char * str2)
|
||||
{
|
||||
char *p = str1 + (strlen(str1) - 1);
|
||||
|
||||
while (*--p != '/')
|
||||
continue;
|
||||
strcpy(str2, ++p);
|
||||
}
|
||||
|
||||
static int
|
||||
get_lun_strings(struct env * conf, struct path * mypath)
|
||||
{
|
||||
int fd;
|
||||
char buff[36];
|
||||
char attr_path[FILE_NAME_SIZE];
|
||||
char basedev[FILE_NAME_SIZE];
|
||||
|
||||
if(conf->with_sysfs) {
|
||||
/* sysfs style */
|
||||
basename(mypath->sg_dev, basedev);
|
||||
|
||||
sprintf(attr_path, "%s/block/%s/device/vendor",
|
||||
conf->sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path,
|
||||
mypath->vendor_id, 8)) return 0;
|
||||
|
||||
sprintf(attr_path, "%s/block/%s/device/model",
|
||||
conf->sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path,
|
||||
mypath->product_id, 16)) return 0;
|
||||
|
||||
sprintf(attr_path, "%s/block/%s/device/rev",
|
||||
conf->sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path,
|
||||
mypath->rev, 4)) return 0;
|
||||
} else {
|
||||
/* ioctl style */
|
||||
if ((fd = open(mypath->sg_dev, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
if (0 != do_inq(fd, 0, 0, 0, buff, 36, 1))
|
||||
return 0;
|
||||
memcpy(mypath->vendor_id, &buff[8], 8);
|
||||
memcpy(mypath->product_id, &buff[16], 16);
|
||||
memcpy(mypath->rev, &buff[32], 4);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hardware vendor specifics : add support for new models below */
|
||||
|
||||
/* this one get EVPD page 0x83 off 8 */
|
||||
/* tested ok with StorageWorks */
|
||||
static int
|
||||
get_evpd_wwid(struct path * mypath)
|
||||
{
|
||||
int fd;
|
||||
char buff[64];
|
||||
|
||||
if ((fd = open(mypath->sg_dev, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
|
||||
if (0 == do_inq(fd, 0, 1, 0x83, buff, sizeof (buff), 1)) {
|
||||
sprint_wwid(mypath->wwid, &buff[8]);
|
||||
close(fd);
|
||||
return 1; /* success */
|
||||
}
|
||||
close(fd);
|
||||
return 0; /* not good */
|
||||
}
|
||||
#include "devinfo.h"
|
||||
|
||||
/* White list switch */
|
||||
static int
|
||||
@ -182,13 +39,13 @@ get_unique_id(struct path * mypath)
|
||||
char * vendor;
|
||||
char * product;
|
||||
int iopolicy;
|
||||
int (*getuid) (struct path *);
|
||||
int (*getuid) (char *, char *);
|
||||
} wlist[] = {
|
||||
{"COMPAQ ", "HSV110 (C)COMPAQ", MULTIBUS, &get_evpd_wwid},
|
||||
{"COMPAQ ", "MSA1000 ", MULTIBUS, &get_evpd_wwid},
|
||||
{"COMPAQ ", "MSA1000 VOLUME ", MULTIBUS, &get_evpd_wwid},
|
||||
{"DEC ", "HSG80 ", MULTIBUS, &get_evpd_wwid},
|
||||
{"HP ", "HSV100 ", MULTIBUS, &get_evpd_wwid},
|
||||
{"COMPAQ ", "HSV110 (C)COMPAQ", GROUP_BY_SERIAL, &get_evpd_wwid},
|
||||
{"COMPAQ ", "MSA1000 ", GROUP_BY_SERIAL, &get_evpd_wwid},
|
||||
{"COMPAQ ", "MSA1000 VOLUME ", GROUP_BY_SERIAL, &get_evpd_wwid},
|
||||
{"DEC ", "HSG80 ", GROUP_BY_SERIAL, &get_evpd_wwid},
|
||||
{"HP ", "HSV100 ", GROUP_BY_SERIAL, &get_evpd_wwid},
|
||||
{"HP ", "A6189A ", MULTIBUS, &get_evpd_wwid},
|
||||
{"HP ", "OPEN- ", MULTIBUS, &get_evpd_wwid},
|
||||
{"DDN ", "SAN DataDirector", MULTIBUS, &get_evpd_wwid},
|
||||
@ -208,7 +65,7 @@ get_unique_id(struct path * mypath)
|
||||
if (strncmp(mypath->vendor_id, wlist[i].vendor, 8) == 0 &&
|
||||
strncmp(mypath->product_id, wlist[i].product, 16) == 0) {
|
||||
mypath->iopolicy = wlist[i].iopolicy;
|
||||
if (!wlist[i].getuid(mypath))
|
||||
if (!wlist[i].getuid(mypath->sg_dev, mypath->wwid))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -269,7 +126,11 @@ get_all_paths_sysfs(struct env * conf, struct path * all_paths)
|
||||
basename(conf->hotplugdev, buff);
|
||||
sprintf(curpath.sg_dev, "/dev/%s", buff);
|
||||
|
||||
get_lun_strings(conf, &curpath);
|
||||
get_lun_strings(curpath.vendor_id,
|
||||
curpath.product_id,
|
||||
curpath.rev,
|
||||
curpath.sg_dev);
|
||||
get_serial(curpath.serial, curpath.sg_dev);
|
||||
if (!get_unique_id(&curpath))
|
||||
return 0;
|
||||
strcpy(refwwid, curpath.wwid);
|
||||
@ -301,7 +162,11 @@ get_all_paths_sysfs(struct env * conf, struct path * all_paths)
|
||||
basename(devp->path, buff);
|
||||
sprintf(curpath.sg_dev, "/dev/%s", buff);
|
||||
|
||||
get_lun_strings(conf, &curpath);
|
||||
get_lun_strings(curpath.vendor_id,
|
||||
curpath.product_id,
|
||||
curpath.rev,
|
||||
curpath.sg_dev);
|
||||
get_serial(curpath.serial, curpath.sg_dev);
|
||||
if(!get_unique_id(&curpath)) {
|
||||
memset(&curpath, 0, sizeof(path));
|
||||
continue;
|
||||
@ -349,7 +214,11 @@ get_all_paths_nosysfs(struct env * conf, struct path * all_paths,
|
||||
strncat(file_name, buff, FILE_NAME_SIZE);
|
||||
strcpy(all_paths[k].sg_dev, file_name);
|
||||
|
||||
get_lun_strings(conf, &all_paths[k]);
|
||||
get_lun_strings(all_paths[k].vendor_id,
|
||||
all_paths[k].product_id,
|
||||
all_paths[k].rev,
|
||||
all_paths[k].sg_dev);
|
||||
get_serial(all_paths[k].serial, all_paths[k].sg_dev);
|
||||
if (!get_unique_id(&all_paths[k]))
|
||||
continue;
|
||||
|
||||
@ -484,32 +353,6 @@ print_all_mp(struct path * all_paths, struct multipath * mp, int nmp)
|
||||
}
|
||||
}
|
||||
|
||||
static long
|
||||
get_disk_size (struct env * conf, char * dev) {
|
||||
long size;
|
||||
int fd;
|
||||
char attr_path[FILE_NAME_SIZE];
|
||||
char buff[FILE_NAME_SIZE];
|
||||
char basedev[FILE_NAME_SIZE];
|
||||
|
||||
if(conf->with_sysfs) {
|
||||
basename(dev, basedev);
|
||||
sprintf(attr_path, "%s/block/%s/size",
|
||||
conf->sysfs_path, basedev);
|
||||
if (0 > sysfs_read_attribute_value(attr_path, buff,
|
||||
FILE_NAME_SIZE * sizeof(char)))
|
||||
return -1;
|
||||
size = atoi(buff);
|
||||
return size;
|
||||
} else {
|
||||
if ((fd = open(dev, O_RDONLY)) < 0)
|
||||
return -1;
|
||||
if(!ioctl(fd, BLKGETSIZE, &size))
|
||||
return size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
coalesce_paths(struct env * conf, struct multipath * mp,
|
||||
struct path * all_paths)
|
||||
@ -528,7 +371,7 @@ coalesce_paths(struct env * conf, struct multipath * mp,
|
||||
if (memcmp(empty_buff, all_paths[k].wwid, WWID_SIZE) == 0)
|
||||
continue;
|
||||
|
||||
/* 2. mp with this uid already instanciated */
|
||||
/* 2. if mp with this uid already instanciated */
|
||||
for (i = 0; i <= nmp; i++) {
|
||||
if (0 == strcmp(mp[i].wwid, all_paths[k].wwid))
|
||||
already_done = 1;
|
||||
@ -545,7 +388,7 @@ coalesce_paths(struct env * conf, struct multipath * mp,
|
||||
PINDEX(nmp,np) = k;
|
||||
|
||||
if (mp[nmp].size == 0)
|
||||
mp[nmp].size = get_disk_size(conf, all_paths[k].dev);
|
||||
mp[nmp].size = get_disk_size(all_paths[k].dev);
|
||||
|
||||
for (i = k + 1; i < conf->max_devs; i++) {
|
||||
if (0 == strcmp(all_paths[k].wwid, all_paths[i].wwid)) {
|
||||
@ -558,6 +401,49 @@ coalesce_paths(struct env * conf, struct multipath * mp,
|
||||
return nmp;
|
||||
}
|
||||
|
||||
static void
|
||||
group_by_serial(struct multipath * mp, struct path * all_paths, char * str) {
|
||||
int path_count, pg_count = 0;
|
||||
int i, k;
|
||||
int * bitmap;
|
||||
char path_buff[FILE_NAME_SIZE];
|
||||
char pg_buff[FILE_NAME_SIZE];
|
||||
char * path_buff_p = &path_buff[0];
|
||||
char * pg_buff_p = &pg_buff[0];
|
||||
|
||||
/* init the bitmap */
|
||||
bitmap = malloc((mp->npaths + 1) * sizeof(int));
|
||||
memset(bitmap, 0, (mp->npaths + 1) * sizeof(int));
|
||||
|
||||
for (i = 0; i <= mp->npaths; i++) {
|
||||
if (bitmap[i])
|
||||
continue;
|
||||
|
||||
/* here, we really got a new pg */
|
||||
pg_count++;
|
||||
path_count = 1;
|
||||
memset(&path_buff, 0, FILE_NAME_SIZE * sizeof(char));
|
||||
path_buff_p = &path_buff[0];
|
||||
|
||||
path_buff_p += sprintf(path_buff_p, " %s", all_paths[mp->pindex[i]].dev);
|
||||
bitmap[i] = 1;
|
||||
|
||||
for (k = i + 1; k <= mp->npaths; k++) {
|
||||
if (bitmap[k])
|
||||
continue;
|
||||
if (0 == strcmp(all_paths[mp->pindex[i]].serial,
|
||||
all_paths[mp->pindex[k]].serial)) {
|
||||
path_buff_p += sprintf(path_buff_p, " %s", all_paths[mp->pindex[k]].dev);
|
||||
bitmap[k] = 1;
|
||||
path_count++;
|
||||
}
|
||||
}
|
||||
pg_buff_p += sprintf(pg_buff_p, " 1 round-robin %i 0%s",
|
||||
path_count, path_buff);
|
||||
}
|
||||
sprintf(str, " %i%s", pg_count, pg_buff);
|
||||
}
|
||||
|
||||
static int
|
||||
dm_simplecmd(int task, const char *name) {
|
||||
int r = 0;
|
||||
@ -651,6 +537,11 @@ setup_map(struct env * conf, struct path * all_paths,
|
||||
}
|
||||
}
|
||||
|
||||
if (all_paths[PINDEX(index,0)].iopolicy == GROUP_BY_SERIAL &&
|
||||
!conf->forcedfailover ) {
|
||||
group_by_serial(&mp[index], all_paths, params_p);
|
||||
}
|
||||
|
||||
if (mp[index].size < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -28,29 +28,25 @@
|
||||
#define SG_ERR_DRIVER_SENSE 0x08
|
||||
|
||||
/* exerpt from "scsi.h" */
|
||||
#define RECOVERED_ERROR 0x01
|
||||
#define SCSI_IOCTL_GET_IDLUN 0x5382
|
||||
#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
|
||||
|
||||
/* global defs */
|
||||
#define WWID_SIZE 33
|
||||
#define SERIAL_SIZE 14
|
||||
#define MAX_DEVS 128
|
||||
#define MAX_MP MAX_DEVS / 2
|
||||
#define MAX_MP_PATHS MAX_DEVS / 4
|
||||
#define FILE_NAME_SIZE 256
|
||||
#define INQUIRY_CMDLEN 6
|
||||
#define INQUIRY_CMD 0x12
|
||||
#define SENSE_BUFF_LEN 32
|
||||
#define DEF_TIMEOUT 60000
|
||||
#define EBUFF_SZ 256
|
||||
#define TUR_CMD_LEN 6
|
||||
#define MX_ALLOC_LEN 255
|
||||
#define BLKGETSIZE _IO(0x12,96)
|
||||
#define DM_TARGET "multipath"
|
||||
|
||||
/* Storage controlers cpabilities */
|
||||
#define FAILOVER 0
|
||||
#define MULTIBUS 1
|
||||
#define GROUP_BY_SERIAL 2
|
||||
|
||||
#define PINDEX(x,y) mp[(x)].pindex[(y)]
|
||||
|
||||
@ -88,6 +84,7 @@ struct path {
|
||||
char vendor_id[8];
|
||||
char product_id[16];
|
||||
char rev[4];
|
||||
char serial[SERIAL_SIZE];
|
||||
int iopolicy;
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user