// Copyright (c) Vitaliy Filippov, 2019+ // License: VNPL-1.1 (see README.md for details) #pragma once #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #include #include #include #include #include #include "json11/json11.hpp" #include "blockstore_disk.h" #include "blockstore.h" #include "blockstore_heap.h" #include "ondisk_formats.h" #include "crc32c.h" #include "allocator.h" // vITADisk #define VITASTOR_DISK_MAGIC 0x6b73694441544976 #define VITASTOR_DISK_MAX_SB_SIZE 128*1024 #define VITASTOR_PART_TYPE "e7009fac-a5a1-4d72-af72-53de13059903" #define DEFAULT_HYBRID_JOURNAL "1G" #define DEFAULT_HYBRID_SSD_JOURNAL "128M" #define VITASTOR_META_FORMAT_NAME_V1 "0.6" #define VITASTOR_META_FORMAT_NAME_V2 "0.9" #define VITASTOR_META_FORMAT_NAME_HEAP "3.0" struct resizer_data_moving_t; struct vitastor_dev_info_t { std::string path; bool is_hdd; json11::Json pt; // pt = partition table int osd_part_count; uint64_t size; uint64_t free; }; struct disk_tool_t { /**** Parameters ****/ std::map options; bool test_mode = false; bool all = false, json = false, now = false; bool dump_with_blocks = false, dump_with_data = false; bool dump_as_old = false; bool skip_obsolete = false; int log_level = 1; double meta_reserve_multiple = 2; uint64_t meta_reserve_min_size = (uint64_t)1024*1024*1024; blockstore_disk_t dsk; // resize data and/or move metadata and journal int iodepth; std::string new_meta_device, new_journal_device; uint64_t new_data_offset = 0, new_data_len = 0; uint64_t new_journal_offset = 0, new_journal_len = 0; uint64_t new_meta_offset = 0, new_meta_len = 0; /**** State ****/ uint64_t journal_pos = 0, journal_calc_data_pos = 0; uint8_t *buffer_area = NULL; bool first_block, first_entry; allocator_t *data_alloc = NULL; std::map data_remap; std::map::iterator remap_it; ring_loop_t *ringloop = NULL; ring_consumer_t ring_consumer; int remap_active = 0; journal_entry_start je_start; uint8_t *new_journal_buf = NULL, *new_meta_buf = NULL, *new_journal_ptr = NULL, *new_journal_data = NULL; blockstore_meta_header_v3_t *new_meta_hdr = NULL; uint64_t new_journal_in_pos = 0; int64_t data_idx_diff = 0; uint64_t total_blocks = 0, free_first = 0, free_last = 0; uint64_t new_clean_entry_bitmap_size = 0, new_data_csum_size = 0, new_clean_entry_size = 0, new_entries_per_block = 0; uint32_t new_meta_format = 0; int new_journal_fd = -1, new_meta_fd = -1; resizer_data_moving_t *moving_blocks = NULL; bool atomic_warned = false; bool started = false; void *small_write_data = NULL; uint32_t data_crc32 = 0; bool data_csum_valid = false; uint32_t crc32_last = 0; uint32_t new_crc32_prev = 0; ~disk_tool_t(); int dump_journal(); void dump_journal_entry(int num, journal_entry *je, bool json); int process_journal(std::function block_fn, bool do_open = true); int process_journal_block(void *buf, std::function iter_fn); int process_meta(std::function hdr_fn, std::function obj_fn, std::function record_fn, bool with_data, bool do_open); int dump_meta(); void dump_meta_header(blockstore_meta_header_v3_t *hdr); void dump_meta_entry(uint64_t block_num, clean_disk_entry *entry, uint8_t *bitmap); void dump_heap_entry_as_old(blockstore_heap_t *heap, heap_entry_t *obj); void dump_heap_entry(blockstore_heap_t *heap, heap_entry_t *obj); int dump_load_check_superblock(const std::string & device); int write_json_journal(json11::Json entries); int write_json_meta(json11::Json meta); int write_json_heap(json11::Json meta, json11::Json journal); int index_journal_by_object(json11::Json journal, std::map> & journal_by_object); int resize_data(std::string device); int resize_parse_move_journal(std::map & move_options, bool dry_run); int resize_parse_move_meta(std::map & move_options, bool dry_run); int raw_resize(); int resize_parse_params(); void resize_init(blockstore_meta_header_v3_t *hdr); int resize_remap_blocks(); int resize_copy_data(); void resize_alloc_journal(); void build_journal_start(); void choose_journal_block(uint32_t je_size); int resize_rebuild_journal(); int resize_write_new_journal(); void remap_big_write(heap_entry_t *wr); void remap_small_write(heap_entry_t *wr); void fill_old_clean_entry(blockstore_heap_t *heap, heap_entry_t *big_wr); void fill_old_journal_entry(blockstore_heap_t *heap, heap_entry_t *wr); int resize_rebuild_meta(); int resize_write_new_meta(); void free_new_meta(); int udev_import(std::string device); int read_sb(std::string device); int write_sb(std::string device); int update_sb(std::string device); int exec_osd(std::string device); int systemd_start_stop_osds(const std::vector & cmd, const std::vector & devices); int pre_exec_osd(std::string device); int purge_devices(const std::vector & devices); int clear_osd_superblock(const std::string & dev); int trim_data(std::string device); json11::Json read_osd_superblock(std::string device, bool expect_exist = true, bool ignore_nonref = false); uint32_t write_osd_superblock(std::string device, json11::Json params); void parse_meta_reserve(); int prepare_one(std::map options, int is_hdd, json11::Json::object & result); int check_existing_partition(std::string & dev_by_uuid); int fix_partition_type(std::string & dev_by_uuid); int prepare(std::vector devices); std::vector collect_devices(const std::vector & devices); json11::Json add_partitions(vitastor_dev_info_t & devinfo, std::vector sizes); std::vector get_new_data_parts(vitastor_dev_info_t & dev, uint64_t osd_per_disk, uint64_t max_other_percent, uint64_t *check_new_count); int get_meta_partition(std::vector & ssds, std::map & options); int upgrade_simple_unit(std::string unit); }; void disk_tool_simple_offsets(json11::Json cfg, bool json_output); uint64_t sscanf_json(const char *fmt, const json11::Json & str); void fromhexstr(const std::string & from, int bytes, uint8_t *to); int disable_cache(const std::string & dev); uint64_t get_atomic_write_size(const std::string & dev); uint64_t get_device_size(const std::string & dev, bool should_exist = false); std::string get_parent_device(std::string dev); int shell_exec(const std::vector & cmd, const std::string & in, std::string *out, std::string *err); int write_zero(int fd, uint64_t offset, uint64_t size); json11::Json read_parttable(std::string dev); uint64_t dev_size_from_parttable(json11::Json pt); uint64_t free_from_parttable(json11::Json pt); int fix_partition_type_uuid(std::string & dev_by_uuid, const std::string & type_uuid); std::string csum_type_str(uint32_t data_csum_type); uint32_t csum_type_from_str(std::string data_csum_type);