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:
parent
c42ec1ed43
commit
90c8b70714
2
mdadm.h
2
mdadm.h
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
65
sysfs.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue