Skip to contentSkip to conversation

block: optimizations in blk_rq_timed_out_timer()

PATCH In review [email protected] 3 participants 10 messages Oct 28, 2008 – Oct 30, 2008

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

PATCH 1/1 block: optimizations in blk_rq_timed_out_timer()

Now the rq->deadline can't be zero if the request is in the timeout_list, so there is no need to have next_set. There is no need to access a request's deadline field if blk_rq_timed_out is called on it.

block/blk-timeout.c +5 -7
diff -r a6ae42397ede block/blk-timeout.c
@@ -118,7 +118,7 @@
 void blk_rq_timed_out_timer(unsigned long data)
 {
 	struct request_queue *q = (struct request_queue *) data;
-	unsigned long flags, uninitialized_var(next), next_set = 0;
+	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
 
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -133,15 +133,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		} else {
+			if (!next || time_after(next, rq->deadline))
+				next = rq->deadline;
 		}
-		if (!next_set) {
-			next = rq->deadline;
-			next_set = 1;
-		} else if (time_after(next, rq->deadline))
-			next = rq->deadline;
 	}
 
-	if (next_set && !list_empty(&q->timeout_list))
+	if (next)
 		mod_timer(&q->timeout, round_jiffies(next));
 
 	spin_unlock_irqrestore(q->queue_lock, flags);
#1 lore raw
Quoted 19 lines · On Tue, 28 Oct 2008 11:22:43 -0700 [email protected] wrote:

Now the rq->deadline can't be zero if the request is in the timeout_list, so there is no need to have next_set. There is no need to access a request's deadline field if blk_rq_timed_out is called on it.

diff -r a6ae42397ede block/blk-timeout.c

block/blk-timeout.c +1 -1
@@ -118,7 +118,7 @@
 void blk_rq_timed_out_timer(unsigned long data)
 {
 	struct request_queue *q = (struct request_queue *) data;
-	unsigned long flags, uninitialized_var(next), next_set = 0;
+	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
 
 	spin_lock_irqsave(q->queue_lock, flags);

block/blk-timeout.c line 138

Quoted 6 lines
block/blk-timeout.c +3 -0
@@ -133,15 +133,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		} else {
+			if (!next || time_after(next, rq->deadline))
+				next = rq->deadline;

Hmm, blk_rq_timed_out(rq) could put the rq back to q->timeout_list. We need to take care of the rq->deadline like this?

block/blk-timeout.c line 138

Quoted 7 lines
block/blk-timeout.c +3 -0
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		}
 
+		if (!next || time_after(next, rq->deadline))
+			next = rq->deadline;

But if blk_rq_timed_out calls __blk_complete_request, we don't want to touch the rq here, I guess.

Quoted 17 lines
block/blk-timeout.c +1 -7
 		}
-		if (!next_set) {
-			next = rq->deadline;
-			next_set = 1;
-		} else if (time_after(next, rq->deadline))
-			next = rq->deadline;
 	}
 
-	if (next_set && !list_empty(&q->timeout_list))
+	if (next)
 		mod_timer(&q->timeout, round_jiffies(next));
 
 	spin_unlock_irqrestore(q->queue_lock, flags);
--

To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#2 lore raw
Quoted 20 lines · FUJITA Tomonori [[email protected]] wrote:
Quoted 17 lines · On Tue, 28 Oct 2008 11:22:43 -0700 [email protected] wrote:

Now the rq->deadline can't be zero if the request is in the timeout_list, so there is no need to have next_set. There is no need to access a request's deadline field if blk_rq_timed_out is called on it.

diff -r a6ae42397ede block/blk-timeout.c

block/blk-timeout.c +1 -1
@@ -118,7 +118,7 @@
 void blk_rq_timed_out_timer(unsigned long data)
 {
 	struct request_queue *q = (struct request_queue *) data;
-	unsigned long flags, uninitialized_var(next), next_set = 0;
+	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
 
Quoted 11 lines

block/blk-timeout.c line 138

Quoted 8 lines
block/blk-timeout.c +3 -0
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -133,15 +133,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		} else {
+			if (!next || time_after(next, rq->deadline))
+				next = rq->deadline;

Hmm, blk_rq_timed_out(rq) could put the rq back to q->timeout_list. We need to take care of the rq->deadline like this?

If it is put back on the list, it would be placed at the end of the list so we will get to work on it again in the list traversal. There is no need to access it now.

Quoted 11 lines

block/blk-timeout.c line 138

Quoted 8 lines
block/blk-timeout.c +3 -0
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		}
 
+		if (!next || time_after(next, rq->deadline))
+			next = rq->deadline;

But if blk_rq_timed_out calls __blk_complete_request, we don't want to touch the rq here, I guess.

Yes, we should not access it although I don't think the request can be freed while the existing code is accessing the deadline field. What likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

#3 lore raw
Quoted 49 lines · On Tue, Oct 28 2008, [email protected] wrote:
Quoted 20 lines · FUJITA Tomonori [[email protected]] wrote:
Quoted 17 lines · On Tue, 28 Oct 2008 11:22:43 -0700 [email protected] wrote:

Now the rq->deadline can't be zero if the request is in the timeout_list, so there is no need to have next_set. There is no need to access a request's deadline field if blk_rq_timed_out is called on it.

diff -r a6ae42397ede block/blk-timeout.c

block/blk-timeout.c +1 -1
@@ -118,7 +118,7 @@
 void blk_rq_timed_out_timer(unsigned long data)
 {
 	struct request_queue *q = (struct request_queue *) data;
-	unsigned long flags, uninitialized_var(next), next_set = 0;
+	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
 
Quoted 11 lines

block/blk-timeout.c line 138

Quoted 8 lines
block/blk-timeout.c +3 -0
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -133,15 +133,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		} else {
+			if (!next || time_after(next, rq->deadline))
+				next = rq->deadline;

Hmm, blk_rq_timed_out(rq) could put the rq back to q->timeout_list. We need to take care of the rq->deadline like this?

If it is put back on the list, it would be placed at the end of the list so we will get to work on it again in the list traversal. There is no need to access it now.

Quoted 11 lines

block/blk-timeout.c line 138

Quoted 8 lines
block/blk-timeout.c +3 -0
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		}
 
+		if (!next || time_after(next, rq->deadline))
+			next = rq->deadline;

But if blk_rq_timed_out calls __blk_complete_request, we don't want to touch the rq here, I guess.

Quoted 4 lines

Yes, we should not access it although I don't think the request can be freed while the existing code is accessing the deadline field. What likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

That would not call the timer immediately, that will not call it until jiffies reaches that value again. So you're looking at a minimum of 49 days :-)

Signature · 1 line
Jens Axboe
#4 lore raw
Quoted 8 lines · Jens Axboe [[email protected]] wrote:
Quoted 4 lines

Yes, we should not access it although I don't think the request can be freed while the existing code is accessing the deadline field. What likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

That would not call the timer immediately, that will not call it until jiffies reaches that value again. So you're looking at a minimum of 49 days :-)

I remember the timer code treating "past" expiry times as special. If not, then we have a real bug! It is also hard to guarantee in blk_rq_timed_out_timer() that we always call mod_timer with future expiry time!

--Malahal.

#5 lore raw
In reply to [email protected]
Quoted 33 lines · On Tue, 28 Oct 2008 23:06:25 -0700 [email protected] wrote:
Quoted 20 lines · FUJITA Tomonori [[email protected]] wrote:
Quoted 17 lines · On Tue, 28 Oct 2008 11:22:43 -0700 [email protected] wrote:

Now the rq->deadline can't be zero if the request is in the timeout_list, so there is no need to have next_set. There is no need to access a request's deadline field if blk_rq_timed_out is called on it.

diff -r a6ae42397ede block/blk-timeout.c

block/blk-timeout.c +1 -1
@@ -118,7 +118,7 @@
 void blk_rq_timed_out_timer(unsigned long data)
 {
 	struct request_queue *q = (struct request_queue *) data;
-	unsigned long flags, uninitialized_var(next), next_set = 0;
+	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
 
Quoted 11 lines

block/blk-timeout.c line 138

Quoted 8 lines
block/blk-timeout.c +3 -0
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -133,15 +133,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		} else {
+			if (!next || time_after(next, rq->deadline))
+				next = rq->deadline;

Hmm, blk_rq_timed_out(rq) could put the rq back to q->timeout_list. We need to take care of the rq->deadline like this?

Quoted 3 lines

If it is put back on the list, it would be placed at the end of the list so we will get to work on it again in the list traversal. There is no need to access it now.

Ah, I see.

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
block/blk-timeout.c +1 -0
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		}
 
Quoted 8 lines
Quoted 5 lines

block/blk-timeout.c line 138

Quoted 2 lines
block/blk-timeout.c +2 -0
+		if (!next || time_after(next, rq->deadline))
+			next = rq->deadline;

But if blk_rq_timed_out calls __blk_complete_request, we don't want to touch the rq here, I guess.

Yes, we should not access it although I don't think the request can be freed while the existing code is accessing the deadline field.

I don't think so too.

Quoted 3 lines

What
likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

Yeah, I think that the timer is called immediately here. It's unnecessary.

The patch looks good to me.

#6 lore raw
Quoted 57 lines · FUJITA Tomonori
Quoted 33 lines · On Tue, 28 Oct 2008 23:06:25 -0700 [email protected] wrote:
Quoted 20 lines · FUJITA Tomonori [[email protected]] wrote:
Quoted 17 lines · On Tue, 28 Oct 2008 11:22:43 -0700 [email protected] wrote:

Now the rq->deadline can't be zero if the request is in the timeout_list, so there is no need to have next_set. There is no need to access a request's deadline field if blk_rq_timed_out is called on it.

diff -r a6ae42397ede block/blk-timeout.c

block/blk-timeout.c +1 -1
@@ -118,7 +118,7 @@
 void blk_rq_timed_out_timer(unsigned long data)
 {
 	struct request_queue *q = (struct request_queue *) data;
-	unsigned long flags, uninitialized_var(next), next_set = 0;
+	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
 
Quoted 11 lines

block/blk-timeout.c line 138

Quoted 8 lines
block/blk-timeout.c +3 -0
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -133,15 +133,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		} else {
+			if (!next || time_after(next, rq->deadline))
+				next = rq->deadline;

Hmm, blk_rq_timed_out(rq) could put the rq back to q->timeout_list. We need to take care of the rq->deadline like this?

Quoted 3 lines

If it is put back on the list, it would be placed at the end of the list so we will get to work on it again in the list traversal. There is no need to access it now.

Ah, I see.

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
block/blk-timeout.c +1 -0
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
+		}
 
Quoted 8 lines
Quoted 5 lines

block/blk-timeout.c line 138

Quoted 2 lines
block/blk-timeout.c +2 -0
+		if (!next || time_after(next, rq->deadline))
+			next = rq->deadline;

But if blk_rq_timed_out calls __blk_complete_request, we don't want to touch the rq here, I guess.

Yes, we should not access it although I don't think the request can be freed while the existing code is accessing the deadline field.

Quoted 8 lines

I don't think so too.

Quoted 3 lines

What
likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

Yeah, I think that the timer is called immediately here. It's unnecessary.

Hmm, just checked the code, and indeed it does. Have the timers always behaved like that?

Quoted 1 line

The patch looks good to me.

No further gried from me either, I've applied it. It does need a comment on why 'next' cannot be 0 validly, because ->deadline is always rounded one up if that happens.

Signature · 1 line
Jens Axboe
#7 lore raw
Quoted 9 lines · On Thu, 30 Oct 2008 08:49:07 +0100 Jens Axboe <[email protected]> wrote:
Quoted 6 lines
Quoted 3 lines

What
likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

Yeah, I think that the timer is called immediately here. It's unnecessary.

Hmm, just checked the code, and indeed it does. Have the timers always behaved like that?

I guess so because it's unrealistic that the caller of mod_time makes sure that expires is future time, in particular if the caller wants short timeout?

#8 lore raw
Quoted 10 lines · FUJITA Tomonori
Quoted 7 lines · On Thu, 30 Oct 2008 08:49:07 +0100 Jens Axboe <[email protected]> wrote:
Quoted 6 lines
Quoted 3 lines

What
likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

Yeah, I think that the timer is called immediately here. It's unnecessary.

Quoted 6 lines
Quoted 2 lines

Hmm, just checked the code, and indeed it does. Have the timers always behaved like that?

I guess so because it's unrealistic that the caller of mod_time makes sure that expires is future time, in particular if the caller wants short timeout?

It's all a little confusing, I think. When do you stop considering it a little in the past and long into the future?

Signature · 1 line
Jens Axboe
#9 lore raw
Quoted 14 lines · On Thu, 30 Oct 2008 09:55:20 +0100 Jens Axboe <[email protected]> wrote:
Quoted 13 lines · FUJITA Tomonori
Quoted 9 lines · On Thu, 30 Oct 2008 08:49:07 +0100 Jens Axboe <[email protected]> wrote:
Quoted 6 lines
Quoted 3 lines

What
likely can happen is that we may call mod_timer with jiffies that is older than current which would call the timer immediately...

Yeah, I think that the timer is called immediately here. It's unnecessary.

Hmm, just checked the code, and indeed it does. Have the timers always behaved like that?

Quoted 6 lines
Quoted 3 lines

I guess so because it's unrealistic that the caller of mod_time makes sure that expires is future time, in particular if the caller wants short timeout?

It's all a little confusing, I think. When do you stop considering it a little in the past and long into the future?

After looking at internal_add_timer(), I guess, if the difference is less than the largest of signed long, it is considered to be the past. But I can say that it's not a good idea to ask me about the timer implementation details. ;)