[dm-devel] [RFC][PATCH 2/10] I/O context inheritance

Hirokazu Takahashi taka at valinux.co.jp
Tue Apr 22 13:53:01 UTC 2008


Every I/O scheduler should get a iocontext from a given bio,
not from the current process.


Signed-off-by: Hirokazu Takahashi <taka at valinux.co.jp>


--- linux-2.6.25.bio0/block/blk-core.c	2008-04-22 15:48:32.000000000 +0900
+++ linux-2.6.25/block/blk-core.c	2008-04-22 16:13:31.000000000 +0900
@@ -600,7 +600,8 @@ static inline void blk_free_request(stru
 }
 
 static struct request *
-blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask)
+blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask,
+						struct io_context *ioc)
 {
 	struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -614,7 +615,7 @@ blk_alloc_request(struct request_queue *
 	rq->cmd_flags = rw | REQ_ALLOCED;
 
 	if (priv) {
-		if (unlikely(elv_set_request(q, rq, gfp_mask))) {
+		if (unlikely(elv_set_request(q, rq, gfp_mask, ioc))) {
 			mempool_free(rq, q->rq.rq_pool);
 			return NULL;
 		}
@@ -702,7 +703,7 @@ static struct request *get_request(struc
 {
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
-	struct io_context *ioc = NULL;
+	struct io_context *ioc;
 	const int rw = rw_flags & 0x01;
 	int may_queue, priv;
 
@@ -710,9 +711,12 @@ static struct request *get_request(struc
 	if (may_queue == ELV_MQUEUE_NO)
 		goto rq_starved;
 
+	ioc = bio ? bio->bi_io_context : current->io_context;
+
 	if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) {
 		if (rl->count[rw]+1 >= q->nr_requests) {
-			ioc = current_io_context(GFP_ATOMIC, q->node);
+			if (!ioc)
+				ioc = current_io_context(GFP_ATOMIC, q->node);
 			/*
 			 * The queue will fill after this allocation, so set
 			 * it as full, and mark this process as "batching".
@@ -754,7 +758,7 @@ static struct request *get_request(struc
 
 	spin_unlock_irq(q->queue_lock);
 
-	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
+	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask, ioc);
 	if (unlikely(!rq)) {
 		/*
 		 * Allocation failed presumably due to memory. Undo anything
--- linux-2.6.25.bio0/include/linux/elevator.h	2008-04-22 15:48:36.000000000 +0900
+++ linux-2.6.25/include/linux/elevator.h	2008-04-22 15:51:27.000000000 +0900
@@ -22,7 +22,7 @@ typedef struct request *(elevator_reques
 typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *);
 typedef int (elevator_may_queue_fn) (struct request_queue *, int);
 
-typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t);
+typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t, struct io_context *);
 typedef void (elevator_put_req_fn) (struct request *);
 typedef void (elevator_activate_req_fn) (struct request_queue *, struct request *);
 typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *);
@@ -113,7 +113,7 @@ extern int elv_register_queue(struct req
 extern void elv_unregister_queue(struct request_queue *q);
 extern int elv_may_queue(struct request_queue *, int);
 extern void elv_completed_request(struct request_queue *, struct request *);
-extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
+extern int elv_set_request(struct request_queue *, struct request *, gfp_t, struct io_context *);
 extern void elv_put_request(struct request_queue *, struct request *);
 
 /*
--- linux-2.6.25.bio0/block/elevator.c	2008-04-22 15:48:32.000000000 +0900
+++ linux-2.6.25/block/elevator.c	2008-04-22 15:51:27.000000000 +0900
@@ -864,12 +864,13 @@ struct request *elv_former_request(struc
 	return NULL;
 }
 
-int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
+int elv_set_request(struct request_queue *q, struct request *rq,
+				 gfp_t gfp_mask, struct io_context *ioc)
 {
 	elevator_t *e = q->elevator;
 
 	if (e->ops->elevator_set_req_fn)
-		return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
+		return e->ops->elevator_set_req_fn(q, rq, gfp_mask, ioc);
 
 	rq->elevator_private = NULL;
 	return 0;
--- linux-2.6.25.bio0/block/cfq-iosched.c	2008-04-22 15:48:32.000000000 +0900
+++ linux-2.6.25/block/cfq-iosched.c	2008-04-22 17:15:21.000000000 +0900
@@ -1571,14 +1571,16 @@ static int cfq_cic_link(struct cfq_data 
  * than one device managed by cfq.
  */
 static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, struct io_context *ioc, gfp_t gfp_mask)
 {
-	struct io_context *ioc = NULL;
 	struct cfq_io_context *cic;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
-	ioc = get_io_context(gfp_mask, cfqd->queue->node);
+	ioc = ioc_object_link(ioc);
+
+	if (!ioc)
+		ioc = get_io_context(gfp_mask, cfqd->queue->node);
 	if (!ioc)
 		return NULL;
 
@@ -1938,7 +1940,8 @@ static void cfq_put_request(struct reque
  * Allocate cfq data structures associated with this request.
  */
 static int
-cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
+cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask,
+				struct io_context *ioc)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_io_context *cic;
@@ -1949,7 +1952,7 @@ cfq_set_request(struct request_queue *q,
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
-	cic = cfq_get_io_context(cfqd, gfp_mask);
+	cic = cfq_get_io_context(cfqd, ioc, gfp_mask);
 
 	spin_lock_irqsave(q->queue_lock, flags);
 




More information about the dm-devel mailing list