git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
dm mpath: simplify failure path of dm_multipath_init()
[pandora-kernel.git]
/
drivers
/
md
/
dm-mpath.c
diff --git
a/drivers/md/dm-mpath.c
b/drivers/md/dm-mpath.c
index
5e0090e
..
8483407
100644
(file)
--- a/
drivers/md/dm-mpath.c
+++ b/
drivers/md/dm-mpath.c
@@
-84,6
+84,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 saved_queue_if_no_path;/* Saved state during suspension */
unsigned queue_io; /* Must we queue all I/O? */
unsigned queue_if_no_path; /* Queue I/O if last path fails? */
unsigned saved_queue_if_no_path;/* Saved state during suspension */
+ unsigned pg_init_disabled:1; /* pg_init is not currently allowed */
unsigned pg_init_retries; /* Number of times to retry pg_init */
unsigned pg_init_count; /* Number of times pg_init called */
unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
unsigned pg_init_retries; /* Number of times to retry pg_init */
unsigned pg_init_count; /* Number of times pg_init called */
unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
@@
-473,7
+474,8
@@
static void process_queued_ios(struct work_struct *work)
(!pgpath && !m->queue_if_no_path))
must_queue = 0;
(!pgpath && !m->queue_if_no_path))
must_queue = 0;
- if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
+ if (m->pg_init_required && !m->pg_init_in_progress && pgpath &&
+ !m->pg_init_disabled)
__pg_init_all_paths(m);
out:
__pg_init_all_paths(m);
out:
@@
-698,8
+700,8
@@
static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
return 0;
m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL);
return 0;
m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL);
- request_module("scsi_dh_%s", m->hw_handler_name);
-
if (scsi_dh_handler_exist(m->hw_handler_name) == 0
) {
+ if (!try_then_request_module(scsi_dh_handler_exist(m->hw_handler_name),
+
"scsi_dh_%s", m->hw_handler_name)
) {
ti->error = "unknown hardware handler type";
ret = -EINVAL;
goto fail;
ti->error = "unknown hardware handler type";
ret = -EINVAL;
goto fail;
@@
-887,10
+889,20
@@
static void multipath_wait_for_pg_init_completion(struct multipath *m)
static void flush_multipath_work(struct multipath *m)
{
static void flush_multipath_work(struct multipath *m)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ m->pg_init_disabled = 1;
+ spin_unlock_irqrestore(&m->lock, flags);
+
flush_workqueue(kmpath_handlerd);
multipath_wait_for_pg_init_completion(m);
flush_workqueue(kmultipathd);
flush_work_sync(&m->trigger_event);
flush_workqueue(kmpath_handlerd);
multipath_wait_for_pg_init_completion(m);
flush_workqueue(kmultipathd);
flush_work_sync(&m->trigger_event);
+
+ spin_lock_irqsave(&m->lock, flags);
+ m->pg_init_disabled = 0;
+ spin_unlock_irqrestore(&m->lock, flags);
}
static void multipath_dtr(struct dm_target *ti)
}
static void multipath_dtr(struct dm_target *ti)
@@
-1111,7
+1123,7
@@
static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
spin_lock_irqsave(&m->lock, flags);
spin_lock_irqsave(&m->lock, flags);
- if (m->pg_init_count <= m->pg_init_retries)
+ if (m->pg_init_count <= m->pg_init_retries
&& !m->pg_init_disabled
)
m->pg_init_required = 1;
else
limit_reached = 1;
m->pg_init_required = 1;
else
limit_reached = 1;
@@
-1323,8
+1335,8
@@
static void multipath_resume(struct dm_target *ti)
* [priority selector-name num_ps_args [ps_args]*
* num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
*/
* [priority selector-name num_ps_args [ps_args]*
* num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
*/
-static
int
multipath_status(struct dm_target *ti, status_type_t type,
-
char *result, unsigned int
maxlen)
+static
void
multipath_status(struct dm_target *ti, status_type_t type,
+
char *result, unsigned
maxlen)
{
int sz = 0;
unsigned long flags;
{
int sz = 0;
unsigned long flags;
@@
-1427,8
+1439,6
@@
static int multipath_status(struct dm_target *ti, status_type_t type,
}
spin_unlock_irqrestore(&m->lock, flags);
}
spin_unlock_irqrestore(&m->lock, flags);
-
- return 0;
}
static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
}
static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
@@
-1520,6
+1530,12
@@
static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
spin_unlock_irqrestore(&m->lock, flags);
spin_unlock_irqrestore(&m->lock, flags);
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
@@
-1617,7
+1633,7
@@
out:
*---------------------------------------------------------------*/
static struct target_type multipath_target = {
.name = "multipath",
*---------------------------------------------------------------*/
static struct target_type multipath_target = {
.name = "multipath",
- .version = {1, 3,
0
},
+ .version = {1, 3,
2
},
.module = THIS_MODULE,
.ctr = multipath_ctr,
.dtr = multipath_dtr,
.module = THIS_MODULE,
.ctr = multipath_ctr,
.dtr = multipath_dtr,
@@
-1645,16
+1661,15
@@
static int __init dm_multipath_init(void)
r = dm_register_target(&multipath_target);
if (r < 0) {
DMERR("register failed %d", r);
r = dm_register_target(&multipath_target);
if (r < 0) {
DMERR("register failed %d", r);
-
kmem_cache_destroy(_mpio_cache)
;
-
return -EINVAL
;
+
r = -EINVAL
;
+
goto bad_register_target
;
}
kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0);
if (!kmultipathd) {
DMERR("failed to create workqueue kmpathd");
}
kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0);
if (!kmultipathd) {
DMERR("failed to create workqueue kmpathd");
- dm_unregister_target(&multipath_target);
- kmem_cache_destroy(_mpio_cache);
- return -ENOMEM;
+ r = -ENOMEM;
+ goto bad_alloc_kmultipathd;
}
/*
}
/*
@@
-1667,16
+1682,23
@@
static int __init dm_multipath_init(void)
WQ_MEM_RECLAIM);
if (!kmpath_handlerd) {
DMERR("failed to create workqueue kmpath_handlerd");
WQ_MEM_RECLAIM);
if (!kmpath_handlerd) {
DMERR("failed to create workqueue kmpath_handlerd");
- destroy_workqueue(kmultipathd);
- dm_unregister_target(&multipath_target);
- kmem_cache_destroy(_mpio_cache);
- return -ENOMEM;
+ r = -ENOMEM;
+ goto bad_alloc_kmpath_handlerd;
}
DMINFO("version %u.%u.%u loaded",
multipath_target.version[0], multipath_target.version[1],
multipath_target.version[2]);
}
DMINFO("version %u.%u.%u loaded",
multipath_target.version[0], multipath_target.version[1],
multipath_target.version[2]);
+ return 0;
+
+bad_alloc_kmpath_handlerd:
+ destroy_workqueue(kmultipathd);
+bad_alloc_kmultipathd:
+ dm_unregister_target(&multipath_target);
+bad_register_target:
+ kmem_cache_destroy(_mpio_cache);
+
return r;
}
return r;
}