* [patch] blk-flush: fix flush policy calculation
@ 2011-08-01 20:32 Jeff Moyer
2011-08-02 1:20 ` Shaohua Li
2011-08-04 10:16 ` Tejun Heo
0 siblings, 2 replies; 16+ messages in thread
From: Jeff Moyer @ 2011-08-01 20:32 UTC (permalink / raw)
To: linux-kernel; +Cc: Tejun Heo, Jens Axboe
Hi,
Reading through the code in blk-flush.c, it appears that there is an
oversight in the policy returned from blk_flush_policy:
if (fflags & REQ_FLUSH) {
if (rq->cmd_flags & REQ_FLUSH)
policy |= REQ_FSEQ_PREFLUSH;
if (blk_rq_sectors(rq))
policy |= REQ_FSEQ_DATA;
if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA))
policy |= REQ_FSEQ_POSTFLUSH;
}
return policy;
This means that REQ_FSEQ_DATA can only be set if the queue flush_flags
include FLUSH and/or FUA. However, the short-circuit for not issuing
flushes when the device doesn't need/support them depends on
REQ_FSEQ_DATA being set while the other two bits are clear:
/*
* If there's data but flush is not necessary, the request can be
* processed directly without going through flush machinery. Queue
* for normal execution.
*/
if ((policy & REQ_FSEQ_DATA) &&
!(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
list_add_tail(&rq->queuelist, &q->queue_head);
return;
}
Given the code as it stands, I don't think the body of this if statement
will ever be executed. I've attached a fix for this below. It seems
like this could be both a performance and a correctness issue, though
I've not run into any problems I can directly attribute to this (perhaps
due to file systems not issuing flushes when support is not advertised?).
Comments are appreciated.
Cheers,
Jeff
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
diff --git a/block/blk-flush.c b/block/blk-flush.c
index bb21e4c..3a06118 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -95,11 +95,11 @@ static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq)
{
unsigned int policy = 0;
+ if (blk_rq_sectors(rq))
+ policy |= REQ_FSEQ_DATA;
if (fflags & REQ_FLUSH) {
if (rq->cmd_flags & REQ_FLUSH)
policy |= REQ_FSEQ_PREFLUSH;
- if (blk_rq_sectors(rq))
- policy |= REQ_FSEQ_DATA;
if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA))
policy |= REQ_FSEQ_POSTFLUSH;
}
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [patch] blk-flush: fix flush policy calculation 2011-08-01 20:32 [patch] blk-flush: fix flush policy calculation Jeff Moyer @ 2011-08-02 1:20 ` Shaohua Li 2011-08-02 15:28 ` Jeff Moyer 2011-08-02 17:39 ` Jeff Moyer 2011-08-04 10:16 ` Tejun Heo 1 sibling, 2 replies; 16+ messages in thread From: Shaohua Li @ 2011-08-02 1:20 UTC (permalink / raw) To: Jeff Moyer; +Cc: linux-kernel, Tejun Heo, Jens Axboe 2011/8/2 Jeff Moyer <jmoyer@redhat.com>: > Hi, > > Reading through the code in blk-flush.c, it appears that there is an > oversight in the policy returned from blk_flush_policy: > > if (fflags & REQ_FLUSH) { > if (rq->cmd_flags & REQ_FLUSH) > policy |= REQ_FSEQ_PREFLUSH; > if (blk_rq_sectors(rq)) > policy |= REQ_FSEQ_DATA; > if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) > policy |= REQ_FSEQ_POSTFLUSH; > } > return policy; > > This means that REQ_FSEQ_DATA can only be set if the queue flush_flags > include FLUSH and/or FUA. However, the short-circuit for not issuing > flushes when the device doesn't need/support them depends on > REQ_FSEQ_DATA being set while the other two bits are clear: > > /* > * If there's data but flush is not necessary, the request can be > * processed directly without going through flush machinery. Queue > * for normal execution. > */ > if ((policy & REQ_FSEQ_DATA) && > !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { > list_add_tail(&rq->queuelist, &q->queue_head); > return; > } > > Given the code as it stands, I don't think the body of this if statement > will ever be executed. I've attached a fix for this below. It seems > like this could be both a performance and a correctness issue, though > I've not run into any problems I can directly attribute to this (perhaps > due to file systems not issuing flushes when support is not advertised?). > > Comments are appreciated. > > Cheers, > Jeff > > Signed-off-by: Jeff Moyer <jmoyer@redhat.com> > > diff --git a/block/blk-flush.c b/block/blk-flush.c > index bb21e4c..3a06118 100644 > --- a/block/blk-flush.c > +++ b/block/blk-flush.c > @@ -95,11 +95,11 @@ static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq) > { > unsigned int policy = 0; > > + if (blk_rq_sectors(rq)) > + policy |= REQ_FSEQ_DATA; > if (fflags & REQ_FLUSH) { > if (rq->cmd_flags & REQ_FLUSH) > policy |= REQ_FSEQ_PREFLUSH; > - if (blk_rq_sectors(rq)) > - policy |= REQ_FSEQ_DATA; > if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) > policy |= REQ_FSEQ_POSTFLUSH; > } > -- __generic_make_request always handles this: if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) { bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA); if (!nr_sectors) { err = 0; goto end_io; } } Thanks, Shaohua ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 1:20 ` Shaohua Li @ 2011-08-02 15:28 ` Jeff Moyer 2011-08-02 17:39 ` Jeff Moyer 1 sibling, 0 replies; 16+ messages in thread From: Jeff Moyer @ 2011-08-02 15:28 UTC (permalink / raw) To: Shaohua Li; +Cc: linux-kernel, Tejun Heo, Jens Axboe, msnitzer Shaohua Li <shli@kernel.org> writes: > 2011/8/2 Jeff Moyer <jmoyer@redhat.com>: >> Hi, >> >> Reading through the code in blk-flush.c, it appears that there is an >> oversight in the policy returned from blk_flush_policy: >> >> if (fflags & REQ_FLUSH) { >> if (rq->cmd_flags & REQ_FLUSH) >> policy |= REQ_FSEQ_PREFLUSH; >> if (blk_rq_sectors(rq)) >> policy |= REQ_FSEQ_DATA; >> if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) >> policy |= REQ_FSEQ_POSTFLUSH; >> } >> return policy; >> >> This means that REQ_FSEQ_DATA can only be set if the queue flush_flags >> include FLUSH and/or FUA. However, the short-circuit for not issuing >> flushes when the device doesn't need/support them depends on >> REQ_FSEQ_DATA being set while the other two bits are clear: >> >> /* >> * If there's data but flush is not necessary, the request can be >> * processed directly without going through flush machinery. Queue >> * for normal execution. >> */ >> if ((policy & REQ_FSEQ_DATA) && >> !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { >> list_add_tail(&rq->queuelist, &q->queue_head); >> return; >> } >> >> Given the code as it stands, I don't think the body of this if statement >> will ever be executed. I've attached a fix for this below. It seems >> like this could be both a performance and a correctness issue, though >> I've not run into any problems I can directly attribute to this (perhaps >> due to file systems not issuing flushes when support is not advertised?). >> >> Comments are appreciated. >> >> Cheers, >> Jeff >> >> Signed-off-by: Jeff Moyer <jmoyer@redhat.com> >> >> diff --git a/block/blk-flush.c b/block/blk-flush.c >> index bb21e4c..3a06118 100644 >> --- a/block/blk-flush.c >> +++ b/block/blk-flush.c >> @@ -95,11 +95,11 @@ static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq) >> { >> unsigned int policy = 0; >> >> + if (blk_rq_sectors(rq)) >> + policy |= REQ_FSEQ_DATA; >> if (fflags & REQ_FLUSH) { >> if (rq->cmd_flags & REQ_FLUSH) >> policy |= REQ_FSEQ_PREFLUSH; >> - if (blk_rq_sectors(rq)) >> - policy |= REQ_FSEQ_DATA; >> if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) >> policy |= REQ_FSEQ_POSTFLUSH; >> } >> -- > __generic_make_request always handles this: > if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) { > bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA); > if (!nr_sectors) { > err = 0; > goto end_io; > } > } > dm-multipath exports flush and fua, even if underlying devices do not support those flags (but this will change shortly). It then issues I/O using blk_insert_cloned_request, which bypasses generic_make_request. Plus, the logic was clearly wrong so I think we should take the proposed patch. Cheers, Jeff ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 1:20 ` Shaohua Li 2011-08-02 15:28 ` Jeff Moyer @ 2011-08-02 17:39 ` Jeff Moyer 2011-08-02 18:17 ` Vivek Goyal 2011-08-04 10:20 ` Tejun Heo 1 sibling, 2 replies; 16+ messages in thread From: Jeff Moyer @ 2011-08-02 17:39 UTC (permalink / raw) To: Shaohua Li; +Cc: linux-kernel, Tejun Heo, Jens Axboe, msnitzer OK, sorry for top-posting here, but I chased the problem down further. Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement FLUSH/FUA to support merge, introduced a regression when running any sort of fsyncing workload using dm-multipath and certain storage (in our case, an HP EVA). It turns out that dm-multipath always advertised flush+fua support, and passed commands on down the stack, where they used to get stripped off. The above commit, unfortunately, changed that behavior: static inline struct request *__elv_next_request(struct request_queue *q) { struct request *rq; while (1) { - while (!list_empty(&q->queue_head)) { + if (!list_empty(&q->queue_head)) { rq = list_entry_rq(q->queue_head.next); - if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) || - (rq->cmd_flags & REQ_FLUSH_SEQ)) - return rq; - rq = blk_do_flush(q, rq); - if (rq) - return rq; + return rq; } Note that previously, a command would come in here, have REQ_FLUSH|REQ_FUA set, and then get handed off to blk_do_flush: struct request *blk_do_flush(struct request_queue *q, struct request *rq) { unsigned int fflags = q->flush_flags; /* may change, cache it */ bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA; bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH); bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA); unsigned skip = 0; ... if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) { rq->cmd_flags &= ~REQ_FLUSH; if (!has_fua) rq->cmd_flags &= ~REQ_FUA; return rq; } So, the flush machinery was bypassed in such cases (q->flush_flags == 0 && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). Now, however, we don't get into the flush machinery at all (which is why my initial patch didn't help this situation). Instead, __elv_next_request just hands a request with flush and fua bits set to the scsi_request_fn, even though the underlying request_queue does not support flush or fua. So, where do we fix this? We could just accept Mike's patch to not send such requests down from dm-mpath, but that seems short-sighted. We could reinstate some checks in __elv_next_request. Or, we could put the checks into blk_insert_cloned_request. Suggestions? Cheers, Jeff Shaohua Li <shli@kernel.org> writes: > 2011/8/2 Jeff Moyer <jmoyer@redhat.com>: >> Hi, >> >> Reading through the code in blk-flush.c, it appears that there is an >> oversight in the policy returned from blk_flush_policy: >> >> if (fflags & REQ_FLUSH) { >> if (rq->cmd_flags & REQ_FLUSH) >> policy |= REQ_FSEQ_PREFLUSH; >> if (blk_rq_sectors(rq)) >> policy |= REQ_FSEQ_DATA; >> if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) >> policy |= REQ_FSEQ_POSTFLUSH; >> } >> return policy; >> >> This means that REQ_FSEQ_DATA can only be set if the queue flush_flags >> include FLUSH and/or FUA. However, the short-circuit for not issuing >> flushes when the device doesn't need/support them depends on >> REQ_FSEQ_DATA being set while the other two bits are clear: >> >> /* >> * If there's data but flush is not necessary, the request can be >> * processed directly without going through flush machinery. Queue >> * for normal execution. >> */ >> if ((policy & REQ_FSEQ_DATA) && >> !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { >> list_add_tail(&rq->queuelist, &q->queue_head); >> return; >> } >> >> Given the code as it stands, I don't think the body of this if statement >> will ever be executed. I've attached a fix for this below. It seems >> like this could be both a performance and a correctness issue, though >> I've not run into any problems I can directly attribute to this (perhaps >> due to file systems not issuing flushes when support is not advertised?). >> >> Comments are appreciated. >> >> Cheers, >> Jeff >> >> Signed-off-by: Jeff Moyer <jmoyer@redhat.com> >> >> diff --git a/block/blk-flush.c b/block/blk-flush.c >> index bb21e4c..3a06118 100644 >> --- a/block/blk-flush.c >> +++ b/block/blk-flush.c >> @@ -95,11 +95,11 @@ static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq) >> { >> unsigned int policy = 0; >> >> + if (blk_rq_sectors(rq)) >> + policy |= REQ_FSEQ_DATA; >> if (fflags & REQ_FLUSH) { >> if (rq->cmd_flags & REQ_FLUSH) >> policy |= REQ_FSEQ_PREFLUSH; >> - if (blk_rq_sectors(rq)) >> - policy |= REQ_FSEQ_DATA; >> if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) >> policy |= REQ_FSEQ_POSTFLUSH; >> } >> -- > __generic_make_request always handles this: > if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) { > bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA); > if (!nr_sectors) { > err = 0; > goto end_io; > } > } > > Thanks, > Shaohua ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 17:39 ` Jeff Moyer @ 2011-08-02 18:17 ` Vivek Goyal 2011-08-02 18:31 ` Jeff Moyer 2011-08-02 18:40 ` Mike Snitzer 2011-08-04 10:20 ` Tejun Heo 1 sibling, 2 replies; 16+ messages in thread From: Vivek Goyal @ 2011-08-02 18:17 UTC (permalink / raw) To: Jeff Moyer; +Cc: Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe, msnitzer On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: > OK, sorry for top-posting here, but I chased the problem down further. > > Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement > FLUSH/FUA to support merge, introduced a regression when running any > sort of fsyncing workload using dm-multipath and certain storage (in our > case, an HP EVA). It turns out that dm-multipath always advertised > flush+fua support, and passed commands on down the stack, where they > used to get stripped off. The above commit, unfortunately, changed that > behavior: > > static inline struct request *__elv_next_request(struct request_queue *q) > { > struct request *rq; > > while (1) { > - while (!list_empty(&q->queue_head)) { > + if (!list_empty(&q->queue_head)) { > rq = list_entry_rq(q->queue_head.next); > - if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) || > - (rq->cmd_flags & REQ_FLUSH_SEQ)) > - return rq; > - rq = blk_do_flush(q, rq); > - if (rq) > - return rq; > + return rq; > } > > Note that previously, a command would come in here, have > REQ_FLUSH|REQ_FUA set, and then get handed off to blk_do_flush: > > struct request *blk_do_flush(struct request_queue *q, struct request *rq) > { > unsigned int fflags = q->flush_flags; /* may change, cache it */ > bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA; > bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH); > bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & > REQ_FUA); > unsigned skip = 0; > ... > if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) { > rq->cmd_flags &= ~REQ_FLUSH; > if (!has_fua) > rq->cmd_flags &= ~REQ_FUA; > return rq; > } > > So, the flush machinery was bypassed in such cases (q->flush_flags == 0 > && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). > > Now, however, we don't get into the flush machinery at all (which is why > my initial patch didn't help this situation). Instead, > __elv_next_request just hands a request with flush and fua bits set to > the scsi_request_fn, even though the underlying request_queue does not > support flush or fua. > > So, where do we fix this? We could just accept Mike's patch to not send > such requests down from dm-mpath, but that seems short-sighted. We > could reinstate some checks in __elv_next_request. Or, we could put the > checks into blk_insert_cloned_request. > > Suggestions? IMHO, we should fix it at multiple places. - Your initial fix in blk_insert_flush makes sense. blk_insert_flush() is equivalent of blk_do_flush() so resetting REQ_FLUSH and REQ_FUA there makes sense to me. - Fixing blk_insert_cloned_request() also makes sense to me so that if a request is REQ_FLUSH or REQ_FUA set, we try to add it to underlying device using ELEVATOR_INSERT_FLUSH and not ELEVATOR_INSERT_BACK. - Fixing dm-multipath makes sense too as what's the point in dispatching unnecessary flush/fua requests to underlying devices if underlying queue does not have FLUSH capability. So I would say, fix it at all the places. :-) I have one question though. What happens if we have an empty request with REQ_FLUSH set and request queue does not support flush. Where will we complete the IO for that request? I see that __generic_make_request() takes care of that but we might have to take care of if it insert_cloned path too. Thanks Vivek ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 18:17 ` Vivek Goyal @ 2011-08-02 18:31 ` Jeff Moyer 2011-08-02 18:41 ` Vivek Goyal 2011-08-02 18:40 ` Mike Snitzer 1 sibling, 1 reply; 16+ messages in thread From: Jeff Moyer @ 2011-08-02 18:31 UTC (permalink / raw) To: Vivek Goyal; +Cc: Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe, msnitzer Vivek Goyal <vgoyal@redhat.com> writes: > On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: >> OK, sorry for top-posting here, but I chased the problem down further. >> >> Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement >> FLUSH/FUA to support merge, introduced a regression when running any >> sort of fsyncing workload using dm-multipath and certain storage (in our >> case, an HP EVA). It turns out that dm-multipath always advertised >> flush+fua support, and passed commands on down the stack, where they >> used to get stripped off. The above commit, unfortunately, changed that >> behavior: >> >> static inline struct request *__elv_next_request(struct request_queue *q) >> { >> struct request *rq; >> >> while (1) { >> - while (!list_empty(&q->queue_head)) { >> + if (!list_empty(&q->queue_head)) { >> rq = list_entry_rq(q->queue_head.next); >> - if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) || >> - (rq->cmd_flags & REQ_FLUSH_SEQ)) >> - return rq; >> - rq = blk_do_flush(q, rq); >> - if (rq) >> - return rq; >> + return rq; >> } >> >> Note that previously, a command would come in here, have >> REQ_FLUSH|REQ_FUA set, and then get handed off to blk_do_flush: >> >> struct request *blk_do_flush(struct request_queue *q, struct request *rq) >> { >> unsigned int fflags = q->flush_flags; /* may change, cache it */ >> bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA; >> bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH); >> bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & >> REQ_FUA); >> unsigned skip = 0; >> ... >> if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) { >> rq->cmd_flags &= ~REQ_FLUSH; >> if (!has_fua) >> rq->cmd_flags &= ~REQ_FUA; >> return rq; >> } >> >> So, the flush machinery was bypassed in such cases (q->flush_flags == 0 >> && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). >> >> Now, however, we don't get into the flush machinery at all (which is why >> my initial patch didn't help this situation). Instead, >> __elv_next_request just hands a request with flush and fua bits set to >> the scsi_request_fn, even though the underlying request_queue does not >> support flush or fua. >> >> So, where do we fix this? We could just accept Mike's patch to not send >> such requests down from dm-mpath, but that seems short-sighted. We >> could reinstate some checks in __elv_next_request. Or, we could put the >> checks into blk_insert_cloned_request. >> >> Suggestions? > > IMHO, we should fix it at multiple places. > > - Your initial fix in blk_insert_flush makes sense. blk_insert_flush() > is equivalent of blk_do_flush() so resetting REQ_FLUSH and REQ_FUA there > makes sense to me. Right, I still stand by that fix. It was a thinko. > - Fixing blk_insert_cloned_request() also makes sense to me so that if > a request is REQ_FLUSH or REQ_FUA set, we try to add it to underlying > device using ELEVATOR_INSERT_FLUSH and not ELEVATOR_INSERT_BACK. Good point. > - Fixing dm-multipath makes sense too as what's the point in dispatching > unnecessary flush/fua requests to underlying devices if underlying > queue does not have FLUSH capability. > > So I would say, fix it at all the places. :-) You missed __elv_next_request. :) > I have one question though. What happens if we have an empty request > with REQ_FLUSH set and request queue does not support flush. Where > will we complete the IO for that request? I see that __generic_make_request() > takes care of that but we might have to take care of if it insert_cloned > path too. In testing, I did this: @@ -1817,6 +1817,14 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) return -EIO; #endif + if ((rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) && !q->flush_flags) { + rq->cmd_flags &= ~(REQ_FLUSH|REQ_FUA); + if (!blk_rq_bytes(rq)) { + blk_end_request(rq, 0, 0); + return 0; + } + } + Cheers, Jeff ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 18:31 ` Jeff Moyer @ 2011-08-02 18:41 ` Vivek Goyal 2011-08-02 19:46 ` Jeff Moyer 0 siblings, 1 reply; 16+ messages in thread From: Vivek Goyal @ 2011-08-02 18:41 UTC (permalink / raw) To: Jeff Moyer; +Cc: Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe, msnitzer On Tue, Aug 02, 2011 at 02:31:00PM -0400, Jeff Moyer wrote: > Vivek Goyal <vgoyal@redhat.com> writes: > > > On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: > >> OK, sorry for top-posting here, but I chased the problem down further. > >> > >> Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement > >> FLUSH/FUA to support merge, introduced a regression when running any > >> sort of fsyncing workload using dm-multipath and certain storage (in our > >> case, an HP EVA). It turns out that dm-multipath always advertised > >> flush+fua support, and passed commands on down the stack, where they > >> used to get stripped off. The above commit, unfortunately, changed that > >> behavior: > >> > >> static inline struct request *__elv_next_request(struct request_queue *q) > >> { > >> struct request *rq; > >> > >> while (1) { > >> - while (!list_empty(&q->queue_head)) { > >> + if (!list_empty(&q->queue_head)) { > >> rq = list_entry_rq(q->queue_head.next); > >> - if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) || > >> - (rq->cmd_flags & REQ_FLUSH_SEQ)) > >> - return rq; > >> - rq = blk_do_flush(q, rq); > >> - if (rq) > >> - return rq; > >> + return rq; > >> } > >> > >> Note that previously, a command would come in here, have > >> REQ_FLUSH|REQ_FUA set, and then get handed off to blk_do_flush: > >> > >> struct request *blk_do_flush(struct request_queue *q, struct request *rq) > >> { > >> unsigned int fflags = q->flush_flags; /* may change, cache it */ > >> bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA; > >> bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH); > >> bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & > >> REQ_FUA); > >> unsigned skip = 0; > >> ... > >> if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) { > >> rq->cmd_flags &= ~REQ_FLUSH; > >> if (!has_fua) > >> rq->cmd_flags &= ~REQ_FUA; > >> return rq; > >> } > >> > >> So, the flush machinery was bypassed in such cases (q->flush_flags == 0 > >> && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). > >> > >> Now, however, we don't get into the flush machinery at all (which is why > >> my initial patch didn't help this situation). Instead, > >> __elv_next_request just hands a request with flush and fua bits set to > >> the scsi_request_fn, even though the underlying request_queue does not > >> support flush or fua. > >> > >> So, where do we fix this? We could just accept Mike's patch to not send > >> such requests down from dm-mpath, but that seems short-sighted. We > >> could reinstate some checks in __elv_next_request. Or, we could put the > >> checks into blk_insert_cloned_request. > >> > >> Suggestions? > > > > IMHO, we should fix it at multiple places. > > > > - Your initial fix in blk_insert_flush makes sense. blk_insert_flush() > > is equivalent of blk_do_flush() so resetting REQ_FLUSH and REQ_FUA there > > makes sense to me. > > Right, I still stand by that fix. It was a thinko. > > > - Fixing blk_insert_cloned_request() also makes sense to me so that if > > a request is REQ_FLUSH or REQ_FUA set, we try to add it to underlying > > device using ELEVATOR_INSERT_FLUSH and not ELEVATOR_INSERT_BACK. > > Good point. > > > - Fixing dm-multipath makes sense too as what's the point in dispatching > > unnecessary flush/fua requests to underlying devices if underlying > > queue does not have FLUSH capability. > > > > So I would say, fix it at all the places. :-) > > You missed __elv_next_request. :) Actually we will take care of resetting FLUSH/FUA flag when request is being queued on request queue (blk_insert_flush()). So I think there is no need to fix __elv_next_request(). That's why I had skipped it. > > > I have one question though. What happens if we have an empty request > > with REQ_FLUSH set and request queue does not support flush. Where > > will we complete the IO for that request? I see that __generic_make_request() > > takes care of that but we might have to take care of if it insert_cloned > > path too. > > In testing, I did this: > > @@ -1817,6 +1817,14 @@ int blk_insert_cloned_request(struct > request_queue *q, struct request *rq) > return -EIO; > #endif > > + if ((rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) && !q->flush_flags) { > + rq->cmd_flags &= ~(REQ_FLUSH|REQ_FUA); > + if (!blk_rq_bytes(rq)) { > + blk_end_request(rq, 0, 0); > + return 0; > + } > + } > + Will it make more sense to take care resetting flush/fua flags in blk_insert_flush() and also the part which will end the request if request is empty. And in cloned request we just take care of using ELVATOR_FLUSH_INSERT. The reason being that it will make __elv_insert() path safe for all the cases and insert_cloned_request is just one of the consumers. But this is just a minor point. At the end of the day, I think both the solutions will work. Thanks Vivek ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 18:41 ` Vivek Goyal @ 2011-08-02 19:46 ` Jeff Moyer 2011-08-03 1:19 ` Shaohua Li 2011-08-09 17:13 ` Vivek Goyal 0 siblings, 2 replies; 16+ messages in thread From: Jeff Moyer @ 2011-08-02 19:46 UTC (permalink / raw) To: Vivek Goyal; +Cc: Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe, msnitzer Vivek Goyal <vgoyal@redhat.com> writes: >> In testing, I did this: >> >> @@ -1817,6 +1817,14 @@ int blk_insert_cloned_request(struct >> request_queue *q, struct request *rq) >> return -EIO; >> #endif >> >> + if ((rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) && !q->flush_flags) { >> + rq->cmd_flags &= ~(REQ_FLUSH|REQ_FUA); >> + if (!blk_rq_bytes(rq)) { >> + blk_end_request(rq, 0, 0); >> + return 0; >> + } >> + } >> + > > Will it make more sense to take care resetting flush/fua flags in > blk_insert_flush() Yes, that's much cleaner. > and also the part which will end the request if request is empty. Mmm-hmm. I tried this, and it blew up in my face. ;-) Cloned requests from device-mapper-land have rq->end_io filled in, which causes blk_insert_flush to BUG here: BUG_ON(rq->end_io); So, we can take the usual route of trying to squirrel away a pointer, and reinstate that after the flush_data_end_io. Or, perhaps someone has a more clever idea, that might keep us from further expanding struct request...? Cheers, Jeff ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 19:46 ` Jeff Moyer @ 2011-08-03 1:19 ` Shaohua Li 2011-08-09 17:13 ` Vivek Goyal 1 sibling, 0 replies; 16+ messages in thread From: Shaohua Li @ 2011-08-03 1:19 UTC (permalink / raw) To: Jeff Moyer; +Cc: Vivek Goyal, linux-kernel, Tejun Heo, Jens Axboe, msnitzer 2011/8/3 Jeff Moyer <jmoyer@redhat.com>: > Vivek Goyal <vgoyal@redhat.com> writes: > >>> In testing, I did this: >>> >>> @@ -1817,6 +1817,14 @@ int blk_insert_cloned_request(struct >>> request_queue *q, struct request *rq) >>> return -EIO; >>> #endif >>> >>> + if ((rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) && !q->flush_flags) { >>> + rq->cmd_flags &= ~(REQ_FLUSH|REQ_FUA); >>> + if (!blk_rq_bytes(rq)) { >>> + blk_end_request(rq, 0, 0); >>> + return 0; >>> + } >>> + } >>> + >> >> Will it make more sense to take care resetting flush/fua flags in >> blk_insert_flush() > > Yes, that's much cleaner. agreed. doing at blk_insert_flush makes a lot of sense, maybe we have similar issue like blk_insert_cloned_request in the future. >> and also the part which will end the request if request is empty. > > Mmm-hmm. > > I tried this, and it blew up in my face. ;-) Cloned requests from > device-mapper-land have rq->end_io filled in, which causes > blk_insert_flush to BUG here: > > BUG_ON(rq->end_io); > > So, we can take the usual route of trying to squirrel away a pointer, > and reinstate that after the flush_data_end_io. Or, perhaps someone has > a more clever idea, that might keep us from further expanding struct > request...? we still have space at request->rb_node union. And since flush request doesn't go to io scheduler, we can use the space. Thanks, Shaohua ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 19:46 ` Jeff Moyer 2011-08-03 1:19 ` Shaohua Li @ 2011-08-09 17:13 ` Vivek Goyal 2011-08-09 17:29 ` Jeff Moyer 1 sibling, 1 reply; 16+ messages in thread From: Vivek Goyal @ 2011-08-09 17:13 UTC (permalink / raw) To: Jeff Moyer; +Cc: Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe, msnitzer On Tue, Aug 02, 2011 at 03:46:49PM -0400, Jeff Moyer wrote: > Vivek Goyal <vgoyal@redhat.com> writes: > > >> In testing, I did this: > >> > >> @@ -1817,6 +1817,14 @@ int blk_insert_cloned_request(struct > >> request_queue *q, struct request *rq) > >> return -EIO; > >> #endif > >> > >> + if ((rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) && !q->flush_flags) { > >> + rq->cmd_flags &= ~(REQ_FLUSH|REQ_FUA); > >> + if (!blk_rq_bytes(rq)) { > >> + blk_end_request(rq, 0, 0); > >> + return 0; > >> + } > >> + } > >> + > > > > Will it make more sense to take care resetting flush/fua flags in > > blk_insert_flush() > > Yes, that's much cleaner. > > > and also the part which will end the request if request is empty. > > Mmm-hmm. > > I tried this, and it blew up in my face. ;-) Cloned requests from > device-mapper-land have rq->end_io filled in, which causes > blk_insert_flush to BUG here: > > BUG_ON(rq->end_io); So how does it work when underlying device supports FLUSH/FUA? That means that dm-multipath requets never go through flush machinery? So if a queue does not support FUA but supports FLUSH, then FUA will not be honored by the underlying driver and request can very well be in cache? IOW, looks like even if component devices of a multipath device support FLUSH, requests don't go through it and hence atleast FUA is broken? And that would also mean that these don't benefit from flush merge logic. I guess we need to sort out this req->end_io issue and if both caller and flush machinery needs to make use of this pointer, then flush machinery should save it and restore on completion path. Thanks Vivek ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-09 17:13 ` Vivek Goyal @ 2011-08-09 17:29 ` Jeff Moyer 0 siblings, 0 replies; 16+ messages in thread From: Jeff Moyer @ 2011-08-09 17:29 UTC (permalink / raw) To: Vivek Goyal; +Cc: Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe, msnitzer Vivek Goyal <vgoyal@redhat.com> writes: > On Tue, Aug 02, 2011 at 03:46:49PM -0400, Jeff Moyer wrote: >> Vivek Goyal <vgoyal@redhat.com> writes: >> >> >> In testing, I did this: >> >> >> >> @@ -1817,6 +1817,14 @@ int blk_insert_cloned_request(struct >> >> request_queue *q, struct request *rq) >> >> return -EIO; >> >> #endif >> >> >> >> + if ((rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) && !q->flush_flags) { >> >> + rq->cmd_flags &= ~(REQ_FLUSH|REQ_FUA); >> >> + if (!blk_rq_bytes(rq)) { >> >> + blk_end_request(rq, 0, 0); >> >> + return 0; >> >> + } >> >> + } >> >> + >> > >> > Will it make more sense to take care resetting flush/fua flags in >> > blk_insert_flush() >> >> Yes, that's much cleaner. >> >> > and also the part which will end the request if request is empty. >> >> Mmm-hmm. >> >> I tried this, and it blew up in my face. ;-) Cloned requests from >> device-mapper-land have rq->end_io filled in, which causes >> blk_insert_flush to BUG here: >> >> BUG_ON(rq->end_io); > > So how does it work when underlying device supports FLUSH/FUA? That means > that dm-multipath requets never go through flush machinery? So if a Yes, they do. They go through it *above* dm-multipath, and dm-multipath just hands the requests down to the device via whatever path it selects. Cheers, Jeff ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 18:17 ` Vivek Goyal 2011-08-02 18:31 ` Jeff Moyer @ 2011-08-02 18:40 ` Mike Snitzer 1 sibling, 0 replies; 16+ messages in thread From: Mike Snitzer @ 2011-08-02 18:40 UTC (permalink / raw) To: Vivek Goyal; +Cc: Jeff Moyer, Shaohua Li, linux-kernel, Tejun Heo, Jens Axboe On Tue, Aug 2, 2011 at 2:17 PM, Vivek Goyal <vgoyal@redhat.com> wrote: > On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: >> So, where do we fix this? We could just accept Mike's patch to not send >> such requests down from dm-mpath, but that seems short-sighted. We >> could reinstate some checks in __elv_next_request. Or, we could put the >> checks into blk_insert_cloned_request. >> >> Suggestions? > > IMHO, we should fix it at multiple places. > > - Your initial fix in blk_insert_flush makes sense. blk_insert_flush() > is equivalent of blk_do_flush() so resetting REQ_FLUSH and REQ_FUA there > makes sense to me. Makes sense to me too. > - Fixing blk_insert_cloned_request() also makes sense to me so that if > a request is REQ_FLUSH or REQ_FUA set, we try to add it to underlying > device using ELEVATOR_INSERT_FLUSH and not ELEVATOR_INSERT_BACK. blk_insert_cloned_request is currently only used for request-based DM (so just dm-mpath). I don't see a problem with adding logic to it but in practice the DM change to properly propagate underlying devices' flush_flags is going to obviate the need (until the kernel grows another blk_insert_cloned_request caller). > - Fixing dm-multipath makes sense too as what's the point in dispatching > unnecessary flush/fua requests to underlying devices if underlying > queue does not have FLUSH capability. To be clear: It isn't just a fix for dm-multipath. It fixes all DM devices (both bio-based and request-based). That change is already destined for 3.1 via Alasdair's recent DM pull request. Mike ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-02 17:39 ` Jeff Moyer 2011-08-02 18:17 ` Vivek Goyal @ 2011-08-04 10:20 ` Tejun Heo 2011-08-08 17:31 ` Jeff Moyer 2011-08-08 17:31 ` Jeff Moyer 1 sibling, 2 replies; 16+ messages in thread From: Tejun Heo @ 2011-08-04 10:20 UTC (permalink / raw) To: Jeff Moyer; +Cc: Shaohua Li, linux-kernel, Jens Axboe, msnitzer Hello, On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: > OK, sorry for top-posting here, but I chased the problem down further. > > Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement > FLUSH/FUA to support merge, introduced a regression when running any > sort of fsyncing workload using dm-multipath and certain storage (in our > case, an HP EVA). It turns out that dm-multipath always advertised > flush+fua support, and passed commands on down the stack, where they > used to get stripped off. The above commit, unfortunately, changed that > behavior: ... > So, the flush machinery was bypassed in such cases (q->flush_flags == 0 > && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). > > Now, however, we don't get into the flush machinery at all (which is why > my initial patch didn't help this situation). Instead, > __elv_next_request just hands a request with flush and fua bits set to > the scsi_request_fn, even though the underlying request_queue does not > support flush or fua. > > So, where do we fix this? We could just accept Mike's patch to not send > such requests down from dm-mpath, but that seems short-sighted. We > could reinstate some checks in __elv_next_request. Or, we could put the > checks into blk_insert_cloned_request. Ah, okay, what changed there was where a request is passed into flush machinery. Before, it was while the request was being dispatched from elevator to device. After, it's de-composed when the request enters elevator. The bug is that there are paths which insert new requests to elevator but didn't check for REQ_FLUSH|FUA. I think it would be cleaner to add a wrapper around __elv_add_request() which checks for REQ_FLUSH|FUA and enforce REQ_INSERT_FLUSH if the request needs it. Note that this should only happen when a request enters the queue for the first time but not on requeues - that was the reason why the decision wasn't made inside __elv_add_request(). Thank you. -- tejun ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-04 10:20 ` Tejun Heo @ 2011-08-08 17:31 ` Jeff Moyer 2011-08-08 17:31 ` Jeff Moyer 1 sibling, 0 replies; 16+ messages in thread From: Jeff Moyer @ 2011-08-08 17:31 UTC (permalink / raw) To: Tejun Heo; +Cc: Shaohua Li, linux-kernel, Jens Axboe, msnitzer Tejun Heo <tj@kernel.org> writes: > Hello, > > On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: >> OK, sorry for top-posting here, but I chased the problem down further. >> >> Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement >> FLUSH/FUA to support merge, introduced a regression when running any >> sort of fsyncing workload using dm-multipath and certain storage (in our >> case, an HP EVA). It turns out that dm-multipath always advertised >> flush+fua support, and passed commands on down the stack, where they >> used to get stripped off. The above commit, unfortunately, changed that >> behavior: > ... >> So, the flush machinery was bypassed in such cases (q->flush_flags == 0 >> && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). >> >> Now, however, we don't get into the flush machinery at all (which is why >> my initial patch didn't help this situation). Instead, >> __elv_next_request just hands a request with flush and fua bits set to >> the scsi_request_fn, even though the underlying request_queue does not >> support flush or fua. >> >> So, where do we fix this? We could just accept Mike's patch to not send >> such requests down from dm-mpath, but that seems short-sighted. We >> could reinstate some checks in __elv_next_request. Or, we could put the >> checks into blk_insert_cloned_request. > > Ah, okay, what changed there was where a request is passed into flush > machinery. Before, it was while the request was being dispatched from > elevator to device. After, it's de-composed when the request enters > elevator. The bug is that there are paths which insert new requests > to elevator but didn't check for REQ_FLUSH|FUA. > > I think it would be cleaner to add a wrapper around > __elv_add_request() which checks for REQ_FLUSH|FUA and enforce > REQ_INSERT_FLUSH if the request needs it. Note that this should only > happen when a request enters the queue for the first time but not on > requeues - that was the reason why the decision wasn't made inside > __elv_add_request(). OK, we can do a wrapper, but it probably wouldn't be too horrific to just fix up blk_insert_cloned_request. Now, the next issue is that flush requests issued from the dm target down through the stack have no bio associated with them, so we blow up on the BUG_ON(!req->bio || req->bio != req->biotail). Cheers, Jeff ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-04 10:20 ` Tejun Heo 2011-08-08 17:31 ` Jeff Moyer @ 2011-08-08 17:31 ` Jeff Moyer 1 sibling, 0 replies; 16+ messages in thread From: Jeff Moyer @ 2011-08-08 17:31 UTC (permalink / raw) To: Tejun Heo; +Cc: Jens Axboe, msnitzer, Shaohua Li, linux-kernel Tejun Heo <tj@kernel.org> writes: > Hello, > > On Tue, Aug 02, 2011 at 01:39:46PM -0400, Jeff Moyer wrote: >> OK, sorry for top-posting here, but I chased the problem down further. >> >> Commit ae1b1539622fb46e51b4d13b3f9e5f4c713f86ae, block: reimplement >> FLUSH/FUA to support merge, introduced a regression when running any >> sort of fsyncing workload using dm-multipath and certain storage (in our >> case, an HP EVA). It turns out that dm-multipath always advertised >> flush+fua support, and passed commands on down the stack, where they >> used to get stripped off. The above commit, unfortunately, changed that >> behavior: > ... >> So, the flush machinery was bypassed in such cases (q->flush_flags == 0 >> && rq->cmd_flags & (REQ_FLUSH|REQ_FUA)). >> >> Now, however, we don't get into the flush machinery at all (which is why >> my initial patch didn't help this situation). Instead, >> __elv_next_request just hands a request with flush and fua bits set to >> the scsi_request_fn, even though the underlying request_queue does not >> support flush or fua. >> >> So, where do we fix this? We could just accept Mike's patch to not send >> such requests down from dm-mpath, but that seems short-sighted. We >> could reinstate some checks in __elv_next_request. Or, we could put the >> checks into blk_insert_cloned_request. > > Ah, okay, what changed there was where a request is passed into flush > machinery. Before, it was while the request was being dispatched from > elevator to device. After, it's de-composed when the request enters > elevator. The bug is that there are paths which insert new requests > to elevator but didn't check for REQ_FLUSH|FUA. > > I think it would be cleaner to add a wrapper around > __elv_add_request() which checks for REQ_FLUSH|FUA and enforce > REQ_INSERT_FLUSH if the request needs it. Note that this should only > happen when a request enters the queue for the first time but not on > requeues - that was the reason why the decision wasn't made inside > __elv_add_request(). OK, we can do a wrapper, but it probably wouldn't be too horrific to just fix up blk_insert_cloned_request. Now, the next issue is that flush requests issued from the dm target down through the stack have no bio associated with them, so we blow up on the BUG_ON(!req->bio || req->bio != req->biotail). Cheers, Jeff ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [patch] blk-flush: fix flush policy calculation 2011-08-01 20:32 [patch] blk-flush: fix flush policy calculation Jeff Moyer 2011-08-02 1:20 ` Shaohua Li @ 2011-08-04 10:16 ` Tejun Heo 1 sibling, 0 replies; 16+ messages in thread From: Tejun Heo @ 2011-08-04 10:16 UTC (permalink / raw) To: Jeff Moyer; +Cc: linux-kernel, Tejun Heo, Jens Axboe Hello, On Mon, Aug 01, 2011 at 04:32:17PM -0400, Jeff Moyer wrote: > /* > * If there's data but flush is not necessary, the request can be > * processed directly without going through flush machinery. Queue > * for normal execution. > */ > if ((policy & REQ_FSEQ_DATA) && > !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { > list_add_tail(&rq->queuelist, &q->queue_head); > return; > } > > Given the code as it stands, I don't think the body of this if statement > will ever be executed. It does if the device has a WB cache and filesystem sends down a FUA (but no FLUSH) request. > I've attached a fix for this below. It seems > like this could be both a performance and a correctness issue, though > I've not run into any problems I can directly attribute to this (perhaps > due to file systems not issuing flushes when support is not advertised?). > > Signed-off-by: Jeff Moyer <jmoyer@redhat.com> Hmmm... yes, this can become a correctness issue if (and only if) blk_queue_flush() is called to change q->flush_flags while requests are in-flight; otherwise, requests wouldn't reach the function at all. Also, I think it would be a generally good idea to always set FSEQ_DATA if the request has data. Acked-by: Tejun Heo <tj@kernel.org> but can you please update the description? Thank you. -- tejun ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2011-08-09 17:29 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-08-01 20:32 [patch] blk-flush: fix flush policy calculation Jeff Moyer 2011-08-02 1:20 ` Shaohua Li 2011-08-02 15:28 ` Jeff Moyer 2011-08-02 17:39 ` Jeff Moyer 2011-08-02 18:17 ` Vivek Goyal 2011-08-02 18:31 ` Jeff Moyer 2011-08-02 18:41 ` Vivek Goyal 2011-08-02 19:46 ` Jeff Moyer 2011-08-03 1:19 ` Shaohua Li 2011-08-09 17:13 ` Vivek Goyal 2011-08-09 17:29 ` Jeff Moyer 2011-08-02 18:40 ` Mike Snitzer 2011-08-04 10:20 ` Tejun Heo 2011-08-08 17:31 ` Jeff Moyer 2011-08-08 17:31 ` Jeff Moyer 2011-08-04 10:16 ` Tejun Heo
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.