Rework of /proc/stat
PATCH 1/1 Rework of /proc/stat
Hi,
I've made a new version of IO statistics in kstat that remove the previous limitations of MAX_MAJOR
I've made tests on my machine.
Could someone test it, please?
Feedback welcome.
Bye
-jec
toc/linux-2.4.18-reempt/include/linux/kernel_stat.h renamed from tmp/linux-2.4.18-vanilla/include/linux/kernel_stat.h +48 -7
@@ -12,18 +12,37 @@* used by rstatd/perfmeter */ -#define DK_MAX_MAJOR 16 -#define DK_MAX_DISK 16 +#define DK_MAX_DEVICES 64 +#define DK_BUCKETS 256 + + +struct _kstat_block_io +{ +struct _kstat_block_io * next; + +unsigned int major; +unsigned int minor; + +unsigned int io; +unsigned int rio; +unsigned int wio; +unsigned int rblk; +unsigned int wblk; +}; +typedef struct _kstat_block_io kstat_block_io ; + + +/* static array of IO stats */ +extern unsigned int kstat_devices_current_index; +extern kstat_block_io kstat_devices_array[DK_MAX_DEVICES ]; + +struct kernel_stat {unsigned int per_cpu_user[NR_CPUS ], per_cpu_nice[NR_CPUS ], per_cpu_system[NR_CPUS ]; -unsigned int dk_drive[DK_MAX_MAJOR ][DK_MAX_DISK ]; -unsigned int dk_drive_rio[DK_MAX_MAJOR ][DK_MAX_DISK ]; -unsigned int dk_drive_wio[DK_MAX_MAJOR ][DK_MAX_DISK ]; -unsigned int dk_drive_rblk[DK_MAX_MAJOR ][DK_MAX_DISK ]; -unsigned int dk_drive_wblk[DK_MAX_MAJOR ][DK_MAX_DISK ]; +kstat_block_io * io_stat_tbl[DK_BUCKETS ];unsigned int pgpgin, pgpgout;unsigned int pswpin, pswpout;#if !defined(CONFIG_ARCH_S390 )
@@ -37,6 +56,103 @@extern struct kernel_stat kstat; + + +/* Size of the table */ +extern const unsigned int kstat_block_io_tbl_size; + +/* hash function */ +static inline unsigned kstat_block_io_hash (unsigned int major,unsigned int minor) +{ +return major *1999 ^ minor; +} + + +/* add an IO stat */ +static inline kstat_block_io *kstat_block_io_add (unsigned int major,unsigned int minor) +{ +unsigned int i; +kstat_block_io * p; +kstat_block_io * pstat; + +if (kstat_devices_current_index >=DK_MAX_DEVICES ) + { + printk("ERROR: kstat: No more slot for device IO stats. Try
extending DK_MAX_DEVICES\n");
+
return 0;
+ }
+
+ pstat = &kstat_devices_array[kstat_devices_current_index];
+ kstat_devices_current_index++;
+ pstat->next = 0; + pstat->major = major; + pstat->minor = minor; + pstat->io = 0; + pstat->rio = 0; + pstat->wio = 0; + pstat->rblk = 0; + pstat->wblk = 0;
+
+ i = kstat_block_io_hash(major, minor) % kstat_block_io_tbl_size;
+ p = kstat.io_stat_tbl[i];
+ if (p == 0)
+ {
+
kstat.io_stat_tbl[i] = pstat;
+ }
+ else
+ {
+
printk("WARNING: kstat: Collision found in IO stat accounting table
(add). Try extending DK_BUCKETS\n");
+ while (p->next != 0)
+
{
+ p = p->next;
+
}
+
p->next = pstat;+ }
+ return pstat;
+}
+
+/* lookup an IO stat */
+static inline kstat_block_io* kstat_block_io_lookup(unsigned major, unsigned minor) +{
+ unsigned int i = kstat_block_io_hash(major, minor) % kstat_block_io_tbl_size;
+ kstat_block_io* p = kstat.io_stat_tbl[i];
+ while (p && p->major != major && p->minor != minor)
+ {
+
printk("WARNING: kstat: Collision found in IO stat accounting table
(lookup). Try extending DK_BUCKETS\n");
+
p = p->next;
+ }
+ if (p == 0)
+ {
+
p = kstat_block_io_add(major, minor);
+
if (p == 0)
+
{
+
return 0;
+
}+ }
+ return p;
+}
+
+/* This is used by MD to see if IDLE */
+static inline unsigned long kstat_get_rwblk(unsigned int major, unsigned int minor) +{
+ kstat_block_io* stat = kstat_block_io_lookup(major, minor);
+ if (stat == 0)
+ {
+
printk("ERROR: kstat: No IO stat found for (%d/%d)\n", major, minor);+ return 0;
+ }
+ return stat->rblk + stat->wblk;
+}
+
+
+
+
+
+
+
+
+
+
+
#if !defined(CONFIG_ARCH_S390)
/*
* Number of interrupts per specific IRQ source, since bootup
toc/linux-2.4.18-reempt/drivers/md/md.c renamed from tmp/linux-2.4.18-vanilla/drivers/md/md.c +5 -2
@@ -3284,6 +3284,9 @@return NULL ; } +/* MD devices are major=9 and minor=1-31 */ +#define DK_MAX_MAJOR 16 +#define DK_MAX_DISK 32static unsigned int sync_io[DK_MAX_MAJOR ][DK_MAX_DISK ];void md_sync_acct (kdev_t dev,unsigned long nr_sectors) {
@@ -3305,15 +3308,12 @@unsigned long curr_events; idle =1 ; - ITERATE_RDEV(mddev,rdev,tmp) { + ITERATE_RDEV(mddev,rdev,tmp) + {int major =MAJOR (rdev->dev);int idx =disk_index (rdev->dev); -
if ((idx >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR)) - continue;
-
-
curr_events = kstat.dk_drive_rblk[major][idx] +
-
kstat.dk_drive_wblk[major][idx] ;
+ curr_events = kstat_get_rwblk(major, idx);
curr_events -= sync_io[major][idx]; if ((curr_events - rdev->last_events) > 32) {
rdev->last_events = curr_events;
toc/linux-2.4.18-reempt/drivers/block/ll_rw_blk.c renamed from tmp/linux-2.4.18-vanilla/drivers/block/ll_rw_blk.c +0 -0
@@ -501,19 +501,22 @@
unsigned long nr_sectors, int new_io)
{
unsigned int major = MAJOR(dev);
- unsigned int index;
+ unsigned int minor = MINOR(dev);
+ kstat_block_io* stat = kstat_block_io_lookup(major, minor);
- index = disk_index(dev);
- if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR)) -
return;
+ if (stat == 0)
+ {
+
printk("ERROR: kstat: Haven't found an IO stat struct for major=%d
/ minor=%d\n", major, minor);
+ return;
+ }
- kstat.dk_drive[major][index] += new_io;
+ stat->io += new_io;
if (rw == READ) {
-
kstat.dk_drive_rio[major][index] += new_io;
-
kstat.dk_drive_rblk[major][index] += nr_sectors;
+
stat->rio += new_io;
+
stat->rblk += nr_sectors;
} else if (rw == WRITE) {
-
kstat.dk_drive_wio[major][index] += new_io;
-
kstat.dk_drive_wblk[major][index] += nr_sectors;
+
stat->wio += new_io;
+
stat->wblk += nr_sectors; } else
printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
}
toc/linux-2.4.18-reempt/fs/proc/proc_misc.c renamed from tmp/linux-2.4.18-vanilla/fs/proc/proc_misc.c +1 -3
@@ -282,25 +282,19 @@ len +=sprintf (page + len," %u" ,kstat_irqs (i));#endif - len +=sprintf (page + len,"\ndisk_io: " ); + len +=sprintf (page + len,"\ndisk_io: " ); -for (major =0 ; major <DK_MAX_MAJOR ; major++) { -
for (disk = 0; disk < DK_MAX_DISK; disk++) {-
int active = kstat.dk_drive[major][disk] +
-
kstat.dk_drive_rblk[major][disk] +
-
kstat.dk_drive_wblk[major][disk]; - if (active) - len += sprintf(page + len, - "(%u,%u):(%u,%u,%u,%u,%u) ",
-
major, disk,
-
kstat.dk_drive[major][disk],
-
kstat.dk_drive_rio[major][disk],
-
kstat.dk_drive_rblk[major][disk],
-
kstat.dk_drive_wio[major][disk],
-
kstat.dk_drive_wblk[major][disk]
-
); - }
- }
+ for (i = 0; i < kstat_devices_current_index; i++)
+ {
+ kstat_block_io* stat = &kstat_devices_array[i];
+ len += sprintf( page + len, "(%u,%u):(%u,%u,%u,%u,%u) ",
+ stat->major, stat->minor, + stat->io, + stat->rio, + stat->wio, + stat->rblk, + stat->wblk );
+ }
len += sprintf(page + len,
"\nctxt %u\n"
Quoted 5 lines · Jean-Eric Cuendet
I've made a new version of IO statistics in kstat that remove the previous limitations of
MAX_MAJOR
I've made tests on my machine.
Could someone test it, please?
Feedback welcome.
Your mailer was hungry and ate the patch (small examples):
Quoted 9 lines
+
+
unsigned int major;toc/linux-2.4.18-reempt/include/linux/kernel_stat.h renamed from tmp/linux-2.4.18-vanilla/include/linux/kernel_stat.h +3
-0+unsigned int minor; + +unsigned int io;
toc/linux-2.4.18-reempt/include/linux/kernel_stat.h renamed from tmp/linux-2.4.18-vanilla/include/linux/kernel_stat.h +2
-0+unsigned int rio; +unsigned int wio;
...
Quoted 9 lines
+
if (p == 0)
+
{
+kstat.io_stat_tbl[i] = pstat;+
}
+
Signature · 2 lines
Russell King ([email protected]) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html
On Wed, Mar 06, 2002 at 06:16:55PM +0100, Jean-Eric Cuendet wrote:
[...]
Quoted 26 lines
len += sprintf(page + len, - "(%u,%u):(%u,%u,%u,%u,%u) ",-
major, disk,
-
kstat.dk_drive[major][disk],
-
kstat.dk_drive_rio[major][disk],
-
kstat.dk_drive_rblk[major][disk],
-
kstat.dk_drive_wio[major][disk],
-
kstat.dk_drive_wblk[major][disk]
-); - }-
}(quoted diff) +5
-0+ for (i = 0; i < kstat_devices_current_index; i++) + { + kstat_block_io* stat = &kstat_devices_array[i]; + len += sprintf( page + len, "(%u,%u):(%u,%u,%u,%u,%u) ", + stat->major, stat->minor,
Review
Quoted 10 lines
(quoted diff) +6
-0+ stat->io, + stat->rio, + stat->wio, + stat->rblk, + stat->wblk ); + } len += sprintf(page + len, "\nctxt %u\n"
You are changing the order of the fields in /proc/stat. That breaks compatibility.
Dominik Kubla
Signature · 3 lines
ScioByte GmbH Zum Schiersteiner Grund 2 55127 Mainz (Germany) Phone: +49 700 724 629 83 Fax: +49 700 724 629 84 1024D/717F16BB A384 F5F1 F566 5716 5485 27EF 3B00 C007 717F 16BB
Quoted 9 lines · Jean-Eric Cuendet
Hi,
I've made a new version of IO statistics in kstat that remove the previous limitations ofMAX_MAJOR
I've made tests on my machine.
Could someone test it, please?
Feedback welcome.
Bye
-jec
Thank for your attention and help on updating my disk io patch. Here is the link to the original patch http://marc.theaimsgroup.com/?l=linux-kernel&m=100570447604813&w=2. I re-submitted it a while ago against 2.4 kernels and 2.5.2 kernel. You
can find patches related to disk io statistics at
http://lse.sourceforge.net/resource/diskio/diskio.html
Quoted 10 lines
Review
Quoted 10 lines
(quoted diff) +8
-0+ len += sprintf( page + len, "(%u,%u):(%u,%u,%u,%u,%u) ", + stat->major, stat->minor, + stat->io, + stat->rio, + stat->wio, + stat->rblk, + stat->wblk ); + }
Quoted 3 lines
You are changing the order of the fields in
/proc/stat. That breaks compatibility.
Thanks, you are right.
I'll change that.
-jec