mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-28 12:25:31 +00:00
dm mpath: use atomic_t for counting members of 'struct multipath'
The use of atomic_t for nr_valid_paths, pg_init_in_progress and pg_init_count will allow relaxing the use of the m->lock spinlock. Suggested-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
518257b132
commit
91e968aa60
@ -76,9 +76,6 @@ struct multipath {
|
|||||||
|
|
||||||
wait_queue_head_t pg_init_wait; /* Wait for pg_init completion */
|
wait_queue_head_t pg_init_wait; /* Wait for pg_init completion */
|
||||||
|
|
||||||
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;
|
struct pgpath *current_pgpath;
|
||||||
struct priority_group *current_pg;
|
struct priority_group *current_pg;
|
||||||
struct priority_group *next_pg; /* Switch to this PG if set */
|
struct priority_group *next_pg; /* Switch to this PG if set */
|
||||||
@ -86,9 +83,12 @@ struct multipath {
|
|||||||
unsigned long flags; /* Multipath state flags */
|
unsigned long flags; /* Multipath state flags */
|
||||||
|
|
||||||
unsigned pg_init_retries; /* Number of times to retry pg_init */
|
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_delay_msecs; /* Number of msecs before pg_init retry */
|
||||||
|
|
||||||
|
atomic_t nr_valid_paths; /* Total number of usable paths */
|
||||||
|
atomic_t pg_init_in_progress; /* Only one pg_init allowed at once */
|
||||||
|
atomic_t pg_init_count; /* Number of times pg_init called */
|
||||||
|
|
||||||
struct work_struct trigger_event;
|
struct work_struct trigger_event;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -195,6 +195,9 @@ static struct multipath *alloc_multipath(struct dm_target *ti, bool use_blk_mq)
|
|||||||
INIT_LIST_HEAD(&m->priority_groups);
|
INIT_LIST_HEAD(&m->priority_groups);
|
||||||
spin_lock_init(&m->lock);
|
spin_lock_init(&m->lock);
|
||||||
set_bit(MPATHF_QUEUE_IO, &m->flags);
|
set_bit(MPATHF_QUEUE_IO, &m->flags);
|
||||||
|
atomic_set(&m->nr_valid_paths, 0);
|
||||||
|
atomic_set(&m->pg_init_in_progress, 0);
|
||||||
|
atomic_set(&m->pg_init_count, 0);
|
||||||
m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
|
m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
|
||||||
INIT_WORK(&m->trigger_event, trigger_event);
|
INIT_WORK(&m->trigger_event, trigger_event);
|
||||||
init_waitqueue_head(&m->pg_init_wait);
|
init_waitqueue_head(&m->pg_init_wait);
|
||||||
@ -279,10 +282,10 @@ static int __pg_init_all_paths(struct multipath *m)
|
|||||||
struct pgpath *pgpath;
|
struct pgpath *pgpath;
|
||||||
unsigned long pg_init_delay = 0;
|
unsigned long pg_init_delay = 0;
|
||||||
|
|
||||||
if (m->pg_init_in_progress || test_bit(MPATHF_PG_INIT_DISABLED, &m->flags))
|
if (atomic_read(&m->pg_init_in_progress) || test_bit(MPATHF_PG_INIT_DISABLED, &m->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
m->pg_init_count++;
|
atomic_inc(&m->pg_init_count);
|
||||||
clear_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
|
clear_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
|
||||||
|
|
||||||
/* Check here to reset pg_init_required */
|
/* Check here to reset pg_init_required */
|
||||||
@ -298,9 +301,9 @@ static int __pg_init_all_paths(struct multipath *m)
|
|||||||
continue;
|
continue;
|
||||||
if (queue_delayed_work(kmpath_handlerd, &pgpath->activate_path,
|
if (queue_delayed_work(kmpath_handlerd, &pgpath->activate_path,
|
||||||
pg_init_delay))
|
pg_init_delay))
|
||||||
m->pg_init_in_progress++;
|
atomic_inc(&m->pg_init_in_progress);
|
||||||
}
|
}
|
||||||
return m->pg_init_in_progress;
|
return atomic_read(&m->pg_init_in_progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
|
static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
|
||||||
@ -316,7 +319,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
|
|||||||
clear_bit(MPATHF_QUEUE_IO, &m->flags);
|
clear_bit(MPATHF_QUEUE_IO, &m->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
m->pg_init_count = 0;
|
atomic_set(&m->pg_init_count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg,
|
static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg,
|
||||||
@ -341,7 +344,7 @@ static void __choose_pgpath(struct multipath *m, size_t nr_bytes)
|
|||||||
struct priority_group *pg;
|
struct priority_group *pg;
|
||||||
bool bypassed = true;
|
bool bypassed = true;
|
||||||
|
|
||||||
if (!m->nr_valid_paths) {
|
if (!atomic_read(&m->nr_valid_paths)) {
|
||||||
clear_bit(MPATHF_QUEUE_IO, &m->flags);
|
clear_bit(MPATHF_QUEUE_IO, &m->flags);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -902,6 +905,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
|
|||||||
/* parse the priority groups */
|
/* parse the priority groups */
|
||||||
while (as.argc) {
|
while (as.argc) {
|
||||||
struct priority_group *pg;
|
struct priority_group *pg;
|
||||||
|
unsigned nr_valid_paths = atomic_read(&m->nr_valid_paths);
|
||||||
|
|
||||||
pg = parse_priority_group(&as, m);
|
pg = parse_priority_group(&as, m);
|
||||||
if (IS_ERR(pg)) {
|
if (IS_ERR(pg)) {
|
||||||
@ -909,7 +913,9 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->nr_valid_paths += pg->nr_pgpaths;
|
nr_valid_paths += pg->nr_pgpaths;
|
||||||
|
atomic_set(&m->nr_valid_paths, nr_valid_paths);
|
||||||
|
|
||||||
list_add_tail(&pg->list, &m->priority_groups);
|
list_add_tail(&pg->list, &m->priority_groups);
|
||||||
pg_count++;
|
pg_count++;
|
||||||
pg->pg_num = pg_count;
|
pg->pg_num = pg_count;
|
||||||
@ -939,19 +945,14 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
|
|||||||
static void multipath_wait_for_pg_init_completion(struct multipath *m)
|
static void multipath_wait_for_pg_init_completion(struct multipath *m)
|
||||||
{
|
{
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
add_wait_queue(&m->pg_init_wait, &wait);
|
add_wait_queue(&m->pg_init_wait, &wait);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
|
|
||||||
spin_lock_irqsave(&m->lock, flags);
|
if (!atomic_read(&m->pg_init_in_progress))
|
||||||
if (!m->pg_init_in_progress) {
|
|
||||||
spin_unlock_irqrestore(&m->lock, flags);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&m->lock, flags);
|
|
||||||
|
|
||||||
io_schedule();
|
io_schedule();
|
||||||
}
|
}
|
||||||
@ -1001,13 +1002,13 @@ static int fail_path(struct pgpath *pgpath)
|
|||||||
pgpath->is_active = false;
|
pgpath->is_active = false;
|
||||||
pgpath->fail_count++;
|
pgpath->fail_count++;
|
||||||
|
|
||||||
m->nr_valid_paths--;
|
atomic_dec(&m->nr_valid_paths);
|
||||||
|
|
||||||
if (pgpath == m->current_pgpath)
|
if (pgpath == m->current_pgpath)
|
||||||
m->current_pgpath = NULL;
|
m->current_pgpath = NULL;
|
||||||
|
|
||||||
dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
|
dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
|
||||||
pgpath->path.dev->name, m->nr_valid_paths);
|
pgpath->path.dev->name, atomic_read(&m->nr_valid_paths));
|
||||||
|
|
||||||
schedule_work(&m->trigger_event);
|
schedule_work(&m->trigger_event);
|
||||||
|
|
||||||
@ -1025,6 +1026,7 @@ static int reinstate_path(struct pgpath *pgpath)
|
|||||||
int r = 0, run_queue = 0;
|
int r = 0, run_queue = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct multipath *m = pgpath->pg->m;
|
struct multipath *m = pgpath->pg->m;
|
||||||
|
unsigned nr_valid_paths;
|
||||||
|
|
||||||
spin_lock_irqsave(&m->lock, flags);
|
spin_lock_irqsave(&m->lock, flags);
|
||||||
|
|
||||||
@ -1039,16 +1041,17 @@ static int reinstate_path(struct pgpath *pgpath)
|
|||||||
|
|
||||||
pgpath->is_active = true;
|
pgpath->is_active = true;
|
||||||
|
|
||||||
if (!m->nr_valid_paths++) {
|
nr_valid_paths = atomic_inc_return(&m->nr_valid_paths);
|
||||||
|
if (nr_valid_paths == 1) {
|
||||||
m->current_pgpath = NULL;
|
m->current_pgpath = NULL;
|
||||||
run_queue = 1;
|
run_queue = 1;
|
||||||
} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
|
} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
|
||||||
if (queue_work(kmpath_handlerd, &pgpath->activate_path.work))
|
if (queue_work(kmpath_handlerd, &pgpath->activate_path.work))
|
||||||
m->pg_init_in_progress++;
|
atomic_inc(&m->pg_init_in_progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
|
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
|
||||||
pgpath->path.dev->name, m->nr_valid_paths);
|
pgpath->path.dev->name, nr_valid_paths);
|
||||||
|
|
||||||
schedule_work(&m->trigger_event);
|
schedule_work(&m->trigger_event);
|
||||||
|
|
||||||
@ -1166,7 +1169,8 @@ static bool 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 && !test_bit(MPATHF_PG_INIT_DISABLED, &m->flags))
|
if (atomic_read(&m->pg_init_count) <= m->pg_init_retries &&
|
||||||
|
!test_bit(MPATHF_PG_INIT_DISABLED, &m->flags))
|
||||||
set_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
|
set_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
|
||||||
else
|
else
|
||||||
limit_reached = true;
|
limit_reached = true;
|
||||||
@ -1236,7 +1240,7 @@ static void pg_init_done(void *data, int errors)
|
|||||||
} else if (!test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
|
} else if (!test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
|
||||||
pg->bypassed = false;
|
pg->bypassed = false;
|
||||||
|
|
||||||
if (--m->pg_init_in_progress)
|
if (atomic_dec_return(&m->pg_init_in_progress) > 0)
|
||||||
/* Activations of other paths are still on going */
|
/* Activations of other paths are still on going */
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1317,7 +1321,7 @@ static int do_end_io(struct multipath *m, struct request *clone,
|
|||||||
fail_path(mpio->pgpath);
|
fail_path(mpio->pgpath);
|
||||||
|
|
||||||
spin_lock_irqsave(&m->lock, flags);
|
spin_lock_irqsave(&m->lock, flags);
|
||||||
if (!m->nr_valid_paths) {
|
if (!atomic_read(&m->nr_valid_paths)) {
|
||||||
if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
|
if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
|
||||||
if (!__must_push_back(m))
|
if (!__must_push_back(m))
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
@ -1421,7 +1425,8 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
|
|||||||
|
|
||||||
/* Features */
|
/* Features */
|
||||||
if (type == STATUSTYPE_INFO)
|
if (type == STATUSTYPE_INFO)
|
||||||
DMEMIT("2 %u %u ", test_bit(MPATHF_QUEUE_IO, &m->flags), m->pg_init_count);
|
DMEMIT("2 %u %u ", test_bit(MPATHF_QUEUE_IO, &m->flags),
|
||||||
|
atomic_read(&m->pg_init_count));
|
||||||
else {
|
else {
|
||||||
DMEMIT("%u ", test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) +
|
DMEMIT("%u ", test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) +
|
||||||
(m->pg_init_retries > 0) * 2 +
|
(m->pg_init_retries > 0) * 2 +
|
||||||
@ -1675,8 +1680,8 @@ static int multipath_busy(struct dm_target *ti)
|
|||||||
spin_lock_irqsave(&m->lock, flags);
|
spin_lock_irqsave(&m->lock, flags);
|
||||||
|
|
||||||
/* pg_init in progress or no paths available */
|
/* pg_init in progress or no paths available */
|
||||||
if (m->pg_init_in_progress ||
|
if (atomic_read(&m->pg_init_in_progress) ||
|
||||||
(!m->nr_valid_paths && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
|
(!atomic_read(&m->nr_valid_paths) && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
|
||||||
busy = true;
|
busy = true;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user