C/C++ disk io

covacat

Daemon

Reaction score: 514
Messages: 1,040

code to find sysctl names needed to extract per dataset fs statistics
use as ./prog tank/var
(large) parts of the code taken of /usr/src/sbin/sysctl/sysctl.c

C:
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <errno.h>
#include <sys/sysctl.h>
#include <string.h>
/*
oid = binary oid of kstat.zfs.<poolname>
len = sizeof oid
dataset = dataset name eg tank/var
szbuf = sizeof receiving buffer
buf = buffer to copy resulting string eg kstat.zfs.ntank.dataset.objset-0x46
*/
int find_dataset_sstr(int *oid, int len,char *dataset,size_t szbuf,char *buf)
{
    int name1[22], name2[22];
    int i, j, si;
    size_t l1, l2, sj;
    int qoid[24];
    char name[256];
    name1[0] = 0;
    name1[1] = 2;
    l1 = 2;
    if (len) {
        memcpy(name1+2, oid, len * sizeof(int));
        l1 += len;
    } else {
        name1[2] = 1;
        l1++;
    }
    for (;;) {
        l2 = sizeof(name2);
        j = sysctl(name1, l1, name2, &l2, 0, 0);
        if (j < 0) {
            if (errno == ENOENT)
                return (0);
            else
                err(1, "sysctl(getnext) %d %zu", j, l2);
        }

        l2 /= sizeof(int);

        if (len < 0 || l2 < (unsigned int)len)
            return (0);

        for (i = 0; i < len; i++)
            if (name2[i] != oid[i])
                return (0);

    bzero(name, sizeof(name));
    qoid[0] = 0;
    memcpy(qoid + 2, name2, l2 * sizeof(int));

    qoid[1] = 1;
    sj = sizeof(name);
    si = sysctl(qoid, l2 + 2, name, &sj, 0, 0);
    
    if (si || !sj)
        err(1, "sysctl name %d %zu %d", si, sj, errno);
    if(strstr(name,"dataset_name")) {
      sj = szbuf;
      si = sysctl(name2,l2,(void *)buf,&sj,0,0);
      if (si || !szbuf)
                err(1, "sysctl name %d %zu %d", si, szbuf, errno);
      if(!strcmp(dataset,buf)) {
       strcpy(buf,name);
       char *pp = strrchr(buf,'.');
       *pp = 0;
       return 1;
       }
      }
        
//        i = show_var(name2, l2);
        memcpy(name1+2, name2, l2 * sizeof(int));
        l1 = 2 + l2;
    }
return 0;
}

int main(int argc,char **argv)
{
int error,found;
char *pool, *dataset;
char oid_str[256];
int mib[24];
size_t sizep;;
if(argc !=2 ) {
 errx(1,"usage %s dataset",argv[0]);
 }
dataset = strchr(argv[1],'/');
if(!dataset) {
 errx(1,"%s is not in correct format pool/dataset",argv[1]);
 }
*dataset = '\0';
pool = argv[1];

sprintf(oid_str,"kstat.zfs.%s",pool);
error = sysctlnametomib(oid_str, mib, &sizep);
//printf("%s %d %zu\n",oid_str,error,sizep);
if(error == -1) {
 errx(1,"sysctlnametomib %s invalid",oid_str);
 }
*dataset = '/';
 found = find_dataset_sstr(mib,sizep,argv[1],256,oid_str);
 if(found) {
  printf("FOUND %s\n",oid_str);
  }
}
 
Top