Originally posted by: SystemAdmin
Hi,
I want to programatically read disk information on AIX and below is the code to extract that information using iostat and dkstat structure. But I am getting some strange error while reading the dkstat structure and before that I am getting disk count number very large : 760596008.
If i run iostat -d then i just get 3 disks on my system.
So in nutshell i get the following error while reading the dkstat structure
" No such device or address". The code snippet is below.
Can anyone please tell me why I am not able to get the proper offset of iostat and henceforth offset for dskstat.
Thanks
System configuration: lcpu=8 drives=3 paths=2 vdisks=0
Disks: % tm_act Kbps tps Kb_read Kb_wrtn
hdisk1 0.1 1.5 0.2 365205 5138900
hdisk0 0.0 0.0 0.0 0 0
cd0 0.0 0.0 0.0 0 0
#include <stdio.h> /* for perror */
#include <stdlib.h>
#include <string.h> /* for memset */
#include <nlist.h>
#include <sys/types.h>
#include <sys/iostat.h>
#include <unistd.h>
#include <fcntl.h>
int kmemfd = -1;
struct nlist diskaddr[] = {
{"iostat", 0, 0, 0, 0, 0},
{NULL, 0, 0, 0, 0, 0},
};
int dk_cnt; /* number of disks in system */
caddr_t iostat_addr = 0;
struct iostat iostat;
extern int errno;
extern char *sys_errlist[];
extern int sys_nerr;
static const char * ahmGetErrStrFromErrno()
{
if (errno <= sys_nerr) {
return (sys_errlist
errno);
} else {
return ("cannot lookup error message");
}
}
int getkmemdata(void *buf, int bufsize, caddr_t address, char *refrstr)
{
int n,l;
/*
* Do stuff we only need to do once per invocation, like opening
* the kmem file and fetching the parts of the symbol table.
*/
if (kmemfd < 0) {
if ((kmemfd = open("/dev/kmem", O_RDONLY)) < 0) {
perror("kmem");
exit(1);
}
/*
* We only need to be root for getting access to kmem, so give up
* root permissions now!
*/
setuid(getuid());
setgid(getgid());
/*
* Set the close on exec bit for the kmem file descriptor.
*/
if (fcntl(kmemfd, F_SETFD, FD_CLOEXEC) == -1) {
perror("fcntl kmem");
close(kmemfd);
exit(1);
}
printf("Opened the file successfully , handle = %d\n", kmemfd);
}
/*
* Get the structure from the running kernel.
*/
l = lseek(kmemfd, (off_t) address, SEEK_SET);
printf("lseek for %s= %d\n", refrstr, l);
n = read(kmemfd, buf, bufsize);
printf("read for %s = %d, err = %d, errmsg = %s\n",refrstr,n, errno, ahmGetErrStrFromErrno() );
return(n);
} /* getkmemdata */
int init_dkstat()
{
int ret;
if (!iostat_addr) {
if (knlist(diskaddr, 1, sizeof(struct nlist)) == -1)
perror("diskaddr: entry not found");
else
iostat_addr = (caddr_t) diskaddr[0].n_value;
}
ret = getkmemdata((char *) &iostat, sizeof(struct iostat), iostat_addr, "iostat");
if (ret < 0)
return ret;
dk_cnt = iostat.dk_cnt;
printf ("diskcount = %d\n", dk_cnt);
return dk_cnt;
} /* init_dkstat */
/*
* get the dkstat list from kernel.
*/
int get_dkstat()
{
int i,ret;
struct dkstat * diskaddr;
diskaddr = (caddr_t) iostat.dkstatp;
for (i = 0; i < dk_cnt; i++) {
struct dkstat m_dkstat;
ret = getkmemdata((char *) &m_dkstat, sizeof(struct dkstat), diskaddr, "dkstat");
if (ret < 0)
return -1;
printf("disk %d name %s\n", i, m_dkstat.diskname);
printf("disk %d next %0lx\n", i, m_dkstat.dknextp);
printf("disk %d status %0x\n", i, m_dkstat.dk_status);
printf("disk %d time %ld\n", i, m_dkstat.dk_time);
printf("disk %d xrate %ld\n", i, m_dkstat.dk_xrate);
printf("disk %d bsize %ld\n", i, m_dkstat.dk_bsize);
printf("disk %d xfers %ld\n", i, m_dkstat.dk_xfers);
printf("disk %d rblks %ld\n", i, m_dkstat.dk_rblks);
printf("disk %d wblks %ld\n", i, m_dkstat.dk_wblks);
printf("disk %d seek %ld\n", i, m_dkstat.dk_seek);
diskaddr = m_dkstat.dknextp;
}
return i;
} /* get_dkstat */
int main()
{
int diskcount;
diskcount = init_dkstat();
if (diskcount > 0)
get_dkstat();
}
#AIX-Forum