aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_req.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/drbd/drbd_req.c')
-rw-r--r--drivers/block/drbd/drbd_req.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 43bc1d064bc7..b923d41678e1 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1164,32 +1164,74 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
1164 drbd_send_and_submit(mdev, req); 1164 drbd_send_and_submit(mdev, req);
1165} 1165}
1166 1166
1167void __drbd_make_request_from_worker(struct drbd_conf *mdev, struct drbd_request *req) 1167static void submit_fast_path(struct drbd_conf *mdev, struct list_head *incoming)
1168{ 1168{
1169 const int rw = bio_rw(req->master_bio); 1169 struct drbd_request *req, *tmp;
1170 list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
1171 const int rw = bio_data_dir(req->master_bio);
1170 1172
1171 if (rw == WRITE && req->private_bio && req->i.size 1173 if (rw == WRITE /* rw != WRITE should not even end up here! */
1172 && !test_bit(AL_SUSPENDED, &mdev->flags)) { 1174 && req->private_bio && req->i.size
1173 drbd_al_begin_io(mdev, &req->i, false); 1175 && !test_bit(AL_SUSPENDED, &mdev->flags)) {
1174 req->rq_state |= RQ_IN_ACT_LOG; 1176 if (!drbd_al_begin_io_fastpath(mdev, &req->i))
1177 continue;
1178
1179 req->rq_state |= RQ_IN_ACT_LOG;
1180 }
1181
1182 list_del_init(&req->tl_requests);
1183 drbd_send_and_submit(mdev, req);
1175 } 1184 }
1176 drbd_send_and_submit(mdev, req);
1177} 1185}
1178 1186
1187static bool prepare_al_transaction_nonblock(struct drbd_conf *mdev,
1188 struct list_head *incoming,
1189 struct list_head *pending)
1190{
1191 struct drbd_request *req, *tmp;
1192 int wake = 0;
1193 int err;
1194
1195 spin_lock_irq(&mdev->al_lock);
1196 list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
1197 err = drbd_al_begin_io_nonblock(mdev, &req->i);
1198 if (err == -EBUSY)
1199 wake = 1;
1200 if (err)
1201 continue;
1202 req->rq_state |= RQ_IN_ACT_LOG;
1203 list_move_tail(&req->tl_requests, pending);
1204 }
1205 spin_unlock_irq(&mdev->al_lock);
1206 if (wake)
1207 wake_up(&mdev->al_wait);
1208
1209 return !list_empty(pending);
1210}
1179 1211
1180void do_submit(struct work_struct *ws) 1212void do_submit(struct work_struct *ws)
1181{ 1213{
1182 struct drbd_conf *mdev = container_of(ws, struct drbd_conf, submit.worker); 1214 struct drbd_conf *mdev = container_of(ws, struct drbd_conf, submit.worker);
1183 LIST_HEAD(writes); 1215 LIST_HEAD(incoming);
1216 LIST_HEAD(pending);
1184 struct drbd_request *req, *tmp; 1217 struct drbd_request *req, *tmp;
1185 1218
1186 spin_lock(&mdev->submit.lock); 1219 for (;;) {
1187 list_splice_init(&mdev->submit.writes, &writes); 1220 spin_lock(&mdev->submit.lock);
1188 spin_unlock(&mdev->submit.lock); 1221 list_splice_tail_init(&mdev->submit.writes, &incoming);
1222 spin_unlock(&mdev->submit.lock);
1189 1223
1190 list_for_each_entry_safe(req, tmp, &writes, tl_requests) { 1224 submit_fast_path(mdev, &incoming);
1191 list_del_init(&req->tl_requests); 1225 if (list_empty(&incoming))
1192 __drbd_make_request_from_worker(mdev, req); 1226 break;
1227
1228 wait_event(mdev->al_wait, prepare_al_transaction_nonblock(mdev, &incoming, &pending));
1229 drbd_al_begin_io_commit(mdev, false);
1230
1231 list_for_each_entry_safe(req, tmp, &pending, tl_requests) {
1232 list_del_init(&req->tl_requests);
1233 drbd_send_and_submit(mdev, req);
1234 }
1193 } 1235 }
1194} 1236}
1195 1237