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(int fd, struct path * mypath)
+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 (0 == do_inq(fd, 0, 0, 0, buff, 36, 1)) {
+ 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;
}
-/*
-static int
-get_serial (int fd, char * str)
-{
- char buff[MX_ALLOC_LEN + 1];
- int len;
-
- 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';
- }
- 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(int fd, char *str)
+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(str, &buff[8]);
- return 1;
+ sprint_wwid(mypath->wwid, &buff[8]);
+ close(fd);
+ return 1; /* success */
}
- return 0;
+ close(fd);
+ return 0; /* not good */
}
/* White list switch */
static int
-get_unique_id(int fd, struct path * mypath)
+get_unique_id(struct path * mypath)
{
int i;
static struct {
char * vendor;
char * product;
int iopolicy;
- int (*getuid) (int fd, char * wwid);
+ int (*getuid) (struct path *);
} wlist[] = {
{"COMPAQ ", "HSV110 (C)COMPAQ", MULTIBUS, &get_evpd_wwid},
{"COMPAQ ", "MSA1000 ", MULTIBUS, &get_evpd_wwid},
for (i = 0; wlist[i].vendor; i++) {
if (strncmp(mypath->vendor_id, wlist[i].vendor, 8) == 0 &&
strncmp(mypath->product_id, wlist[i].product, 16) == 0) {
- wlist[i].getuid(fd, mypath->wwid);
mypath->iopolicy = wlist[i].iopolicy;
- return 0;
+ if (!wlist[i].getuid(mypath))
+ return 0;
}
}
return 1;
}
-static void
-basename(char * str1, char * str2)
-{
- char *p = str1 + (strlen(str1) - 1);
-
- while (*--p != '/')
- continue;
- strcpy(str2, ++p);
-}
-
static int
blacklist (char * dev) {
int i;
get_all_paths_sysfs(struct env * conf, struct path * all_paths)
{
int k=0;
- int sg_fd;
struct sysfs_directory * sdir;
struct sysfs_directory * devp;
struct sysfs_link * linkp;
sprintf(buff, "%s%s/block",
conf->sysfs_path, conf->hotplugdev);
memset(conf->hotplugdev, 0, FILE_NAME_SIZE);
- readlink(buff, conf->hotplugdev, FILE_NAME_SIZE);
+
+ /* if called from hotplug but with no block, leave */
+ if (0 > readlink(buff, conf->hotplugdev, FILE_NAME_SIZE))
+ return 0;
+
basename(conf->hotplugdev, buff);
sprintf(curpath.sg_dev, "/dev/%s", buff);
- if ((sg_fd = open(curpath.sg_dev, O_RDONLY)) < 0)
- exit(1);
-
- get_lun_strings(sg_fd, &curpath);
- get_unique_id(sg_fd, &curpath);
+ get_lun_strings(conf, &curpath);
+ if (!get_unique_id(&curpath))
+ return 0;
strcpy(refwwid, curpath.wwid);
memset(&curpath, 0, sizeof(path));
}
basename(devp->path, buff);
sprintf(curpath.sg_dev, "/dev/%s", buff);
- if ((sg_fd = open(curpath.sg_dev, O_RDONLY)) < 0) {
- if (conf->verbose)
- fprintf(stderr, "can't open %s\n",
- curpath.sg_dev);
+ get_lun_strings(conf, &curpath);
+ if(!get_unique_id(&curpath)) {
+ memset(&curpath, 0, sizeof(path));
continue;
}
- get_lun_strings(sg_fd, &curpath);
- get_unique_id(sg_fd, &curpath);
-
if (memcmp(empty_buff, refwwid, WWID_SIZE) != 0 &&
strncmp(curpath.wwid, refwwid, WWID_SIZE) != 0) {
memset(&curpath, 0, sizeof(path));
/* done with curpath, zero for reuse */
memset(&curpath, 0, sizeof(path));
- close(sg_fd);
basename(linkp->target, buff);
sscanf(buff, "%i:%i:%i:%i",
&all_paths[k].sg_id.host_no,
get_all_paths_nosysfs(struct env * conf, struct path * all_paths,
struct scsi_dev * all_scsi_ids)
{
- int k, i, sg_fd;
+ int k, i, fd;
char buff[FILE_NAME_SIZE];
char file_name[FILE_NAME_SIZE];
sprintf(buff, "%d", k);
strncat(file_name, buff, FILE_NAME_SIZE);
strcpy(all_paths[k].sg_dev, file_name);
- if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
- if (conf->verbose)
- fprintf(stderr, "can't open %s. mknod ?",
- file_name);
+
+ get_lun_strings(conf, &all_paths[k]);
+ if (!get_unique_id(&all_paths[k]))
continue;
- }
- get_lun_strings(sg_fd, &all_paths[k]);
- get_unique_id(sg_fd, &all_paths[k]);
- if (0 > ioctl(sg_fd, SG_GET_SCSI_ID, &(all_paths[k].sg_id)))
+
+ if ((fd = open(all_paths[k].sg_dev, O_RDONLY)) < 0)
+ return 0;
+
+ if (0 > ioctl(fd, SG_GET_SCSI_ID, &(all_paths[k].sg_id)))
printf("device %s failed on sg ioctl, skip\n",
file_name);
- close(sg_fd);
+ close(fd);
for (i = 0; i < conf->max_devs; i++) {
if ((all_paths[k].sg_id.host_no ==
}
static int
-add_map(struct env * conf, struct path * all_paths,
+dm_simplecmd(int task, const char *name) {
+ int r = 0;
+ struct dm_task *dmt;
+
+ if (!(dmt = dm_task_create(task)))
+ return 0;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ r = dm_task_run(dmt);
+
+ out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+static int
+dm_addmap(int task, const char *name, const char *params, long size) {
+ struct dm_task *dmt;
+
+ if (!(dmt = dm_task_create(task)))
+ return 0;
+
+ if (!dm_task_set_name(dmt, name))
+ goto addout;
+
+ if (!dm_task_add_target(dmt, 0, size, DM_TARGET, params))
+ goto addout;
+
+ if (!dm_task_run(dmt))
+ goto addout;
+
+ addout:
+ dm_task_destroy(dmt);
+ return 1;
+}
+
+static int
+setup_map(struct env * conf, struct path * all_paths,
struct multipath * mp, int index, int op)
{
char params[255];
char * params_p;
- struct dm_task *dmt;
int i, np;
/* defaults for multipath target */
char * dm_ps_name = "round-robin";
int dm_ps_nr_args = 0;
- if (!(dmt = dm_task_create(op)))
- return 0;
-
- if (!dm_task_set_name(dmt, mp[index].wwid))
- goto addout;
params_p = ¶ms[0];
np = 0;
if (0 == all_paths[PINDEX(index,i)].sg_id.scsi_type)
np++;
}
- if (np == 0)
- goto addout;
if (np < 1)
- goto addout;
+ return 0;
params_p += sprintf(params_p, "%i", conf->dm_path_test_int);
if (all_paths[PINDEX(index,0)].iopolicy == MULTIBUS &&
!conf->forcedfailover ) {
- params_p += sprintf(params_p, " %i %s %i %i",
+ params_p += sprintf(params_p, " 1 %i %s %i %i",
dm_pg_prio, dm_ps_name, np, dm_ps_nr_args);
for (i=0; i<=mp[index].npaths; i++) {
if (all_paths[PINDEX(index,0)].iopolicy == FAILOVER ||
conf->forcedfailover) {
+ params_p += sprintf(params_p, " %i", mp[index].npaths + 1);
for (i=0; i<=mp[index].npaths; i++) {
if (0 != all_paths[PINDEX(index,i)].sg_id.scsi_type)
continue;
}
if (mp[index].size < 0)
- goto addout;
+ return 0;
if (!conf->quiet) {
if (op == DM_DEVICE_RELOAD)
mp[index].wwid, mp[index].size, DM_TARGET, params);
}
- if (!dm_task_add_target(dmt, 0, mp[index].size, DM_TARGET, params))
- goto addout;
+ if (op == DM_DEVICE_RELOAD)
+ dm_simplecmd(DM_DEVICE_SUSPEND, mp[index].wwid);
- if (!dm_task_run(dmt))
- goto addout;
+ dm_addmap(op, mp[index].wwid, params, mp[index].size);
+ if (op == DM_DEVICE_RELOAD)
+ dm_simplecmd(DM_DEVICE_RESUME, mp[index].wwid);
make_dm_node(mp[index].wwid);
-
- addout:
- dm_task_destroy(dmt);
return 1;
}
for (k=0; k<=nmp; k++) {
if (map_present(mp[k].wwid)) {
- add_map(&conf, all_paths, mp, k, DM_DEVICE_RELOAD);
+ setup_map(&conf, all_paths, mp, k, DM_DEVICE_RELOAD);
} else {
- add_map(&conf, all_paths, mp, k, DM_DEVICE_CREATE);
+ setup_map(&conf, all_paths, mp, k, DM_DEVICE_CREATE);
}
}