Skip to content

Commit defce4e

Browse files
bjohnstoMikulas Patocka
authored andcommitted
dm vdo: add formatting logic and initialization
Add the core formatting logic. The initialization path is updated to read the geometry block (block 0 on the storage device). If the block is entirely zeroed, the device is treated as unformatted and vdo_format() is called. Otherwise, the existing geometry is parsed and the VDO is loaded as before. The vdo_format() function initializes the volume geometry and super block, and marks the VDO as needing it's layout saved to disk. 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 9d9c28a commit defce4e

2 files changed

Lines changed: 81 additions & 25 deletions

File tree

drivers/md/dm-vdo/status-codes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ int vdo_status_to_errno(int error)
8080

8181
/* VDO or UDS error */
8282
switch (error) {
83+
case VDO_BAD_CONFIGURATION:
84+
return -EINVAL;
8385
case VDO_NO_SPACE:
8486
return -ENOSPC;
8587
case VDO_READ_ONLY:

drivers/md/dm-vdo/vdo.c

Lines changed: 79 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
#include <linux/lz4.h>
3535
#include <linux/mutex.h>
3636
#include <linux/spinlock.h>
37+
#include <linux/string.h>
3738
#include <linux/types.h>
39+
#include <linux/uuid.h>
3840

3941
#include "logger.h"
4042
#include "memory-alloc.h"
@@ -55,6 +57,7 @@
5557
#include "slab-depot.h"
5658
#include "statistics.h"
5759
#include "status-codes.h"
60+
#include "time-utils.h"
5861
#include "vio.h"
5962

6063
#define PARANOID_THREAD_CONSISTENCY_CHECKS 0
@@ -286,30 +289,6 @@ static int initialize_super_block(struct vdo *vdo, struct vdo_super_block *super
286289
&vdo->super_block.vio);
287290
}
288291

289-
/**
290-
* read_geometry_block() - Synchronously read the geometry block from a vdo's underlying block
291-
* device.
292-
* @vdo: The vdo whose geometry is to be read.
293-
*
294-
* Return: VDO_SUCCESS or an error code.
295-
*/
296-
static int __must_check read_geometry_block(struct vdo *vdo)
297-
{
298-
int result;
299-
300-
/*
301-
* This is only safe because, having not already loaded the geometry, the vdo's geometry's
302-
* bio_offset field is 0, so the fact that vio_reset_bio() will subtract that offset from
303-
* the supplied pbn is not a problem.
304-
*/
305-
result = vdo_submit_metadata_vio_wait(&vdo->geometry_block.vio,
306-
VDO_GEOMETRY_BLOCK_LOCATION, REQ_OP_READ);
307-
if (result != VDO_SUCCESS)
308-
return result;
309-
310-
return vdo_parse_geometry_block(vdo->geometry_block.buffer, &vdo->geometry);
311-
}
312-
313292
static bool get_zone_thread_name(const thread_id_t thread_ids[], zone_count_t count,
314293
thread_id_t id, const char *prefix,
315294
char *buffer, size_t buffer_length)
@@ -454,6 +433,67 @@ static int register_vdo(struct vdo *vdo)
454433
return result;
455434
}
456435

436+
/**
437+
* vdo_format() - Format a block device to function as a new VDO.
438+
* @vdo: The vdo to format.
439+
* @error_ptr: The reason for any failure during this call.
440+
*
441+
* This function must be called on a device before a VDO can be loaded for the first time.
442+
* Once a device has been formatted, the VDO can be loaded and shut down repeatedly.
443+
* If a new VDO is desired, this function should be called again.
444+
*
445+
* Return: VDO_SUCCESS or an error
446+
**/
447+
static int __must_check vdo_format(struct vdo *vdo, char **error_ptr)
448+
{
449+
int result;
450+
uuid_t uuid;
451+
nonce_t nonce = current_time_us();
452+
struct device_config *config = vdo->device_config;
453+
454+
struct index_config index_config = {
455+
.mem = config->index_memory,
456+
.sparse = config->index_sparse,
457+
};
458+
459+
struct vdo_config vdo_config = {
460+
.logical_blocks = config->logical_blocks,
461+
.physical_blocks = config->physical_blocks,
462+
.slab_size = config->slab_blocks,
463+
.slab_journal_blocks = DEFAULT_VDO_SLAB_JOURNAL_SIZE,
464+
.recovery_journal_size = DEFAULT_VDO_RECOVERY_JOURNAL_SIZE,
465+
};
466+
467+
uuid_gen(&uuid);
468+
result = vdo_initialize_volume_geometry(nonce, &uuid, &index_config, &vdo->geometry);
469+
if (result != VDO_SUCCESS) {
470+
*error_ptr = "Could not initialize volume geometry during format";
471+
return result;
472+
}
473+
474+
result = vdo_initialize_component_states(&vdo_config, &vdo->geometry, nonce, &vdo->states);
475+
if (result == VDO_NO_SPACE) {
476+
block_count_t slab_blocks = config->slab_blocks;
477+
/* 1 is counting geometry block */
478+
block_count_t fixed_layout_size = 1 +
479+
vdo->geometry.regions[VDO_DATA_REGION].start_block +
480+
DEFAULT_VDO_BLOCK_MAP_TREE_ROOT_COUNT +
481+
DEFAULT_VDO_RECOVERY_JOURNAL_SIZE + VDO_SLAB_SUMMARY_BLOCKS;
482+
block_count_t necessary_size = fixed_layout_size + slab_blocks;
483+
484+
vdo_log_error("Minimum required size for VDO volume: %llu bytes",
485+
(unsigned long long) necessary_size * VDO_BLOCK_SIZE);
486+
*error_ptr = "Could not allocate enough space for VDO during format";
487+
return result;
488+
}
489+
if (result != VDO_SUCCESS) {
490+
*error_ptr = "Could not initialize data layout during format";
491+
return result;
492+
}
493+
494+
return VDO_SUCCESS;
495+
}
496+
457497
/**
458498
* initialize_vdo() - Do the portion of initializing a vdo which will clean up after itself on
459499
* error.
@@ -490,12 +530,26 @@ static int initialize_vdo(struct vdo *vdo, struct device_config *config,
490530
return result;
491531
}
492532

493-
result = read_geometry_block(vdo);
533+
result = vdo_submit_metadata_vio_wait(&vdo->geometry_block.vio,
534+
VDO_GEOMETRY_BLOCK_LOCATION, REQ_OP_READ);
494535
if (result != VDO_SUCCESS) {
495536
*reason = "Could not load geometry block";
496537
return result;
497538
}
498539

540+
if (mem_is_zero(vdo->geometry_block.vio.data, VDO_BLOCK_SIZE)) {
541+
result = vdo_format(vdo, reason);
542+
if (result != VDO_SUCCESS)
543+
return result;
544+
} else {
545+
result = vdo_parse_geometry_block(vdo->geometry_block.buffer,
546+
&vdo->geometry);
547+
if (result != VDO_SUCCESS) {
548+
*reason = "Could not parse geometry block";
549+
return result;
550+
}
551+
}
552+
499553
result = initialize_thread_config(config->thread_counts, &vdo->thread_config);
500554
if (result != VDO_SUCCESS) {
501555
*reason = "Cannot create thread configuration";

0 commit comments

Comments
 (0)