|
@@ -2783,6 +2783,122 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
|
|
|
return info;
|
|
|
}
|
|
|
|
|
|
+#define MAX_NAME_LEN 128
|
|
|
+static GuestDiskStatsInfoList *guest_get_diskstats(Error **errp)
|
|
|
+{
|
|
|
+#ifdef CONFIG_LINUX
|
|
|
+ GuestDiskStatsInfoList *head = NULL, **tail = &head;
|
|
|
+ const char *diskstats = "/proc/diskstats";
|
|
|
+ FILE *fp;
|
|
|
+ size_t n;
|
|
|
+ char *line = NULL;
|
|
|
+
|
|
|
+ fp = fopen(diskstats, "r");
|
|
|
+ if (fp == NULL) {
|
|
|
+ error_setg_errno(errp, errno, "open(\"%s\")", diskstats);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (getline(&line, &n, fp) != -1) {
|
|
|
+ g_autofree GuestDiskStatsInfo *diskstatinfo = NULL;
|
|
|
+ g_autofree GuestDiskStats *diskstat = NULL;
|
|
|
+ char dev_name[MAX_NAME_LEN];
|
|
|
+ unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks, dc_ticks, fl_ticks;
|
|
|
+ unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios;
|
|
|
+ unsigned long wr_merges, rd_sec_or_wr_ios, wr_sec;
|
|
|
+ unsigned long dc_ios, dc_merges, dc_sec, fl_ios;
|
|
|
+ unsigned int major, minor;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ i = sscanf(line, "%u %u %s %lu %lu %lu"
|
|
|
+ "%lu %lu %lu %lu %u %u %u %u"
|
|
|
+ "%lu %lu %lu %u %lu %u",
|
|
|
+ &major, &minor, dev_name,
|
|
|
+ &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios,
|
|
|
+ &rd_ticks_or_wr_sec, &wr_ios, &wr_merges, &wr_sec,
|
|
|
+ &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks,
|
|
|
+ &dc_ios, &dc_merges, &dc_sec, &dc_ticks,
|
|
|
+ &fl_ios, &fl_ticks);
|
|
|
+
|
|
|
+ if (i < 7) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ diskstatinfo = g_new0(GuestDiskStatsInfo, 1);
|
|
|
+ diskstatinfo->name = g_strdup(dev_name);
|
|
|
+ diskstatinfo->major = major;
|
|
|
+ diskstatinfo->minor = minor;
|
|
|
+
|
|
|
+ diskstat = g_new0(GuestDiskStats, 1);
|
|
|
+ if (i == 7) {
|
|
|
+ diskstat->has_read_ios = true;
|
|
|
+ diskstat->read_ios = rd_ios;
|
|
|
+ diskstat->has_read_sectors = true;
|
|
|
+ diskstat->read_sectors = rd_merges_or_rd_sec;
|
|
|
+ diskstat->has_write_ios = true;
|
|
|
+ diskstat->write_ios = rd_sec_or_wr_ios;
|
|
|
+ diskstat->has_write_sectors = true;
|
|
|
+ diskstat->write_sectors = rd_ticks_or_wr_sec;
|
|
|
+ }
|
|
|
+ if (i >= 14) {
|
|
|
+ diskstat->has_read_ios = true;
|
|
|
+ diskstat->read_ios = rd_ios;
|
|
|
+ diskstat->has_read_sectors = true;
|
|
|
+ diskstat->read_sectors = rd_sec_or_wr_ios;
|
|
|
+ diskstat->has_read_merges = true;
|
|
|
+ diskstat->read_merges = rd_merges_or_rd_sec;
|
|
|
+ diskstat->has_read_ticks = true;
|
|
|
+ diskstat->read_ticks = rd_ticks_or_wr_sec;
|
|
|
+ diskstat->has_write_ios = true;
|
|
|
+ diskstat->write_ios = wr_ios;
|
|
|
+ diskstat->has_write_sectors = true;
|
|
|
+ diskstat->write_sectors = wr_sec;
|
|
|
+ diskstat->has_write_merges = true;
|
|
|
+ diskstat->write_merges = wr_merges;
|
|
|
+ diskstat->has_write_ticks = true;
|
|
|
+ diskstat->write_ticks = wr_ticks;
|
|
|
+ diskstat->has_ios_pgr = true;
|
|
|
+ diskstat->ios_pgr = ios_pgr;
|
|
|
+ diskstat->has_total_ticks = true;
|
|
|
+ diskstat->total_ticks = tot_ticks;
|
|
|
+ diskstat->has_weight_ticks = true;
|
|
|
+ diskstat->weight_ticks = rq_ticks;
|
|
|
+ }
|
|
|
+ if (i >= 18) {
|
|
|
+ diskstat->has_discard_ios = true;
|
|
|
+ diskstat->discard_ios = dc_ios;
|
|
|
+ diskstat->has_discard_merges = true;
|
|
|
+ diskstat->discard_merges = dc_merges;
|
|
|
+ diskstat->has_discard_sectors = true;
|
|
|
+ diskstat->discard_sectors = dc_sec;
|
|
|
+ diskstat->has_discard_ticks = true;
|
|
|
+ diskstat->discard_ticks = dc_ticks;
|
|
|
+ }
|
|
|
+ if (i >= 20) {
|
|
|
+ diskstat->has_flush_ios = true;
|
|
|
+ diskstat->flush_ios = fl_ios;
|
|
|
+ diskstat->has_flush_ticks = true;
|
|
|
+ diskstat->flush_ticks = fl_ticks;
|
|
|
+ }
|
|
|
+
|
|
|
+ diskstatinfo->stats = g_steal_pointer(&diskstat);
|
|
|
+ QAPI_LIST_APPEND(tail, diskstatinfo);
|
|
|
+ diskstatinfo = NULL;
|
|
|
+ }
|
|
|
+ free(line);
|
|
|
+ fclose(fp);
|
|
|
+ return head;
|
|
|
+#else
|
|
|
+ g_debug("disk stats reporting available only for Linux");
|
|
|
+ return NULL;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
|
|
|
+{
|
|
|
+ return guest_get_diskstats(errp);
|
|
|
+}
|
|
|
+
|
|
|
#else /* defined(__linux__) */
|
|
|
|
|
|
void qmp_guest_suspend_disk(Error **errp)
|
|
@@ -3131,6 +3247,13 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
|
|
|
+{
|
|
|
+ error_setg(errp, QERR_UNSUPPORTED);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
#endif /* CONFIG_FSFREEZE */
|
|
|
|
|
|
#if !defined(CONFIG_FSTRIM)
|