diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2013-03-19 13:16:48 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-03-22 20:14:00 -0400 |
commit | 56392d2f40aac4b520fc50bc356f40e07f7e1c7d (patch) | |
tree | de6d360f081f47f9ed29f0063db12325dbb560c6 /drivers/block | |
parent | c04ccaa669e147ffb66e4e74d82c7dbfc100ec5e (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.c | 49 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 2 |
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 | ||
107 | static int al_write_transaction(struct drbd_conf *mdev); | 107 | static int al_write_transaction(struct drbd_conf *mdev, bool delegate); |
108 | 108 | ||
109 | void *drbd_md_get_buffer(struct drbd_conf *mdev) | 109 | void *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 | ||
249 | void 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 | */ | ||
252 | void 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. */ |
498 | static int al_write_transaction(struct drbd_conf *mdev) | 505 | static 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 | ||
514 | static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext) | 519 | static 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); | |||
1598 | extern const char *drbd_role_str(enum drbd_role s); | 1598 | extern const char *drbd_role_str(enum drbd_role s); |
1599 | 1599 | ||
1600 | /* drbd_actlog.c */ | 1600 | /* drbd_actlog.c */ |
1601 | extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i); | 1601 | extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate); |
1602 | extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i); | 1602 | extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i); |
1603 | extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector); | 1603 | extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector); |
1604 | extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector); | 1604 | extern 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; |