summaryrefslogtreecommitdiffstats
path: root/sysfs.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-06-14 02:27:30 +0200
committerDan Williams <dan.j.williams@intel.com>2008-06-14 02:27:30 +0200
commitf1665f720035ab37913a68838d3310188f3a4b08 (patch)
tree1635b0affc86320fa2f0833185c910c2bd2d34c4 /sysfs.c
parentsysfs: provide a helper function for locating scsi_generic interfaces (diff)
downloadmdadm-f1665f720035ab37913a68838d3310188f3a4b08.tar.xz
mdadm-f1665f720035ab37913a68838d3310188f3a4b08.zip
sysfs: helper routine to retrieve the scsi id
imsm records this information in its metadata Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'sysfs.c')
-rw-r--r--sysfs.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/sysfs.c b/sysfs.c
index 37b8b097..5f0c2127 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -464,3 +464,52 @@ int sysfs_disk_to_sg(int fd)
return -1;
}
+int sysfs_disk_to_scsi_id(int fd, __u32 *id)
+{
+ /* from an open block device, try to retrieve it scsi_id */
+ struct stat st;
+ char path[256];
+ char *c1, *c2;
+ DIR *dir;
+ struct dirent *de;
+
+ 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_disk:", de->d_name,
+ strlen("scsi_disk:")) == 0)
+ break;
+ de = readdir(dir);
+ }
+ closedir(dir);
+
+ if (!de)
+ return 1;
+
+ c1 = strchr(de->d_name, ':');
+ c1++;
+ c2 = strchr(c1, ':');
+ *c2 = '\0';
+ *id = strtol(c1, NULL, 10) << 24; /* host */
+ c1 = c2 + 1;
+ c2 = strchr(c1, ':');
+ *c2 = '\0';
+ *id |= strtol(c1, NULL, 10) << 16; /* channel */
+ c1 = c2 + 1;
+ c2 = strchr(c1, ':');
+ *c2 = '\0';
+ *id |= strtol(c1, NULL, 10) << 8; /* lun */
+ c1 = c2 + 1;
+ *id |= strtol(c1, NULL, 10); /* id */
+
+ return 0;
+}