sysfs: provide a helper function for locating scsi_generic interfaces

imsm records and validates this data in its metadata

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2008-06-13 17:27:30 -07:00
parent c42ec1ed43
commit 90c8b70714
3 changed files with 69 additions and 11 deletions

View File

@ -346,7 +346,7 @@ extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev,
extern int sysfs_set_array(struct mdinfo *sra,
struct mdinfo *info);
extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd);
extern int sysfs_disk_to_sg(int fd);

View File

@ -544,26 +544,19 @@ static int imsm_read_serial(int fd, char *devname,
__u8 serial[MAX_RAID_SERIAL_LEN])
{
unsigned char scsi_serial[255];
struct stat stb;
int sg_fd;
int minor;
char sg_path[20];
int rv;
int rsp_len;
int i, cnt;
memset(scsi_serial, 0, sizeof(scsi_serial));
fstat(fd, &stb);
minor = minor(stb.st_rdev);
minor /= 16;
sprintf(sg_path, "/dev/sg%d", minor);
sg_fd = open(sg_path, O_RDONLY);
sg_fd = sysfs_disk_to_sg(fd);
if (sg_fd < 0) {
if (devname)
fprintf(stderr,
Name ": Failed to open %s for %s: %s\n",
sg_path, devname, strerror(errno));
Name ": Failed to open sg interface for %s: %s\n",
devname, strerror(errno));
return 1;
}

65
sysfs.c
View File

@ -399,3 +399,68 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd)
}
return rv;
}
int sysfs_disk_to_sg(int fd)
{
/* from an open block device, try find and open its corresponding
* scsi_generic interface
*/
struct stat st;
char path[256];
char sg_path[256];
char sg_major_minor[8];
char *c;
DIR *dir;
struct dirent *de;
int major, minor, rv;
if (fstat(fd, &st))
return -1;
snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/device",
major(st.st_rdev), minor(st.st_rdev));
dir = opendir(path);
if (!dir)
return -1;
de = readdir(dir);
while (de) {
if (strncmp("scsi_generic:", de->d_name,
strlen("scsi_generic:")) == 0)
break;
de = readdir(dir);
}
closedir(dir);
if (!de)
return -1;
snprintf(sg_path, sizeof(sg_path), "%s/%s/dev", path, de->d_name);
fd = open(sg_path, O_RDONLY);
if (fd < 0)
return fd;
rv = read(fd, sg_major_minor, sizeof(sg_major_minor));
close(fd);
if (rv < 0)
return -1;
else
sg_major_minor[rv - 1] = '\0';
c = strchr(sg_major_minor, ':');
*c = '\0';
c++;
major = strtol(sg_major_minor, NULL, 10);
minor = strtol(c, NULL, 10);
snprintf(path, sizeof(path), "/dev/.tmp.md.%d:%d:%d",
(int) getpid(), major, minor);
if (mknod(path, S_IFCHR|0600, makedev(major, minor))==0) {
fd = open(path, O_RDONLY);
unlink(path);
return fd;
}
return -1;
}