aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2013-03-19 13:16:48 -0400
committerJens Axboe <axboe@kernel.dk>2013-03-22 20:14:00 -0400
commit56392d2f40aac4b520fc50bc356f40e07f7e1c7d (patch)
treede6d360f081f47f9ed29f0063db12325dbb560c6 /drivers/block
parentc04ccaa669e147ffb66e4e74d82c7dbfc100ec5e (diff)
drbd: Clarify when activity log I/O is delegated to the worker thread
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')
-rw-r--r--drivers/block/drbd/drbd_actlog.c49
-rw-r--r--drivers/block/drbd/drbd_int.h2
-rw-r--r--drivers/block/drbd/drbd_receiver.c2
-rw-r--r--drivers/block/drbd/drbd_req.c2
-rw-r--r--drivers/block/drbd/drbd_worker.c2
5 files changed, 31 insertions, 26 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index c79625aa8cf2..82199d9a9a61 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -104,7 +104,7 @@ struct update_al_work {
104 int err; 104 int err;
105}; 105};
106 106
107static int al_write_transaction(struct drbd_conf *mdev); 107static int al_write_transaction(struct drbd_conf *mdev, bool delegate);
108 108
109void *drbd_md_get_buffer(struct drbd_conf *mdev) 109void *drbd_md_get_buffer(struct drbd_conf *mdev)
110{ 110{
@@ -246,7 +246,10 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
246 return al_ext; 246 return al_ext;
247} 247}
248 248
249void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i) 249/*
250 * @delegate: delegate activity log I/O to the worker thread
251 */
252void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate)
250{ 253{
251 /* for bios crossing activity log extent boundaries, 254 /* for bios crossing activity log extent boundaries,
252 * we may need to activate two extents in one go */ 255 * we may need to activate two extents in one go */
@@ -255,6 +258,17 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
255 unsigned enr; 258 unsigned enr;
256 bool locked = false; 259 bool locked = false;
257 260
261 /* When called through generic_make_request(), we must delegate
262 * activity log I/O to the worker thread: a further request
263 * submitted via generic_make_request() within the same task
264 * would be queued on current->bio_list, and would only start
265 * after this function returns (see generic_make_request()).
266 *
267 * However, if we *are* the worker, we must not delegate to ourselves.
268 */
269
270 if (delegate)
271 BUG_ON(current == mdev->tconn->worker.task);
258 272
259 D_ASSERT(first <= last); 273 D_ASSERT(first <= last);
260 D_ASSERT(atomic_read(&mdev->local_cnt) > 0); 274 D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
@@ -270,13 +284,6 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
270 (locked = lc_try_lock_for_transaction(mdev->act_log))); 284 (locked = lc_try_lock_for_transaction(mdev->act_log)));
271 285
272 if (locked) { 286 if (locked) {
273 /* drbd_al_write_transaction(mdev,al_ext,enr);
274 * recurses into generic_make_request(), which
275 * disallows recursion, bios being serialized on the
276 * current->bio_tail list now.
277 * we have to delegate updates to the activity log
278 * to the worker thread. */
279
280 /* Double check: it may have been committed by someone else, 287 /* Double check: it may have been committed by someone else,
281 * while we have been waiting for the lock. */ 288 * while we have been waiting for the lock. */
282 if (mdev->act_log->pending_changes) { 289 if (mdev->act_log->pending_changes) {
@@ -287,7 +294,7 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
287 rcu_read_unlock(); 294 rcu_read_unlock();
288 295
289 if (write_al_updates) { 296 if (write_al_updates) {
290 al_write_transaction(mdev); 297 al_write_transaction(mdev, delegate);
291 mdev->al_writ_cnt++; 298 mdev->al_writ_cnt++;
292 } 299 }
293 300
@@ -495,20 +502,18 @@ static int w_al_write_transaction(struct drbd_work *w, int unused)
495/* Calls from worker context (see w_restart_disk_io()) need to write the 502/* Calls from worker context (see w_restart_disk_io()) need to write the
496 transaction directly. Others came through generic_make_request(), 503 transaction directly. Others came through generic_make_request(),
497 those need to delegate it to the worker. */ 504 those need to delegate it to the worker. */
498static int al_write_transaction(struct drbd_conf *mdev) 505static int al_write_transaction(struct drbd_conf *mdev, bool delegate)
499{ 506{
500 struct update_al_work al_work; 507 if (delegate) {
501 508 struct update_al_work al_work;
502 if (current == mdev->tconn->worker.task) 509 init_completion(&al_work.event);
510 al_work.w.cb = w_al_write_transaction;
511 al_work.w.mdev = mdev;
512 drbd_queue_work_front(&mdev->tconn->sender_work, &al_work.w);
513 wait_for_completion(&al_work.event);
514 return al_work.err;
515 } else
503 return _al_write_transaction(mdev); 516 return _al_write_transaction(mdev);
504
505 init_completion(&al_work.event);
506 al_work.w.cb = w_al_write_transaction;
507 al_work.w.mdev = mdev;
508 drbd_queue_work_front(&mdev->tconn->sender_work, &al_work.w);
509 wait_for_completion(&al_work.event);
510
511 return al_work.err;
512} 517}
513 518
514static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext) 519static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext)
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 6eecdec9da2b..453fccfc440c 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1598,7 +1598,7 @@ extern const char *drbd_conn_str(enum drbd_conns s);
1598extern const char *drbd_role_str(enum drbd_role s); 1598extern const char *drbd_role_str(enum drbd_role s);
1599 1599
1600/* drbd_actlog.c */ 1600/* drbd_actlog.c */
1601extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i); 1601extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate);
1602extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i); 1602extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i);
1603extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector); 1603extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector);
1604extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector); 1604extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 8172a2cfdead..1921871ca9a8 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -2265,7 +2265,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
2265 drbd_set_out_of_sync(mdev, peer_req->i.sector, peer_req->i.size); 2265 drbd_set_out_of_sync(mdev, peer_req->i.sector, peer_req->i.size);
2266 peer_req->flags |= EE_CALL_AL_COMPLETE_IO; 2266 peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
2267 peer_req->flags &= ~EE_MAY_SET_IN_SYNC; 2267 peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
2268 drbd_al_begin_io(mdev, &peer_req->i); 2268 drbd_al_begin_io(mdev, &peer_req->i, true);
2269 } 2269 }
2270 2270
2271 err = drbd_submit_peer_request(mdev, peer_req, rw, DRBD_FAULT_DT_WR); 2271 err = drbd_submit_peer_request(mdev, peer_req, rw, DRBD_FAULT_DT_WR);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 2b8303ad63c9..7d1ff1aaeb71 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1054,7 +1054,7 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
1054 if (rw == WRITE && req->private_bio && req->i.size 1054 if (rw == WRITE && req->private_bio && req->i.size
1055 && !test_bit(AL_SUSPENDED, &mdev->flags)) { 1055 && !test_bit(AL_SUSPENDED, &mdev->flags)) {
1056 req->rq_state |= RQ_IN_ACT_LOG; 1056 req->rq_state |= RQ_IN_ACT_LOG;
1057 drbd_al_begin_io(mdev, &req->i); 1057 drbd_al_begin_io(mdev, &req->i, true);
1058 } 1058 }
1059 1059
1060 spin_lock_irq(&mdev->tconn->req_lock); 1060 spin_lock_irq(&mdev->tconn->req_lock);
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 34b5d5d23ac4..f41e224caa7c 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1411,7 +1411,7 @@ int w_restart_disk_io(struct drbd_work *w, int cancel)
1411 struct drbd_conf *mdev = w->mdev; 1411 struct drbd_conf *mdev = w->mdev;
1412 1412
1413 if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG) 1413 if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
1414 drbd_al_begin_io(mdev, &req->i); 1414 drbd_al_begin_io(mdev, &req->i, false);
1415 1415
1416 drbd_req_make_private_bio(req, req->master_bio); 1416 drbd_req_make_private_bio(req, req->master_bio);
1417 req->private_bio->bi_bdev = mdev->ldev->backing_bdev; 1417 req->private_bio->bi_bdev = mdev->ldev->backing_bdev;