aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-thin-metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-thin-metadata.c')
-rw-r--r--drivers/md/dm-thin-metadata.c109
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
425static 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
425static int __open_or_format_metadata(struct dm_pool_metadata *pmd, 460static 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
500bad_data_sm: 552bad_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
770bad:
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
776int dm_pool_metadata_close(struct dm_pool_metadata *pmd) 783int dm_pool_metadata_close(struct dm_pool_metadata *pmd)