Skip to contentSkip to conversation

Updated disk I/O statistics patch for 2.5.3-pre6

PATCH Mingming cao 1 participant 1 message Jan 29, 2002

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Hi, Jens and All,

A couple of months ago, I made a patch to gathering disk I/O statistics for all majors. Thank you all for your feedbacks. Basically, in that patch, the disk I/O statistics are gathered at the per request queue level, instead of at the global level in the current implementation. Statistic data are moved from the global kstat structure to the request_queue structures, and it is allocated/freed when the request queue is initialized and freed. This way it is 1)self-controlled, 2)statistics implementation is not affected by the major/minor numbers,
3) faster the lookup, and 4)able to gathering statistics for all disks while keep the memory needs minimized.

Here is the updated disk I/O statistics patch corresponding to the block I/O layer changes in 2.5. It's aganist 2.5.3-pre6. Please take a look.

Signature · 2 lines
Mingming Cao
IBM Linux Technology Center
drivers/block/ll_rw_blk.c +25 -9
diff -urN -X dontdiff 253-pre6/drivers/block/ll_rw_blk.c dk-pre6/drivers/block/ll_rw_blk.c
@@ -724,6 +724,11 @@
 
 	elevator_exit(q, &q->elevator);
 
+	/*
+	 * free statistics structure
+	 */
+	kfree(q->dk_stat);
+
 	memset(q, 0, sizeof(*q));
 }
 
@@ -800,6 +805,7 @@
 int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
 {
 	int ret;
+	struct disk_stat * new;
 
 	if (blk_init_free_list(q))
 		return -ENOMEM;
@@ -827,6 +833,17 @@
 
 	blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
 	blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+
+	/*
+	 * At last, allocate and initilize the statistics
+	 */
+	new = kmalloc(sizeof(struct disk_stat),GFP_KERNEL);
+	if ( new == NULL)
+		printk(KERN_WARNING "blk_init_queue:error in allocating queue statistics\n");
+	else
+		memset(new, 0, sizeof(struct disk_stat));
+	q->dk_stat = new;
+
 	return 0;
 }
 
@@ -934,21 +951,20 @@
 
 void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
-	unsigned int major = major(rq->rq_dev);
 	int rw = rq_data_dir(rq);
-	unsigned int index;
+	request_queue_t * q = rq->q;
+	struct disk_stat * ds;
 
-	index = disk_index(rq->rq_dev);
-	if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
+	ds = q->dk_stat;
+	if (ds == NULL)
 		return;
 
-	kstat.dk_drive[major][index] += new_io;
 	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;
+		ds->dk_drive_wio += new_io;
+		ds->dk_drive_wblk += nr_sectors;
 	} else
 		printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
 }
drivers/ide/ide.c +4 -1
diff -urN -X dontdiff 253-pre6/drivers/ide/ide.c dk-pre6/drivers/ide/ide.c
@@ -1409,7 +1409,10 @@
 {
 	ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[major(dev)].data;
 
-	return &hwif->drives[DEVICE_NR(dev) & 1].queue;
+	if (DEVICE_NR(dev) >= MAX_DRIVES)
+		return NULL;
+	else
+		return &hwif->drives[DEVICE_NR(dev) & 1].queue;
 }
 
 /*
drivers/md/md.c +7 -4
diff -urN -X dontdiff 253-pre6/drivers/md/md.c dk-pre6/drivers/md/md.c
@@ -3311,12 +3311,15 @@
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		int major = major(rdev->dev);
 		int idx = disk_index(rdev->dev);
-
+		request_queue_t * rq = blk_get_queue(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] ;
+		
+		if (rq == NULL || (rq->dk_stat == NULL))
+			continue;
+		curr_events = rq->dk_stat->dk_drive_rblk + 
+			rq->dk_stat->dk_drive_wblk ;
 		curr_events -= sync_io[major][idx];
 		if ((curr_events - rdev->last_events) > 32) {
 			rdev->last_events = curr_events;
fs/proc/proc_misc.c +39 -16

75 lines not on this page · raw message

include/linux/blkdev.h +11 -0
diff -urN -X dontdiff 253-pre6/include/linux/blkdev.h dk-pre6/include/linux/blkdev.h
@@ -131,6 +131,13 @@
  */
 #define QUEUE_NR_REQUESTS	8192
 
+struct disk_stat{
+	unsigned int dk_drive_rio;
+	unsigned int dk_drive_wio;
+	unsigned int dk_drive_rblk;
+	unsigned int dk_drive_wblk;
+};
+
 struct request_queue
 {
 	/*
@@ -191,6 +198,10 @@
 	unsigned long		seg_boundary_mask;
 
 	wait_queue_head_t	queue_wait;
+	/*
+	 * statistics
+	 */
+	struct disk_stat 	*dk_stat;
 };
 
 #define RQ_INACTIVE		(-1)
include/linux/kernel_stat.h +0 -5
diff -urN -X dontdiff 253-pre6/include/linux/kernel_stat.h dk-pre6/include/linux/kernel_stat.h
@@ -19,11 +19,6 @@
 	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];
 	unsigned int pgpgin, pgpgout;
 	unsigned int pswpin, pswpout;
 #if !defined(CONFIG_ARCH_S390)