FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor


 
 
LinkBack Thread Tools
 
Old 02-23-2009, 06:18 PM
Mikulas Patocka
 
Default barriers

Hi

This is the series of 14 patches for barriers. This is the "correct"
implementation --- i.e. enabling barriers for any targets.

These patches address the upper layer only (providing barriers to
filesystem), they don't send barrier request (there will be more patches
for that, but they are not yet finalized).

The patches are sorted from the simples to the more complicated.

The first 11 patches shouldn't have effect on anything, they just move
code around. So you can start slowly applying them.

Patch 11 changes generic block layer code, other patches change only dm.

Mikulas

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:19 PM
Mikulas Patocka
 
Default barriers

Introduce a function that adds a bio to the head of the list.

It will be needed for barriers.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm-bio-list.h | 10 ++++++++++
1 file changed, 10 insertions(+)

Index: linux-2.6.29-rc1-devel/drivers/md/dm-bio-list.h
================================================== =================
--- linux-2.6.29-rc1-devel.orig/drivers/md/dm-bio-list.h 2009-01-19 02:03:49.000000000 +0100
+++ linux-2.6.29-rc1-devel/drivers/md/dm-bio-list.h 2009-01-19 02:05:01.000000000 +0100
@@ -52,6 +52,16 @@ static inline void bio_list_add(struct b
bl->tail = bio;
}

