|
Converting Logical Disk Names to Physical Disk Names Programmatically
by Shridhar Acharya
(May 2003)
We want to hear from you! Please send us your FEEDBACK.
The following code sample may contain actual software programs in source
code form. This source code is made available for developers to use as needed,
pursuant to the terms and conditions of this license.
Overview:
Users of the Solaris[tm] 8/9 Operating Environment (OE) have asked if
there is a reliable way to convert logical disk names to the physical
disk names (that is, sd0 -> cXtYdZ). They have been relying on links
in /dev/<logical>
to point to /dev/dsk/<physical>. What they are seeing is that they
do not always have these links and as such, they do not accurately report
the physical disk names associated with the logical disk names. These users
would like to get information similar to that supplied by the "iostat -xn"
command. They do not want to use scripts to manipulate the iostat output
to get this information.
Sample Program:
The following program prints out the logical disk names and their corresponding
physical disk names. The program uses the libdevinfo library to obtain the
disk's complete physical path, and then uses the readlink(2) command to compare
this with the link path of each entry in the /dev/dsk directory.
You need to supply the disk drivers' names as arguments to the program.
A disk driver's name can be determined by sifting through the output of
the modinfo(1M) command. This program has been tested with the "sd"
(Solaris SCSI Disk Driver), "dad" (Solaris IDE Disk Driver) and "ssd" (Solaris
Fibre Channel Disk Driver) drivers only. However, it should work with any generic
driver.
For more information on using the devinfo interface, please refer to the
man pages of libdevinfo(3DEVINFO), libdevinfo(3LIB) and
di_init(3DEVINFO).
This example program is provided only for information and understanding
purposes.
/* This program prints out the "Device Driver Instance Name" style * disk ID's and their equivalent SVR4 style disk ID's using the * libdevinfo library. * * To Compile : cc -o <output filename> <program name> -ldevinfo * * Example Output : * * #./disk sd dad * Device Driver Instance Name = dad0, SVR4 name = /dev/dsk/c0t0d0s0 * Device Driver Instance Name = sd1, SVR4 name = /dev/dsk/c1t1d0s0 * Device Driver Instance Name = sd3, SVR4 name = /dev/dsk/c1t3d0s0 * Device Driver Instance Name = sd15, SVR4 name = /dev/dsk/c0t2d0s0 * */
#include <stdio.h> #include <sys/types.h> #include <sys/dkio.h> #include <sys/stat.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <ctype.h> #include <fcntl.h> #include <sys/fcntl.h> #include <libdevinfo.h> #include <dirent.h>
/* This routine is used to traverse the devinfo tree */ int get_alias(char *alias);
/* This routine is used to match the device path */ int read_dir(char *disk_path);
/* To store the device link info */ char value[MAXPATHLEN];
int main(int argc, char** argv) { int driver_num; driver_num = argc;
if ( argc < 2 ) { printf(" The correct syntax is <program> <driver1> <driver2> ..\n"); return(-1); }
while (driver_num > 1) {
get_alias(argv[(driver_num - 1)]) ; driver_num = driver_num - 1;
}
}
/* * This routine is used to traverse the devinfo tree looking * for devices using the driver specified in the argument * list and obtaining the physical path information about them. */
int get_alias(char *alias) { char file[MAXPATHLEN]; di_node_t root_node; di_node_t node; di_minor_t minor = DI_MINOR_NIL; char tmpnode[MAXPATHLEN]; char *phys_path; char *minor_name; int instance;
if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { fprintf(stderr, "di_init() failed\n"); exit(1); } node = di_drv_first_node(alias, root_node); while (node != DI_NODE_NIL) {
if ((minor = di_minor_next(node, DI_MINOR_NIL)) != DI_MINOR_NIL) { instance = di_instance(node); phys_path = di_devfs_path(node); minor_name = di_minor_name(minor);
strcpy(tmpnode, alias); sprintf(tmpnode, "%s%d", tmpnode, instance);
strcpy(file, "/devices"); strcat(file, phys_path); strcat(file, ":"); strcat(file, minor_name);
read_dir(file);
printf("Device Driver Instance Name = %8s, SVR4 name = %s\n", tmpnode, value); di_devfs_path_free(phys_path); node = di_drv_next_node(node); }
else { node = di_drv_next_node(node); }
} /* End of the while loop */
di_fini(root_node); return (-1); }
/* This routine just reads the link of each entry in the * /dev/dsk directory and compares it with the physical * path information recieved from the caller routine. If * they match and the file is a block device, the routine * updates the value character array and returns 0. Else * it returns a -1. */
int read_dir(char *disk_path) { DIR *dirp; struct dirent *dp; struct stat stbuf; char current_dir[MAXPATHLEN]; char file_name[MAXPATHLEN]; char temp_name[MAXPATHLEN]; char dir_dname[MAXPATHLEN];
strcpy(current_dir, "/dev/dsk");
if ((dirp = opendir(current_dir)) != NULL) { while ((dp = readdir(dirp)) != NULL) { sprintf(temp_name,"../..%s",disk_path); sprintf(dir_dname,"/dev/dsk/%s",dp->d_name); stat(dir_dname,&stbuf); if (S_ISBLK(stbuf.st_mode)) {
readlink(dir_dname, file_name, sizeof(file_name));
if (strcmp(file_name, temp_name) == 0) { strcpy(value,dir_dname); closedir(dirp); return 0; } }
bzero(file_name,MAXPATHLEN); bzero(temp_name,MAXPATHLEN); bzero(dir_dname,MAXPATHLEN); } closedir(dirp); }
return(-1);
}
DOC ID #1862
|