/* * 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)); }
/* * 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); } }
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; }