+static inline void bio_list_add_head(struct bio_list *bl, struct bio *bio)
+{
+ bio->bi_next = bl->head;
+
+ bl->head = bio;
+
+ if (!bl->tail)
+ bl->tail = bio;
+}
+
static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
{
if (!bl2->head)

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:20 PM
Mikulas Patocka
 
Default barriers

Remove "type" argument of dm_wq_req because it can have only one value.
And it won't be used later.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:37:44.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:38:27.000000000 +0100
@@ -100,9 +100,6 @@ union map_info *dm_get_mapinfo(struct bi
* Work processed by per-device workqueue.
*/
struct dm_wq_req {
- enum {
- DM_WQ_FLUSH_DEFERRED,
- } type;
struct work_struct work;
struct mapped_device *md;
void *context;
@@ -1431,32 +1428,24 @@ static void dm_wq_work(struct work_struc
struct mapped_device *md = req->md;

down_write(&md->io_lock);
- switch (req->type) {
- case DM_WQ_FLUSH_DEFERRED:
- __flush_deferred_io(md);
- break;
- default:
- DMERR("dm_wq_work: unrecognised work type %d", req->type);
- BUG();
- }
+ __flush_deferred_io(md);
up_write(&md->io_lock);
}

-static void dm_wq_queue(struct mapped_device *md, int type, void *context,
+static void dm_wq_queue(struct mapped_device *md, void *context,
struct dm_wq_req *req)
{
- req->type = type;
req->md = md;
req->context = context;
INIT_WORK(&req->work, dm_wq_work);
queue_work(md->wq, &req->work);
}

-static void dm_queue_flush(struct mapped_device *md, int type, void *context)
+static void dm_queue_flush(struct mapped_device *md, void *context)
{
struct dm_wq_req req;

- dm_wq_queue(md, type, context, &req);
+ dm_wq_queue(md, context, &req);
flush_workqueue(md->wq);
}

@@ -1590,7 +1579,7 @@ int dm_suspend(struct mapped_device *md,

/* were we interrupted ? */
if (r < 0) {
- dm_queue_flush(md, DM_WQ_FLUSH_DEFERRED, NULL);
+ dm_queue_flush(md, NULL);

unlock_fs(md);
goto out; /* pushback list is already flushed, so skip flush */
@@ -1625,7 +1614,7 @@ int dm_resume(struct mapped_device *md)
if (r)
goto out;

- dm_queue_flush(md, DM_WQ_FLUSH_DEFERRED, NULL);
+ dm_queue_flush(md, NULL);

unlock_fs(md);


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:20 PM
Mikulas Patocka
 
Default barriers

Remove the context entry because it is unused. And it won't be used later.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:38:27.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:38:32.000000000 +0100
@@ -102,7 +102,6 @@ union map_info *dm_get_mapinfo(struct bi
struct dm_wq_req {
struct work_struct work;
struct mapped_device *md;
- void *context;
};

struct mapped_device {
@@ -1432,20 +1431,18 @@ static void dm_wq_work(struct work_struc
up_write(&md->io_lock);
}

-static void dm_wq_queue(struct mapped_device *md, void *context,
- struct dm_wq_req *req)
+static void dm_wq_queue(struct mapped_device *md, struct dm_wq_req *req)
{
req->md = md;
- req->context = context;
INIT_WORK(&req->work, dm_wq_work);
queue_work(md->wq, &req->work);
}

-static void dm_queue_flush(struct mapped_device *md, void *context)
+static void dm_queue_flush(struct mapped_device *md)
{
struct dm_wq_req req;

- dm_wq_queue(md, context, &req);
+ dm_wq_queue(md, &req);
flush_workqueue(md->wq);
}

@@ -1579,7 +1576,7 @@ int dm_suspend(struct mapped_device *md,

/* were we interrupted ? */
if (r < 0) {
- dm_queue_flush(md, NULL);
+ dm_queue_flush(md);

unlock_fs(md);
goto out; /* pushback list is already flushed, so skip flush */
@@ -1614,7 +1611,7 @@ int dm_resume(struct mapped_device *md)
if (r)
goto out;

- dm_queue_flush(md, NULL);
+ dm_queue_flush(md);

unlock_fs(md);


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:20 PM
Mikulas Patocka
 
Default barriers

Remove struct dm_wq_req and move "work" directly to struct mapped_device.

In the new implementation, the thread will do just one type of work (processing
the queue), there is no need for separate work requests for it.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:38:32.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:38:36.000000000 +0100
@@ -99,11 +99,6 @@ union map_info *dm_get_mapinfo(struct bi
/*
* Work processed by per-device workqueue.
*/
-struct dm_wq_req {
- struct work_struct work;
- struct mapped_device *md;
-};
-
struct mapped_device {
struct rw_semaphore io_lock;
struct mutex suspend_lock;
@@ -125,6 +120,7 @@ struct mapped_device {
*/
atomic_t pending;
wait_queue_head_t wait;
+ struct work_struct work;
struct bio_list deferred;
struct bio_list pushback;

@@ -1064,6 +1060,8 @@ out:

static struct block_device_operations dm_blk_dops;

+static void dm_wq_work(struct work_struct *work);
+
/*
* Allocate and initialise a blank device with a given minor.
*/
@@ -1130,6 +1128,7 @@ static struct mapped_device *alloc_dev(i

atomic_set(&md->pending, 0);
init_waitqueue_head(&md->wait);
+ INIT_WORK(&md->work, dm_wq_work);
init_waitqueue_head(&md->eventq);

md->disk->major = _major;
@@ -1423,26 +1422,16 @@ static void __merge_pushback_list(struct

static void dm_wq_work(struct work_struct *work)
{
- struct dm_wq_req *req = container_of(work, struct dm_wq_req, work);
- struct mapped_device *md = req->md;
+ struct mapped_device *md = container_of(work, struct mapped_device, work);

down_write(&md->io_lock);
__flush_deferred_io(md);
up_write(&md->io_lock);
}

-static void dm_wq_queue(struct mapped_device *md, struct dm_wq_req *req)
-{
- req->md = md;
- INIT_WORK(&req->work, dm_wq_work);
- queue_work(md->wq, &req->work);
-}
-
static void dm_queue_flush(struct mapped_device *md)
{
- struct dm_wq_req req;
-
- dm_wq_queue(md, &req);
+ queue_work(md->wq, &md->work);
flush_workqueue(md->wq);
}


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:20 PM
Mikulas Patocka
 
Default barriers

Rename __split_bio to __process_bio because it not only splits the bio to
serveral parts, but also submits them to target drivers.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:38:36.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:39:45.000000000 +0100
@@ -820,9 +820,9 @@ static int __clone_and_map(struct clone_
}

/*
- * Split the bio into several clones.
+ * Split the bio into several clones and submit it to targets.
*/
-static int __split_bio(struct mapped_device *md, struct bio *bio)
+static int __process_bio(struct mapped_device *md, struct bio *bio)
{
struct clone_info ci;
int error = 0;
@@ -945,7 +945,7 @@ static int dm_request(struct request_que
down_read(&md->io_lock);
}

- r = __split_bio(md, bio);
+ r = __process_bio(md, bio);
up_read(&md->io_lock);

out_req:
@@ -1402,7 +1402,7 @@ static void __flush_deferred_io(struct m
struct bio *c;

while ((c = bio_list_pop(&md->deferred))) {
- if (__split_bio(md, c))
+ if (__process_bio(md, c))
bio_io_error(c);
}


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:21 PM
Mikulas Patocka
 
Default barriers

Move bio_io_error directly to __process_bio, from its caller.

This saves some code duplication in further patches.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:39:45.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:40:54.000000000 +0100
@@ -822,18 +822,20 @@ static int __clone_and_map(struct clone_
/*
* Split the bio into several clones and submit it to targets.
*/
-static int __process_bio(struct mapped_device *md, struct bio *bio)
+static void __process_bio(struct mapped_device *md, struct bio *bio)
{
struct clone_info ci;
int error = 0;

ci.map = dm_get_table(md);
- if (unlikely(!ci.map))
- return -EIO;
+ if (unlikely(!ci.map)) {
+ bio_io_error(bio);
+ return;
+ }
if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
dm_table_put(ci.map);
bio_endio(bio, -EOPNOTSUPP);
- return 0;
+ return;
}
ci.md = md;
ci.bio = bio;
@@ -853,8 +855,6 @@ static int __process_bio(struct mapped_d
/* drop the extra reference count */
dec_pending(ci.io, error);
dm_table_put(ci.map);
-
- return 0;
}
/*-----------------------------------------------------------------
* CRUD END
@@ -945,8 +945,9 @@ static int dm_request(struct request_que
down_read(&md->io_lock);
}

- r = __process_bio(md, bio);
+ __process_bio(md, bio);
up_read(&md->io_lock);
+ return 0;

out_req:
if (r < 0)
@@ -1401,10 +1402,8 @@ static void __flush_deferred_io(struct m
{
struct bio *c;

- while ((c = bio_list_pop(&md->deferred))) {
- if (__process_bio(md, c))
- bio_io_error(c);
- }
+ while ((c = bio_list_pop(&md->deferred)))
+ __process_bio(md, c);

clear_bit(DMF_BLOCK_IO, &md->flags);
}

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:21 PM
Mikulas Patocka
 
Default barriers

Move content of __flush_deferred_io to the calling function: dm_wq_work.

There's no need to have a function that has only one caller.

It makes further patches more clean (i.e. no more dropping a lock inside a
subfunction that was took by the parent function)

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:51:29.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:52:11.000000000 +0100
@@ -1398,14 +1398,19 @@ static int dm_wait_for_completion(struct
/*
* Process the deferred bios
*/
-static void __flush_deferred_io(struct mapped_device *md)
+static void dm_wq_work(struct work_struct *work)
{
+ struct mapped_device *md = container_of(work, struct mapped_device, work);
struct bio *c;

+ down_write(&md->io_lock);
+
while ((c = bio_list_pop(&md->deferred)))
__process_bio(md, c);

clear_bit(DMF_BLOCK_IO, &md->flags);
+
+ up_write(&md->io_lock);
}

static void __merge_pushback_list(struct mapped_device *md)
@@ -1419,14 +1424,6 @@ static void __merge_pushback_list(struct
spin_unlock_irqrestore(&md->pushback_lock, flags);
}

-static void dm_wq_work(struct work_struct *work)
-{
- struct mapped_device *md = container_of(work, struct mapped_device, work);
-
- down_write(&md->io_lock);
- __flush_deferred_io(md);
- up_write(&md->io_lock);
-}

static void dm_queue_flush(struct mapped_device *md)
{

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:21 PM
Mikulas Patocka
 
Default barriers

Move wait queue declaration and unplug to dm_wait_for_completion.

The purpose is to minimize duplicate code in the further patches.

The patch reorders functions a little bit. It doesn't change any
functionality. For proper non-deadlock operation, it is required
hat add_wait_queue happens before set_current_state(interruptible)
and before the test for !atomic_read(&md->pending) --- and this
patch follows that.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:52:18.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:52:19.000000000 +0100
@@ -1375,6 +1375,11 @@ EXPORT_SYMBOL_GPL(dm_put);
static int dm_wait_for_completion(struct mapped_device *md)
{
int r = 0;
+ DECLARE_WAITQUEUE(wait, current);
+
+ dm_unplug_all(md->queue);
+
+ add_wait_queue(&md->wait, &wait);

while (1) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -1392,6 +1397,8 @@ static int dm_wait_for_completion(struct
}
set_current_state(TASK_RUNNING);

+ remove_wait_queue(&md->wait, &wait);
+
return r;
}

@@ -1497,7 +1504,6 @@ static void unlock_fs(struct mapped_devi
int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
{
struct dm_table *map = NULL;
- DECLARE_WAITQUEUE(wait, current);
int r = 0;
int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0;
int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0;
@@ -1540,20 +1546,14 @@ int dm_suspend(struct mapped_device *md,
down_write(&md->io_lock);
set_bit(DMF_BLOCK_IO, &md->flags);

- add_wait_queue(&md->wait, &wait);
up_write(&md->io_lock);

- /* unplug */
- if (map)
- dm_table_unplug_all(map);
-
/*
* Wait for the already-mapped ios to complete.
*/
r = dm_wait_for_completion(md);

down_write(&md->io_lock);
- remove_wait_queue(&md->wait, &wait);

if (noflush)
__merge_pushback_list(md);

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-23-2009, 06:22 PM
Mikulas Patocka
 
Default barriers

Allow uninterruptible wait for pending IOs.

Add argument "interruptible" to dm_wait_for_completion that specifies
either interruptible or uninterruptible waiting.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

Index: linux-2.6.29-rc3-devel/drivers/md/dm.c
================================================== =================
--- linux-2.6.29-rc3-devel.orig/drivers/md/dm.c 2009-02-05 05:52:19.000000000 +0100
+++ linux-2.6.29-rc3-devel/drivers/md/dm.c 2009-02-05 05:52:23.000000000 +0100
@@ -1372,7 +1372,7 @@ void dm_put(struct mapped_device *md)
}
EXPORT_SYMBOL_GPL(dm_put);

-static int dm_wait_for_completion(struct mapped_device *md)
+static int dm_wait_for_completion(struct mapped_device *md, int interruptible)
{
int r = 0;
DECLARE_WAITQUEUE(wait, current);
@@ -1382,13 +1382,13 @@ static int dm_wait_for_completion(struct
add_wait_queue(&md->wait, &wait);

while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
+ set_current_state(interruptible);

smp_mb();
if (!atomic_read(&md->pending))
break;

- if (signal_pending(current)) {
+ if (interruptible == TASK_INTERRUPTIBLE && signal_pending(current)) {
r = -EINTR;
break;
}
@@ -1551,7 +1551,7 @@ int dm_suspend(struct mapped_device *md,
/*
* Wait for the already-mapped ios to complete.
*/
- r = dm_wait_for_completion(md);
+ 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
 

Thread Tools




All times are GMT. The time now is 01:33 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org