diff options
Diffstat (limited to 'drivers/md/persistent-data/dm-block-manager.c')
-rw-r--r-- | drivers/md/persistent-data/dm-block-manager.c | 105 |
1 files changed, 59 insertions, 46 deletions
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index 0317ecdc6e53..5ba277768d99 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c | |||
@@ -325,11 +325,6 @@ static struct dm_buffer *to_buffer(struct dm_block *b) | |||
325 | return (struct dm_buffer *) b; | 325 | return (struct dm_buffer *) b; |
326 | } | 326 | } |
327 | 327 | ||
328 | static struct dm_bufio_client *to_bufio(struct dm_block_manager *bm) | ||
329 | { | ||
330 | return (struct dm_bufio_client *) bm; | ||
331 | } | ||
332 | |||
333 | dm_block_t dm_block_location(struct dm_block *b) | 328 | dm_block_t dm_block_location(struct dm_block *b) |
334 | { | 329 | { |
335 | return dm_bufio_get_block_number(to_buffer(b)); | 330 | return dm_bufio_get_block_number(to_buffer(b)); |
@@ -367,34 +362,60 @@ static void dm_block_manager_write_callback(struct dm_buffer *buf) | |||
367 | /*---------------------------------------------------------------- | 362 | /*---------------------------------------------------------------- |
368 | * Public interface | 363 | * Public interface |
369 | *--------------------------------------------------------------*/ | 364 | *--------------------------------------------------------------*/ |
365 | struct dm_block_manager { | ||
366 | struct dm_bufio_client *bufio; | ||
367 | bool read_only:1; | ||
368 | }; | ||
369 | |||
370 | struct dm_block_manager *dm_block_manager_create(struct block_device *bdev, | 370 | struct dm_block_manager *dm_block_manager_create(struct block_device *bdev, |
371 | unsigned block_size, | 371 | unsigned block_size, |
372 | unsigned cache_size, | 372 | unsigned cache_size, |
373 | unsigned max_held_per_thread) | 373 | unsigned max_held_per_thread) |
374 | { | 374 | { |
375 | return (struct dm_block_manager *) | 375 | int r; |
376 | dm_bufio_client_create(bdev, block_size, max_held_per_thread, | 376 | struct dm_block_manager *bm; |
377 | sizeof(struct buffer_aux), | 377 | |
378 | dm_block_manager_alloc_callback, | 378 | bm = kmalloc(sizeof(*bm), GFP_KERNEL); |
379 | dm_block_manager_write_callback); | 379 | if (!bm) { |
380 | r = -ENOMEM; | ||
381 | goto bad; | ||
382 | } | ||
383 | |||
384 | bm->bufio = dm_bufio_client_create(bdev, block_size, max_held_per_thread, | ||
385 | sizeof(struct buffer_aux), | ||
386 | dm_block_manager_alloc_callback, | ||
387 | dm_block_manager_write_callback); | ||
388 | if (IS_ERR(bm->bufio)) { | ||
389 | r = PTR_ERR(bm->bufio); | ||
390 | kfree(bm); | ||
391 | goto bad; | ||
392 | } | ||
393 | |||
394 | bm->read_only = false; | ||
395 | |||
396 | return bm; | ||
397 | |||
398 | bad: | ||
399 | return ERR_PTR(r); | ||
380 | } | 400 | } |
381 | EXPORT_SYMBOL_GPL(dm_block_manager_create); | 401 | EXPORT_SYMBOL_GPL(dm_block_manager_create); |
382 | 402 | ||
383 | void dm_block_manager_destroy(struct dm_block_manager *bm) | 403 | void dm_block_manager_destroy(struct dm_block_manager *bm) |
384 | { | 404 | { |
385 | return dm_bufio_client_destroy(to_bufio(bm)); | 405 | dm_bufio_client_destroy(bm->bufio); |
406 | kfree(bm); | ||
386 | } | 407 | } |
387 | EXPORT_SYMBOL_GPL(dm_block_manager_destroy); | 408 | EXPORT_SYMBOL_GPL(dm_block_manager_destroy); |
388 | 409 | ||
389 | unsigned dm_bm_block_size(struct dm_block_manager *bm) | 410 | unsigned dm_bm_block_size(struct dm_block_manager *bm) |
390 | { | 411 | { |
391 | return dm_bufio_get_block_size(to_bufio(bm)); | 412 | return dm_bufio_get_block_size(bm->bufio); |
392 | } | 413 | } |
393 | EXPORT_SYMBOL_GPL(dm_bm_block_size); | 414 | EXPORT_SYMBOL_GPL(dm_bm_block_size); |
394 | 415 | ||
395 | dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm) | 416 | dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm) |
396 | { | 417 | { |
397 | return dm_bufio_get_device_size(to_bufio(bm)); | 418 | return dm_bufio_get_device_size(bm->bufio); |
398 | } | 419 | } |
399 | 420 | ||
400 | static int dm_bm_validate_buffer(struct dm_block_manager *bm, | 421 | static int dm_bm_validate_buffer(struct dm_block_manager *bm, |
@@ -406,7 +427,7 @@ static int dm_bm_validate_buffer(struct dm_block_manager *bm, | |||
406 | int r; | 427 | int r; |
407 | if (!v) | 428 | if (!v) |
408 | return 0; | 429 | return 0; |
409 | r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(to_bufio(bm))); | 430 | r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(bm->bufio)); |
410 | if (unlikely(r)) | 431 | if (unlikely(r)) |
411 | return r; | 432 | return r; |
412 | aux->validator = v; | 433 | aux->validator = v; |
@@ -430,7 +451,7 @@ int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b, | |||
430 | void *p; | 451 | void *p; |
431 | int r; | 452 | int r; |
432 | 453 | ||
433 | p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result); | 454 | p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); |
434 | if (unlikely(IS_ERR(p))) | 455 | if (unlikely(IS_ERR(p))) |
435 | return PTR_ERR(p); | 456 | return PTR_ERR(p); |
436 | 457 | ||
@@ -463,7 +484,10 @@ int dm_bm_write_lock(struct dm_block_manager *bm, | |||
463 | void *p; | 484 | void *p; |
464 | int r; | 485 | int r; |
465 | 486 | ||
466 | p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result); | 487 | if (bm->read_only) |
488 | return -EPERM; | ||
489 | |||
490 | p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); | ||
467 | if (unlikely(IS_ERR(p))) | 491 | if (unlikely(IS_ERR(p))) |
468 | return PTR_ERR(p); | 492 | return PTR_ERR(p); |
469 | 493 | ||
@@ -496,7 +520,7 @@ int dm_bm_read_try_lock(struct dm_block_manager *bm, | |||
496 | void *p; | 520 | void *p; |
497 | int r; | 521 | int r; |
498 | 522 | ||
499 | p = dm_bufio_get(to_bufio(bm), b, (struct dm_buffer **) result); | 523 | p = dm_bufio_get(bm->bufio, b, (struct dm_buffer **) result); |
500 | if (unlikely(IS_ERR(p))) | 524 | if (unlikely(IS_ERR(p))) |
501 | return PTR_ERR(p); | 525 | return PTR_ERR(p); |
502 | if (unlikely(!p)) | 526 | if (unlikely(!p)) |
@@ -529,7 +553,10 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, | |||
529 | struct buffer_aux *aux; | 553 | struct buffer_aux *aux; |
530 | void *p; | 554 | void *p; |
531 | 555 | ||
532 | p = dm_bufio_new(to_bufio(bm), b, (struct dm_buffer **) result); | 556 | if (bm->read_only) |
557 | return -EPERM; | ||
558 | |||
559 | p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result); | ||
533 | if (unlikely(IS_ERR(p))) | 560 | if (unlikely(IS_ERR(p))) |
534 | return PTR_ERR(p); | 561 | return PTR_ERR(p); |
535 | 562 | ||
@@ -547,6 +574,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, | |||
547 | 574 | ||
548 | return 0; | 575 | return 0; |
549 | } | 576 | } |
577 | EXPORT_SYMBOL_GPL(dm_bm_write_lock_zero); | ||
550 | 578 | ||
551 | int dm_bm_unlock(struct dm_block *b) | 579 | int dm_bm_unlock(struct dm_block *b) |
552 | { | 580 | { |
@@ -565,45 +593,30 @@ int dm_bm_unlock(struct dm_block *b) | |||
565 | } | 593 | } |
566 | EXPORT_SYMBOL_GPL(dm_bm_unlock); | 594 | EXPORT_SYMBOL_GPL(dm_bm_unlock); |
567 | 595 | ||
568 | int dm_bm_unlock_move(struct dm_block *b, dm_block_t n) | ||
569 | { | ||
570 | struct buffer_aux *aux; | ||
571 | |||
572 | aux = dm_bufio_get_aux_data(to_buffer(b)); | ||
573 | |||
574 | if (aux->write_locked) { | ||
575 | dm_bufio_mark_buffer_dirty(to_buffer(b)); | ||
576 | bl_up_write(&aux->lock); | ||
577 | } else | ||
578 | bl_up_read(&aux->lock); | ||
579 | |||
580 | dm_bufio_release_move(to_buffer(b), n); | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | int dm_bm_flush_and_unlock(struct dm_block_manager *bm, | 596 | int dm_bm_flush_and_unlock(struct dm_block_manager *bm, |
585 | struct dm_block *superblock) | 597 | struct dm_block *superblock) |
586 | { | 598 | { |
587 | int r; | 599 | int r; |
588 | 600 | ||
589 | r = dm_bufio_write_dirty_buffers(to_bufio(bm)); | 601 | if (bm->read_only) |
590 | if (unlikely(r)) | 602 | return -EPERM; |
591 | return r; | 603 | |
592 | r = dm_bufio_issue_flush(to_bufio(bm)); | 604 | r = dm_bufio_write_dirty_buffers(bm->bufio); |
593 | if (unlikely(r)) | 605 | if (unlikely(r)) { |
606 | dm_bm_unlock(superblock); | ||
594 | return r; | 607 | return r; |
608 | } | ||
595 | 609 | ||
596 | dm_bm_unlock(superblock); | 610 | dm_bm_unlock(superblock); |
597 | 611 | ||
598 | r = dm_bufio_write_dirty_buffers(to_bufio(bm)); | 612 | return dm_bufio_write_dirty_buffers(bm->bufio); |
599 | if (unlikely(r)) | 613 | } |
600 | return r; | ||
601 | r = dm_bufio_issue_flush(to_bufio(bm)); | ||
602 | if (unlikely(r)) | ||
603 | return r; | ||
604 | 614 | ||
605 | return 0; | 615 | void dm_bm_set_read_only(struct dm_block_manager *bm) |
616 | { | ||
617 | bm->read_only = true; | ||
606 | } | 618 | } |
619 | EXPORT_SYMBOL_GPL(dm_bm_set_read_only); | ||
607 | 620 | ||
608 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) | 621 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) |
609 | { | 622 | { |