101 lines
3.0 KiB
C++
101 lines
3.0 KiB
C++
// 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;
|
|
}
|