diff options
author | Mike Snitzer <snitzer@redhat.com> | 2016-02-15 14:25:00 -0500 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2016-02-22 22:34:41 -0500 |
commit | 9659f811446a67951127d4e81576204ffce9c86e (patch) | |
tree | 115ce6ad350c9e431c0995130b57a67e43150f24 /drivers/md/dm-round-robin.c | |
parent | 21136f89d76dc10d31d294f2bb79c585a039bad6 (diff) |
dm mpath: push path selector locking down to path selectors
Proper locking of the lists used by the path selectors should be handled
within the selectors (relying on dm-mpath.c code's use of the m->lock
spinlock was reckless).
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-round-robin.c')
-rw-r--r-- | drivers/md/dm-round-robin.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index 65ffdc3403b6..be9aa7f30b61 100644 --- a/drivers/md/dm-round-robin.c +++ b/drivers/md/dm-round-robin.c @@ -46,6 +46,7 @@ static void free_paths(struct list_head *paths) struct selector { struct list_head valid_paths; struct list_head invalid_paths; + spinlock_t lock; }; static struct selector *alloc_selector(void) @@ -55,6 +56,7 @@ static struct selector *alloc_selector(void) if (s) { INIT_LIST_HEAD(&s->valid_paths); INIT_LIST_HEAD(&s->invalid_paths); + spin_lock_init(&s->lock); } return s; @@ -74,7 +76,7 @@ static int rr_create(struct path_selector *ps, unsigned argc, char **argv) static void rr_destroy(struct path_selector *ps) { - struct selector *s = (struct selector *) ps->context; + struct selector *s = ps->context; free_paths(&s->valid_paths); free_paths(&s->invalid_paths); @@ -111,10 +113,11 @@ static int rr_status(struct path_selector *ps, struct dm_path *path, static int rr_add_path(struct path_selector *ps, struct dm_path *path, int argc, char **argv, char **error) { - struct selector *s = (struct selector *) ps->context; + struct selector *s = ps->context; struct path_info *pi; unsigned repeat_count = RR_MIN_IO; char dummy; + unsigned long flags; if (argc > 1) { *error = "round-robin ps: incorrect number of arguments"; @@ -144,25 +147,33 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path, path->pscontext = pi; + spin_lock_irqsave(&s->lock, flags); list_add_tail(&pi->list, &s->valid_paths); + spin_unlock_irqrestore(&s->lock, flags); return 0; } static void rr_fail_path(struct path_selector *ps, struct dm_path *p) { - struct selector *s = (struct selector *) ps->context; + unsigned long flags; + struct selector *s = ps->context; struct path_info *pi = p->pscontext; + spin_lock_irqsave(&s->lock, flags); list_move(&pi->list, &s->invalid_paths); + spin_unlock_irqrestore(&s->lock, flags); } static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p) { - struct selector *s = (struct selector *) ps->context; + unsigned long flags; + struct selector *s = ps->context; struct path_info *pi = p->pscontext; + spin_lock_irqsave(&s->lock, flags); list_move(&pi->list, &s->valid_paths); + spin_unlock_irqrestore(&s->lock, flags); return 0; } @@ -170,14 +181,17 @@ static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p) static struct dm_path *rr_select_path(struct path_selector *ps, unsigned *repeat_count, size_t nr_bytes) { - struct selector *s = (struct selector *) ps->context; + unsigned long flags; + struct selector *s = ps->context; struct path_info *pi = NULL; + spin_lock_irqsave(&s->lock, flags); if (!list_empty(&s->valid_paths)) { pi = list_entry(s->valid_paths.next, struct path_info, list); list_move_tail(&pi->list, &s->valid_paths); *repeat_count = pi->repeat_count; } + spin_unlock_irqrestore(&s->lock, flags); return pi ? pi->path : NULL; } |