| From 7c8a3679e3d8e9d92d58f282161760a0e247df97 Mon Sep 17 00:00:00 2001 |
| From: Tomoki Sekiyama <tomoki.sekiyama@hds.com> |
| Date: Tue, 15 Oct 2013 16:42:19 -0600 |
| Subject: elevator: acquire q->sysfs_lock in elevator_change() |
| |
| From: Tomoki Sekiyama <tomoki.sekiyama@hds.com> |
| |
| commit 7c8a3679e3d8e9d92d58f282161760a0e247df97 upstream. |
| |
| Add locking of q->sysfs_lock into elevator_change() (an exported function) |
| to ensure it is held to protect q->elevator from elevator_init(), even if |
| elevator_change() is called from non-sysfs paths. |
| sysfs path (elv_iosched_store) uses __elevator_change(), non-locking |
| version, as the lock is already taken by elv_iosched_store(). |
| |
| Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Cc: Josh Boyer <jwboyer@fedoraproject.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| block/elevator.c | 16 ++++++++++++++-- |
| 1 file changed, 14 insertions(+), 2 deletions(-) |
| |
| --- a/block/elevator.c |
| +++ b/block/elevator.c |
| @@ -965,7 +965,7 @@ fail_init: |
| /* |
| * Switch this queue to the given IO scheduler. |
| */ |
| -int elevator_change(struct request_queue *q, const char *name) |
| +static int __elevator_change(struct request_queue *q, const char *name) |
| { |
| char elevator_name[ELV_NAME_MAX]; |
| struct elevator_type *e; |
| @@ -987,6 +987,18 @@ int elevator_change(struct request_queue |
| |
| return elevator_switch(q, e); |
| } |
| + |
| +int elevator_change(struct request_queue *q, const char *name) |
| +{ |
| + int ret; |
| + |
| + /* Protect q->elevator from elevator_init() */ |
| + mutex_lock(&q->sysfs_lock); |
| + ret = __elevator_change(q, name); |
| + mutex_unlock(&q->sysfs_lock); |
| + |
| + return ret; |
| +} |
| EXPORT_SYMBOL(elevator_change); |
| |
| ssize_t elv_iosched_store(struct request_queue *q, const char *name, |
| @@ -997,7 +1009,7 @@ ssize_t elv_iosched_store(struct request |
| if (!q->elevator) |
| return count; |
| |
| - ret = elevator_change(q, name); |
| + ret = __elevator_change(q, name); |
| if (!ret) |
| return count; |
| |