diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2013-03-19 13:16:49 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-03-22 20:14:00 -0400 |
commit | ebfd5d8f715167b886c9401e6b123847187f137b (patch) | |
tree | 33da96fa4f1949af33492299930491f2ee797c9a /drivers/block/drbd/drbd_actlog.c | |
parent | 56392d2f40aac4b520fc50bc356f40e07f7e1c7d (diff) |
drbd: drbd_al_being_io: short circuit to reduce latency
A request hitting an already "hot" extent should proceed right away,
even if some other requests need to wait for pending transactions.
Without that short-circuit, several simultaneous make_request contexts
race for committing the transaction, possibly penalizing the innocent.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/drbd/drbd_actlog.c')
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 82199d9a9a61..1d7244d2a910 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c | |||
@@ -256,6 +256,7 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool dele | |||
256 | unsigned first = i->sector >> (AL_EXTENT_SHIFT-9); | 256 | unsigned first = i->sector >> (AL_EXTENT_SHIFT-9); |
257 | unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9); | 257 | unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9); |
258 | unsigned enr; | 258 | unsigned enr; |
259 | bool need_transaction = false; | ||
259 | bool locked = false; | 260 | bool locked = false; |
260 | 261 | ||
261 | /* When called through generic_make_request(), we must delegate | 262 | /* When called through generic_make_request(), we must delegate |
@@ -273,8 +274,17 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool dele | |||
273 | D_ASSERT(first <= last); | 274 | D_ASSERT(first <= last); |
274 | D_ASSERT(atomic_read(&mdev->local_cnt) > 0); | 275 | D_ASSERT(atomic_read(&mdev->local_cnt) > 0); |
275 | 276 | ||
276 | for (enr = first; enr <= last; enr++) | 277 | for (enr = first; enr <= last; enr++) { |
277 | wait_event(mdev->al_wait, _al_get(mdev, enr) != NULL); | 278 | struct lc_element *al_ext; |
279 | wait_event(mdev->al_wait, (al_ext = _al_get(mdev, enr)) != NULL); | ||
280 | if (al_ext->lc_number != enr) | ||
281 | need_transaction = true; | ||
282 | } | ||
283 | |||
284 | /* If *this* request was to an already active extent, | ||
285 | * we're done, even if there are pending changes. */ | ||
286 | if (!need_transaction) | ||
287 | return; | ||
278 | 288 | ||
279 | /* Serialize multiple transactions. | 289 | /* Serialize multiple transactions. |
280 | * This uses test_and_set_bit, memory barrier is implicit. | 290 | * This uses test_and_set_bit, memory barrier is implicit. |