aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-07-15 11:19:02 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 10:57:58 -0500
commit1b7ab15b11716d075b3dca34cf41e8d7aba3cba2 (patch)
tree3aaa51da655ed15215d5ad1367cf4f0140bc4d89
parent9b743da96c8640dbfc864cb5d79c51547c3fadb4 (diff)
drbd: Fixed w_restart_disk_io() to handle non active AL-extents
Since we now apply the AL in user space onto the bitmap, the AL is not active for the requests we want to reply. For that a al_write_transaction() that might be called from worker context became necessary. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r--drivers/block/drbd/drbd_actlog.c70
-rw-r--r--drivers/block/drbd/drbd_worker.c4
2 files changed, 45 insertions, 29 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index da8ffd54fc18..5731d6019518 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -112,7 +112,7 @@ struct drbd_atodb_wait {
112}; 112};
113 113
114 114
115static int w_al_write_transaction(struct drbd_work *, int); 115static int al_write_transaction(struct drbd_conf *mdev);
116 116
117void *drbd_md_get_buffer(struct drbd_conf *mdev) 117void *drbd_md_get_buffer(struct drbd_conf *mdev)
118{ 118{
@@ -272,18 +272,13 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
272 /* Double check: it may have been committed by someone else, 272 /* Double check: it may have been committed by someone else,
273 * while we have been waiting for the lock. */ 273 * while we have been waiting for the lock. */
274 if (mdev->act_log->pending_changes) { 274 if (mdev->act_log->pending_changes) {
275 struct update_al_work al_work; 275 int err;
276 init_completion(&al_work.event); 276 err = al_write_transaction(mdev);
277 al_work.w.cb = w_al_write_transaction;
278 al_work.w.mdev = mdev;
279 drbd_queue_work_front(&mdev->tconn->data.work, &al_work.w);
280 wait_for_completion(&al_work.event);
281
282 mdev->al_writ_cnt++; 277 mdev->al_writ_cnt++;
283 278
284 spin_lock_irq(&mdev->al_lock); 279 spin_lock_irq(&mdev->al_lock);
285 /* FIXME 280 /* FIXME
286 if (al_work.err) 281 if (err)
287 we need an "lc_cancel" here; 282 we need an "lc_cancel" here;
288 */ 283 */
289 lc_committed(mdev->act_log); 284 lc_committed(mdev->act_log);
@@ -348,23 +343,20 @@ static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
348} 343}
349 344
350static int 345static int
351w_al_write_transaction(struct drbd_work *w, int unused) 346_al_write_transaction(struct drbd_conf *mdev)
352{ 347{
353 struct update_al_work *aw = container_of(w, struct update_al_work, w);
354 struct drbd_conf *mdev = w->mdev;
355 struct al_transaction_on_disk *buffer; 348 struct al_transaction_on_disk *buffer;
356 struct lc_element *e; 349 struct lc_element *e;
357 sector_t sector; 350 sector_t sector;
358 int i, mx; 351 int i, mx;
359 unsigned extent_nr; 352 unsigned extent_nr;
360 unsigned crc = 0; 353 unsigned crc = 0;
354 int err = 0;
361 355
362 if (!get_ldev(mdev)) { 356 if (!get_ldev(mdev)) {
363 dev_err(DEV, "disk is %s, cannot start al transaction\n", 357 dev_err(DEV, "disk is %s, cannot start al transaction\n",
364 drbd_disk_str(mdev->state.disk)); 358 drbd_disk_str(mdev->state.disk));
365 aw->err = -EIO; 359 return -EIO;
366 complete(&((struct update_al_work *)w)->event);
367 return 0;
368 } 360 }
369 361
370 /* The bitmap write may have failed, causing a state change. */ 362 /* The bitmap write may have failed, causing a state change. */
@@ -372,19 +364,15 @@ w_al_write_transaction(struct drbd_work *w, int unused)
372 dev_err(DEV, 364 dev_err(DEV,
373 "disk is %s, cannot write al transaction\n", 365 "disk is %s, cannot write al transaction\n",
374 drbd_disk_str(mdev->state.disk)); 366 drbd_disk_str(mdev->state.disk));
375 aw->err = -EIO;
376 complete(&((struct update_al_work *)w)->event);
377 put_ldev(mdev); 367 put_ldev(mdev);
378 return 0; 368 return -EIO;
379 } 369 }
380 370
381 buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */ 371 buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */
382 if (!buffer) { 372 if (!buffer) {
383 dev_err(DEV, "disk failed while waiting for md_io buffer\n"); 373 dev_err(DEV, "disk failed while waiting for md_io buffer\n");
384 aw->err = -EIO;
385 complete(&((struct update_al_work *)w)->event);
386 put_ldev(mdev); 374 put_ldev(mdev);
387 return 1; 375 return -ENODEV;
388 } 376 }
389 377
390 memset(buffer, 0, sizeof(*buffer)); 378 memset(buffer, 0, sizeof(*buffer));
@@ -444,10 +432,10 @@ w_al_write_transaction(struct drbd_work *w, int unused)
444 buffer->crc32c = cpu_to_be32(crc); 432 buffer->crc32c = cpu_to_be32(crc);
445 433
446 if (drbd_bm_write_hinted(mdev)) 434 if (drbd_bm_write_hinted(mdev))
447 aw->err = -EIO; 435 err = -EIO;
448 /* drbd_chk_io_error done already */ 436 /* drbd_chk_io_error done already */
449 else if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) { 437 else if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
450 aw->err = -EIO; 438 err = -EIO;
451 drbd_chk_io_error(mdev, 1, true); 439 drbd_chk_io_error(mdev, 1, true);
452 } else { 440 } else {
453 /* advance ringbuffer position and transaction counter */ 441 /* advance ringbuffer position and transaction counter */
@@ -456,10 +444,42 @@ w_al_write_transaction(struct drbd_work *w, int unused)
456 } 444 }
457 445
458 drbd_md_put_buffer(mdev); 446 drbd_md_put_buffer(mdev);
459 complete(&((struct update_al_work *)w)->event);
460 put_ldev(mdev); 447 put_ldev(mdev);
461 448
462 return 0; 449 return err;
450}
451
452
453static int w_al_write_transaction(struct drbd_work *w, int unused)
454{
455 struct update_al_work *aw = container_of(w, struct update_al_work, w);
456 struct drbd_conf *mdev = w->mdev;
457 int err;
458
459 err = _al_write_transaction(mdev);
460 aw->err = err;
461 complete(&aw->event);
462
463 return err != -EIO ? err : 0;
464}
465
466/* Calls from worker context (see w_restart_disk_io()) need to write the
467 transaction directly. Others came through generic_make_request(),
468 those need to delegate it to the worker. */
469static int al_write_transaction(struct drbd_conf *mdev)
470{
471 struct update_al_work al_work;
472
473 if (current == mdev->tconn->worker.task)
474 return _al_write_transaction(mdev);
475
476 init_completion(&al_work.event);
477 al_work.w.cb = w_al_write_transaction;
478 al_work.w.mdev = mdev;
479 drbd_queue_work_front(&mdev->tconn->data.work, &al_work.w);
480 wait_for_completion(&al_work.event);
481
482 return al_work.err;
463} 483}
464 484
465static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext) 485static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext)
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 9ee9b9fab7a8..c57e47c0a1f5 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1333,10 +1333,6 @@ int w_restart_disk_io(struct drbd_work *w, int cancel)
1333 1333
1334 if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG) 1334 if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
1335 drbd_al_begin_io(mdev, &req->i); 1335 drbd_al_begin_io(mdev, &req->i);
1336 /* Calling drbd_al_begin_io() out of the worker might deadlocks
1337 theoretically. Practically it can not deadlock, since this is
1338 only used when unfreezing IOs. All the extents of the requests
1339 that made it into the TL are already active */
1340 1336
1341 drbd_req_make_private_bio(req, req->master_bio); 1337 drbd_req_make_private_bio(req, req->master_bio);
1342 req->private_bio->bi_bdev = mdev->ldev->backing_bdev; 1338 req->private_bio->bi_bdev = mdev->ldev->backing_bdev;