diff options
| author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2014-09-11 08:29:12 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@fb.com> | 2014-09-11 10:41:29 -0400 |
| commit | 729e8b87bac63dee09302ddffc05a7ba0e50c9ad (patch) | |
| tree | f5e211f46358cec78fe411b1ddbba5f8f307991f /drivers/block | |
| parent | abde9cc6a59cb7f07fda4c77fee2150314e423fa (diff) | |
drbd: reduce lock contention in drbd_worker
The worker may now dequeue work items in batches.
This should reduce lock contention during busy periods.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
| -rw-r--r-- | drivers/block/drbd/drbd_worker.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 3ed2d871272e..d2d1f97511bd 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
| @@ -2026,8 +2026,6 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head * | |||
| 2026 | prepare_to_wait(&connection->sender_work.q_wait, &wait, TASK_INTERRUPTIBLE); | 2026 | prepare_to_wait(&connection->sender_work.q_wait, &wait, TASK_INTERRUPTIBLE); |
| 2027 | spin_lock_irq(&connection->resource->req_lock); | 2027 | spin_lock_irq(&connection->resource->req_lock); |
| 2028 | spin_lock(&connection->sender_work.q_lock); /* FIXME get rid of this one? */ | 2028 | spin_lock(&connection->sender_work.q_lock); /* FIXME get rid of this one? */ |
| 2029 | /* dequeue single item only, | ||
| 2030 | * we still use drbd_queue_work_front() in some places */ | ||
| 2031 | if (!list_empty(&connection->sender_work.q)) | 2029 | if (!list_empty(&connection->sender_work.q)) |
| 2032 | list_splice_tail_init(&connection->sender_work.q, work_list); | 2030 | list_splice_tail_init(&connection->sender_work.q, work_list); |
| 2033 | spin_unlock(&connection->sender_work.q_lock); /* FIXME get rid of this one? */ | 2031 | spin_unlock(&connection->sender_work.q_lock); /* FIXME get rid of this one? */ |
| @@ -2114,7 +2112,7 @@ int drbd_worker(struct drbd_thread *thi) | |||
| 2114 | if (get_t_state(thi) != RUNNING) | 2112 | if (get_t_state(thi) != RUNNING) |
| 2115 | break; | 2113 | break; |
| 2116 | 2114 | ||
| 2117 | while (!list_empty(&work_list)) { | 2115 | if (!list_empty(&work_list)) { |
| 2118 | w = list_first_entry(&work_list, struct drbd_work, list); | 2116 | w = list_first_entry(&work_list, struct drbd_work, list); |
| 2119 | list_del_init(&w->list); | 2117 | list_del_init(&w->list); |
| 2120 | update_worker_timing_details(connection, w->cb); | 2118 | update_worker_timing_details(connection, w->cb); |
| @@ -2130,13 +2128,13 @@ int drbd_worker(struct drbd_thread *thi) | |||
| 2130 | update_worker_timing_details(connection, do_unqueued_work); | 2128 | update_worker_timing_details(connection, do_unqueued_work); |
| 2131 | do_unqueued_work(connection); | 2129 | do_unqueued_work(connection); |
| 2132 | } | 2130 | } |
| 2133 | while (!list_empty(&work_list)) { | 2131 | if (!list_empty(&work_list)) { |
| 2134 | w = list_first_entry(&work_list, struct drbd_work, list); | 2132 | w = list_first_entry(&work_list, struct drbd_work, list); |
| 2135 | list_del_init(&w->list); | 2133 | list_del_init(&w->list); |
| 2136 | update_worker_timing_details(connection, w->cb); | 2134 | update_worker_timing_details(connection, w->cb); |
| 2137 | w->cb(w, 1); | 2135 | w->cb(w, 1); |
| 2138 | } | 2136 | } else |
| 2139 | dequeue_work_batch(&connection->sender_work, &work_list); | 2137 | dequeue_work_batch(&connection->sender_work, &work_list); |
| 2140 | } while (!list_empty(&work_list) || test_bit(DEVICE_WORK_PENDING, &connection->flags)); | 2138 | } while (!list_empty(&work_list) || test_bit(DEVICE_WORK_PENDING, &connection->flags)); |
| 2141 | 2139 | ||
| 2142 | rcu_read_lock(); | 2140 | rcu_read_lock(); |
