Implement "deleted" flag

This commit is contained in:
Vitaliy Filippov
2024-12-27 01:18:55 +03:00
parent 651c055bd9
commit 0b0c2afbce
9 changed files with 81 additions and 60 deletions
+1
View File
@@ -146,6 +146,7 @@ Rename, resize image or change its readonly status. Images with children can't b
If the new size is smaller than the old size, extra data will be purged.
You should resize file system in the image, if present, before shrinking it.
* `--deleted 1|0` - Set/clear 'deleted image' flag (set automatically during unfinished deletes).
* `-f|--force` - Proceed with shrinking or setting readwrite flag even if the image has children.
* `--down-ok` - Proceed with shrinking even if some data will be left on unavailable OSDs.
+1
View File
@@ -149,6 +149,7 @@ vitastor-cli snap-create [-p|--pool <id|name>] <image>@<snapshot>
Если новый размер меньше старого, "лишние" данные будут удалены, поэтому перед уменьшением
образа сначала уменьшите файловую систему в нём.
* `--deleted 1|0` - Установить/снять флаг "образ удалён" (устанавливается при незавершённом удалении).
* `-f|--force` - Разрешить уменьшение или перевод в чтение-запись образа, у которого есть клоны.
* `--down-ok` - Разрешить уменьшение, даже если часть данных останется неудалённой на недоступных OSD.
+1
View File
@@ -216,6 +216,7 @@ const etcd_tree = {
parent_pool?: <pool_id>,
parent_id?: <inode_t>,
readonly?: boolean,
deleted?: boolean,
}
}
}, */
+5
View File
@@ -1217,6 +1217,7 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
.size = value["size"].uint64_value(),
.parent_id = parent_inode_num,
.readonly = value["readonly"].bool_value(),
.deleted = value["deleted"].bool_value(),
.meta = value["meta"],
.mod_revision = kv.mod_revision,
});
@@ -1305,6 +1306,10 @@ json11::Json::object etcd_state_client_t::serialize_inode_cfg(inode_config_t *cf
{
new_cfg["readonly"] = true;
}
if (cfg->deleted)
{
new_cfg["deleted"] = true;
}
if (cfg->meta.is_object())
{
new_cfg["meta"] = cfg->meta;
+1
View File
@@ -72,6 +72,7 @@ struct inode_config_t
uint64_t size = 0;
inode_t parent_id = 0;
bool readonly = false;
bool deleted = false;
// Arbitrary metadata
json11::Json meta;
// Change revision of the metadata in etcd
+3 -2
View File
@@ -51,8 +51,9 @@ static const char* help_text =
" Rename, resize image or change its readonly status. Images with children can't be made read-write.\n"
" If the new size is smaller than the old size, extra data will be purged.\n"
" You should resize file system in the image, if present, before shrinking it.\n"
" -f|--force Proceed with shrinking or setting readwrite flag even if the image has children.\n"
" --down-ok Proceed with shrinking even if some data will be left on unavailable OSDs.\n"
" --deleted 1|0 Set/clear 'deleted image' flag (set automatically during unfinished deletes).\n"
" -f|--force Proceed with shrinking or setting readwrite flag even if the image has children.\n"
" --down-ok Proceed with shrinking even if some data will be left on unavailable OSDs.\n"
"\n"
"vitastor-cli dd [iimg=<image> | if=<file>] [oimg=<image> | of=<file>] [bs=1M]\n"
" [count=N] [seek/oseek=N] [skip/iseek=M] [iodepth=N] [status=progress]\n"
+2 -1
View File
@@ -371,7 +371,8 @@ resume_1:
kv.second["delete_q"] = format_q(kv.second["delete_queue"].number_value());
}
kv.second["size_fmt"] = format_size(kv.second["size"].uint64_value());
kv.second["ro"] = kv.second["readonly"].bool_value() ? "RO" : "-";
kv.second["ro"] = kv.second["deleted"].bool_value() ? "DEL" :
(kv.second["readonly"].bool_value() ? "RO" : "-");
}
result.text = print_table(to_list(), cols, parent->color);
state = 100;
+9
View File
@@ -4,6 +4,7 @@
#include "cli.h"
#include "cluster_client.h"
#include "str_util.h"
#include "json_util.h"
// Rename, resize image (and purge extra data on shrink) or change its readonly status
struct image_changer_t
@@ -15,6 +16,7 @@ struct image_changer_t
uint64_t new_size = 0;
bool force_size = false, inc_size = false;
bool set_readonly = false, set_readwrite = false, force = false;
bool set_deleted = false, new_deleted = false;
bool down_ok = false;
// interval between fsyncs
int fsync_interval = 128;
@@ -82,6 +84,7 @@ struct image_changer_t
}
if ((!set_readwrite || !cfg.readonly) &&
(!set_readonly || cfg.readonly) &&
(!set_deleted || cfg.deleted == new_deleted) &&
(!new_size && !force_size || cfg.size == new_size || cfg.size >= new_size && inc_size) &&
(new_name == "" || new_name == image_name))
{
@@ -141,6 +144,10 @@ resume_1:
return;
}
}
if (set_deleted)
{
cfg.deleted = new_deleted;
}
if (new_name != "")
{
cfg.name = new_name;
@@ -251,6 +258,8 @@ std::function<bool(cli_result_t &)> cli_tool_t::start_modify(json11::Json cfg)
changer->force = cfg["force"].bool_value();
changer->set_readonly = cfg["readonly"].bool_value();
changer->set_readwrite = cfg["readwrite"].bool_value();
changer->set_deleted = !cfg["deleted"].is_null();
changer->new_deleted = json_is_true(cfg["deleted"]);
changer->fsync_interval = cfg["fsync_interval"].uint64_value();
if (!changer->fsync_interval)
changer->fsync_interval = 128;
+58 -57
View File
@@ -95,6 +95,10 @@ struct snap_remover_t
goto resume_7;
else if (state == 8)
goto resume_8;
else if (state == 9)
goto resume_9;
else if (state == 10)
goto resume_10;
else if (state == 100)
goto resume_100;
assert(!state);
@@ -129,23 +133,9 @@ resume_1:
continue;
rebased_images.push_back(parent->cli->st_cli.inode_config.at(merge_children[current_child]).name);
start_merge_child(merge_children[current_child], merge_children[current_child]);
if (state == 100)
return;
resume_2:
while (!cb(result))
{
state = 2;
while (!wait_result(2))
return;
}
cb = NULL;
if (result.err)
{
result.data = my_result(result.data);
state = 100;
return;
}
else if (parent->progress)
printf("%s\n", result.text.c_str());
parent->change_parent(merge_children[current_child], new_parent, &result);
state = 3;
resume_3:
@@ -164,42 +154,19 @@ resume_3:
if (inverse_child != 0)
{
start_merge_child(inverse_child, inverse_parent);
if (state == 100)
return;
resume_4:
while (!cb(result))
{
state = 4;
while (!wait_result(4))
return;
}
cb = NULL;
if (result.err)
{
result.data = my_result(result.data);
state = 100;
// Mark child as deleted
start_mark_deleted(inverse_child);
resume_9:
while (!wait_result(9))
return;
}
else if (parent->progress)
printf("%s\n", result.text.c_str());
// Delete "inverse" child data
start_delete_source(inverse_child);
if (state == 100)
return;
resume_5:
while (!cb(result))
{
state = 5;
while (!wait_result(5))
return;
}
cb = NULL;
if (result.err)
{
result.data = my_result(result.data);
state = 100;
return;
}
else if (parent->progress)
printf("%s\n", result.text.c_str());
// Delete "inverse" child metadata, rename parent over it,
// and also change parent links of the previous "inverse" child
rename_inverse_parent();
@@ -221,22 +188,15 @@ resume_6:
deleted_images.push_back(parent_it->second.name);
deleted_ids.push_back(chain_list[current_child]);
}
// Mark child as deleted
start_mark_deleted(chain_list[current_child]);
resume_10:
while (!wait_result(10))
return;
start_delete_source(chain_list[current_child]);
resume_7:
while (!cb(result))
{
state = 7;
while (!wait_result(7))
return;
}
cb = NULL;
if (result.err)
{
result.data = my_result(result.data);
state = 100;
return;
}
else if (parent->progress)
printf("%s\n", result.text.c_str());
delete_inode_config(chain_list[current_child]);
if (state == 100)
return;
@@ -256,6 +216,26 @@ resume_100:
return;
}
bool wait_result(int base_state)
{
if (state == 100 || !cb)
return true;
while (!cb(result))
{
state = base_state;
return false;
}
cb = NULL;
if (result.err)
{
result.data = my_result(result.data);
state = 100;
}
else if (parent->progress)
printf("%s\n", result.text.c_str());
return true;
}
json11::Json my_result(json11::Json src)
{
auto obj = src.object_items();
@@ -667,6 +647,27 @@ resume_100:
});
}
void start_mark_deleted(inode_t inode)
{
auto ino_it = parent->cli->st_cli.inode_config.find(inode);
if (ino_it == parent->cli->st_cli.inode_config.end())
{
char buf[1024];
snprintf(buf, 1024, "Inode 0x%jx disappeared", inode);
result = (cli_result_t){ .err = EIO, .text = std::string(buf) };
state = 100;
return;
}
if (ino_it->second.deleted)
{
return;
}
cb = parent->start_modify(json11::Json::object {
{ "image", ino_it->second.name },
{ "deleted", true },
});
}
void start_delete_source(inode_t inode)
{
auto source = parent->cli->st_cli.inode_config.find(inode);