[dm-devel] [PATCH] add endio fn to request structures

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jens,

Some storage devices have a mode where they require a special
command be sent inorder to perform failover. IBM's fastt is one of
these devices we are trying to add support for using the dm-multipath
framework.

The problem is that dm works at the bio level and we need to send down
something like a block pc or special request. So from dm multipath we could
have a thread and do a blk_execute_rq, or if we had some sort of end_request
function similar to the bio's and bh's endio function we could send the
failover command asynchronously. The attached patch adds an end_request fn
to the request structure for this purpose.

Maybe the fact that I have to ask for such a change should indidcate that
I am doing something brain dead, in which case please be gentle in your review
of my patch :)


--
Mike Christie
mikenc@xxxxxxxxxx
diff -aurp linux-2.6.6/drivers/block/ll_rw_blk.c linux-2.6.6-work/drivers/block/ll_rw_blk.c
--- linux-2.6.6/drivers/block/ll_rw_blk.c	2004-05-09 19:32:00.000000000 -0700
+++ linux-2.6.6-work/drivers/block/ll_rw_blk.c	2004-05-22 15:26:37.000000000 -0700
@@ -1599,6 +1599,7 @@ static struct request *get_request(reque
 	rq->ref_count = 1;
 	rq->q = q;
 	rq->rl = rl;
+	rq->end_request = NULL;
 	rq->waiting = NULL;
 	rq->special = NULL;
 	rq->data_len = 0;
@@ -1842,6 +1843,21 @@ int blk_rq_unmap_user(struct request *rq
 EXPORT_SYMBOL(blk_rq_unmap_user);
 
 /**
+ * blk_end_sync_rq - executes a completion event on a request
+ *			when it has completed.
+ * @rq: request to complete.
+ */
+void blk_end_sync_rq(struct request *rq)
+{
+	struct completion *waiting = rq->waiting;
+
+	rq->waiting = NULL;
+	complete(waiting);
+}
+
+EXPORT_SYMBOL(blk_end_sync_rq);
+
+/**
  * blk_execute_rq - insert a request into queue for execution
  * @q:		queue to insert the request in
  * @bd_disk:	matching gendisk
@@ -1874,6 +1890,7 @@ int blk_execute_rq(request_queue_t *q, s
 
 	rq->flags |= REQ_NOMERGE;
 	rq->waiting = &wait;
+	rq->end_request = blk_end_sync_rq;
 	elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
 	generic_unplug_device(q);
 	wait_for_completion(&wait);
@@ -2731,7 +2748,7 @@ EXPORT_SYMBOL(end_that_request_chunk);
 void end_that_request_last(struct request *req)
 {
 	struct gendisk *disk = req->rq_disk;
-	struct completion *waiting = req->waiting;
+	end_request_fn *end_fn = req->end_request;
 
 	if (unlikely(laptop_mode) && blk_fs_request(req))
 		laptop_io_completion();
@@ -2752,9 +2769,16 @@ void end_that_request_last(struct reques
 		disk->in_flight--;
 	}
 	__blk_put_request(req->q, req);
-	/* Do this LAST! The structure may be freed immediately afterwards */
-	if (waiting)
-		complete(waiting);
+
+	/*
+	 * If you are allocating reqs from the block layer you
+	 * should get a handle to the req and release it after
+	 * your end_request_fn is run.
+	 */
+	if (end_fn) {
+		req->end_request = NULL;
+		end_fn(req);
+	}
 }
 
 EXPORT_SYMBOL(end_that_request_last);
diff -aurp linux-2.6.6/drivers/block/paride/pd.c linux-2.6.6-work/drivers/block/paride/pd.c
--- linux-2.6.6/drivers/block/paride/pd.c	2004-05-09 19:33:13.000000000 -0700
+++ linux-2.6.6-work/drivers/block/paride/pd.c	2004-05-22 15:17:05.000000000 -0700
@@ -743,6 +743,7 @@ static int pd_special_command(struct pd_
 	rq.rq_disk = disk->gd;
 	rq.ref_count = 1;
 	rq.waiting = &wait;
+	rq.end_request = blk_end_sync_rq;
 	blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
 	wait_for_completion(&wait);
 	rq.waiting = NULL;
diff -aurp linux-2.6.6/drivers/ide/ide-cd.c linux-2.6.6-work/drivers/ide/ide-cd.c
--- linux-2.6.6/drivers/ide/ide-cd.c	2004-05-09 19:32:29.000000000 -0700
+++ linux-2.6.6-work/drivers/ide/ide-cd.c	2004-05-22 15:17:05.000000000 -0700
@@ -555,6 +555,8 @@ static void cdrom_queue_request_sense(id
 
 	rq->flags = REQ_SENSE;
 	rq->waiting = wait;
+	if (wait)
+		rq->end_request = blk_end_sync_rq;
 
 	/* NOTE! Save the failed command in "rq->buffer" */
 	rq->buffer = (void *) failed_command;
@@ -719,6 +721,7 @@ static int cdrom_decode_status(ide_drive
 		if ((stat & ERR_STAT) != 0) {
 			wait = rq->waiting;
 			rq->waiting = NULL;
+			rq->end_request = NULL;
 			if ((rq->flags & REQ_BLOCK_PC) != 0) {
 				cdrom_queue_request_sense(drive, wait,
 							  rq->sense, rq);
diff -aurp linux-2.6.6/drivers/ide/ide-io.c linux-2.6.6-work/drivers/ide/ide-io.c
--- linux-2.6.6/drivers/ide/ide-io.c	2004-05-09 19:33:13.000000000 -0700
+++ linux-2.6.6-work/drivers/ide/ide-io.c	2004-05-22 15:17:05.000000000 -0700
@@ -1372,6 +1372,7 @@ int ide_do_drive_cmd (ide_drive_t *drive
 	if (must_wait) {
 		rq->ref_count++;
 		rq->waiting = &wait;
+		rq->end_request = blk_end_sync_rq;
 	}
 
 	spin_lock_irqsave(&ide_lock, flags);
diff -aurp linux-2.6.6/drivers/ide/ide-tape.c linux-2.6.6-work/drivers/ide/ide-tape.c
--- linux-2.6.6/drivers/ide/ide-tape.c	2004-05-09 19:32:27.000000000 -0700
+++ linux-2.6.6-work/drivers/ide/ide-tape.c	2004-05-22 15:17:06.000000000 -0700
@@ -2798,6 +2798,7 @@ static void idetape_wait_for_request (id
 	}
 #endif /* IDETAPE_DEBUG_BUGS */
 	rq->waiting = &wait;
+	rq->end_request = blk_end_sync_rq;
 	spin_unlock_irq(&tape->spinlock);
 	wait_for_completion(&wait);
 	/* The stage and its struct request have been deallocated */
diff -aurp linux-2.6.6/include/linux/blkdev.h linux-2.6.6-work/include/linux/blkdev.h
--- linux-2.6.6/include/linux/blkdev.h	2004-05-09 19:32:26.000000000 -0700
+++ linux-2.6.6-work/include/linux/blkdev.h	2004-05-22 15:17:06.000000000 -0700
@@ -17,6 +17,7 @@
 
 #include <asm/scatterlist.h>
 
+struct request;
 struct request_queue;
 typedef struct request_queue request_queue_t;
 struct elevator_s;
@@ -84,6 +85,8 @@ struct request_list {
 
 #define BLK_MAX_CDB	16
 
+typedef void end_request_fn(struct request *rq);
+
 /*
  * try to put the fields that are referenced together in the same cacheline
  */
@@ -144,6 +147,7 @@ struct request {
 
 	struct completion *waiting;
 	void *special;
+	end_request_fn *end_request;
 
 	/*
 	 * when request is used as a packet command carrier
@@ -503,6 +507,7 @@ extern int blk_register_queue(struct gen
 extern void blk_unregister_queue(struct gendisk *disk);
 extern void register_disk(struct gendisk *dev);
 extern void generic_make_request(struct bio *bio);
+extern void blk_end_sync_rq(struct request *rq);
 extern void blk_put_request(struct request *);
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
 extern void __blk_attempt_remerge(request_queue_t *, struct request *);

[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux