public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH]Disk IO statisitics gathering for all disks
@ 2001-11-08 22:33 Mingming cao
  2001-11-08 22:39 ` [Lse-tech] " Christoph Hellwig
  0 siblings, 1 reply; 3+ messages in thread
From: Mingming cao @ 2001-11-08 22:33 UTC (permalink / raw)
  To: Alan Cox, linux-kernel, lse-tech

[-- Attachment #1: Type: text/plain, Size: 944 bytes --]

Hello,

Attached is a patch to dynamically allocate the data buffers for the
disk statistics, and to extend the gathering of disk statistics to
include major numbers greater than 15.

A disk statistics structure is allocated when a new block device 
is registered.  A global array (kstat.dkdrive_info[]) is used
to hold the address of the statistics structures for all block
devices.  The  disk statistics lookup is the same as before: indexed by
the major number and the disk number.  Note that this patch includes the
changes 
of function disk_index() in genhd.h from linux-2.4.10-ac kernel, in
order to make the disk index lookup work for more disks.

This patch is against 2.4.14 kernel and has been tested.  I greatly
appreciate any feedback from you.  Please take a look and cc you
comments to me.


Have a good day.

-- 
Mingming Cao
IBM Linux Technology Center
503-578-5024  IBM T/L: 775-5024
cmm@us.ibm.com
http://www.ibm.com/linux/ltc

[-- Attachment #2: dk-scale --]
[-- Type: text/plain, Size: 7420 bytes --]

diff -urN -X dontdiff linux-2.4.13/drivers/block/ll_rw_blk.c /home/ming/linux-13-dk/drivers/block/ll_rw_blk.c
--- linux-2.4.13/drivers/block/ll_rw_blk.c	Sat Oct 13 10:30:30 2001
+++ /home/ming/linux-13-dk/drivers/block/ll_rw_blk.c	Tue Nov  6 15:55:16 2001
@@ -501,20 +501,26 @@
 {
 	unsigned int major = MAJOR(dev);
 	unsigned int index;
+	dk_stat_t * ds;
 
+	ds = kstat.dk_drive_info[major];
+	if (ds == NULL) 
+		return;
+	
 	index = disk_index(dev);
-	if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
+	if (index >= DK_MAX_DISK)
 		return;
-
-	kstat.dk_drive[major][index] += new_io;
+	
+	ds += index;
 	if (rw == READ) {
-		kstat.dk_drive_rio[major][index] += new_io;
-		kstat.dk_drive_rblk[major][index] += nr_sectors;
+		ds->dk_drive_rio += new_io;
+		ds->dk_drive_rblk += nr_sectors;
 	} else if (rw == WRITE) {
-		kstat.dk_drive_wio[major][index] += new_io;
-		kstat.dk_drive_wblk[major][index] += nr_sectors;
-	} else
+		ds->dk_drive_wio += new_io;
+		ds->dk_drive_wblk += nr_sectors;
+	} else {
 		printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
+	}
 }
 
 /*
diff -urN -X dontdiff linux-2.4.13/drivers/md/md.c /home/ming/linux-13-dk/drivers/md/md.c
--- linux-2.4.13/drivers/md/md.c	Wed Oct 17 14:21:00 2001
+++ /home/ming/linux-13-dk/drivers/md/md.c	Tue Nov  6 15:55:36 2001
@@ -3301,12 +3301,15 @@
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		int major = MAJOR(rdev->dev);
 		int idx = disk_index(rdev->dev);
+		dk_stat_t * ds;
 
 		if ((idx >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
 			continue;
 
-		curr_events = kstat.dk_drive_rblk[major][idx] +
-						kstat.dk_drive_wblk[major][idx] ;
+        	if ((ds = kstat.dk_drive_info[major]) == NULL) 
+			continue;
+		ds += idx;
+		curr_events = ds->dk_drive_rblk + ds->dk_drive_wblk;
 		curr_events -= sync_io[major][idx];
 		if ((curr_events - rdev->last_events) > 32) {
 			rdev->last_events = curr_events;
diff -urN -X dontdiff linux-2.4.13/fs/block_dev.c /home/ming/linux-13-dk/fs/block_dev.c
--- linux-2.4.13/fs/block_dev.c	Thu Oct 11 08:32:35 2001
+++ /home/ming/linux-13-dk/fs/block_dev.c	Tue Nov  6 15:20:14 2001
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 #include <linux/major.h>
+#include <linux/kernel_stat.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/iobuf.h>
@@ -437,11 +438,52 @@
 	return ret;
 }
 
+/*
+ *        Allocate a statistics structure for the give device
+ */
+
+static int alloc_dk_stat(unsigned int major)
+{
+	dk_stat_t * new; 
+	
+	/*allocate space for statistics */
+	if (kstat.dk_drive_info[major] != NULL) {
+		printk(KERN_WARNING "register_blkdev: stat struct"
+			" for device %d exists before register\n",
+			major);
+	} else {
+		int size = sizeof(dk_stat_t) * DK_MAX_DISK;
+		new = (dk_stat_t *)kmalloc(size, GFP_KERNEL);
+		if (new == NULL) {
+			return -ENOMEM;
+		}
+		memset(new, 0, size);
+		kstat.dk_drive_info[major] = new;
+	}
+	return 0;
+}
+
+static void free_dk_stat(unsigned int major)
+{
+	dk_stat_t * ds;
+	
+	ds = kstat.dk_drive_info[major];
+	kstat.dk_drive_info[major] = NULL;
+	
+	if (ds != NULL)
+		kfree(ds);
+}
+
 int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
 {
+	int err;
+	
 	if (major == 0) {
 		for (major = MAX_BLKDEV-1; major > 0; major--) {
 			if (blkdevs[major].bdops == NULL) {
+				err = alloc_dk_stat(major);
+				if (err != 0)
+					return err;
 				blkdevs[major].name = name;
 				blkdevs[major].bdops = bdops;
 				return major;
@@ -453,8 +495,13 @@
 		return -EINVAL;
 	if (blkdevs[major].bdops && blkdevs[major].bdops != bdops)
 		return -EBUSY;
+
+	err = alloc_dk_stat(major);
+	if (err != 0)
+		return err;
 	blkdevs[major].name = name;
 	blkdevs[major].bdops = bdops;
+	
 	return 0;
 }
 
@@ -468,6 +515,9 @@
 		return -EINVAL;
 	blkdevs[major].name = NULL;
 	blkdevs[major].bdops = NULL;
+
+	/* free statistic structure */
+	free_dk_stat(major);
 	return 0;
 }
 
diff -urN -X dontdiff linux-2.4.13/fs/proc/proc_misc.c /home/ming/linux-13-dk/fs/proc/proc_misc.c
--- linux-2.4.13/fs/proc/proc_misc.c	Thu Oct 11 10:46:57 2001
+++ /home/ming/linux-13-dk/fs/proc/proc_misc.c	Tue Nov  6 16:16:40 2001
@@ -309,21 +309,26 @@
 
 	len += sprintf(page + len, "\ndisk_io: ");
 
-	for (major = 0; major < DK_MAX_MAJOR; major++) {
+	for (major = 0; major < MAX_BLKDEV; major++) {
+		if ( kstat.dk_drive_info[major] == NULL)
+			continue;
 		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];
+			dk_stat_t * ds;
+			int active;
+
+			ds = kstat.dk_drive_info[major] + disk;
+			active = ds->dk_drive_rio + ds->dk_drive_wio +
+				ds->dk_drive_rblk + ds->dk_drive_wblk;
 			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]
-			);
+					ds->dk_drive_rio + ds->dk_drive_wio,
+					ds->dk_drive_rio,
+					ds->dk_drive_rblk,
+					ds->dk_drive_wio,
+					ds->dk_drive_wblk
+				);
 		}
 	}
 
diff -urN -X dontdiff linux-2.4.13/include/linux/genhd.h /home/ming/linux-13-dk/include/linux/genhd.h
--- linux-2.4.13/include/linux/genhd.h	Tue Oct 23 22:00:42 2001
+++ /home/ming/linux-13-dk/include/linux/genhd.h	Mon Nov  5 16:11:08 2001
@@ -256,21 +256,30 @@
 	unsigned int index;
 
 	switch (major) {
-		case DAC960_MAJOR+0:
-			index = (minor & 0x00f8) >> 3;
-			break;
 		case SCSI_DISK0_MAJOR:
 			index = (minor & 0x00f0) >> 4;
 			break;
 		case IDE0_MAJOR:	/* same as HD_MAJOR */
 		case XT_DISK_MAJOR:
+		case IDE1_MAJOR:
+		case IDE2_MAJOR:
+		case IDE3_MAJOR:
+		case IDE4_MAJOR:
+		case IDE5_MAJOR:
 			index = (minor & 0x0040) >> 6;
 			break;
-		case IDE1_MAJOR:
-			index = ((minor & 0x0040) >> 6) + 2;
+		case SCSI_CDROM_MAJOR:
+			index = minor & 0x000f;
 			break;
 		default:
-			return 0;
+			if (major >= SCSI_DISK1_MAJOR && major <= SCSI_DISK7_MAJOR)
+				index = (minor & 0x00f0) >> 4;
+			else if (major >= DAC960_MAJOR && major <= DAC960_MAJOR + 7)
+				index = (minor & 0x00f8) >> 3;
+			else if (major >= IDE6_MAJOR && major <= IDE9_MAJOR)
+				index = (minor & 0x0040) >> 6;
+			else
+				return 0;
 	}
 	return index;
 }
diff -urN -X dontdiff linux-2.4.13/include/linux/kernel_stat.h /home/ming/linux-13-dk/include/linux/kernel_stat.h
--- linux-2.4.13/include/linux/kernel_stat.h	Tue Oct 23 21:59:06 2001
+++ /home/ming/linux-13-dk/include/linux/kernel_stat.h	Mon Nov  5 16:11:08 2001
@@ -15,15 +15,19 @@
 #define DK_MAX_MAJOR 16
 #define DK_MAX_DISK 16
 
+struct dk_stat{
+	unsigned int dk_drive_rio;
+	unsigned int dk_drive_wio;
+	unsigned int dk_drive_rblk;
+	unsigned int dk_drive_wblk;
+};
+
+typedef struct dk_stat dk_stat_t;
 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];
+	dk_stat_t *dk_drive_info[MAX_BLKDEV];	     
 	unsigned int pgpgin, pgpgout;
 	unsigned int pswpin, pswpout;
 #if !defined(CONFIG_ARCH_S390)


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Lse-tech] [PATCH]Disk IO statisitics gathering for all disks
  2001-11-08 22:33 [PATCH]Disk IO statisitics gathering for all disks Mingming cao
@ 2001-11-08 22:39 ` Christoph Hellwig
  2001-11-09  0:45   ` Mingming cao
  0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2001-11-08 22:39 UTC (permalink / raw)
  To: Mingming cao; +Cc: Alan Cox, linux-kernel, lse-tech

On Thu, Nov 08, 2001 at 02:33:44PM -0800, Mingming cao wrote:
> Hello,
> 
> Attached is a patch to dynamically allocate the data buffers for the
> disk statistics, and to extend the gathering of disk statistics to
> include major numbers greater than 15.
> 
> A disk statistics structure is allocated when a new block device 
> is registered.  A global array (kstat.dkdrive_info[]) is used
> to hold the address of the statistics structures for all block
> devices.  The  disk statistics lookup is the same as before: indexed by
> the major number and the disk number.

A very minor nitpick: please use struct dk_stat (or disk_stat) instead of
dk_stat_t - it is by no means an opaque type.

	Christoph

-- 
Of course it doesn't work. We've performed a software upgrade.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Lse-tech] [PATCH]Disk IO statisitics gathering for all disks
  2001-11-08 22:39 ` [Lse-tech] " Christoph Hellwig
@ 2001-11-09  0:45   ` Mingming cao
  0 siblings, 0 replies; 3+ messages in thread
From: Mingming cao @ 2001-11-09  0:45 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Alan Cox, linux-kernel, lse-tech

Christoph Hellwig wrote:
> 
> A very minor nitpick: please use struct dk_stat (or disk_stat) instead of
> dk_stat_t - it is by no means an opaque type.
> 

You are right.  Thank you for pointing it out. 

-- 
Mingming Cao
IBM Linux Technology Center
503-578-5024  IBM T/L: 775-5024
cmm@us.ibm.com
http://www.ibm.com/linux/ltc

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2001-11-09  0:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-11-08 22:33 [PATCH]Disk IO statisitics gathering for all disks Mingming cao
2001-11-08 22:39 ` [Lse-tech] " Christoph Hellwig
2001-11-09  0:45   ` Mingming cao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox