2005-05-29 04:23:36

by Tejun Heo

[permalink] [raw]
Subject: [PATCH Linux 2.6.12-rc5-mm1 00/06] blk: barrier flushing reimplementation

Hello, guys.

This patchset is reimplementation of QUEUE_ORDERED_FLUSH feature. It
doens't update API docs yet. If it's determined that this patchset
can go in, I'll regenerate this patchset with doc updates (sans the
last debug message patch of course).

Major changes are.

* Implementation is contained inside the blk layer (ll_rw_blk.c and
elevator.c). Specific drivers only need to supply
prepare_flush_fn. end_flush_fn, blk_complete_barrier_rq_* removed.

* Tagged queues can use flushing safely. All in-flight requests are
drained before pre-flush and no other request is allowed during
flush sequence. So, SCSI devices which only support simple tags
can now use flush barrier (SATA NCQ falls in this category, I think).

* Multi-bio barrier requests supported.

This patchset makes the following behavior changes.

* Original code used to BUG_ON in __elv_next_request() when
elevator_next_req_fn() returns a barrier request when ordered is
QUEUE_ORDERED_NONE. This is a bug as ordered could have been
changed dynamically by previous barrier request while a barrier
request in already on the queue. New code just completes such
requests w/ -EOPNOTSUPP.

* Barrier request is not deactivated during pre-flushing. The
original code ends up calling elv_deactivate_request() twice
consecutively on a barrier request as it's also called by
elv_requeue_request(). Currently, all elevators cope with the
consecutive deactivations, but I don't think it's a very good idea.
This is easy to revert, please let me know what you guys think.

* When an error occurs while writing a barrier request, the whole
request is completed with error after executing it till the end.
In fact, any error during flush sequence results in error
completion of whole barrier request. (IDE used to report partial
success, and SCSI didn't handle errors during barrier request
properly.)

* ordered is changed to QUEUE_ORDERED_NONE only if pre/post flush
completes w/ -EOPNOTSUPP. (SCSI used to revert to
QUEUE_ORDERED_NONE on any error during preflush)

[ Start of patch descriptions ]

01_blk_add_uptodate_to_end_that_request_last.patch
: add @uptodate to end_that_request_last() and @error to rq_end_io_fn()

Add @uptodate argument to end_that_request_last() and @error
to rq_end_io_fn(). There's no generic way to pass error code
to request completion function, making generic error handling
of non-fs request difficult (rq->errors is driver-specific and
each driver uses it differently). This patch adds @uptodate
to end_that_request_last() and @error to rq_end_io_fn().

For fs requests, this doesn't really matter, so just using the
same uptodate argument used in the last call to
end_that_request_first() should suffice. IMHO, this can also
help the generic command-carrying request Jens is working on.

One thing that bothers me is this change can be user-visible
in that additional error codes may be seen by some ioctls.
eg. -EOPNOTSUPP instead of -EIO can be seen with the following
two patches on direct-command ioctls.

02_blk_scsi_eopnotsupp.patch
: make scsi use -EOPNOTSUPP instead of -EIO on ILLEGAL_REQUEST

Use -EOPNOTSUPP instead of -EIO on ILLEGAL_REQUEST.

03_blk_ide_eopnotsupp.patch
: make ide use -EOPNOTSUPP instead of -EIO on ABRT_ERR

Use -EOPNOTSUPP instead of -EIO on ABRT_ERR.

04_blk_flush_reimplementation.patch
: reimplement QUEUE_OREDERED_FLUSH

Reimplement QUEUE_ORDERED_FLUSH.

* Implementation is contained inside blk layer. Only
prepare_flush_fn() is needed from individual drivers.
* Tagged queues which don't support ordered tag can use
flushing.
* Multi-bio barrier requests supported.

05_blk_scsi_turn_on_flushing_by_default.patch
: turn on QUEUE_ORDERED_FLUSH by default if ordered tag isn't supported

As flushing can now be used by devices which only support
simple tags, there's no need to use
Scsi_Host_Template->ordered_flush to enable it selectively.
This patch removes ->ordered_flush and enables flushing
implicitly when ordered tag isn't supported. If the device
doesn't support flushing, it can just return -EOPNOTSUPP for
flush requests. blk layer will switch to QUEUE_OREDERED_NONE
automatically.

06_blk_flush_reimplementation_debug_messages.patch
: debug messages

These are debug messages I've used. If you are interested how
it works...

[ End of patch descriptions ]

Thanks.

--
tejun


2005-05-29 04:24:58

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 01/06] blk: add @uptodate to end_that_request_last() and @error to rq_end_io_fn()

01_blk_add_uptodate_to_end_that_request_last.patch

Add @uptodate argument to end_that_request_last() and @error
to rq_end_io_fn(). There's no generic way to pass error code
to request completion function, making generic error handling
of non-fs request difficult (rq->errors is driver-specific and
each driver uses it differently). This patch adds @uptodate
to end_that_request_last() and @error to rq_end_io_fn().

For fs requests, this doesn't really matter, so just using the
same uptodate argument used in the last call to
end_that_request_first() should suffice. IMHO, this can also
help the generic command-carrying request Jens is working on.

One thing that bothers me is this change can be user-visible
in that additional error codes may be seen by some ioctls.
eg. -EOPNOTSUPP instead of -EIO can be seen with the following
two patches on direct-command ioctls.

Signed-off-by: Tejun Heo <[email protected]>

drivers/block/DAC960.c | 2 +-
drivers/block/cciss.c | 2 +-
drivers/block/cpqarray.c | 2 +-
drivers/block/elevator.c | 2 +-
drivers/block/floppy.c | 2 +-
drivers/block/ll_rw_blk.c | 20 ++++++++++++++------
drivers/block/nbd.c | 2 +-
drivers/block/sx8.c | 2 +-
drivers/block/ub.c | 2 +-
drivers/block/viodasd.c | 2 +-
drivers/cdrom/cdu31a.c | 2 +-
drivers/ide/ide-cd.c | 4 ++--
drivers/ide/ide-io.c | 6 +++---
drivers/message/i2o/i2o_block.c | 2 +-
drivers/mmc/mmc_block.c | 4 ++--
drivers/s390/block/dasd.c | 2 +-
drivers/s390/char/tape_block.c | 2 +-
drivers/scsi/ide-scsi.c | 4 ++--
drivers/scsi/scsi_lib.c | 8 ++++----
drivers/scsi/sd.c | 2 +-
include/linux/blkdev.h | 6 +++---
21 files changed, 44 insertions(+), 36 deletions(-)

Index: blk-fixes/drivers/block/DAC960.c
===================================================================
--- blk-fixes.orig/drivers/block/DAC960.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/DAC960.c 2005-05-29 13:20:30.000000000 +0900
@@ -3480,7 +3480,7 @@ static inline boolean DAC960_ProcessComp

