git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git]
/
drivers
/
md
/
dm-mpath.c
diff --git
a/drivers/md/dm-mpath.c
b/drivers/md/dm-mpath.c
index
0c1b852
..
1816f30
100644
(file)
--- a/
drivers/md/dm-mpath.c
+++ b/
drivers/md/dm-mpath.c
@@
-63,6
+63,7
@@
struct multipath {
unsigned nr_priority_groups;
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
unsigned nr_priority_groups;
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
+ unsigned pg_init_in_progress; /* Only one pg_init allowed at once */
unsigned nr_valid_paths; /* Total number of usable paths */
struct pgpath *current_pgpath;
unsigned nr_valid_paths; /* Total number of usable paths */
struct pgpath *current_pgpath;
@@
-72,7
+73,7
@@
struct multipath {
unsigned queue_io; /* Must we queue all I/O? */
unsigned queue_if_no_path; /* Queue I/O if last path fails? */
unsigned queue_io; /* Must we queue all I/O? */
unsigned queue_if_no_path; /* Queue I/O if last path fails? */
- unsigned s
uspended; /* Has dm core suspended our I/O?
*/
+ unsigned s
aved_queue_if_no_path;/* Saved state during suspension
*/
struct work_struct process_queued_ios;
struct bio_list queued_ios;
struct work_struct process_queued_ios;
struct bio_list queued_ios;
@@
-178,8
+179,7
@@
static struct multipath *alloc_multipath(void)
m->queue_io = 1;
INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
INIT_WORK(&m->trigger_event, trigger_event, m);
m->queue_io = 1;
INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
INIT_WORK(&m->trigger_event, trigger_event, m);
- m->mpio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
- mempool_free_slab, _mpio_cache);
+ m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
if (!m->mpio_pool) {
kfree(m);
return NULL;
if (!m->mpio_pool) {
kfree(m);
return NULL;
@@
-304,11
+304,12
@@
static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
m->queue_size--;
if ((pgpath && m->queue_io) ||
m->queue_size--;
if ((pgpath && m->queue_io) ||
- (!pgpath && m->queue_if_no_path
&& !m->suspended
)) {
+ (!pgpath && m->queue_if_no_path)) {
/* Queue for the daemon to resubmit */
bio_list_add(&m->queued_ios, bio);
m->queue_size++;
/* Queue for the daemon to resubmit */
bio_list_add(&m->queued_ios, bio);
m->queue_size++;
- if (m->pg_init_required || !m->queue_io)
+ if ((m->pg_init_required && !m->pg_init_in_progress) ||
+ !m->queue_io)
queue_work(kmultipathd, &m->process_queued_ios);
pgpath = NULL;
r = 0;
queue_work(kmultipathd, &m->process_queued_ios);
pgpath = NULL;
r = 0;
@@
-327,14
+328,19
@@
static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
/*
* If we run out of usable paths, should we queue I/O or error it?
*/
/*
* If we run out of usable paths, should we queue I/O or error it?
*/
-static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path)
+static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
+ unsigned save_old_value)
{
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
{
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
+ if (save_old_value)
+ m->saved_queue_if_no_path = m->queue_if_no_path;
+ else
+ m->saved_queue_if_no_path = queue_if_no_path;
m->queue_if_no_path = queue_if_no_path;
m->queue_if_no_path = queue_if_no_path;
- if (!m->queue_if_no_path)
+ if (!m->queue_if_no_path
&& m->queue_size
)
queue_work(kmultipathd, &m->process_queued_ios);
spin_unlock_irqrestore(&m->lock, flags);
queue_work(kmultipathd, &m->process_queued_ios);
spin_unlock_irqrestore(&m->lock, flags);
@@
-379,25
+385,31
@@
static void process_queued_ios(void *data)
{
struct multipath *m = (struct multipath *) data;
struct hw_handler *hwh = &m->hw_handler;
{
struct multipath *m = (struct multipath *) data;
struct hw_handler *hwh = &m->hw_handler;
- struct pgpath *pgpath;
- unsigned init_required
, must_queue = 0
;
+ struct pgpath *pgpath
= NULL
;
+ unsigned init_required
= 0, must_queue = 1
;
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
+ if (!m->queue_size)
+ goto out;
+
if (!m->current_pgpath)
__choose_pgpath(m);
pgpath = m->current_pgpath;
if (!m->current_pgpath)
__choose_pgpath(m);
pgpath = m->current_pgpath;
- if ((pgpath && m->queue_io) ||
- (!pgpath &&
m->queue_if_no_path && !m->suspended
))
- must_queue =
1
;
+ if ((pgpath &&
!
m->queue_io) ||
+ (!pgpath &&
!m->queue_if_no_path
))
+ must_queue =
0
;
- init_required = m->pg_init_required;
- if (init_required)
+ if (m->pg_init_required && !m->pg_init_in_progress) {
m->pg_init_required = 0;
m->pg_init_required = 0;
+ m->pg_init_in_progress = 1;
+ init_required = 1;
+ }
+out:
spin_unlock_irqrestore(&m->lock, flags);
if (init_required)
spin_unlock_irqrestore(&m->lock, flags);
if (init_required)
@@
-668,7
+680,7
@@
static int parse_features(struct arg_set *as, struct multipath *m,
return 0;
if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
return 0;
if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
- return queue_if_no_path(m, 1);
+ return queue_if_no_path(m, 1
, 0
);
else {
ti->error = "Unrecognised multipath feature request";
return -EINVAL;
else {
ti->error = "Unrecognised multipath feature request";
return -EINVAL;
@@
-752,6
+764,8
@@
static int multipath_ctr(struct dm_target *ti, unsigned int argc,
static void multipath_dtr(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
static void multipath_dtr(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
+
+ flush_workqueue(kmultipathd);
free_multipath(m);
}
free_multipath(m);
}
@@
-765,6
+779,9
@@
static int multipath_map(struct dm_target *ti, struct bio *bio,
struct mpath_io *mpio;
struct multipath *m = (struct multipath *) ti->private;
struct mpath_io *mpio;
struct multipath *m = (struct multipath *) ti->private;
+ if (bio_barrier(bio))
+ return -EOPNOTSUPP;
+
mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
dm_bio_record(&mpio->details, bio);
mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
dm_bio_record(&mpio->details, bio);
@@
-837,7
+854,7
@@
static int reinstate_path(struct pgpath *pgpath)
pgpath->path.is_active = 1;
m->current_pgpath = NULL;
pgpath->path.is_active = 1;
m->current_pgpath = NULL;
- if (!m->nr_valid_paths++)
+ if (!m->nr_valid_paths++
&& m->queue_size
)
queue_work(kmultipathd, &m->process_queued_ios);
queue_work(kmultipathd, &m->trigger_event);
queue_work(kmultipathd, &m->process_queued_ios);
queue_work(kmultipathd, &m->trigger_event);
@@
-963,12
+980,13
@@
void dm_pg_init_complete(struct path *path, unsigned err_flags)
bypass_pg(m, pg, 1);
spin_lock_irqsave(&m->lock, flags);
bypass_pg(m, pg, 1);
spin_lock_irqsave(&m->lock, flags);
- if (!err_flags)
- m->queue_io = 0;
- else {
+ if (err_flags) {
m->current_pgpath = NULL;
m->current_pg = NULL;
m->current_pgpath = NULL;
m->current_pg = NULL;
- }
+ } else if (!m->pg_init_required)
+ m->queue_io = 0;
+
+ m->pg_init_in_progress = 0;
queue_work(kmultipathd, &m->process_queued_ios);
spin_unlock_irqrestore(&m->lock, flags);
}
queue_work(kmultipathd, &m->process_queued_ios);
spin_unlock_irqrestore(&m->lock, flags);
}
@@
-981,6
+999,7
@@
static int do_end_io(struct multipath *m, struct bio *bio,
{
struct hw_handler *hwh = &m->hw_handler;
unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
{
struct hw_handler *hwh = &m->hw_handler;
unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
+ unsigned long flags;
if (!error)
return 0; /* I/O complete */
if (!error)
return 0; /* I/O complete */
@@
-988,17
+1007,20
@@
static int do_end_io(struct multipath *m, struct bio *bio,
if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
return error;
if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
return error;
- spin_lock(&m->lock);
+ if (error == -EOPNOTSUPP)
+ return error;
+
+ spin_lock_irqsave(&m->lock, flags);
if (!m->nr_valid_paths) {
if (!m->nr_valid_paths) {
- if (!m->queue_if_no_path
|| m->suspended
) {
- spin_unlock
(&m->lock
);
+ if (!m->queue_if_no_path) {
+ spin_unlock
_irqrestore(&m->lock, flags
);
return -EIO;
} else {
return -EIO;
} else {
- spin_unlock
(&m->lock
);
+ spin_unlock
_irqrestore(&m->lock, flags
);
goto requeue;
}
}
goto requeue;
}
}
- spin_unlock
(&m->lock
);
+ spin_unlock
_irqrestore(&m->lock, flags
);
if (hwh->type && hwh->type->error)
err_flags = hwh->type->error(hwh, bio);
if (hwh->type && hwh->type->error)
err_flags = hwh->type->error(hwh, bio);
@@
-1018,12
+1040,12
@@
static int do_end_io(struct multipath *m, struct bio *bio,
dm_bio_restore(&mpio->details, bio);
/* queue for the daemon to resubmit or fail */
dm_bio_restore(&mpio->details, bio);
/* queue for the daemon to resubmit or fail */
- spin_lock
(&m->lock
);
+ spin_lock
_irqsave(&m->lock, flags
);
bio_list_add(&m->queued_ios, bio);
m->queue_size++;
if (!m->queue_io)
queue_work(kmultipathd, &m->process_queued_ios);
bio_list_add(&m->queued_ios, bio);
m->queue_size++;
if (!m->queue_io)
queue_work(kmultipathd, &m->process_queued_ios);
- spin_unlock
(&m->lock
);
+ spin_unlock
_irqrestore(&m->lock, flags
);
return 1; /* io not complete */
}
return 1; /* io not complete */
}
@@
-1051,27
+1073,27
@@
static int multipath_end_io(struct dm_target *ti, struct bio *bio,
/*
* Suspend can't complete until all the I/O is processed so if
/*
* Suspend can't complete until all the I/O is processed so if
- * the last path failed we will now error any queued I/O.
+ * the last path fails we must error any remaining I/O.
+ * Note that if the freeze_bdev fails while suspending, the
+ * queue_if_no_path state is lost - userspace should reset it.
*/
static void multipath_presuspend(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
*/
static void multipath_presuspend(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
- unsigned long flags;
- spin_lock_irqsave(&m->lock, flags);
- m->suspended = 1;
- if (m->queue_if_no_path)
- queue_work(kmultipathd, &m->process_queued_ios);
- spin_unlock_irqrestore(&m->lock, flags);
+ queue_if_no_path(m, 0, 1);
}
}
+/*
+ * Restore the queue_if_no_path setting.
+ */
static void multipath_resume(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
static void multipath_resume(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
- m->
suspended = 0
;
+ m->
queue_if_no_path = m->saved_queue_if_no_path
;
spin_unlock_irqrestore(&m->lock, flags);
}
spin_unlock_irqrestore(&m->lock, flags);
}
@@
-1204,9
+1226,9
@@
static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
if (argc == 1) {
if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
if (argc == 1) {
if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
- return queue_if_no_path(m, 1);
+ return queue_if_no_path(m, 1
, 0
);
else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
- return queue_if_no_path(m, 0);
+ return queue_if_no_path(m, 0
, 0
);
}
if (argc != 2)
}
if (argc != 2)