Skip to content

Commit 72a2865

Browse files
jthornberkamalmostafa
authored andcommitted
dm: take care to copy the space map roots before locking the superblock
commit 5a32083 upstream. In theory copying the space map root can fail, but in practice it never does because we're careful to check what size buffer is needed. But make certain we're able to copy the space map roots before locking the superblock. Signed-off-by: Joe Thornber <[email protected]> Signed-off-by: Mike Snitzer <[email protected]> [ kamal: backport to 3.8 (no dm-cache-metadata.c, dm-era-target.c) ] Signed-off-by: Kamal Mostafa <[email protected]>
1 parent 2d4dfde commit 72a2865

File tree

1 file changed

+47
-33
lines changed

1 file changed

+47
-33
lines changed

drivers/md/dm-thin-metadata.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ struct dm_pool_metadata {
192192
* operation possible in this state is the closing of the device.
193193
*/
194194
bool fail_io:1;
195+
196+
/*
197+
* Reading the space map roots can fail, so we read it into these
198+
* buffers before the superblock is locked and updated.
199+
*/
200+
__u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];
201+
__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
195202
};
196203

197204
struct dm_thin_device {
@@ -431,26 +438,53 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd)
431438
pmd->details_info.value_type.equal = NULL;
432439
}
433440

441+
static int save_sm_roots(struct dm_pool_metadata *pmd)
442+
{
443+
int r;
444+
size_t len;
445+
446+
r = dm_sm_root_size(pmd->metadata_sm, &len);
447+
if (r < 0)
448+
return r;
449+
450+
r = dm_sm_copy_root(pmd->metadata_sm, &pmd->metadata_space_map_root, len);
451+
if (r < 0)
452+
return r;
453+
454+
r = dm_sm_root_size(pmd->data_sm, &len);
455+
if (r < 0)
456+
return r;
457+
458+
return dm_sm_copy_root(pmd->data_sm, &pmd->data_space_map_root, len);
459+
}
460+
461+
static void copy_sm_roots(struct dm_pool_metadata *pmd,
462+
struct thin_disk_superblock *disk)
463+
{
464+
memcpy(&disk->metadata_space_map_root,
465+
&pmd->metadata_space_map_root,
466+
sizeof(pmd->metadata_space_map_root));
467+
468+
memcpy(&disk->data_space_map_root,
469+
&pmd->data_space_map_root,
470+
sizeof(pmd->data_space_map_root));
471+
}
472+
434473
static int __write_initial_superblock(struct dm_pool_metadata *pmd)
435474
{
436475
int r;
437476
struct dm_block *sblock;
438-
size_t metadata_len, data_len;
439477
struct thin_disk_superblock *disk_super;
440478
sector_t bdev_size = i_size_read(pmd->bdev->bd_inode) >> SECTOR_SHIFT;
441479

442480
if (bdev_size > THIN_METADATA_MAX_SECTORS)
443481
bdev_size = THIN_METADATA_MAX_SECTORS;
444482

445-
r = dm_sm_root_size(pmd->metadata_sm, &metadata_len);
446-
if (r < 0)
447-
return r;
448-
449-
r = dm_sm_root_size(pmd->data_sm, &data_len);
483+
r = dm_sm_commit(pmd->data_sm);
450484
if (r < 0)
451485
return r;
452486

453-
r = dm_sm_commit(pmd->data_sm);
487+
r = save_sm_roots(pmd);
454488
if (r < 0)
455489
return r;
456490

@@ -471,15 +505,7 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
471505
disk_super->trans_id = 0;
472506
disk_super->held_root = 0;
473507

474-
r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root,
475-
metadata_len);
476-
if (r < 0)
477-
goto bad_locked;
478-
479-
r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root,
480-
data_len);
481-
if (r < 0)
482-
goto bad_locked;
508+
copy_sm_roots(pmd, disk_super);
483509

484510
disk_super->data_mapping_root = cpu_to_le64(pmd->root);
485511
disk_super->device_details_root = cpu_to_le64(pmd->details_root);
@@ -488,10 +514,6 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
488514
disk_super->data_block_size = cpu_to_le32(pmd->data_block_size);
489515

490516
return dm_tm_commit(pmd->tm, sblock);
491-
492-
bad_locked:
493-
dm_bm_unlock(sblock);
494-
return r;
495517
}
496518

497519
static int __format_metadata(struct dm_pool_metadata *pmd)
@@ -769,6 +791,10 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
769791
if (r < 0)
770792
return r;
771793

794+
r = save_sm_roots(pmd);
795+
if (r < 0)
796+
return r;
797+
772798
r = superblock_lock(pmd, &sblock);
773799
if (r)
774800
return r;
@@ -780,21 +806,9 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
780806
disk_super->trans_id = cpu_to_le64(pmd->trans_id);
781807
disk_super->flags = cpu_to_le32(pmd->flags);
782808

783-
r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root,
784-
metadata_len);
785-
if (r < 0)
786-
goto out_locked;
787-
788-
r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root,
789-
data_len);
790-
if (r < 0)
791-
goto out_locked;
809+
copy_sm_roots(pmd, disk_super);
792810

793811
return dm_tm_commit(pmd->tm, sblock);
794-
795-
out_locked:
796-
dm_bm_unlock(sblock);
797-
return r;
798812
}
799813

800814
struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,

0 commit comments

Comments
 (0)