Skip to content

Commit fc1d438

Browse files
bjohnstoMikulas Patocka
authored andcommitted
dm vdo: save the formatted metadata to disk
Add vdo_save_super_block() and vdo_save_geometry_block() to perform asynchronous writes of the super block and geometry block respectively. Add vdo_clear_layout() to zero the UDS index's first block, the block map partition, and the recovery journal partition. These operations are driven by new phases in the pre-load state machine (PRE_LOAD_PHASE_FORMAT_*), ensuring that disk writes happen during pre-resume rather than during dmsetup create. Signed-off-by: Bruce Johnston <bjohnsto@redhat.com> Reviewed-by: Matthew Sakai <msakai@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
1 parent defce4e commit fc1d438

3 files changed

Lines changed: 147 additions & 20 deletions

File tree

drivers/md/dm-vdo/dm-vdo-target.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ enum admin_phases {
6161
LOAD_PHASE_DRAIN_JOURNAL,
6262
LOAD_PHASE_WAIT_FOR_READ_ONLY,
6363
PRE_LOAD_PHASE_START,
64+
PRE_LOAD_PHASE_FORMAT_START,
65+
PRE_LOAD_PHASE_FORMAT_SUPER,
66+
PRE_LOAD_PHASE_FORMAT_GEOMETRY,
67+
PRE_LOAD_PHASE_FORMAT_END,
68+
PRE_LOAD_PHASE_LOAD_SUPER,
6469
PRE_LOAD_PHASE_LOAD_COMPONENTS,
6570
PRE_LOAD_PHASE_END,
6671
PREPARE_GROW_PHYSICAL_PHASE_START,
@@ -110,6 +115,11 @@ static const char * const ADMIN_PHASE_NAMES[] = {
110115
"LOAD_PHASE_DRAIN_JOURNAL",
111116
"LOAD_PHASE_WAIT_FOR_READ_ONLY",
112117
"PRE_LOAD_PHASE_START",
118+
"PRE_LOAD_PHASE_FORMAT_START",
119+
"PRE_LOAD_PHASE_FORMAT_SUPER",
120+
"PRE_LOAD_PHASE_FORMAT_GEOMETRY",
121+
"PRE_LOAD_PHASE_FORMAT_END",
122+
"PRE_LOAD_PHASE_LOAD_SUPER",
113123
"PRE_LOAD_PHASE_LOAD_COMPONENTS",
114124
"PRE_LOAD_PHASE_END",
115125
"PREPARE_GROW_PHYSICAL_PHASE_START",
@@ -1487,7 +1497,33 @@ static void pre_load_callback(struct vdo_completion *completion)
14871497
vdo_continue_completion(completion, result);
14881498
return;
14891499
}
1500+
if (vdo->needs_formatting)
1501+
vdo->admin.phase = PRE_LOAD_PHASE_FORMAT_START;
1502+
else
1503+
vdo->admin.phase = PRE_LOAD_PHASE_LOAD_SUPER;
14901504

1505+
vdo_continue_completion(completion, VDO_SUCCESS);
1506+
return;
1507+
1508+
case PRE_LOAD_PHASE_FORMAT_START:
1509+
vdo_continue_completion(completion, vdo_clear_layout(vdo));
1510+
return;
1511+
1512+
case PRE_LOAD_PHASE_FORMAT_SUPER:
1513+
vdo_save_super_block(vdo, completion);
1514+
return;
1515+
1516+
case PRE_LOAD_PHASE_FORMAT_GEOMETRY:
1517+
vdo_save_geometry_block(vdo, completion);
1518+
return;
1519+
1520+
case PRE_LOAD_PHASE_FORMAT_END:
1521+
/* cleanup layout before load adds to it */
1522+
vdo_uninitialize_layout(&vdo->states.layout);
1523+
vdo_continue_completion(completion, VDO_SUCCESS);
1524+
return;
1525+
1526+
case PRE_LOAD_PHASE_LOAD_SUPER:
14911527
vdo_load_super_block(vdo, completion);
14921528
return;
14931529

drivers/md/dm-vdo/vdo.c

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ static int __must_check vdo_format(struct vdo *vdo, char **error_ptr)
491491
return result;
492492
}
493493

494+
vdo->needs_formatting = true;
495+
494496
return VDO_SUCCESS;
495497
}
496498

