diff options
Diffstat (limited to 'drivers/md/dm-thin-metadata.c')
-rw-r--r-- | drivers/md/dm-thin-metadata.c | 109 |
1 files changed, 58 insertions, 51 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index ce487aada0d8..5ead655706d4 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
@@ -422,6 +422,41 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd) | |||
422 | pmd->details_info.value_type.equal = NULL; | 422 | pmd->details_info.value_type.equal = NULL; |
423 | } | 423 | } |
424 | 424 | ||
425 | static int __write_initial_superblock(struct dm_pool_metadata *pmd) | ||
426 | { | ||
427 | int r; | ||
428 | struct dm_block *sblock; | ||
429 | struct thin_disk_superblock *disk_super; | ||
430 | sector_t bdev_size = i_size_read(pmd->bdev->bd_inode) >> SECTOR_SHIFT; | ||
431 | |||
432 | if (bdev_size > THIN_METADATA_MAX_SECTORS) | ||
433 | bdev_size = THIN_METADATA_MAX_SECTORS; | ||
434 | |||
435 | r = superblock_lock_zero(pmd, &sblock); | ||
436 | if (r) | ||
437 | return r; | ||
438 | |||
439 | disk_super = dm_block_data(sblock); | ||
440 | disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC); | ||
441 | disk_super->version = cpu_to_le32(THIN_VERSION); | ||
442 | disk_super->time = 0; | ||
443 | disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); | ||
444 | disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT); | ||
445 | disk_super->data_block_size = cpu_to_le32(pmd->data_block_size); | ||
446 | |||
447 | r = dm_bm_unlock(sblock); | ||
448 | if (r) | ||
449 | return r; | ||
450 | |||
451 | pmd->flags = 0; | ||
452 | r = dm_pool_commit_metadata(pmd); | ||
453 | if (r < 0) | ||
454 | DMERR("%s: dm_pool_commit_metadata() failed, error = %d", | ||
455 | __func__, r); | ||
456 | |||
457 | return r; | ||
458 | } | ||
459 | |||
425 | static int __open_or_format_metadata(struct dm_pool_metadata *pmd, | 460 | static int __open_or_format_metadata(struct dm_pool_metadata *pmd, |
426 | struct dm_block_manager *bm, | 461 | struct dm_block_manager *bm, |
427 | dm_block_t nr_blocks, int create) | 462 | dm_block_t nr_blocks, int create) |
@@ -495,6 +530,23 @@ static int __open_or_format_metadata(struct dm_pool_metadata *pmd, | |||
495 | pmd->trans_id = 0; | 530 | pmd->trans_id = 0; |
496 | pmd->flags = 0; | 531 | pmd->flags = 0; |
497 | 532 | ||
533 | if (!create) | ||
534 | return 0; | ||
535 | |||
536 | r = dm_btree_empty(&pmd->info, &pmd->root); | ||
537 | if (r < 0) | ||
538 | goto bad_data_sm; | ||
539 | |||
540 | r = dm_btree_empty(&pmd->details_info, &pmd->details_root); | ||
541 | if (r < 0) { | ||
542 | DMERR("couldn't create devices root"); | ||
543 | goto bad_data_sm; | ||
544 | } | ||
545 | |||
546 | r = __write_initial_superblock(pmd); | ||
547 | if (r) | ||
548 | goto bad_data_sm; | ||
549 | |||
498 | return 0; | 550 | return 0; |
499 | 551 | ||
500 | bad_data_sm: | 552 | bad_data_sm: |
@@ -695,11 +747,8 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, | |||
695 | sector_t data_block_size) | 747 | sector_t data_block_size) |
696 | { | 748 | { |
697 | int r; | 749 | int r; |
698 | struct thin_disk_superblock *disk_super; | ||
699 | struct dm_pool_metadata *pmd; | 750 | struct dm_pool_metadata *pmd; |
700 | sector_t bdev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; | ||
701 | int create; | 751 | int create; |
702 | struct dm_block *sblock; | ||
703 | 752 | ||
704 | pmd = kmalloc(sizeof(*pmd), GFP_KERNEL); | 753 | pmd = kmalloc(sizeof(*pmd), GFP_KERNEL); |
705 | if (!pmd) { | 754 | if (!pmd) { |
@@ -711,6 +760,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, | |||
711 | pmd->time = 0; | 760 | pmd->time = 0; |
712 | INIT_LIST_HEAD(&pmd->thin_devices); | 761 | INIT_LIST_HEAD(&pmd->thin_devices); |
713 | pmd->bdev = bdev; | 762 | pmd->bdev = bdev; |
763 | pmd->data_block_size = data_block_size; | ||
714 | 764 | ||
715 | r = __create_persistent_data_objects(pmd, 0, &create); | 765 | r = __create_persistent_data_objects(pmd, 0, &create); |
716 | if (r) { | 766 | if (r) { |
@@ -720,57 +770,14 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, | |||
720 | 770 | ||
721 | if (!create) { | 771 | if (!create) { |
722 | r = __begin_transaction(pmd); | 772 | r = __begin_transaction(pmd); |
723 | if (r < 0) | 773 | if (r < 0) { |
724 | goto bad; | 774 | if (dm_pool_metadata_close(pmd) < 0) |
725 | return pmd; | 775 | DMWARN("%s: dm_pool_metadata_close() failed.", __func__); |
726 | } | 776 | return ERR_PTR(r); |
727 | 777 | } | |
728 | /* | ||
729 | * Create. | ||
730 | */ | ||
731 | r = superblock_lock_zero(pmd, &sblock); | ||
732 | if (r) | ||
733 | goto bad; | ||
734 | |||
735 | if (bdev_size > THIN_METADATA_MAX_SECTORS) | ||
736 | bdev_size = THIN_METADATA_MAX_SECTORS; | ||
737 | |||
738 | disk_super = dm_block_data(sblock); | ||
739 | disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC); | ||
740 | disk_super->version = cpu_to_le32(THIN_VERSION); | ||
741 | disk_super->time = 0; | ||
742 | disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); | ||
743 | disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT); | ||
744 | disk_super->data_block_size = cpu_to_le32(data_block_size); | ||
745 | |||
746 | r = dm_bm_unlock(sblock); | ||
747 | if (r < 0) | ||
748 | goto bad; | ||
749 | |||
750 | r = dm_btree_empty(&pmd->info, &pmd->root); | ||
751 | if (r < 0) | ||
752 | goto bad; | ||
753 | |||
754 | r = dm_btree_empty(&pmd->details_info, &pmd->details_root); | ||
755 | if (r < 0) { | ||
756 | DMERR("couldn't create devices root"); | ||
757 | goto bad; | ||
758 | } | ||
759 | |||
760 | pmd->flags = 0; | ||
761 | r = dm_pool_commit_metadata(pmd); | ||
762 | if (r < 0) { | ||
763 | DMERR("%s: dm_pool_commit_metadata() failed, error = %d", | ||
764 | __func__, r); | ||
765 | goto bad; | ||
766 | } | 778 | } |
767 | 779 | ||
768 | return pmd; | 780 | return pmd; |
769 | |||
770 | bad: | ||
771 | if (dm_pool_metadata_close(pmd) < 0) | ||
772 | DMWARN("%s: dm_pool_metadata_close() failed.", __func__); | ||
773 | return ERR_PTR(r); | ||
774 | } | 781 | } |
775 | 782 | ||
776 | int dm_pool_metadata_close(struct dm_pool_metadata *pmd) | 783 | int dm_pool_metadata_close(struct dm_pool_metadata *pmd) |