diff options
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index d72f2fef1cba..9f7ff1cb46ff 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -1226,6 +1226,37 @@ void do_submit(struct work_struct *ws) | |||
1226 | break; | 1226 | break; |
1227 | 1227 | ||
1228 | wait_event(mdev->al_wait, prepare_al_transaction_nonblock(mdev, &incoming, &pending)); | 1228 | wait_event(mdev->al_wait, prepare_al_transaction_nonblock(mdev, &incoming, &pending)); |
1229 | /* Maybe more was queued, while we prepared the transaction? | ||
1230 | * Try to stuff them into this transaction as well. | ||
1231 | * Be strictly non-blocking here, no wait_event, we already | ||
1232 | * have something to commit. | ||
1233 | * Stop if we don't make any more progres. | ||
1234 | */ | ||
1235 | for (;;) { | ||
1236 | LIST_HEAD(more_pending); | ||
1237 | LIST_HEAD(more_incoming); | ||
1238 | bool made_progress; | ||
1239 | |||
1240 | /* It is ok to look outside the lock, | ||
1241 | * it's only an optimization anyways */ | ||
1242 | if (list_empty(&mdev->submit.writes)) | ||
1243 | break; | ||
1244 | |||
1245 | spin_lock(&mdev->submit.lock); | ||
1246 | list_splice_tail_init(&mdev->submit.writes, &more_incoming); | ||
1247 | spin_unlock(&mdev->submit.lock); | ||
1248 | |||
1249 | if (list_empty(&more_incoming)) | ||
1250 | break; | ||
1251 | |||
1252 | made_progress = prepare_al_transaction_nonblock(mdev, &more_incoming, &more_pending); | ||
1253 | |||
1254 | list_splice_tail_init(&more_pending, &pending); | ||
1255 | list_splice_tail_init(&more_incoming, &incoming); | ||
1256 | |||
1257 | if (!made_progress) | ||
1258 | break; | ||
1259 | } | ||
1229 | drbd_al_begin_io_commit(mdev, false); | 1260 | drbd_al_begin_io_commit(mdev, false); |
1230 | 1261 | ||
1231 | list_for_each_entry_safe(req, tmp, &pending, tl_requests) { | 1262 | list_for_each_entry_safe(req, tmp, &pending, tl_requests) { |