@@ -951,24 +953,101 @@ static void record_vdo(struct vdo *vdo)
951953
vdo->states.layout = vdo->layout;
952954
}
953955

956+
static int __must_check clear_partition(struct vdo *vdo, enum partition_id id)
957+
{
958+
struct partition *partition;
959+
int result;
960+
961+
result = vdo_get_partition(&vdo->states.layout, id, &partition);
962+
if (result != VDO_SUCCESS)
963+
return result;
964+
965+
return blkdev_issue_zeroout(vdo_get_backing_device(vdo),
966+
partition->offset * VDO_SECTORS_PER_BLOCK,
967+
partition->count * VDO_SECTORS_PER_BLOCK,
968+
GFP_NOWAIT, 0);
969+
}
970+
971+
int vdo_clear_layout(struct vdo *vdo)
972+
{
973+
int result;
974+
975+
/* Zero out the uds index's first block. */
976+
result = blkdev_issue_zeroout(vdo_get_backing_device(vdo),
977+
VDO_SECTORS_PER_BLOCK,
978+
VDO_SECTORS_PER_BLOCK,
979+
GFP_NOWAIT, 0);
980+
if (result != VDO_SUCCESS)
981+
return result;
982+
983+
result = clear_partition(vdo, VDO_BLOCK_MAP_PARTITION);
984+
if (result != VDO_SUCCESS)
985+
return result;
986+
987+
return clear_partition(vdo, VDO_RECOVERY_JOURNAL_PARTITION);
988+
}
989+
954990
/**
955-
* continue_super_block_parent() - Continue the parent of a super block save operation.
956-
* @completion: The super block vio.
991+
* continue_parent() - Continue the parent of a save operation.
992+
* @completion: The completion to continue.
957993
*
958-
* This callback is registered in vdo_save_components().
959994
*/
960-
static void continue_super_block_parent(struct vdo_completion *completion)
995+
static void continue_parent(struct vdo_completion *completion)
961996
{
962997
vdo_continue_completion(vdo_forget(completion->parent), completion->result);
963998
}
964999

1000+
static void handle_write_endio(struct bio *bio)
1001+
{
1002+
struct vio *vio = bio->bi_private;
1003+
struct vdo_completion *parent = vio->completion.parent;
1004+
1005+
continue_vio_after_io(vio, continue_parent,
1006+
parent->callback_thread_id);
1007+
}
1008+
9651009
/**
966-
* handle_save_error() - Log a super block save error.
1010+
* handle_geometry_block_save_error() - Log a geometry block save error.
1011+
* @completion: The super block vio.
1012+
*
1013+
* This error handler is registered in vdo_save_geometry_block().
1014+
*/
1015+
static void handle_geometry_block_save_error(struct vdo_completion *completion)
1016+
{
1017+
struct vdo_geometry_block *geometry_block =
1018+
container_of(as_vio(completion), struct vdo_geometry_block, vio);
1019+
1020+
vio_record_metadata_io_error(&geometry_block->vio);
1021+
vdo_log_error_strerror(completion->result, "geometry block save failed");
1022+
completion->callback(completion);
1023+
}
1024+
1025+
/**
1026+
* vdo_save_geometry_block() - Encode the vdo and save the geometry block asynchronously.
1027+
* @vdo: The vdo whose state is being saved.
1028+
* @parent: The completion to notify when the save is complete.
1029+
*/
1030+
void vdo_save_geometry_block(struct vdo *vdo, struct vdo_completion *parent)
1031+
{
1032+
struct vdo_geometry_block *geometry_block = &vdo->geometry_block;
1033+
1034+
vdo_encode_volume_geometry(geometry_block->buffer, &vdo->geometry,
1035+
VDO_DEFAULT_GEOMETRY_BLOCK_VERSION);
1036+
geometry_block->vio.completion.parent = parent;
1037+
geometry_block->vio.completion.callback_thread_id = parent->callback_thread_id;
1038+
vdo_submit_metadata_vio(&geometry_block->vio,
1039+
VDO_GEOMETRY_BLOCK_LOCATION,
1040+
handle_write_endio, handle_geometry_block_save_error,
1041+
REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA);
1042+
}
1043+
1044+
/**
1045+
* handle_super_block_save_error() - Log a super block save error.
9671046
* @completion: The super block vio.
9681047
*
9691048
* This error handler is registered in vdo_save_components().
9701049
*/
971-
static void handle_save_error(struct vdo_completion *completion)
1050+
static void handle_super_block_save_error(struct vdo_completion *completion)
9721051
{
9731052
struct vdo_super_block *super_block =
9741053
container_of(as_vio(completion), struct vdo_super_block, vio);
@@ -987,17 +1066,27 @@ static void handle_save_error(struct vdo_completion *completion)
9871066
completion->callback(completion);
9881067
}
9891068

