/* * 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)); }
static void refresh_udev(pmInDom disk_indom, pmInDom partitions_indom) { char buf[MAXNAMELEN]; char realname[MAXNAMELEN]; char *shortname; char *p; char *udevname; FILE *pfp; partitions_entry_t *entry; int indom; int inst; if (access("/dev/xscsi", R_OK) != 0) return; if (!(pfp = popen("find /dev/xscsi -name disc -o -name part[0-9]*", "r"))) return; while (fgets(buf, sizeof(buf), pfp)) { if ((p = strrchr(buf, '\n')) != NULL) *p = '\0'; if (realpath(buf, realname)) { udevname = buf + 5; /* /dev/xscsi/.... */ if ((shortname = strrchr(realname, '/')) != NULL) { shortname++; indom = _pm_ispartition(shortname) ? partitions_indom : disk_indom; if (pmdaCacheLookupName(indom, shortname, &inst, (void **)&entry) != PMDA_CACHE_ACTIVE) continue; entry->udevnamebuf = strdup(udevname); pmdaCacheStore(indom, PMDA_CACHE_HIDE, shortname, entry); /* inactive */ pmdaCacheStore(indom, PMDA_CACHE_ADD, udevname, entry); /* active */ } } } pclose(pfp); }
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; }