#include #include #include #include #include #include #include #include #include #ifdef ZFS #include #include #endif #include #include #include "scsi_vhci_modified.h" #define CONTROLDEVICE "/devices/scsi_vhci:devctl" sv_path_info_t *pathinfo; sv_iocdata_t iocdata; mdi_pathinfo_state_t status; static const char prefixes[]=" kMGTPEZ"; int failurecount; conv_size(char *buffer, uint64_t size, int buflen) { double sizeval; int pc=0; memset(buffer,0,buflen); sizeval=(double)size; while (sizeval>1024) { sizeval=sizeval/1024; pc++; } snprintf(buffer,buflen-1,"%.2f%c",sizeval,prefixes[pc]); } #ifdef ZFS do_zfs(char *devicename) { libzfs_handle_t *zh; int fd2; nvlist_t *properties; nvlist_t *properties2; nvpair_t *nv=NULL; nvpair_t *nva=NULL; data_type_t nvt,nvtt; char *value; char zpool[256]; char pooltype[256]; uint64_t v; uint64_t zversion=0; uint64_t size=0; char printable_size[16]; char devicepath[256]; int data=0; zh=libzfs_init(); if (zh != NULL) { snprintf(devicepath,255,"/devices%s:a,raw",devicename); memset(zpool,0,256); memset(pooltype,0,256); fd2=open(devicepath,O_RDONLY); if (fd2!=-1) { if (zpool_read_label(fd2,&properties)==0) { if (nvlist_lookup_string(properties,"name",&value)==0) { strncpy(zpool,value,255); data=1; } nvlist_lookup_uint64(properties,"version",&v); zversion=v; if (nvlist_lookup_nvlist(properties,"vdev_tree",&properties2)==0) { nvlist_lookup_uint64(properties2,"asize",&v); size=v; nvlist_lookup_string(properties2,"type",&value); strncpy(pooltype,value,255); } if (data==1) { conv_size(printable_size,size,16); printf(" ZFS: pool name = %s, ZFS Version: %llu\n",zpool,zversion); printf(" ZFS: size = %s, member type = %s\n",printable_size,pooltype); } } close(fd2); } libzfs_fini(zh); } } #endif do_inquiry(char *devicename, char *inquirybuffer, int inquirybuffersize) { char devicepath[256]; union scsi_cdb scsicommand; struct uscsi_cmd uscsicommand; int erg; int fd; snprintf(devicepath,255,"/devices%s:c,raw",devicename); fd=open(devicepath,O_RDWR|O_NDELAY); if (fd!=-1) { memset((char *)inquirybuffer, 0, inquirybuffersize); memset((char *)&scsicommand, 0, sizeof(union scsi_cdb)); memset((char *)&uscsicommand, 0, sizeof(struct uscsi_cmd)); scsicommand.scc_cmd=SCMD_INQUIRY; FORMG0COUNT(&scsicommand, (uchar_t)inquirybuffersize); uscsicommand.uscsi_bufaddr=(caddr_t)inquirybuffer; uscsicommand.uscsi_buflen=inquirybuffersize; uscsicommand.uscsi_cdb=(caddr_t)&scsicommand; uscsicommand.uscsi_cdblen=CDB_GROUP0; uscsicommand.uscsi_timeout=10; uscsicommand.uscsi_flags=USCSI_ISOLATE|USCSI_READ; erg=ioctl(fd, USCSICMD, &uscsicommand); if (erg!=0) { printf("SCSI Inquiry failed: %i %i\n",erg,errno); } close(fd); } else { printf("Disk device does not exist\n"); } } do_work(int fd, char *devicename) { int i; int erg; uint_t np; char clientbuffer[MAXPATHLEN+1]; strlcpy(clientbuffer,devicename,MAXPATHLEN); bzero(&iocdata,sizeof(sv_iocdata_t)); iocdata.client=clientbuffer; iocdata.ret_elem=&np; erg=ioctl(fd,SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO,&iocdata); if (erg!=0) { printf("Ergebnis: %i,%i,%i\n",erg,errno,np); perror(NULL); printf("Nix npaths %i\n",np); } bzero(&iocdata,sizeof(sv_iocdata_t)); iocdata.client=clientbuffer; iocdata.buf_elem=np; iocdata.ret_elem=&np; if ((iocdata.ret_buf=(sv_path_info_t *)calloc(np,sizeof(sv_path_info_t))) == NULL) { fprintf(stderr,"out of memory\n"); return(-1); } erg=ioctl(fd,SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO,&iocdata); if (erg<0) { fprintf(stderr,"ioctl failed:\n"); fprintf(stderr,"%i,%i,%i\n",erg,errno,np); perror(NULL); return(-1); } if (iocdata.buf_elemdevice.ret_phci,pathinfo->ret_addr); switch (pathinfo->ret_state) { case MDI_PATHINFO_STATE_INIT: puts("INIT"); break; case MDI_PATHINFO_STATE_ONLINE: puts("ONLINE"); break; case MDI_PATHINFO_STATE_STANDBY: puts("STANDBY"); break; case MDI_PATHINFO_STATE_FAULT: failurecount++; puts("*** FAILED ***"); break; case MDI_PATHINFO_STATE_OFFLINE: failurecount++; puts("OFFLINE"); break; default: puts("UNKNOWN"); } pathinfo++; } free(iocdata.ret_buf); } p_print (char *buffer, int n) { char c; while (n > 0) { c=*buffer; if ((isprint(c)) && (isascii(c))) { printf("%c",c); } buffer++; n--; } } main(int argc, char **argv) { int diopts=DINFOCPYALL; int vendorid=0; int dozfs=0; int fd; char arg; static di_node_t devroot = DI_NODE_NIL; di_node_t entry; char hostname[200]; char clientbuffer[MAXPATHLEN]; static char inquirydata[255]; struct scsi_inquiry *inquiry; failurecount=0; gethostname(hostname,199); printf("vhci_stat\n1.3.1; Pascal Gienger ; http://southbrain.com/south/\nHost: %s\n\n",hostname); #ifdef ZFS while ((arg=getopt(argc,argv,"piz"))!=EOF) #else while ((arg=getopt(argc,argv,"pi"))!=EOF) #endif { switch (arg) { case 'p': diopts=DINFOCPYALL|DINFOFORCE; puts("Rebuilding tree..."); break; case 'i': vendorid=1; break; #ifdef ZFS case 'z': dozfs=1; break; #endif default: #ifdef ZFS fprintf(stderr,"Usage: %s [-i] [-p] [-z] -i: get vendor/product id -p: set DINFOFORCE - force tree rebuild -z: get zfs info\n",argv[0]); #else fprintf(stderr,"Usage: %s [-i] [-p] -i: get vendor/product id -p: set DINFOFORCE - force tree rebuild\n",argv[0]); #endif return(-2); } } devroot=di_init("/", diopts); if (devroot == DI_NODE_NIL) { fprintf(stderr,"di_init failed\n"); return(-1); } fd=open(CONTROLDEVICE,O_RDONLY); if (fd<0) { fprintf(stderr,"open of vhci control device failed.\n"); return(-1); } puts("PATH WWPN,LUN STATE"); puts("------------------------------------------------- ------------------- -----"); for (entry = di_drv_first_node("ssd",devroot); entry != DI_NODE_NIL; entry = di_drv_next_node(entry)) { if (strncmp(di_devfs_path(entry),"/scsi_vhci",10) == 0) { puts(di_devfs_path(entry)); if (vendorid) { do_inquiry(di_devfs_path(entry),inquirydata,sizeof(inquirydata)); inquiry=(struct scsi_inquiry *)inquirydata; printf(" (Vendor = "); p_print(inquiry->inq_vid,8); printf(" Model = "); p_print(inquiry->inq_pid,16); printf(" Rev. = "); p_print(inquiry->inq_revision,4); printf( " VolID = "); p_print(inquiry->inq_revision+4,8); printf(")\n"); } if (dozfs) { do_zfs(di_devfs_path(entry)); } do_work(fd,di_devfs_path(entry)); } } for (entry = di_drv_first_node("sd",devroot); entry != DI_NODE_NIL; entry = di_drv_next_node(entry)) { if (strncmp(di_devfs_path(entry),"/scsi_vhci",10) == 0) { puts(di_devfs_path(entry)); if (vendorid) { do_inquiry(di_devfs_path(entry),inquirydata,sizeof(inquirydata)); inquiry=(struct scsi_inquiry *)inquirydata; printf(" (Vendor = "); p_print(inquiry->inq_vid,8); printf(" Model = "); p_print(inquiry->inq_pid,16); printf(" Rev. = "); p_print(inquiry->inq_revision,4); printf( " VolID = "); p_print(inquiry->inq_revision+4,8); printf(")\n"); } if (dozfs==1) { do_zfs(di_devfs_path(entry)); } do_work(fd,di_devfs_path(entry)); } } di_fini(devroot); close(fd); return(failurecount); }