990-
static void super_block_write_endio(struct bio *bio)
1069+
/**
1070+
* vdo_save_super_block() - Save the component states to the super block asynchronously.
1071+
* @vdo: The vdo whose state is being saved.
1072+
* @parent: The completion to notify when the save is complete.
1073+
*/
1074+
void vdo_save_super_block(struct vdo *vdo, struct vdo_completion *parent)
9911075
{
992-
struct vio *vio = bio->bi_private;
993-
struct vdo_completion *parent = vio->completion.parent;
1076+
struct vdo_super_block *super_block = &vdo->super_block;
9941077

995-
continue_vio_after_io(vio, continue_super_block_parent,
996-
parent->callback_thread_id);
1078+
vdo_encode_super_block(super_block->buffer, &vdo->states);
1079+
super_block->vio.completion.parent = parent;
1080+
super_block->vio.completion.callback_thread_id = parent->callback_thread_id;
1081+
vdo_submit_metadata_vio(&super_block->vio,
1082+
vdo_get_data_region_start(vdo->geometry),
1083+
handle_write_endio, handle_super_block_save_error,
1084+
REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA);
9971085
}
9981086

9991087
/**
1000-
* vdo_save_components() - Encode the vdo and save the super block asynchronously.
1088+
* vdo_save_components() - Copy the current state of the VDO to the states struct and save
1089+
* it to the super block asynchronously.
10011090
* @vdo: The vdo whose state is being saved.
10021091
* @parent: The completion to notify when the save is complete.
10031092
*/
@@ -1016,14 +1105,7 @@ void vdo_save_components(struct vdo *vdo, struct vdo_completion *parent)
10161105
}
10171106

10181107
record_vdo(vdo);
1019-
1020-
vdo_encode_super_block(super_block->buffer, &vdo->states);
1021-
super_block->vio.completion.parent = parent;
1022-
super_block->vio.completion.callback_thread_id = parent->callback_thread_id;
1023-
vdo_submit_metadata_vio(&super_block->vio,
1024-
vdo_get_data_region_start(vdo->geometry),
1025-
super_block_write_endio, handle_save_error,
1026-
REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA);
1108+
vdo_save_super_block(vdo, parent);
10271109
}
10281110

10291111
/**

drivers/md/dm-vdo/vdo.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ struct vdo {
246246
const struct admin_state_code *suspend_type;
247247
bool allocations_allowed;
248248
bool dump_on_shutdown;
249+
bool needs_formatting;
249250
atomic_t processing_message;
250251

251252
/*
@@ -314,6 +315,10 @@ int __must_check vdo_make(unsigned int instance, struct device_config *config,
314315

315316
void vdo_destroy(struct vdo *vdo);
316317

318+
int __must_check vdo_format_components(struct vdo *vdo);
319+
320+
void vdo_format_super_block(struct vdo *vdo, struct vdo_completion *parent);
321+
317322
void vdo_load_super_block(struct vdo *vdo, struct vdo_completion *parent);
318323

319324
struct block_device * __must_check vdo_get_backing_device(const struct vdo *vdo);
@@ -336,6 +341,10 @@ enum vdo_state __must_check vdo_get_state(const struct vdo *vdo);
336341

337342
void vdo_set_state(struct vdo *vdo, enum vdo_state state);
338343

344+
int vdo_clear_layout(struct vdo *vdo);
345+
void vdo_save_geometry_block(struct vdo *vdo, struct vdo_completion *parent);
346+
void vdo_save_super_block(struct vdo *vdo, struct vdo_completion *parent);
347+
339348
void vdo_save_components(struct vdo *vdo, struct vdo_completion *parent);
340349

341350
int vdo_register_read_only_listener(struct vdo *vdo, void *listener,

0 commit comments

Comments
 (0)