
Having the average disk IO size really isn't all that interesting.
To determine if the IOs being sent are of approximately what we expect them to be, it's much more interesting to see a histogram of IO sizes.  The patch below
stores that information, and reports it in powers of 2, 

Index: block/genhd.c
===================================================================
RCS file: /var/cvs/linux-2.6/block/genhd.c,v
retrieving revision 1.5
diff -u -p -r1.5 genhd.c
--- block/genhd.c	3 Apr 2006 13:44:01 -0000	1.5
+++ block/genhd.c	21 Apr 2006 18:36:06 -0000
@@ -376,7 +376,9 @@ static ssize_t disk_stats_read(struct ge
 		"%8lu %8lu %8llu %8u "
 		"%8lu %8lu %8llu %8u "
 		"%8u %8u %8u"
-		"\n",
+		"\n"
+		"4k %8u %8u %8u %8u %8u %8u %8u %8u %8u %8u %8u\n"
+		"4k %8u %8u %8u %8u %8u %8u %8u %8u %8u %8u %8u\n",
 		disk_stat_read(disk, ios[READ]),
 		disk_stat_read(disk, merges[READ]),
 		(unsigned long long)disk_stat_read(disk, sectors[READ]),
@@ -387,7 +389,29 @@ static ssize_t disk_stats_read(struct ge
 		jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])),
 		disk->in_flight,
 		jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
-		jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
+		jiffies_to_msecs(disk_stat_read(disk, time_in_queue)),
+		disk_stat_read(disk, sizes[READ][0]),
+		disk_stat_read(disk, sizes[READ][1]),
+		disk_stat_read(disk, sizes[READ][2]),
+		disk_stat_read(disk, sizes[READ][3]),
+		disk_stat_read(disk, sizes[READ][4]),
+		disk_stat_read(disk, sizes[READ][5]),
+		disk_stat_read(disk, sizes[READ][6]),
+		disk_stat_read(disk, sizes[READ][7]),
+		disk_stat_read(disk, sizes[READ][8]),
+		disk_stat_read(disk, sizes[READ][9]),
+		disk_stat_read(disk, sizes[READ][10]),
+		disk_stat_read(disk, sizes[WRITE][0]),
+		disk_stat_read(disk, sizes[WRITE][1]),
+		disk_stat_read(disk, sizes[WRITE][2]),
+		disk_stat_read(disk, sizes[WRITE][3]),
+		disk_stat_read(disk, sizes[WRITE][4]),
+		disk_stat_read(disk, sizes[WRITE][5]),
+		disk_stat_read(disk, sizes[WRITE][6]),
+		disk_stat_read(disk, sizes[WRITE][7]),
+		disk_stat_read(disk, sizes[WRITE][8]),
+		disk_stat_read(disk, sizes[WRITE][9]),
+		disk_stat_read(disk, sizes[WRITE][10]));
 }
 static struct disk_attribute disk_attr_uevent = {
 	.attr = {.name = "uevent", .mode = S_IWUSR },
Index: block/ll_rw_blk.c
===================================================================
RCS file: /var/cvs/linux-2.6/block/ll_rw_blk.c,v
retrieving revision 1.8
diff -u -p -r1.8 ll_rw_blk.c
--- block/ll_rw_blk.c	3 Apr 2006 13:44:01 -0000	1.8
+++ block/ll_rw_blk.c	21 Apr 2006 18:27:37 -0000
@@ -3187,6 +3187,16 @@ static void blk_recalc_rq_sectors(struct
 	}
 }
 
+static void disk_stat_histogram(struct gendisk *disk, int rw, unsigned nr_bytes)
+{
+	int bucket = fls(nr_bytes) - 12; /* Go down to 4k */
+	if (bucket < 0)
+		bucket = 0;
+	if (bucket > 11)
+		bucket = 11;
+	disk_stat_inc(disk, sizes[rw][bucket]);
+}
+
 static int __end_that_request_first(struct request *req, int uptodate,
 				    int nr_bytes)
 {
@@ -3220,6 +3230,7 @@ static int __end_that_request_first(stru
 		const int rw = rq_data_dir(req);
 
 		disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
+		disk_stat_histogram(req->rq_disk, rw, nr_bytes);
 	}
 
 	total_bytes = bio_nbytes = 0;
Index: include/linux/genhd.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/genhd.h,v
retrieving revision 1.17
diff -u -p -r1.17 genhd.h
--- include/linux/genhd.h	19 Apr 2006 04:56:18 -0000	1.17
+++ include/linux/genhd.h	21 Apr 2006 18:19:58 -0000
@@ -96,6 +96,7 @@ struct disk_stats {
 	unsigned long ticks[2];
 	unsigned long io_ticks;
 	unsigned long time_in_queue;
+	unsigned int sizes[2][11];
 };
 	
 struct gendisk {