if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {

- end_that_request_last(Request);
+ end_that_request_last(Request, UpToDate);

if (Command->Completion) {
complete(Command->Completion);
Index: blk-fixes/drivers/block/cciss.c
===================================================================
--- blk-fixes.orig/drivers/block/cciss.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/cciss.c 2005-05-29 13:20:30.000000000 +0900
@@ -2072,7 +2072,7 @@ static inline void complete_command( ctl
printk("Done with %p\n", cmd->rq);
#endif /* CCISS_DEBUG */

- end_that_request_last(cmd->rq);
+ end_that_request_last(cmd->rq, status ? 1 : -EIO);
cmd_free(h,cmd,1);
}

Index: blk-fixes/drivers/block/cpqarray.c
===================================================================
--- blk-fixes.orig/drivers/block/cpqarray.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/cpqarray.c 2005-05-29 13:20:30.000000000 +0900
@@ -1036,7 +1036,7 @@ static inline void complete_command(cmdl
complete_buffers(cmd->rq->bio, ok);

DBGPX(printk("Done with %p\n", cmd->rq););
- end_that_request_last(cmd->rq);
+ end_that_request_last(cmd->rq, ok ? 1 : -EIO);
}

/*
Index: blk-fixes/drivers/block/elevator.c
===================================================================
--- blk-fixes.orig/drivers/block/elevator.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/elevator.c 2005-05-29 13:20:30.000000000 +0900
@@ -410,7 +410,7 @@ struct request *elv_next_request(request
blkdev_dequeue_request(rq);
rq->flags |= REQ_QUIET;
end_that_request_chunk(rq, 0, nr_bytes);
- end_that_request_last(rq);
+ end_that_request_last(rq, 0);
} else {
printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,
ret);
Index: blk-fixes/drivers/block/floppy.c
===================================================================
--- blk-fixes.orig/drivers/block/floppy.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/floppy.c 2005-05-29 13:20:30.000000000 +0900
@@ -2299,7 +2299,7 @@ static void floppy_end_request(struct re
add_disk_randomness(req->rq_disk);
floppy_off((long)req->rq_disk->private_data);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);

/* We're done with the request */
current_req = NULL;
Index: blk-fixes/drivers/block/ll_rw_blk.c
===================================================================
--- blk-fixes.orig/drivers/block/ll_rw_blk.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/ll_rw_blk.c 2005-05-29 13:20:30.000000000 +0900
@@ -347,7 +347,7 @@ EXPORT_SYMBOL(blk_queue_issue_flush_fn);
/*
* Cache flushing for ordered writes handling
*/
-static void blk_pre_flush_end_io(struct request *flush_rq)
+static void blk_pre_flush_end_io(struct request *flush_rq, int error)
{
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
@@ -363,7 +363,7 @@ static void blk_pre_flush_end_io(struct
}
}

-static void blk_post_flush_end_io(struct request *flush_rq)
+static void blk_post_flush_end_io(struct request *flush_rq, int error)
{
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
@@ -2386,7 +2386,7 @@ EXPORT_SYMBOL(blk_put_request);
* blk_end_sync_rq - executes a completion event on a request
* @rq: request to complete
*/
-void blk_end_sync_rq(struct request *rq)
+void blk_end_sync_rq(struct request *rq, int error)
{
struct completion *waiting = rq->waiting;

@@ -3141,9 +3141,17 @@ EXPORT_SYMBOL(end_that_request_chunk);
/*
* queue lock must be held
*/
-void end_that_request_last(struct request *req)
+void end_that_request_last(struct request *req, int uptodate)
{
struct gendisk *disk = req->rq_disk;
+ int error;
+
+ /*
+ * extend uptodate bool to allow < 0 value to be direct io error
+ */
+ error = 0;
+ if (end_io_error(uptodate))
+ error = !uptodate ? -EIO : uptodate;

if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
@@ -3164,7 +3172,7 @@ void end_that_request_last(struct reques
disk->in_flight--;
}
if (req->end_io)
- req->end_io(req);
+ req->end_io(req, error);
else
__blk_put_request(req->q, req);
}
@@ -3176,7 +3184,7 @@ void end_request(struct request *req, in
if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) {
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
}

Index: blk-fixes/drivers/block/nbd.c
===================================================================
--- blk-fixes.orig/drivers/block/nbd.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/nbd.c 2005-05-29 13:20:30.000000000 +0900
@@ -136,7 +136,7 @@ static void nbd_end_request(struct reque

spin_lock_irqsave(q->queue_lock, flags);
if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
spin_unlock_irqrestore(q->queue_lock, flags);
}
Index: blk-fixes/drivers/block/sx8.c
===================================================================
--- blk-fixes.orig/drivers/block/sx8.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/sx8.c 2005-05-29 13:20:30.000000000 +0900
@@ -745,7 +745,7 @@ static inline void carm_end_request_queu
rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
assert(rc == 0);

- end_that_request_last(req);
+ end_that_request_last(req, uptodate);

rc = carm_put_request(host, crq);
assert(rc == 0);
Index: blk-fixes/drivers/block/ub.c
===================================================================
--- blk-fixes.orig/drivers/block/ub.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/ub.c 2005-05-29 13:20:30.000000000 +0900
@@ -875,7 +875,7 @@ static void ub_end_rq(struct request *rq

rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
// assert(rc == 0);
- end_that_request_last(rq);
+ end_that_request_last(rq, uptodate);
}

/*
Index: blk-fixes/drivers/block/viodasd.c
===================================================================
--- blk-fixes.orig/drivers/block/viodasd.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/block/viodasd.c 2005-05-29 13:20:30.000000000 +0900
@@ -305,7 +305,7 @@ static void viodasd_end_request(struct r
if (end_that_request_first(req, uptodate, num_sectors))
return;
add_disk_randomness(req->rq_disk);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}

/*
Index: blk-fixes/drivers/cdrom/cdu31a.c
===================================================================
--- blk-fixes.orig/drivers/cdrom/cdu31a.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/cdrom/cdu31a.c 2005-05-29 13:20:30.000000000 +0900
@@ -1402,7 +1402,7 @@ static void do_cdu31a_request(request_qu
if (!end_that_request_first(req, 1, nblock)) {
spin_lock_irq(q->queue_lock);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 1);
spin_unlock_irq(q->queue_lock);
}
continue;
Index: blk-fixes/drivers/ide/ide-cd.c
===================================================================
--- blk-fixes.orig/drivers/ide/ide-cd.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/ide/ide-cd.c 2005-05-29 13:20:30.000000000 +0900
@@ -614,7 +614,7 @@ static void cdrom_end_request (ide_drive
*/
spin_lock_irqsave(&ide_lock, flags);
end_that_request_chunk(failed, 0, failed->data_len);
- end_that_request_last(failed);
+ end_that_request_last(failed, 0);
spin_unlock_irqrestore(&ide_lock, flags);
}

@@ -1739,7 +1739,7 @@ end_request:

spin_lock_irqsave(&ide_lock, flags);
blkdev_dequeue_request(rq);
- end_that_request_last(rq);
+ end_that_request_last(rq, 1);
HWGROUP(drive)->rq = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
return ide_stopped;
Index: blk-fixes/drivers/ide/ide-io.c
===================================================================
--- blk-fixes.orig/drivers/ide/ide-io.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/ide/ide-io.c 2005-05-29 13:20:30.000000000 +0900
@@ -89,7 +89,7 @@ int __ide_end_request(ide_drive_t *drive

blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
+ end_that_request_last(rq, uptodate);
ret = 0;
}
return ret;
@@ -247,7 +247,7 @@ static void ide_complete_pm_request (ide
}
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
+ end_that_request_last(rq, 1);
spin_unlock_irqrestore(&ide_lock, flags);
}

@@ -379,7 +379,7 @@ void ide_end_drive_cmd (ide_drive_t *dri
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
rq->errors = err;
- end_that_request_last(rq);
+ end_that_request_last(rq, !rq->errors);
spin_unlock_irqrestore(&ide_lock, flags);
}

Index: blk-fixes/drivers/message/i2o/i2o_block.c
===================================================================
--- blk-fixes.orig/drivers/message/i2o/i2o_block.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/message/i2o/i2o_block.c 2005-05-29 13:20:30.000000000 +0900
@@ -466,7 +466,7 @@ static void i2o_block_end_request(struct

spin_lock_irqsave(q->queue_lock, flags);

- end_that_request_last(req);
+ end_that_request_last(req, uptodate);

if (likely(dev)) {
dev->open_queue_depth--;
Index: blk-fixes/drivers/mmc/mmc_block.c
===================================================================
--- blk-fixes.orig/drivers/mmc/mmc_block.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/mmc/mmc_block.c 2005-05-29 13:20:30.000000000 +0900
@@ -254,7 +254,7 @@ static int mmc_blk_issue_rq(struct mmc_q
*/
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 1);
}
spin_unlock_irq(&md->lock);
} while (ret);
@@ -280,7 +280,7 @@ static int mmc_blk_issue_rq(struct mmc_q

add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
spin_unlock_irq(&md->lock);

return 0;
Index: blk-fixes/drivers/s390/block/dasd.c
===================================================================
--- blk-fixes.orig/drivers/s390/block/dasd.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/s390/block/dasd.c 2005-05-29 13:20:30.000000000 +0900
@@ -1039,7 +1039,7 @@ dasd_end_request(struct request *req, in
if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
BUG();
add_disk_randomness(req->rq_disk);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}

/*
Index: blk-fixes/drivers/s390/char/tape_block.c
===================================================================
--- blk-fixes.orig/drivers/s390/char/tape_block.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/s390/char/tape_block.c 2005-05-29 13:20:30.000000000 +0900
@@ -78,7 +78,7 @@ tapeblock_end_request(struct request *re
{
if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
BUG();
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}

static void
Index: blk-fixes/drivers/scsi/ide-scsi.c
===================================================================
--- blk-fixes.orig/drivers/scsi/ide-scsi.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/ide-scsi.c 2005-05-29 13:20:30.000000000 +0900
@@ -1016,7 +1016,7 @@ static int idescsi_eh_reset (struct scsi

/* kill current request */
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
if (req->flags & REQ_SENSE)
kfree(scsi->pc->buffer);
kfree(scsi->pc);
@@ -1026,7 +1026,7 @@ static int idescsi_eh_reset (struct scsi
/* now nuke the drive queue */
while ((req = elv_next_request(drive->queue))) {
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
}

HWGROUP(drive)->rq = NULL;
Index: blk-fixes/drivers/scsi/scsi_lib.c
===================================================================
--- blk-fixes.orig/drivers/scsi/scsi_lib.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/scsi_lib.c 2005-05-29 13:20:30.000000000 +0900
@@ -258,7 +258,7 @@ static void scsi_wait_done(struct scsi_c
/* This is the end routine we get to if a command was never attached
* to the request. Simply complete the request without changing
* rq_status; this will cause a DRIVER_ERROR. */
-static void scsi_wait_req_end_io(struct request *req)
+static void scsi_wait_req_end_io(struct request *req, int error)
{
BUG_ON(!req->waiting);

@@ -574,7 +574,7 @@ static struct scsi_cmnd *scsi_end_reques
spin_lock_irqsave(q->queue_lock, flags);
if (blk_rq_tagged(req))
blk_queue_end_tag(q, req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
spin_unlock_irqrestore(q->queue_lock, flags);

/*
@@ -1259,7 +1259,7 @@ static void scsi_kill_requests(request_q
req->flags |= REQ_QUIET;
while (end_that_request_first(req, 0, req->nr_sectors))
;
- end_that_request_last(req);
+ end_that_request_last(req, 0);
}
}

@@ -1314,7 +1314,7 @@ static void scsi_request_fn(struct reque
req->flags |= REQ_QUIET;
while (end_that_request_first(req, 0, req->nr_sectors))
;
- end_that_request_last(req);
+ end_that_request_last(req, 0);
continue;
}

Index: blk-fixes/drivers/scsi/sd.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sd.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sd.c 2005-05-29 13:20:30.000000000 +0900
@@ -758,7 +758,7 @@ static void sd_end_flush(request_queue_t
* force journal abort of barriers
*/
end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors);
- end_that_request_last(rq);
+ end_that_request_last(rq, -EOPNOTSUPP);
}
}

Index: blk-fixes/include/linux/blkdev.h
===================================================================
--- blk-fixes.orig/include/linux/blkdev.h 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/include/linux/blkdev.h 2005-05-29 13:20:30.000000000 +0900
@@ -102,7 +102,7 @@ void copy_io_context(struct io_context *
void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);

struct request;
-typedef void (rq_end_io_fn)(struct request *);
+typedef void (rq_end_io_fn)(struct request *, int);

struct request_list {
int count[2];
@@ -547,7 +547,7 @@ extern void blk_unregister_queue(struct
extern void register_disk(struct gendisk *dev);
extern void generic_make_request(struct bio *bio);
extern void blk_put_request(struct request *);
-extern void blk_end_sync_rq(struct request *rq);
+extern void blk_end_sync_rq(struct request *rq, int error);
extern void blk_attempt_remerge(request_queue_t *, struct request *);
extern struct request *blk_get_request(request_queue_t *, int, int);
extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
@@ -595,7 +595,7 @@ static inline void blk_run_address_space
*/
extern int end_that_request_first(struct request *, int, int);
extern int end_that_request_chunk(struct request *, int, int);
-extern void end_that_request_last(struct request *);
+extern void end_that_request_last(struct request *, int);
extern void end_request(struct request *req, int uptodate);

/*

2005-05-29 04:25:25

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 03/06] blk: make ide use -EOPNOTSUPP instead of -EIO on ABRT_ERR

03_blk_ide_eopnotsupp.patch

Use -EOPNOTSUPP instead of -EIO on ABRT_ERR.

Signed-off-by: Tejun Heo <[email protected]>

ide-io.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletion(-)

Index: blk-fixes/drivers/ide/ide-io.c
===================================================================
--- blk-fixes.orig/drivers/ide/ide-io.c 2005-05-29 13:20:30.000000000 +0900
+++ blk-fixes/drivers/ide/ide-io.c 2005-05-29 13:20:31.000000000 +0900
@@ -305,6 +305,7 @@ void ide_end_drive_cmd (ide_drive_t *dri
ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
struct request *rq;
+ int uptodate;

spin_lock_irqsave(&ide_lock, flags);
rq = HWGROUP(drive)->rq;
@@ -379,7 +380,10 @@ void ide_end_drive_cmd (ide_drive_t *dri
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
rq->errors = err;
- end_that_request_last(rq, !rq->errors);
+ uptodate = 1;
+ if (err)
+ uptodate = err & ABRT_ERR ? -EOPNOTSUPP : -EIO;
+ end_that_request_last(rq, uptodate);
spin_unlock_irqrestore(&ide_lock, flags);
}


2005-05-29 04:28:55

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 02/06] blk: make scsi use -EOPNOTSUPP instead of -EIO on ILLEGAL_REQUEST

02_blk_scsi_eopnotsupp.patch

Use -EOPNOTSUPP instead of -EIO on ILLEGAL_REQUEST.

Signed-off-by: Tejun Heo <[email protected]>

scsi_lib.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)

Index: blk-fixes/drivers/scsi/scsi_lib.c
===================================================================
--- blk-fixes.orig/drivers/scsi/scsi_lib.c 2005-05-29 13:20:30.000000000 +0900
+++ blk-fixes/drivers/scsi/scsi_lib.c 2005-05-29 13:20:31.000000000 +0900
@@ -849,7 +849,8 @@ void scsi_io_completion(struct scsi_cmnd
scsi_requeue_command(q, cmd);
result = 0;
} else {
- cmd = scsi_end_request(cmd, 0, this_count, 1);
+ cmd = scsi_end_request(cmd, -EOPNOTSUPP,
+ this_count, 1);
return;
}
break;

2005-05-29 04:28:54

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 05/06] blk: turn on QUEUE_ORDERED_FLUSH by default if ordered tag isn't supported

05_blk_scsi_turn_on_flushing_by_default.patch

As flushing can now be used by devices which only support
simple tags, there's no need to use
Scsi_Host_Template->ordered_flush to enable it selectively.
This patch removes ->ordered_flush and enables flushing
implicitly when ordered tag isn't supported. If the device
doesn't support flushing, it can just return -EOPNOTSUPP for
flush requests. blk layer will switch to QUEUE_OREDERED_NONE
automatically.

Signed-off-by: Tejun Heo <[email protected]>

drivers/scsi/ahci.c | 1 -
drivers/scsi/ata_piix.c | 1 -
drivers/scsi/hosts.c | 9 ---------
drivers/scsi/sata_nv.c | 1 -
drivers/scsi/sata_promise.c | 1 -
drivers/scsi/sata_sil.c | 1 -
drivers/scsi/sata_sis.c | 1 -
drivers/scsi/sata_svw.c | 1 -
drivers/scsi/sata_sx4.c | 1 -
drivers/scsi/sata_uli.c | 1 -
drivers/scsi/sata_via.c | 1 -
drivers/scsi/sata_vsc.c | 1 -
drivers/scsi/scsi_lib.c | 2 +-
include/scsi/scsi_host.h | 1 -
14 files changed, 1 insertion(+), 22 deletions(-)

Index: blk-fixes/drivers/scsi/ahci.c
===================================================================
--- blk-fixes.orig/drivers/scsi/ahci.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/ahci.c 2005-05-29 13:20:32.000000000 +0900
@@ -200,7 +200,6 @@ static Scsi_Host_Template ahci_sht = {
.dma_boundary = AHCI_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations ahci_ops = {
Index: blk-fixes/drivers/scsi/ata_piix.c
===================================================================
--- blk-fixes.orig/drivers/scsi/ata_piix.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/ata_piix.c 2005-05-29 13:20:32.000000000 +0900
@@ -123,7 +123,6 @@ static Scsi_Host_Template piix_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations piix_pata_ops = {
Index: blk-fixes/drivers/scsi/hosts.c
===================================================================
--- blk-fixes.orig/drivers/scsi/hosts.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/hosts.c 2005-05-29 13:20:32.000000000 +0900
@@ -264,17 +264,8 @@ struct Scsi_Host *scsi_host_alloc(struct
shost->cmd_per_lun = sht->cmd_per_lun;
shost->unchecked_isa_dma = sht->unchecked_isa_dma;
shost->use_clustering = sht->use_clustering;
- shost->ordered_flush = sht->ordered_flush;
shost->ordered_tag = sht->ordered_tag;

- /*
- * hosts/devices that do queueing must support ordered tags
- */
- if (shost->can_queue > 1 && shost->ordered_flush) {
- printk(KERN_ERR "scsi: ordered flushes don't support queueing\n");
- shost->ordered_flush = 0;
- }
-
if (sht->max_host_blocked)
shost->max_host_blocked = sht->max_host_blocked;
else
Index: blk-fixes/drivers/scsi/sata_nv.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_nv.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_nv.c 2005-05-29 13:20:32.000000000 +0900
@@ -206,7 +206,6 @@ static Scsi_Host_Template nv_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations nv_ops = {
Index: blk-fixes/drivers/scsi/sata_promise.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_promise.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_promise.c 2005-05-29 13:20:32.000000000 +0900
@@ -102,7 +102,6 @@ static Scsi_Host_Template pdc_ata_sht =
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations pdc_ata_ops = {
Index: blk-fixes/drivers/scsi/sata_sil.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_sil.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_sil.c 2005-05-29 13:20:32.000000000 +0900
@@ -134,7 +134,6 @@ static Scsi_Host_Template sil_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations sil_ops = {
Index: blk-fixes/drivers/scsi/sata_sis.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_sis.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_sis.c 2005-05-29 13:20:32.000000000 +0900
@@ -90,7 +90,6 @@ static Scsi_Host_Template sis_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations sis_ops = {
Index: blk-fixes/drivers/scsi/sata_svw.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_svw.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_svw.c 2005-05-29 13:20:32.000000000 +0900
@@ -288,7 +288,6 @@ static Scsi_Host_Template k2_sata_sht =
.proc_info = k2_sata_proc_info,
#endif
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};


Index: blk-fixes/drivers/scsi/sata_sx4.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_sx4.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_sx4.c 2005-05-29 13:20:32.000000000 +0900
@@ -188,7 +188,6 @@ static Scsi_Host_Template pdc_sata_sht =
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations pdc_20621_ops = {
Index: blk-fixes/drivers/scsi/sata_uli.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_uli.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_uli.c 2005-05-29 13:20:32.000000000 +0900
@@ -82,7 +82,6 @@ static Scsi_Host_Template uli_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations uli_ops = {
Index: blk-fixes/drivers/scsi/sata_via.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_via.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_via.c 2005-05-29 13:20:32.000000000 +0900
@@ -102,7 +102,6 @@ static Scsi_Host_Template svia_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};

static struct ata_port_operations svia_sata_ops = {
Index: blk-fixes/drivers/scsi/sata_vsc.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sata_vsc.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/scsi/sata_vsc.c 2005-05-29 13:20:32.000000000 +0900
@@ -205,7 +205,6 @@ static Scsi_Host_Template vsc_sata_sht =
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};


Index: blk-fixes/drivers/scsi/scsi_lib.c
===================================================================
--- blk-fixes.orig/drivers/scsi/scsi_lib.c 2005-05-29 13:20:31.000000000 +0900
+++ blk-fixes/drivers/scsi/scsi_lib.c 2005-05-29 13:20:32.000000000 +0900
@@ -1428,7 +1428,7 @@ struct request_queue *scsi_alloc_queue(s
*/
if (shost->ordered_tag)
blk_queue_ordered(q, QUEUE_ORDERED_TAG);
- else if (shost->ordered_flush) {
+ else {
blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
q->prepare_flush_fn = scsi_prepare_flush_fn;
}
Index: blk-fixes/include/scsi/scsi_host.h
===================================================================
--- blk-fixes.orig/include/scsi/scsi_host.h 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/include/scsi/scsi_host.h 2005-05-29 13:20:32.000000000 +0900
@@ -366,7 +366,6 @@ struct scsi_host_template {
/*
* ordered write support
*/
- unsigned ordered_flush:1;
unsigned ordered_tag:1;

/*

2005-05-29 04:33:15

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 04/06] blk: reimplement QUEUE_OREDERED_FLUSH

04_blk_flush_reimplementation.patch

Reimplement QUEUE_ORDERED_FLUSH.

* Implementation is contained inside blk layer. Only
prepare_flush_fn() is needed from individual drivers.
* Tagged queues which don't support ordered tag can use
flushing.
* Multi-bio barrier requests supported.

Signed-off-by: Tejun Heo <[email protected]>

drivers/block/elevator.c | 52 ++++----
drivers/block/ll_rw_blk.c | 279 +++++++++++++++++++++++++++------------------
drivers/ide/ide-disk.c | 39 ------
drivers/ide/ide-io.c | 5
drivers/scsi/scsi_lib.c | 21 ---
drivers/scsi/sd.c | 25 ----
include/linux/blkdev.h | 29 ++--
include/scsi/scsi_driver.h | 1
8 files changed, 210 insertions(+), 241 deletions(-)

Index: blk-fixes/drivers/block/elevator.c
===================================================================
--- blk-fixes.orig/drivers/block/elevator.c 2005-05-29 13:20:30.000000000 +0900
+++ blk-fixes/drivers/block/elevator.c 2005-05-29 13:20:31.000000000 +0900
@@ -40,6 +40,26 @@
static DEFINE_SPINLOCK(elv_list_lock);
static LIST_HEAD(elv_list);

+static inline void elv_inc_inflight(request_queue_t *q)
+{
+ q->in_flight++;
+}
+
+static inline void elv_dec_inflight(request_queue_t *q)
+{
+ q->in_flight--;
+
+ /*
+ * If the queue is waiting for all accounted requests to be
+ * drained to start flush sequence and we're the last one,
+ * kick the queue in the ass to start the flush sequence.
+ */
+ if (q->flush_seq == QUEUE_FLUSH_DRAIN && q->in_flight == 0) {
+ q->flush_seq = QUEUE_FLUSH_PRE;
+ q->request_fn(q);
+ }
+}
+
/*
* can we safely merge with this request?
*/
@@ -270,7 +290,7 @@ void elv_deactivate_request(request_queu
* in_flight count again
*/
if (blk_account_rq(rq))
- q->in_flight--;
+ elv_dec_inflight(q);

rq->flags &= ~REQ_STARTED;

@@ -283,14 +303,6 @@ void elv_requeue_request(request_queue_t
elv_deactivate_request(q, rq);

/*
- * if this is the flush, requeue the original instead and drop the flush
- */
- if (rq->flags & REQ_BAR_FLUSH) {
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- rq = rq->end_io_data;
- }
-
- /*
* the request is prepped and may have some resources allocated.
* allowing unprepped requests to pass this one may cause resource
* deadlock. turn on softbarrier.
@@ -353,20 +365,10 @@ void elv_add_request(request_queue_t *q,

static inline struct request *__elv_next_request(request_queue_t *q)
{
- struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
-
- /*
- * if this is a barrier write and the device has to issue a
- * flush sequence to support it, check how far we are
- */
- if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
- BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
-
- if (q->ordered == QUEUE_ORDERED_FLUSH &&
- !blk_barrier_preflush(rq))
- rq = blk_start_pre_flush(q, rq);
- }
-
+ struct request *rq;
+ while ((rq = q->elevator->ops->elevator_next_req_fn(q)))
+ if (blk_do_barrier(q, &rq))
+ break;
return rq;
}

@@ -433,7 +435,7 @@ void elv_remove_request(request_queue_t
* for request-request merges
*/
if (blk_account_rq(rq))
- q->in_flight++;
+ elv_inc_inflight(q);

/*
* the main clearing point for q->last_merge is on retrieval of
@@ -529,7 +531,7 @@ void elv_completed_request(request_queue
* request is released from the driver, io must be done
*/
if (blk_account_rq(rq))
- q->in_flight--;
+ elv_dec_inflight(q);

if (e->ops->elevator_completed_req_fn)
e->ops->elevator_completed_req_fn(q, rq);
Index: blk-fixes/drivers/block/ll_rw_blk.c
===================================================================
--- blk-fixes.orig/drivers/block/ll_rw_blk.c 2005-05-29 13:20:30.000000000 +0900
+++ blk-fixes/drivers/block/ll_rw_blk.c 2005-05-29 13:20:31.000000000 +0900
@@ -347,165 +347,216 @@ EXPORT_SYMBOL(blk_queue_issue_flush_fn);
/*
* Cache flushing for ordered writes handling
*/
-static void blk_pre_flush_end_io(struct request *flush_rq, int error)
+static void blk_finish_flush(request_queue_t *q, int error)
{
- struct request *rq = flush_rq->end_io_data;
- request_queue_t *q = rq->q;
+ struct request *rq = q->bar_rq;
+ struct bio *bio = q->bar_bio;

- rq->flags |= REQ_BAR_PREFLUSH;
+ q->flush_seq = QUEUE_FLUSH_NONE;
+ q->bar_rq = NULL;
+ q->bar_bio = NULL;

- if (!flush_rq->errors)
- elv_requeue_request(q, rq);
- else {
- q->end_flush_fn(q, flush_rq);
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- q->request_fn(q);
+ while (bio) {
+ bio_endio(bio, bio->bi_size, error);
+ bio = bio->bi_next;
}
+ end_that_request_last(rq, error ? error : 1);
+
+ q->request_fn(q); /* is this necessary? - tj */
}

-static void blk_post_flush_end_io(struct request *flush_rq, int error)
+static int blk_prep_flush(request_queue_t *q, struct request *flush_rq,
+ struct gendisk *disk)
{
- struct request *rq = flush_rq->end_io_data;
- request_queue_t *q = rq->q;
-
- rq->flags |= REQ_BAR_POSTFLUSH;
+ rq_init(q, flush_rq);
+ flush_rq->flags = 0;
+ flush_rq->elevator_private = NULL;
+ flush_rq->rq_disk = disk;
+ flush_rq->rl = NULL;

- q->end_flush_fn(q, flush_rq);
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- q->request_fn(q);
+ return q->prepare_flush_fn(q, flush_rq);
}

-struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
+static void blk_pre_flush_end_io(struct request *flush_rq, int error)
{
- struct request *flush_rq = q->flush_rq;
+ request_queue_t *q = flush_rq->q;
+ struct request *rq = q->bar_rq;

- BUG_ON(!blk_barrier_rq(rq));
+ switch (error) {
+ case 0:
+ q->flush_seq = QUEUE_FLUSH_BAR;
+ elv_requeue_request(q, rq);
+ break;

- if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags))
- return NULL;
+ case -EOPNOTSUPP:
+ blk_queue_ordered(q, QUEUE_ORDERED_NONE);
+ /* fall through */
+ default:
+ blk_finish_flush(q, error);
+ break;
+ }
+}

- rq_init(q, flush_rq);
- flush_rq->elevator_private = NULL;
- flush_rq->flags = REQ_BAR_FLUSH;
- flush_rq->rq_disk = rq->rq_disk;
- flush_rq->rl = NULL;
+static void blk_post_flush_end_io(struct request *flush_rq, int error)
+{
+ blk_finish_flush(flush_rq->q, error);
+}

- /*
- * prepare_flush returns 0 if no flush is needed, just mark both
- * pre and post flush as done in that case
- */
- if (!q->prepare_flush_fn(q, flush_rq)) {
- rq->flags |= REQ_BAR_PREFLUSH | REQ_BAR_POSTFLUSH;
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- return rq;
- }
+struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
+{
+ struct request *flush_rq = q->flush_rq;

/*
- * some drivers dequeue requests right away, some only after io
- * completion. make sure the request is dequeued.
+ * prepare_flush returns 0 if no flush is needed, just perform
+ * the original barrier request in that case.
*/
- if (!list_empty(&rq->queuelist))
- blkdev_dequeue_request(rq);
+ if (!blk_prep_flush(q, flush_rq, rq->rq_disk))
+ return rq;

- elv_deactivate_request(q, rq);
+ blkdev_dequeue_request(rq);
+ q->bar_rq = rq;
+ q->bar_bio = rq->bio;
+ q->bi_size = 0;
+ q->flush_error = 0;

- flush_rq->end_io_data = rq;
flush_rq->end_io = blk_pre_flush_end_io;

__elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
- return flush_rq;
+
+ if (q->in_flight == 0) {
+ q->flush_seq = QUEUE_FLUSH_PRE;
+ return flush_rq;
+ } else {
+ q->flush_seq = QUEUE_FLUSH_DRAIN;
+ return NULL;
+ }
}

-static void blk_start_post_flush(request_queue_t *q, struct request *rq)
+static void blk_start_post_flush(request_queue_t *q)
{
struct request *flush_rq = q->flush_rq;

- BUG_ON(!blk_barrier_rq(rq));
+ if (blk_prep_flush(q, flush_rq, q->bar_rq->rq_disk)) {
+ flush_rq->end_io = blk_post_flush_end_io;
+ q->flush_seq = QUEUE_FLUSH_POST;
+ __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+ q->request_fn(q); /* is this necessary? - tj */
+ } else
+ blk_finish_flush(q, 0);
+}

- rq_init(q, flush_rq);
- flush_rq->elevator_private = NULL;
- flush_rq->flags = REQ_BAR_FLUSH;
- flush_rq->rq_disk = rq->rq_disk;
- flush_rq->rl = NULL;
+int blk_do_barrier(request_queue_t *q, struct request **rqp)
+{
+ struct request *rq = *rqp;
+ int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq);

- if (q->prepare_flush_fn(q, flush_rq)) {
- flush_rq->end_io_data = rq;
- flush_rq->end_io = blk_post_flush_end_io;
+ switch (q->ordered) {
+ case QUEUE_ORDERED_NONE:
+ if (is_barrier) {
+ /*
+ * This can happen when the queue switches to
+ * ORDERED_NONE while this request is on it.
+ */
+ end_that_request_first(rq, -EOPNOTSUPP,
+ rq->hard_nr_sectors);
+ end_that_request_last(rq, -EOPNOTSUPP);
+ *rqp = NULL;
+ return 0;
+ }
+ return 1;

- __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
- q->request_fn(q);
+ case QUEUE_ORDERED_FLUSH:
+ switch (q->flush_seq) {
+ case QUEUE_FLUSH_NONE:
+ if (is_barrier)
+ *rqp = blk_start_pre_flush(q, rq);
+ break;
+ case QUEUE_FLUSH_DRAIN:
+ *rqp = NULL;
+ break;
+ default:
+ /*
+ * Don't allow any other requests while
+ * flushing is in progress.
+ */
+ if (rq != q->flush_rq && rq != q->bar_rq)
+ *rqp = NULL;
+ break;
+ }
+ return 1;
+
+ case QUEUE_ORDERED_TAG:
+ return 1;
+
+ default:
+ BUG();
+ return 1;
}
}

-static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq,
- int sectors)
+static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
{
- if (sectors > rq->nr_sectors)
- sectors = rq->nr_sectors;
+ request_queue_t *q = bio->bi_private;
+
+ /*
+ * This is dry run, restore bio_sector and size. We'll finish
+ * this request again with the original bi_end_io after an
+ * error occurs or post flush is complete.
+ */
+ q->bi_size += bytes;
+
+ if (bio->bi_size)
+ return 1;
+
+ bio->bi_size = q->bi_size;
+ bio->bi_sector -= (q->bi_size >> 9);
+ q->bi_size = 0;

- rq->nr_sectors -= sectors;
- return rq->nr_sectors;
+ return 0;
}

-static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq,
- int sectors, int queue_locked)
+static inline int blk_flush_bio_endio(struct request *rq, struct bio *bio,
+ unsigned int nbytes, int error)
{
- if (q->ordered != QUEUE_ORDERED_FLUSH)
- return 0;
- if (!blk_fs_request(rq) || !blk_barrier_rq(rq))
- return 0;
- if (blk_barrier_postflush(rq))
+ request_queue_t *q = rq->q;
+ bio_end_io_t *endio;
+ void *private;
+
+ if (q->flush_seq != QUEUE_FLUSH_BAR || q->bar_rq != rq)
return 0;

- if (!blk_check_end_barrier(q, rq, sectors)) {
- unsigned long flags = 0;
+ /*
+ * Okay, this is the barrier request in progress, dry finish it.
+ */
+ if (error)
+ q->flush_error = error;

- if (!queue_locked)
- spin_lock_irqsave(q->queue_lock, flags);
+ endio = bio->bi_end_io;
+ private = bio->bi_private;
+ bio->bi_end_io = flush_dry_bio_endio;
+ bio->bi_private = q;

- blk_start_post_flush(q, rq);
+ bio_endio(bio, nbytes, error);

- if (!queue_locked)
- spin_unlock_irqrestore(q->queue_lock, flags);
- }
+ bio->bi_end_io = endio;
+ bio->bi_private = private;

return 1;
}

-/**
- * blk_complete_barrier_rq - complete possible barrier request
- * @q: the request queue for the device
- * @rq: the request
- * @sectors: number of sectors to complete
- *
- * Description:
- * Used in driver end_io handling to determine whether to postpone
- * completion of a barrier request until a post flush has been done. This
- * is the unlocked variant, used if the caller doesn't already hold the
- * queue lock.
- **/
-int blk_complete_barrier_rq(request_queue_t *q, struct request *rq, int sectors)
+static inline int blk_flush_end_request(struct request *rq)
{
- return __blk_complete_barrier_rq(q, rq, sectors, 0);
-}
-EXPORT_SYMBOL(blk_complete_barrier_rq);
+ request_queue_t *q = rq->q;

-/**
- * blk_complete_barrier_rq_locked - complete possible barrier request
- * @q: the request queue for the device
- * @rq: the request
- * @sectors: number of sectors to complete
- *
- * Description:
- * See blk_complete_barrier_rq(). This variant must be used if the caller
- * holds the queue lock.
- **/
-int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq,
- int sectors)
-{
- return __blk_complete_barrier_rq(q, rq, sectors, 1);
+ if (q->flush_seq != QUEUE_FLUSH_BAR || q->bar_rq != rq)
+ return 0;
+
+ if (!q->flush_error)
+ blk_start_post_flush(q);
+ else
+ blk_finish_flush(q, q->flush_error);
+ return 1;
}
-EXPORT_SYMBOL(blk_complete_barrier_rq_locked);

/**
* blk_queue_bounce_limit - set bounce buffer limit for queue
@@ -3029,7 +3080,8 @@ static int __end_that_request_first(stru
if (nr_bytes >= bio->bi_size) {
req->bio = bio->bi_next;
nbytes = bio->bi_size;
- bio_endio(bio, nbytes, error);
+ if (!blk_flush_bio_endio(req, bio, nbytes, error))
+ bio_endio(bio, nbytes, error);
next_idx = 0;
bio_nbytes = 0;
} else {
@@ -3084,7 +3136,8 @@ static int __end_that_request_first(stru
* if the request wasn't completed, update state
*/
if (bio_nbytes) {
- bio_endio(bio, bio_nbytes, error);
+ if (!blk_flush_bio_endio(req, bio, bio_nbytes, error))
+ bio_endio(bio, bio_nbytes, error);
bio->bi_idx += next_idx;
bio_iovec(bio)->bv_offset += nr_bytes;
bio_iovec(bio)->bv_len -= nr_bytes;
@@ -3147,6 +3200,12 @@ void end_that_request_last(struct reques
int error;

/*
+ * Are we finishing the barrier request?
+ */
+ if (blk_flush_end_request(req))
+ return;
+
+ /*
* extend uptodate bool to allow < 0 value to be direct io error
*/
error = 0;
Index: blk-fixes/drivers/ide/ide-disk.c
===================================================================
--- blk-fixes.orig/drivers/ide/ide-disk.c 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/drivers/ide/ide-disk.c 2005-05-29 13:20:31.000000000 +0900
@@ -681,44 +681,6 @@ static ide_proc_entry_t idedisk_proc[] =

#endif /* CONFIG_PROC_FS */

-static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq)
-{
- ide_drive_t *drive = q->queuedata;
- struct request *rq = flush_rq->end_io_data;
- int good_sectors = rq->hard_nr_sectors;
- int bad_sectors;
- sector_t sector;
-
- if (flush_rq->errors & ABRT_ERR) {
- printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
- blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE);
- blk_queue_issue_flush_fn(drive->queue, NULL);
- good_sectors = 0;
- } else if (flush_rq->errors) {
- good_sectors = 0;
- if (blk_barrier_preflush(rq)) {
- sector = ide_get_error_location(drive,flush_rq->buffer);
- if ((sector >= rq->hard_sector) &&
- (sector < rq->hard_sector + rq->hard_nr_sectors))
- good_sectors = sector - rq->hard_sector;
- }
- }
-
- if (flush_rq->errors)
- printk(KERN_ERR "%s: failed barrier write: "
- "sector=%Lx(good=%d/bad=%d)\n",
- drive->name, (unsigned long long)rq->sector,
- good_sectors,
- (int) (rq->hard_nr_sectors-good_sectors));
-
- bad_sectors = rq->hard_nr_sectors - good_sectors;
-
- if (good_sectors)
- __ide_end_request(drive, rq, 1, good_sectors);
- if (bad_sectors)
- __ide_end_request(drive, rq, 0, bad_sectors);
-}
-
static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
@@ -1016,7 +978,6 @@ static void idedisk_setup (ide_drive_t *
if (barrier) {
blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH);
drive->queue->prepare_flush_fn = idedisk_prepare_flush;
- drive->queue->end_flush_fn = idedisk_end_flush;
blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
}
}
Index: blk-fixes/drivers/ide/ide-io.c
===================================================================
--- blk-fixes.orig/drivers/ide/ide-io.c 2005-05-29 13:20:31.000000000 +0900
+++ blk-fixes/drivers/ide/ide-io.c 2005-05-29 13:20:31.000000000 +0900
@@ -119,10 +119,7 @@ int ide_end_request (ide_drive_t *drive,
if (!nr_sectors)
nr_sectors = rq->hard_cur_sectors;

- if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors))
- ret = rq->nr_sectors != 0;
- else
- ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
+ ret = __ide_end_request(drive, rq, uptodate, nr_sectors);

spin_unlock_irqrestore(&ide_lock, flags);
return ret;
Index: blk-fixes/drivers/scsi/scsi_lib.c
===================================================================
--- blk-fixes.orig/drivers/scsi/scsi_lib.c 2005-05-29 13:20:31.000000000 +0900
+++ blk-fixes/drivers/scsi/scsi_lib.c 2005-05-29 13:20:31.000000000 +0900
@@ -717,9 +717,6 @@ void scsi_io_completion(struct scsi_cmnd
int sense_valid = 0;
int sense_deferred = 0;

- if (blk_complete_barrier_rq(q, req, good_bytes >> 9))
- return;
-
/*
* Free up any indirection buffers we allocated for DMA purposes.
* For the case of a READ, we need to copy the data out of the
@@ -999,23 +996,6 @@ static int scsi_prepare_flush_fn(request
return 0;
}

-static void scsi_end_flush_fn(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct request *flush_rq = rq->end_io_data;
- struct scsi_driver *drv;
-
- if (flush_rq->errors) {
- printk("scsi: barrier error, disabling flush support\n");
- blk_queue_ordered(q, QUEUE_ORDERED_NONE);
- }
-
- if (sdev->sdev_state == SDEV_RUNNING) {
- drv = *(struct scsi_driver **) rq->rq_disk->private_data;
- drv->end_flush(q, rq);
- }
-}
-
static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
@@ -1451,7 +1431,6 @@ struct request_queue *scsi_alloc_queue(s
else if (shost->ordered_flush) {
blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
q->prepare_flush_fn = scsi_prepare_flush_fn;
- q->end_flush_fn = scsi_end_flush_fn;
}

if (!shost->use_clustering)
Index: blk-fixes/drivers/scsi/sd.c
===================================================================
--- blk-fixes.orig/drivers/scsi/sd.c 2005-05-29 13:20:30.000000000 +0900
+++ blk-fixes/drivers/scsi/sd.c 2005-05-29 13:20:31.000000000 +0900
@@ -122,7 +122,6 @@ static void sd_shutdown(struct device *d
static void sd_rescan(struct device *);
static int sd_init_command(struct scsi_cmnd *);
static int sd_issue_flush(struct device *, sector_t *);
-static void sd_end_flush(request_queue_t *, struct request *);
static int sd_prepare_flush(request_queue_t *, struct request *);
static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
struct scsi_request *SRpnt, unsigned char *buffer);
@@ -139,7 +138,6 @@ static struct scsi_driver sd_template =
.init_command = sd_init_command,
.issue_flush = sd_issue_flush,
.prepare_flush = sd_prepare_flush,
- .end_flush = sd_end_flush,
};

/*
@@ -739,29 +737,6 @@ static int sd_issue_flush(struct device
return sd_sync_cache(sdp);
}

-static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
-{
- struct request *rq = flush_rq->end_io_data;
- struct scsi_cmnd *cmd = rq->special;
- unsigned int bytes = rq->hard_nr_sectors << 9;
-
- if (!flush_rq->errors) {
- spin_unlock(q->queue_lock);
- scsi_io_completion(cmd, bytes, 0);
- spin_lock(q->queue_lock);
- } else if (blk_barrier_postflush(rq)) {
- spin_unlock(q->queue_lock);
- scsi_io_completion(cmd, 0, bytes);
- spin_lock(q->queue_lock);
- } else {
- /*
- * force journal abort of barriers
- */
- end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors);
- end_that_request_last(rq, -EOPNOTSUPP);
- }
-}
-
static int sd_prepare_flush(request_queue_t *q, struct request *rq)
{
struct scsi_device *sdev = q->queuedata;
Index: blk-fixes/include/linux/blkdev.h
===================================================================
--- blk-fixes.orig/include/linux/blkdev.h 2005-05-29 13:20:30.000000000 +0900
+++ blk-fixes/include/linux/blkdev.h 2005-05-29 13:20:31.000000000 +0900
@@ -227,9 +227,6 @@ enum rq_flag_bits {
__REQ_PM_SUSPEND, /* suspend request */
__REQ_PM_RESUME, /* resume request */
__REQ_PM_SHUTDOWN, /* shutdown request */
- __REQ_BAR_PREFLUSH, /* barrier pre-flush done */
- __REQ_BAR_POSTFLUSH, /* barrier post-flush */
- __REQ_BAR_FLUSH, /* rq is the flush request */
__REQ_NR_BITS, /* stops here */
};

@@ -255,9 +252,6 @@ enum rq_flag_bits {
#define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND)
#define REQ_PM_RESUME (1 << __REQ_PM_RESUME)
#define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN)
-#define REQ_BAR_PREFLUSH (1 << __REQ_BAR_PREFLUSH)
-#define REQ_BAR_POSTFLUSH (1 << __REQ_BAR_POSTFLUSH)
-#define REQ_BAR_FLUSH (1 << __REQ_BAR_FLUSH)

/*
* State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -288,7 +282,6 @@ typedef int (merge_bvec_fn) (request_que
typedef void (activity_fn) (void *data, int rw);
typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
typedef int (prepare_flush_fn) (request_queue_t *, struct request *);
-typedef void (end_flush_fn) (request_queue_t *, struct request *);

enum blk_queue_state {
Queue_down,
@@ -329,7 +322,6 @@ struct request_queue
activity_fn *activity_fn;
issue_flush_fn *issue_flush_fn;
prepare_flush_fn *prepare_flush_fn;
- end_flush_fn *end_flush_fn;

/*
* Auto-unplugging state
@@ -409,7 +401,11 @@ struct request_queue
/*
* reserved for flush operations
*/
- struct request *flush_rq;
+ int flush_seq; /* QUEUE_FLUSH_* */
+ int flush_error;
+ struct request *flush_rq, *bar_rq;
+ struct bio *bar_bio;
+ unsigned int bi_size;
unsigned char ordered;
};

@@ -434,12 +430,17 @@ enum {
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
#define QUEUE_FLAG_DRAIN 8 /* draining queue for sched switch */
-#define QUEUE_FLAG_FLUSH 9 /* doing barrier flush sequence */
+
+#define QUEUE_FLUSH_NONE 0 /* flushing isn't in progress */
+#define QUEUE_FLUSH_DRAIN 1 /* waiting for the queue to be drained */
+#define QUEUE_FLUSH_PRE 2 /* pre-flushing in progress */
+#define QUEUE_FLUSH_BAR 3 /* original barrier req in progress */
+#define QUEUE_FLUSH_POST 4 /* post-flushing in progress */

#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
#define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
-#define blk_queue_flushing(q) test_bit(QUEUE_FLAG_FLUSH, &(q)->queue_flags)
+#define blk_queue_flushing(q) ((q)->flush_seq != QUEUE_FLUSH_NONE)

#define blk_fs_request(rq) ((rq)->flags & REQ_CMD)
#define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC)
@@ -454,8 +455,6 @@ enum {
((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME))

#define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER)
-#define blk_barrier_preflush(rq) ((rq)->flags & REQ_BAR_PREFLUSH)
-#define blk_barrier_postflush(rq) ((rq)->flags & REQ_BAR_POSTFLUSH)

#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)

@@ -638,9 +637,7 @@ extern void blk_queue_dma_alignment(requ
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
extern void blk_queue_ordered(request_queue_t *, int);
extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
-extern struct request *blk_start_pre_flush(request_queue_t *,struct request *);
-extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int);
-extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int);
+extern int blk_do_barrier(request_queue_t *, struct request **);

extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
extern void blk_dump_rq_flags(struct request *, char *);
Index: blk-fixes/include/scsi/scsi_driver.h
===================================================================
--- blk-fixes.orig/include/scsi/scsi_driver.h 2005-05-29 13:20:29.000000000 +0900
+++ blk-fixes/include/scsi/scsi_driver.h 2005-05-29 13:20:31.000000000 +0900
@@ -15,7 +15,6 @@ struct scsi_driver {
void (*rescan)(struct device *);
int (*issue_flush)(struct device *, sector_t *);
int (*prepare_flush)(struct request_queue *, struct request *);
- void (*end_flush)(struct request_queue *, struct request *);
};
#define to_scsi_driver(drv) \
container_of((drv), struct scsi_driver, gendrv)

2005-05-29 04:34:02

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 06/06] blk: debug messages

06_blk_flush_reimplementation_debug_messages.patch

These are debug messages I've used. If you are interested how
it works...

Signed-off-by: Tejun Heo <[email protected]>

elevator.c | 3 +++
ll_rw_blk.c | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 37 insertions(+), 2 deletions(-)

Index: blk-fixes/drivers/block/elevator.c
===================================================================
--- blk-fixes.orig/drivers/block/elevator.c 2005-05-29 13:20:31.000000000 +0900
+++ blk-fixes/drivers/block/elevator.c 2005-05-29 13:20:32.000000000 +0900
@@ -37,6 +37,8 @@

#include <asm/uaccess.h>

+#define pd(fmt, args...) printk("[%-21s]: " fmt, __FUNCTION__ , ##args);
+
static DEFINE_SPINLOCK(elv_list_lock);
static LIST_HEAD(elv_list);

@@ -55,6 +57,7 @@ static inline void elv_dec_inflight(requ
* kick the queue in the ass to start the flush sequence.
*/
if (q->flush_seq == QUEUE_FLUSH_DRAIN && q->in_flight == 0) {
+ pd("-> FLUSH_PRE\n");
q->flush_seq = QUEUE_FLUSH_PRE;
q->request_fn(q);
}
Index: blk-fixes/drivers/block/ll_rw_blk.c
===================================================================
--- blk-fixes.orig/drivers/block/ll_rw_blk.c 2005-05-29 13:20:31.000000000 +0900
+++ blk-fixes/drivers/block/ll_rw_blk.c 2005-05-29 13:20:32.000000000 +0900
@@ -30,6 +30,8 @@
#include <linux/writeback.h>
#include <linux/blkdev.h>

+#define pd(fmt, args...) printk("[%-21s]: " fmt, __FUNCTION__ , ##args);
+
/*
* for max sense size
*/
@@ -352,6 +354,7 @@ static void blk_finish_flush(request_que
struct request *rq = q->bar_rq;
struct bio *bio = q->bar_bio;

+ pd("ENTER, -> FLUSH_NONE, error=%d\n", error);
q->flush_seq = QUEUE_FLUSH_NONE;
q->bar_rq = NULL;
q->bar_bio = NULL;
@@ -382,9 +385,11 @@ static void blk_pre_flush_end_io(struct
request_queue_t *q = flush_rq->q;
struct request *rq = q->bar_rq;

+ pd("ENTER\n");
switch (error) {
case 0:
q->flush_seq = QUEUE_FLUSH_BAR;
+ pd("-> FLUSH_BAR\n");
elv_requeue_request(q, rq);
break;

@@ -399,6 +404,7 @@ static void blk_pre_flush_end_io(struct

static void blk_post_flush_end_io(struct request *flush_rq, int error)
{
+ pd("ENTER\n");
blk_finish_flush(flush_rq->q, error);
}

@@ -406,12 +412,20 @@ struct request *blk_start_pre_flush(requ
{
struct request *flush_rq = q->flush_rq;

+ pd("ENTER\n");
+ struct bio *bio;
+ for (bio = rq->bio; bio; bio = bio->bi_next)
+ pd("BIO %p %llu %u\n",
+ bio, (unsigned long long)bio->bi_sector, bio->bi_size);
+
/*
* prepare_flush returns 0 if no flush is needed, just perform
* the original barrier request in that case.
*/
- if (!blk_prep_flush(q, flush_rq, rq->rq_disk))
+ if (!blk_prep_flush(q, flush_rq, rq->rq_disk)) {
+ pd("Oh well, prep says it's unnecessary\n");
return rq;
+ }

blkdev_dequeue_request(rq);
q->bar_rq = rq;
@@ -425,9 +439,11 @@ struct request *blk_start_pre_flush(requ

if (q->in_flight == 0) {
q->flush_seq = QUEUE_FLUSH_PRE;
+ pd("-> FLUSH_PRE\n");
return flush_rq;
} else {
q->flush_seq = QUEUE_FLUSH_DRAIN;
+ pd("-> FLUSH_DRAIN, in_flight=%d\n", q->in_flight);
return NULL;
}
}
@@ -436,13 +452,18 @@ static void blk_start_post_flush(request
{
struct request *flush_rq = q->flush_rq;

+ pd("ENTER\n");
+
if (blk_prep_flush(q, flush_rq, q->bar_rq->rq_disk)) {
+ pd("-> FLUSH_POST\n");
flush_rq->end_io = blk_post_flush_end_io;
q->flush_seq = QUEUE_FLUSH_POST;
__elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
q->request_fn(q); /* is this necessary? - tj */
- } else
+ } else {
+ pd("wow, unnecessary?\n");
blk_finish_flush(q, 0);
+ }
}

int blk_do_barrier(request_queue_t *q, struct request **rqp)
@@ -453,6 +474,7 @@ int blk_do_barrier(request_queue_t *q, s
switch (q->ordered) {
case QUEUE_ORDERED_NONE:
if (is_barrier) {
+ pd("ORDERED_NONE, seen barrier\n");
/*
* This can happen when the queue switches to
* ORDERED_NONE while this request is on it.
@@ -473,6 +495,7 @@ int blk_do_barrier(request_queue_t *q, s
break;
case QUEUE_FLUSH_DRAIN:
*rqp = NULL;
+ pd("draining... deferring %p\n", rq);
break;
default:
/*
@@ -481,11 +504,14 @@ int blk_do_barrier(request_queue_t *q, s
*/
if (rq != q->flush_rq && rq != q->bar_rq)
*rqp = NULL;
+ pd("flush_seq == %d, %p->%p\n", q->flush_seq, rq, *rqp);
break;
}
return 1;

case QUEUE_ORDERED_TAG:
+ if (is_barrier)
+ pd("ORDERED_TAG, seen barrier\n");
return 1;

default:
@@ -512,6 +538,9 @@ static int flush_dry_bio_endio(struct bi
bio->bi_sector -= (q->bi_size >> 9);
q->bi_size = 0;

+ pd("%p %llu %u\n",
+ bio, (unsigned long long)bio->bi_sector, bio->bi_size);
+
return 0;
}

@@ -525,6 +554,7 @@ static inline int blk_flush_bio_endio(st
if (q->flush_seq != QUEUE_FLUSH_BAR || q->bar_rq != rq)
return 0;

+ pd("q->flush_error=%d error=%d\n", q->flush_error, error);
/*
* Okay, this is the barrier request in progress, dry finish it.
*/
@@ -551,6 +581,7 @@ static inline int blk_flush_end_request(
if (q->flush_seq != QUEUE_FLUSH_BAR || q->bar_rq != rq)
return 0;

+ pd("q->flush_error=%d\n", q->flush_error);
if (!q->flush_error)
blk_start_post_flush(q);
else
@@ -2601,6 +2632,7 @@ static int __make_request(request_queue_

barrier = bio_barrier(bio);
if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
+ pd("ORDERED_NONE, seen barrier\n");
err = -EOPNOTSUPP;
goto end_io;
}

2005-05-29 09:55:10

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 04/06] blk: reimplement QUEUE_OREDERED_FLUSH

On Sun, May 29, 2005 at 01:23:38PM +0900, Tejun Heo wrote:
> 04_blk_flush_reimplementation.patch
>
> Reimplement QUEUE_ORDERED_FLUSH.
>
> * Implementation is contained inside blk layer. Only
> prepare_flush_fn() is needed from individual drivers.
> * Tagged queues which don't support ordered tag can use
> flushing.
> * Multi-bio barrier requests supported.
>
> Signed-off-by: Tejun Heo <[email protected]>
>
> drivers/block/elevator.c | 52 ++++----
> drivers/block/ll_rw_blk.c | 279 +++++++++++++++++++++++++++------------------
> drivers/ide/ide-disk.c | 39 ------
> drivers/ide/ide-io.c | 5
> drivers/scsi/scsi_lib.c | 21 ---
> drivers/scsi/sd.c | 25 ----
> include/linux/blkdev.h | 29 ++--
> include/scsi/scsi_driver.h | 1
> 8 files changed, 210 insertions(+), 241 deletions(-)

In blk_do_barrier() above patch implements, when a barrier request is
terminated w/ -EOPNOTSUPP, the request is not dequeued. The following
patch fixes this. The fixed path is a very rare error path, so, for
reviewing, this patch doesn't make much difference. I'll use properly
regenerated patch on the next posting of this patchset.

diff -u blk-fixes/drivers/block/ll_rw_blk.c blk-fixes/drivers/block/ll_rw_blk.c
--- blk-fixes/drivers/block/ll_rw_blk.c 2005-05-29 13:20:31.000000000 +0900
+++ blk-fixes/drivers/block/ll_rw_blk.c 2005-05-29 18:23:05.000000000 +0900
@@ -352,6 +352,8 @@
struct request *rq = q->bar_rq;
struct bio *bio = q->bar_bio;

+ BUG_ON(!list_empty(&rq->queuelist));
+
q->flush_seq = QUEUE_FLUSH_NONE;
q->bar_rq = NULL;
q->bar_bio = NULL;
@@ -457,6 +459,7 @@
* This can happen when the queue switches to
* ORDERED_NONE while this request is on it.
*/
+ blkdev_dequeue_request(rq);
end_that_request_first(rq, -EOPNOTSUPP,
rq->hard_nr_sectors);
end_that_request_last(rq, -EOPNOTSUPP);

2005-05-29 17:37:15

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 00/06] blk: barrier flushing reimplementation

Tejun Heo wrote:
> 05_blk_scsi_turn_on_flushing_by_default.patch
> : turn on QUEUE_ORDERED_FLUSH by default if ordered tag isn't supported
>
> As flushing can now be used by devices which only support
> simple tags, there's no need to use
> Scsi_Host_Template->ordered_flush to enable it selectively.
> This patch removes ->ordered_flush and enables flushing
> implicitly when ordered tag isn't supported. If the device
> doesn't support flushing, it can just return -EOPNOTSUPP for
> flush requests. blk layer will switch to QUEUE_OREDERED_NONE
> automatically.


This is rather nice...

Jeff


2005-05-29 19:14:26

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 00/06] blk: barrier flushing reimplementation

On Sun, May 29 2005, Tejun Heo wrote:
> Hello, guys.
>
> This patchset is reimplementation of QUEUE_ORDERED_FLUSH feature. It
> doens't update API docs yet. If it's determined that this patchset
> can go in, I'll regenerate this patchset with doc updates (sans the
> last debug message patch of course).

Awesome work, that's really the last step in getting the barrier code
fully unified and working with tags. I'll review your patchset tomorrow.

--
Jens Axboe

2005-05-30 11:31:26

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 00/06] blk: barrier flushing reimplementation

On Sun, May 29 2005, Jens Axboe wrote:
> On Sun, May 29 2005, Tejun Heo wrote:
> > Hello, guys.
> >
> > This patchset is reimplementation of QUEUE_ORDERED_FLUSH feature. It
> > doens't update API docs yet. If it's determined that this patchset
> > can go in, I'll regenerate this patchset with doc updates (sans the
> > last debug message patch of course).
>
> Awesome work, that's really the last step in getting the barrier code
> fully unified and working with tags. I'll review your patchset tomorrow.

Patches look nice, this is a good step forward. If you feel like doing a
little more work in this area, I would very much like to add
QUEUE_ORDERED_FUA as a third method for implementing barriers. Basically
it would use the FUA commands to put data safely on disk, instead of
using the post flushes.

For NCQ, we have a FUA bit in the FPDMA commands. For non-ncq, we have
the various WRITE_DMA_EXT_FUA (and similar). It would be identical to
ORDERED_FLUSH in that we let the queue drain, issue a pre-flush, and
then a write with FUA set. It would eliminate the need to issue an extra
flush at the end, cutting down the required commands for writing a
barrier from 3 to 2.

--
Jens Axboe

2005-05-30 19:40:31

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH Linux 2.6.12-rc5-mm1 00/06] blk: barrier flushing reimplementation

Jens Axboe wrote:
> On Sun, May 29 2005, Jens Axboe wrote:
>
>>On Sun, May 29 2005, Tejun Heo wrote:
>>
>>> Hello, guys.
>>>
>>> This patchset is reimplementation of QUEUE_ORDERED_FLUSH feature. It
>>>doens't update API docs yet. If it's determined that this patchset
>>>can go in, I'll regenerate this patchset with doc updates (sans the
>>>last debug message patch of course).
>>
>>Awesome work, that's really the last step in getting the barrier code
>>fully unified and working with tags. I'll review your patchset tomorrow.
>
>
> Patches look nice, this is a good step forward. If you feel like doing a
> little more work in this area, I would very much like to add
> QUEUE_ORDERED_FUA as a third method for implementing barriers. Basically
> it would use the FUA commands to put data safely on disk, instead of
> using the post flushes.
>
> For NCQ, we have a FUA bit in the FPDMA commands. For non-ncq, we have
> the various WRITE_DMA_EXT_FUA (and similar). It would be identical to
> ORDERED_FLUSH in that we let the queue drain, issue a pre-flush, and
> then a write with FUA set. It would eliminate the need to issue an extra
> flush at the end, cutting down the required commands for writing a
> barrier from 3 to 2.
>

Hi, Jens.

I'm on it.

Thanks.

--
tejun