Beispiel #1
0
/*
 * return true is arg is a disk name
 */
static int
_pm_isdisk(char *dname)
{
    return (!_pm_isloop(dname) && !_pm_isramdisk(dname) &&
	    !_pm_ispartition(dname) && !_pm_isxvmvol(dname) &&
	    !_pm_isdm(dname) && !_pm_ismd(dname));
}
Beispiel #2
0
/*
 * slight improvement to heuristic suggested by
 * Tim Bradshaw <*****@*****.**> on 29 Dec 2003
 */
int
_pm_ispartition(char *dname)
{
    int p, m = strlen(dname) - 1;

    /*
     * looking at something like foo/x, and we hope x ends p<n>, for 
     * a partition, or not for a disk.
     */
    if (strchr(dname, '/')) {
	for (p = m; p > 0 && isdigit((int)dname[p]); p--)
	    ;
	if (p == m)
	    /* name had no trailing digits.  Wildly guess a disk. */
	    return 1;
	else 
	    /*
	     * ends with digits, if preceding character is a 'p' punt
	     * on a partition
	     */
	    return (dname[p] == 'p'? 1 : 0);
    }
    else {
	/*
	 * default test : partition names end in a digit do not
	 * look like loopback devices.  Handle other special-cases
	 * here - mostly seems to be RAM-type disk drivers that're
	 * choosing to end device names with numbers.
	 */
	return isdigit((int)dname[m]) &&
		!_pm_isloop(dname) &&
		!_pm_isramdisk(dname) &&
		!_pm_ismmcdisk(dname) &&
		!_pm_isnvmedrive(dname) &&
		!_pm_ismd(dname) &&
		!_pm_isdm(dname);
    }
}
Beispiel #3
0
int
refresh_proc_partitions(pmInDom disk_indom, pmInDom partitions_indom, pmInDom dm_indom)
{
    FILE *fp;
    int devmin;
    int devmaj;
    int n;
    int indom;
    int have_proc_diskstats;
    int inst;
    unsigned long long blocks;
    partitions_entry_t *p;
    int indom_changes = 0;
    char *dmname;
    char buf[MAXPATHLEN];
    char namebuf[MAXPATHLEN];
    static int first = 1;

    if (first) {
	/* initialize the instance domain caches */
	pmdaCacheOp(disk_indom, PMDA_CACHE_LOAD);
	pmdaCacheOp(partitions_indom, PMDA_CACHE_LOAD);
	pmdaCacheOp(dm_indom, PMDA_CACHE_LOAD);

	first = 0;
	indom_changes = 1;
    }

    pmdaCacheOp(disk_indom, PMDA_CACHE_INACTIVE);
    pmdaCacheOp(partitions_indom, PMDA_CACHE_INACTIVE);
    pmdaCacheOp(dm_indom, PMDA_CACHE_INACTIVE);

    if ((fp = linux_statsfile("/proc/diskstats", buf, sizeof(buf))) != NULL)
    	/* 2.6 style disk stats */
	have_proc_diskstats = 1;
    else {
	if ((fp = linux_statsfile("/proc/partitions", buf, sizeof(buf))) != NULL)
	    have_proc_diskstats = 0;
	else
	    return -oserror();
    }

    while (fgets(buf, sizeof(buf), fp) != NULL) {
	dmname = NULL;
	if (buf[0] != ' ' || buf[0] == '\n') {
	    /* skip heading */
	    continue;
	}

	if (have_proc_diskstats) {
	    if ((n = sscanf(buf, "%d %d %s", &devmaj, &devmin, namebuf)) != 3)
		continue;
	}
	else {
	    /* /proc/partitions */
	    if ((n = sscanf(buf, "%d %d %llu %s", &devmaj, &devmin, &blocks, namebuf)) != 4)
		continue;
	}

	if (_pm_isdm(namebuf)) {
	    indom = dm_indom;
	    dmname = strdup(namebuf);
	}
	else if (_pm_ispartition(namebuf))
	    indom = partitions_indom;
	else if (_pm_isdisk(namebuf))
	    indom = disk_indom;
	else
	    continue;

	if (indom == dm_indom) {
	    /* replace dm-[0-9]* with the persistent name from /dev/mapper */
	    if (!map_persistent_dm_name(namebuf, sizeof(namebuf), devmaj, devmin)) {
		/* skip dm devices that have no persistent name mapping */
		free(dmname);
		continue;
	    }
	}

	p = NULL;
	if (pmdaCacheLookupName(indom, namebuf, &inst, (void **)&p) < 0 || !p) {
	    /* not found: allocate and add a new entry */
	    p = (partitions_entry_t *)malloc(sizeof(partitions_entry_t));
	    memset(p, 0, sizeof(partitions_entry_t));
	    indom_changes++;
	}

	if (p->dmname)
	    free(p->dmname);
	p->dmname = dmname; /* NULL if not a dm device */

        if (!p->namebuf)
            p->namebuf = strdup(namebuf);
        else
        if (strcmp(namebuf, p->namebuf) != 0) {
            free(p->namebuf);
            p->namebuf = strdup(namebuf);
        }

	/* activate this entry */
	if (p->udevnamebuf)
	    /* long xscsi name */
	    inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, p->udevnamebuf, p);
	else
	    /* short /proc/diskstats or /proc/partitions name */
	    inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, namebuf, p);

	if (have_proc_diskstats) {
	    /* 2.6 style /proc/diskstats */
	    p->nr_blocks = 0;
	    namebuf[0] = '\0';
	    /* Linux source: block/genhd.c::diskstats_show(1) */
	    n = sscanf(buf, "%u %u %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u",
		&p->major, &p->minor, namebuf,
		&p->rd_ios, &p->rd_merges, &p->rd_sectors, &p->rd_ticks,
		&p->wr_ios, &p->wr_merges, &p->wr_sectors, &p->wr_ticks,
		&p->ios_in_flight, &p->io_ticks, &p->aveq);
	    if (n != 14) {
		p->rd_merges = p->wr_merges = p->wr_ticks =
			p->ios_in_flight = p->io_ticks = p->aveq = 0;
		/* Linux source: block/genhd.c::diskstats_show(2) */
		n = sscanf(buf, "%u %u %s %u %u %u %u\n",
		    &p->major, &p->minor, namebuf,
		    (unsigned int *)&p->rd_ios, (unsigned int *)&p->rd_sectors,
		    (unsigned int *)&p->wr_ios, (unsigned int *)&p->wr_sectors);
	    }
	}
	else {
	    /* 2.4 style /proc/partitions */
	    namebuf[0] = '\0';
	    n = sscanf(buf, "%u %u %lu %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u",
		&p->major, &p->minor, &p->nr_blocks, namebuf,
		&p->rd_ios, &p->rd_merges, &p->rd_sectors,
		&p->rd_ticks, &p->wr_ios, &p->wr_merges,
		&p->wr_sectors, &p->wr_ticks, &p->ios_in_flight,
		&p->io_ticks, &p->aveq);
	}

    }

    /*
     * If any new disks or partitions have appeared then we
     * we need to remap the long device names (if /dev/xscsi
     * exists) and then flush the pmda cache.
     *
     * We just let inactive instances rot in the inactive state
     * (this doesn't happen very often, so is only a minor leak).
     */
    if (indom_changes) {
	refresh_udev(disk_indom, partitions_indom);
	pmdaCacheOp(disk_indom, PMDA_CACHE_SAVE);
	pmdaCacheOp(partitions_indom, PMDA_CACHE_SAVE);
	pmdaCacheOp(dm_indom, PMDA_CACHE_SAVE);
    }

    /*
     * success
     */
    if (fp)
	fclose(fp);
    return 0;
}