From: Hannes Reinecke <hare@suse.de>
Date: Thu, 26 Jul 2012 11:11:21 +0200
Subject: md: add raid10 tracepoints
References: bnc#768084
Patch-Mainline: Not yet, not submitted.

This patch adds tracepoints for md/raid10.

It is now careful to not assume mddev->queue exists, as
dmraid doesn't set that (bnc#866843)

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/md/raid10.c |   39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -25,6 +25,9 @@
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 #include <linux/kthread.h>
+
+#include <trace/events/block.h>
+
 #include "md.h"
 #include "raid10.h"
 #include "raid0.h"
@@ -105,6 +108,9 @@ static void reshape_request_write(struct
 static void end_reshape_write(struct bio *bio);
 static void end_reshape(struct r10conf *conf);
 
+#define raid10_log(md, fmt, args...)				\
+	do { if ((md)->queue) blk_add_trace_msg((md)->queue, "raid10 " fmt, ##args); } while (0)
+
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct r10conf *conf = data;
@@ -310,6 +316,8 @@ static void raid_end_bio_io(struct r10bi
 	if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
 		bio->bi_error = -EIO;
 	if (done) {
+		trace_block_bio_complete(bdev_get_queue(bio->bi_bdev), bio, bio->bi_error);
+
 		bio_endio(bio);
 		/*
 		 * Wake up any possible resync thread that waits for the device
@@ -367,6 +375,7 @@ static void raid10_end_read_request(stru
 	struct md_rdev *rdev;
 	struct r10conf *conf = r10_bio->mddev->private;
 
+	trace_block_bio_complete(bdev_get_queue(bio->bi_bdev), bio, bio->bi_error);
 	slot = r10_bio->read_slot;
 	dev = r10_bio->devs[slot].devnum;
 	rdev = r10_bio->devs[slot].rdev;
@@ -450,6 +459,8 @@ static void raid10_end_write_request(str
 	struct md_rdev *rdev = NULL;
 	struct bio *to_put = NULL;
 
+	trace_block_bio_complete(bdev_get_queue(bio->bi_bdev), bio, bio->bi_error);
+
 	dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
 
 	if (repl)
@@ -885,6 +896,7 @@ static void flush_pending_writes(struct
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to disk
 		 * before proceeding w/ I/O */
+		raid10_log(conf->mddev, "bitmap unplug");
 		bitmap_unplug(conf->mddev->bitmap);
 		wake_up(&conf->wait_barrier);
 
@@ -968,6 +980,7 @@ static void wait_barrier(struct r10conf
 		 * that queue to get the nr_pending
 		 * count down.
 		 */
+		raid10_log(conf->mddev, "wait barrier");
 		wait_event_lock_irq(conf->wait_barrier,
 				    !conf->barrier ||
 				    (conf->nr_pending &&
@@ -1113,6 +1126,7 @@ static void __make_request(struct mddev
 		/* IO spans the reshape position.  Need to wait for
 		 * reshape to pass
 		 */
+		raid10_log(mddev, "reshape delay");
 		allow_barrier(conf);
 		wait_event(conf->wait_barrier,
 			   conf->reshape_progress <= bio->bi_iter.bi_sector ||
@@ -1128,6 +1142,7 @@ static void __make_request(struct mddev
 	     : (bio->bi_iter.bi_sector + sectors > conf->reshape_safe &&
 		bio->bi_iter.bi_sector < conf->reshape_progress))) {
 		/* Need to update reshape_position in metadata */
+		raid10_log(mddev, "reshape metadata delay");
 		mddev->reshape_position = conf->reshape_progress;
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		set_bit(MD_CHANGE_PENDING, &mddev->flags);
@@ -1218,8 +1233,13 @@ read_again:
 			r10_bio->sector = bio->bi_iter.bi_sector +
 				sectors_handled;
 			goto read_again;
-		} else
+		} else {
+			if (mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
+						      read_bio, disk_devt(mddev->gendisk),
+						      r10_bio->sector);
 			generic_make_request(read_bio);
+		}
 		return;
 	}
 
@@ -1354,6 +1374,7 @@ retry_write:
 				rdev_dec_pending(rdev, mddev);
 			}
 		}
+		raid10_log(mddev, "rdev %d blocked", blocked_rdev->raid_disk);
 		allow_barrier(conf);
 		md_wait_for_blocked_rdev(blocked_rdev, mddev);
 		wait_barrier(conf);
@@ -1414,6 +1435,10 @@ retry_write:
 				bio_list_add(&conf->pending_bio_list, mbio);
 				conf->pending_count++;
 			}
+			if (mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(mbio->bi_bdev),
+						      mbio, disk_devt(mddev->gendisk),
+						      r10_bio->sector);
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			if (!plug)
 				md_wakeup_thread(mddev->thread);
@@ -1850,6 +1875,8 @@ static void end_sync_read(struct bio *bi
 	struct r10conf *conf = r10_bio->mddev->private;
 	int d;
 
+	trace_block_bio_complete(bdev_get_queue(bio->bi_bdev), bio, bio->bi_error);
+
 	if (bio == r10_bio->master_bio) {
 		/* this is a reshape read */
 		d = r10_bio->read_slot; /* really the read dev */
@@ -1917,6 +1944,8 @@ static void end_sync_write(struct bio *b
 	int repl;
 	struct md_rdev *rdev = NULL;
 
+	trace_block_bio_complete(bdev_get_queue(bio->bi_bdev), bio, bio->bi_error);
+
 	d = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
 	if (repl)
 		rdev = conf->mirrors[d].replacement;
@@ -2545,6 +2574,7 @@ static void handle_read_error(struct mdd
 	char b[BDEVNAME_SIZE];
 	unsigned long do_sync;
 	int max_sectors;
+	dev_t bio_dev;
 
 	/* we got a read error. Maybe the drive is bad.  Maybe just
 	 * the block and we can fix it.
@@ -2556,6 +2586,7 @@ static void handle_read_error(struct mdd
 	 */
 	bio = r10_bio->devs[slot].bio;
 	bdevname(bio->bi_bdev, b);
+	bio_dev = bio->bi_bdev->bd_dev;
 	bio_put(bio);
 	r10_bio->devs[slot].bio = NULL;
 
@@ -2634,8 +2665,12 @@ read_more:
 			+ sectors_handled;
 
 		goto read_more;
-	} else
+	} else {
+		trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
+				      bio, bio_dev,
+				      r10_bio->devs[slot].addr);
 		generic_make_request(bio);
+	}
 }
 
 static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
