// Copyright (c) Vitaliy Filippov, 2019+ // License: VNPL-1.1 (see README.md for details) #include "disk_tool.h" #include "str_util.h" #include "json_util.h" int disk_tool_t::trim_data(std::string device) { int r; // Parse parameters if (stoull_full(device)) device = "/dev/vitastor/osd"+device+"-data"; json11::Json sb = read_osd_superblock(device, true, false); if (sb.is_null()) return 1; auto sb_params = json_to_string_map(sb["params"].object_items()); if (options["discard_granularity"] != "") sb_params["discard_granularity"] = options["discard_granularity"]; if (options["min_discard_size"] != "") sb_params["min_discard_size"] = options["min_discard_size"]; try { dsk.parse_config(sb_params); } catch (std::exception & e) { fprintf(stderr, "Error: %s\n", e.what()); return 1; } if (!dsk.discard_granularity && sb["real_data_device"].string_value().substr(0, 5) == "/dev/") { auto dg = read_file("/sys/block/"+sb["real_data_device"].string_value().substr(5)+"/queue/discard_granularity", true); if (dg != "") dsk.discard_granularity = parse_size(trim(dg)); } // Open devices try { if (options["io"] != "") dsk.data_io = dsk.meta_io = dsk.journal_io = options["io"]; dsk.open_data(); dsk.open_meta(); dsk.open_journal(); dsk.calc_lengths(); } catch (std::exception & e) { dsk.close_all(); fprintf(stderr, "Error: %s\n", e.what()); return 1; } // Fill allocator fprintf(stderr, "Reading metadata\n"); data_alloc = new allocator_t(dsk.block_count); r = process_meta( [](blockstore_meta_header_v3_t *hdr) {}, [this](blockstore_heap_t *heap, heap_entry_t *obj, uint32_t meta_block_num) { for (auto wr = obj; wr; wr = heap->prev(wr)) { if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE || (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_INTENT) { data_alloc->set(wr->big_location(heap) / dsk.data_block_size, true); } } }, [this](uint64_t block_num, clean_disk_entry *entry, uint8_t *bitmap) { data_alloc->set(block_num, true); }, false, false ); if (r != 0) { dsk.close_all(); return r; } fprintf(stderr, "Reading journal\n"); r = process_journal([this](void *buf) { return process_journal_block(buf, [this](int num, journal_entry *je) { if (je->type == JE_BIG_WRITE || je->type == JE_BIG_WRITE_INSTANT) { data_alloc->set(je->big_write.location / dsk.data_block_size, true); } }); }, false); if (r != 0) { dsk.close_all(); return r; } // Trim r = dsk.trim_data([&](uint64_t block_num) { return data_alloc->get(block_num); }); dsk.close_all(); return r == 0; }