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(); |