Merge pushback and deferred lists into one list --- use deferred list
for both deferred and pushed-back bios.
This will be needed for proper support of barrier bios, it is impossible to
support ordering correctly with two lists because the requests on both lists
will be mixed up.
- unsigned barriers_supported:1;
-
/*
* Indicates the rw permissions for the new logical
* device. This should be a combination of FMODE_READ
@@ -240,7 +238,6 @@ int dm_table_create(struct dm_table **re
if (!num_targets)
num_targets = KEYS_PER_NODE;
@@ -741,10 +738,6 @@ int dm_table_add_target(struct dm_table
/* FIXME: the plan is to combine high here and then have
* the merge fn apply the target level restrictions. */
combine_restrictions_low(&t->limits, &tgt->limits);
-
- if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
- t->barriers_supported = 0;
-
return 0;
bad:
@@ -789,12 +782,6 @@ int dm_table_complete(struct dm_table *t
check_for_valid_limits(&t->limits);
- /*
- * We only support barriers if there is exactly one underlying device.
- */
- if (!list_is_singular(&t->devices))
- t->barriers_supported = 0;
-
/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
@@ -1008,12 +995,6 @@ struct mapped_device *dm_table_get_md(st
return t->md;
}
+ /*
+ * There is no use in forwarding any barrier request since we can't
+ * guarantee it is (or can be) handled by the targets correctly.
+ */
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, -EOPNOTSUPP);
+ return 0;
+ }
+
down_read(&md->io_lock);
cpu = part_stat_lock();
Index: linux-2.6.29-rc3-devel/drivers/md/dm.h
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.h 2009-02-05 05:33:48.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.h 2009-02-05 05:33:52.000000000 +0100
@@ -52,7 +52,6 @@ int dm_table_any_congested(struct dm_tab
* To check the return value from dm_table_find_target().
*/
#define dm_target_is_valid(t) ((t)->table)
-int dm_table_barrier_ok(struct dm_table *t);
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
02-23-2009, 06:22 PM
Mikulas Patocka
barriers
Rework helper thread.
IO may be submitted to a worker thread with queue_io().
queue_io() sets DMF_BLOCK_IO so that all further IO goes to the thread.
When the thread finishes its work, it clears DMF_BLOCK_IO and from this point
on, requests are submitted from dm_request again.
Add new flag DMF_BLOCK_FOR_SUSPEND that is set when the IO needs to be blocked
because of an ongoing suspend (DMF_BLOCK_IO had this meaning before this patch).
/*
* Work processed by per-device workqueue.
@@ -435,21 +436,15 @@ static void end_io_acct(struct dm_io *io
/*
* Add the bio to the list of deferred io.
*/
-static int queue_io(struct mapped_device *md, struct bio *bio)
+static void queue_io(struct mapped_device *md, struct bio *bio)
{
down_write(&md->io_lock);
-
- if (!test_bit(DMF_BLOCK_IO, &md->flags)) {
- up_write(&md->io_lock);
- return 1;
- }
-
spin_lock_irq(&md->deferred_lock);
bio_list_add(&md->deferred, bio);
spin_unlock_irq(&md->deferred_lock);
-
+ if (!test_and_set_bit(DMF_BLOCK_IO, &md->flags))
+ queue_work(md->wq, &md->work);
up_write(&md->io_lock);
- return 0; /* deferred successfully */
}
/*
@@ -908,7 +903,6 @@ out:
*/
static int dm_request(struct request_queue *q, struct bio *bio)
{
- int r = -EIO;
int rw = bio_data_dir(bio);
struct mapped_device *md = q->queuedata;
int cpu;
@@ -933,31 +927,23 @@ static int dm_request(struct request_que
* If we're suspended we have to queue
* this io for later.
*/
- while (test_bit(DMF_BLOCK_IO, &md->flags)) {
+ if (unlikely(test_bit(DMF_BLOCK_IO, &md->flags))) {
up_read(&md->io_lock);
- if (bio_rw(bio) != READA)
- r = queue_io(md, bio);
+ if (unlikely(test_bit(DMF_BLOCK_FOR_SUSPEND, &md->flags)) &&
+ bio_rw(bio) == READA) {
+ bio_io_error(bio);
+ return 0;
+ }
- /*
- * We're in a while loop, because someone could suspend
- * before we get to the following read lock.
- */
- down_read(&md->io_lock);
+ return 0;
}
/*
@@ -1543,6 +1534,7 @@ int dm_suspend(struct mapped_device *md,
* First we set the BLOCK_IO flag so no more ios will be mapped.
*/
down_write(&md->io_lock);
+ set_bit(DMF_BLOCK_FOR_SUSPEND, &md->flags);
set_bit(DMF_BLOCK_IO, &md->flags);
up_write(&md->io_lock);
@@ -1550,6 +1542,7 @@ int dm_suspend(struct mapped_device *md,
/*
* Wait for the already-mapped ios to complete.
*/
+ flush_workqueue(md->wq);
r = dm_wait_for_completion(md, TASK_INTERRUPTIBLE);
down_write(&md->io_lock);
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
02-23-2009, 06:23 PM
Mikulas Patocka
barriers
Barrier support.
Barriers are submitted to a worker thread that issues them in-order.
__process_bio functions is modified that when it sees a barrier request,
it waits for all pending IO before the request, then submits the barrier
and waits for it.
DM_ENDIO_REQUEUE doesn't work and I doubt that it can be made work with
barriers.
/*
+ * An error from the barrier request currently being processed.
+ */
+ int barrier_error;
+
+ /*
* Processing queue (flush/barriers)
*/
struct workqueue_struct *wq;
@@ -425,6 +430,10 @@ static void end_io_acct(struct dm_io *io
part_stat_add(cpu, &dm_disk(md)->part0, ticks[rw], duration);
part_stat_unlock();
+ /*
+ * after this is decremented, the bio must not be touched if it is
+ * barrier bio
+ */
dm_disk(md)->part0.in_flight = pending =
atomic_dec_return(&md->pending);
- end_io_acct(io);
+ if (bio_barrier(io->bio)) {
+ /*
+ * There could be just one barrier request, so we use
+ * per-device variable for error reporting is OK.
+ * Note that you can't touch the bio after end_io_acct
+ */
+ io->md->barrier_error = io->error;
+ end_io_acct(io);
+ } else {
+ end_io_acct(io);
- if (io->error != DM_ENDIO_REQUEUE) {
- trace_block_bio_complete(io->md->queue, io->bio);
+ if (io->error != DM_ENDIO_REQUEUE) {
+ trace_block_bio_complete(io->md->queue, io->bio);
@@ -911,11 +934,6 @@ static int dm_request(struct request_que
* There is no use in forwarding any barrier request since we can't
* guarantee it is (or can be) handled by the targets correctly.
*/
- if (unlikely(bio_barrier(bio))) {
- bio_endio(bio, -EOPNOTSUPP);
- return 0;
- }
-
down_read(&md->io_lock);
cpu = part_stat_lock();
@@ -927,7 +945,8 @@ static int dm_request(struct request_que
* If we're suspended we have to queue
* this io for later.
*/
- if (unlikely(test_bit(DMF_BLOCK_IO, &md->flags))) {
+ if (unlikely(test_bit(DMF_BLOCK_IO, &md->flags)) ||
+ unlikely(bio_barrier(bio))) {
up_read(&md->io_lock);
if (unlikely(test_bit(DMF_BLOCK_FOR_SUSPEND, &md->flags)) &&
@@ -1392,6 +1411,12 @@ static int dm_wait_for_completion(struct
return r;
}
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
03-24-2009, 01:24 PM
Alasdair G Kergon
barriers
On Mon, Feb 23, 2009 at 02:23:00PM -0500, Mikulas Patocka wrote:
> DM_ENDIO_REQUEUE doesn't work and I doubt that it can be made work with
> barriers.
Didn't we discuss this before?
We *require* DM_ENDIO_REQUEUE functionality - I can't apply a patch that
breaks it. But it is not something that can be used arbitrarily - it is
only used in situations where core dm is firmly in control (and I/O cannot get
through to the device e.g. all paths down in multipath) and I don't see why it
can't continue to work with barriers.
I hope it's just the comment that is wrong here - or does the patch need
updating?
Alasdair
--
agk@redhat.com
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
03-24-2009, 01:30 PM
Mikulas Patocka
barriers
On Tue, 24 Mar 2009, Alasdair G Kergon wrote:
> On Mon, Feb 23, 2009 at 02:23:00PM -0500, Mikulas Patocka wrote:
> > DM_ENDIO_REQUEUE doesn't work and I doubt that it can be made work with
> > barriers.
>
> Didn't we discuss this before?
> We *require* DM_ENDIO_REQUEUE functionality - I can't apply a patch that
> breaks it. But it is not something that can be used arbitrarily - it is
> only used in situations where core dm is firmly in control (and I/O cannot get
> through to the device e.g. all paths down in multipath) and I don't see why it
> can't continue to work with barriers.
>
> I hope it's just the comment that is wrong here - or does the patch need
> updating?
Oh, sorry, that is old comment for the old version of that patch. I fixed
the code but forgot to remove the comment. The code in the patch should be
correct w.r.t. DM_ENDIO_REQUEUE.
Mikulas
> Alasdair
> --
> agk@redhat.com
>
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel