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. 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. 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. * `-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. * `--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` - Разрешить уменьшение или перевод в чтение-запись образа, у которого есть клоны. * `-f|--force` - Разрешить уменьшение или перевод в чтение-запись образа, у которого есть клоны.
* `--down-ok` - Разрешить уменьшение, даже если часть данных останется неудалённой на недоступных OSD. * `--down-ok` - Разрешить уменьшение, даже если часть данных останется неудалённой на недоступных OSD.
+1
View File
@@ -216,6 +216,7 @@ const etcd_tree = {
parent_pool?: <pool_id>, parent_pool?: <pool_id>,
parent_id?: <inode_t>, parent_id?: <inode_t>,
readonly?: boolean, 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(), .size = value["size"].uint64_value(),
.parent_id = parent_inode_num, .parent_id = parent_inode_num,
.readonly = value["readonly"].bool_value(), .readonly = value["readonly"].bool_value(),
.deleted = value["deleted"].bool_value(),
.meta = value["meta"], .meta = value["meta"],
.mod_revision = kv.mod_revision, .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; new_cfg["readonly"] = true;
} }
if (cfg->deleted)
{
new_cfg["deleted"] = true;
}
if (cfg->meta.is_object()) if (cfg->meta.is_object())
{ {
new_cfg["meta"] = cfg->meta; new_cfg["meta"] = cfg->meta;
+1
View File
@@ -72,6 +72,7 @@ struct inode_config_t
uint64_t size = 0; uint64_t size = 0;
inode_t parent_id = 0; inode_t parent_id = 0;
bool readonly = false; bool readonly = false;
bool deleted = false;
// Arbitrary metadata // Arbitrary metadata
json11::Json meta; json11::Json meta;
// Change revision of the metadata in etcd // 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" " 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" " 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" " 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" " --deleted 1|0 Set/clear 'deleted image' flag (set automatically during unfinished deletes).\n"
" --down-ok Proceed with shrinking even if some data will be left on unavailable OSDs.\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" "\n"
"vitastor-cli dd [iimg=<image> | if=<file>] [oimg=<image> | of=<file>] [bs=1M]\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" " [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["delete_q"] = format_q(kv.second["delete_queue"].number_value());
} }
kv.second["size_fmt"] = format_size(kv.second["size"].uint64_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); result.text = print_table(to_list(), cols, parent->color);
state = 100; state = 100;
+9
View File
@@ -4,6 +4,7 @@
#include "cli.h" #include "cli.h"
#include "cluster_client.h" #include "cluster_client.h"
#include "str_util.h" #include "str_util.h"
#include "json_util.h"
// Rename, resize image (and purge extra data on shrink) or change its readonly status // Rename, resize image (and purge extra data on shrink) or change its readonly status
struct image_changer_t struct image_changer_t
@@ -15,6 +16,7 @@ struct image_changer_t
uint64_t new_size = 0; uint64_t new_size = 0;
bool force_size = false, inc_size = false; bool force_size = false, inc_size = false;
bool set_readonly = false, set_readwrite = false, force = false; bool set_readonly = false, set_readwrite = false, force = false;
bool set_deleted = false, new_deleted = false;
bool down_ok = false; bool down_ok = false;
// interval between fsyncs // interval between fsyncs
int fsync_interval = 128; int fsync_interval = 128;
@@ -82,6 +84,7 @@ struct image_changer_t
} }
if ((!set_readwrite || !cfg.readonly) && if ((!set_readwrite || !cfg.readonly) &&
(!set_readonly || 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_size && !force_size || cfg.size == new_size || cfg.size >= new_size && inc_size) &&
(new_name == "" || new_name == image_name)) (new_name == "" || new_name == image_name))
{ {
@@ -141,6 +144,10 @@ resume_1:
return; return;
} }
} }
if (set_deleted)
{
cfg.deleted = new_deleted;
}
if (new_name != "") if (new_name != "")
{ {
cfg.name = 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->force = cfg["force"].bool_value();
changer->set_readonly = cfg["readonly"].bool_value(); changer->set_readonly = cfg["readonly"].bool_value();
changer->set_readwrite = cfg["readwrite"].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(); changer->fsync_interval = cfg["fsync_interval"].uint64_value();
if (!changer->fsync_interval) if (!changer->fsync_interval)
changer->fsync_interval = 128; changer->fsync_interval = 128;
+58 -57
View File
@@ -95,6 +95,10 @@ struct snap_remover_t
goto resume_7; goto resume_7;
else if (state == 8) else if (state == 8)
goto resume_8; goto resume_8;
else if (state == 9)
goto resume_9;
else if (state == 10)
goto resume_10;
else if (state == 100) else if (state == 100)
goto resume_100; goto resume_100;
assert(!state); assert(!state);
@@ -129,23 +133,9 @@ resume_1:
continue; continue;
rebased_images.push_back(parent->cli->st_cli.inode_config.at(merge_children[current_child]).name); 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]); start_merge_child(merge_children[current_child], merge_children[current_child]);
if (state == 100)
return;
resume_2: resume_2:
while (!cb(result)) while (!wait_result(2))
{
state = 2;
return; 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); parent->change_parent(merge_children[current_child], new_parent, &result);
state = 3; state = 3;
resume_3: resume_3:
@@ -164,42 +154,19 @@ resume_3:
if (inverse_child != 0) if (inverse_child != 0)
{ {
start_merge_child(inverse_child, inverse_parent); start_merge_child(inverse_child, inverse_parent);
if (state == 100)
return;
resume_4: resume_4:
while (!cb(result)) while (!wait_result(4))
{
state = 4;
return; return;
} // Mark child as deleted
cb = NULL; start_mark_deleted(inverse_child);
if (result.err) resume_9:
{ while (!wait_result(9))
result.data = my_result(result.data);
state = 100;
return; return;
}
else if (parent->progress)
printf("%s\n", result.text.c_str());
// Delete "inverse" child data // Delete "inverse" child data
start_delete_source(inverse_child); start_delete_source(inverse_child);
if (state == 100)
return;
resume_5: resume_5:
while (!cb(result)) while (!wait_result(5))
{
state = 5;
return; 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, // Delete "inverse" child metadata, rename parent over it,
// and also change parent links of the previous "inverse" child // and also change parent links of the previous "inverse" child
rename_inverse_parent(); rename_inverse_parent();
@@ -221,22 +188,15 @@ resume_6:
deleted_images.push_back(parent_it->second.name); deleted_images.push_back(parent_it->second.name);
deleted_ids.push_back(chain_list[current_child]); 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]); start_delete_source(chain_list[current_child]);
resume_7: resume_7:
while (!cb(result)) while (!wait_result(7))
{
state = 7;
return; 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]); delete_inode_config(chain_list[current_child]);
if (state == 100) if (state == 100)
return; return;
@@ -256,6 +216,26 @@ resume_100:
return; 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) json11::Json my_result(json11::Json src)
{ {
auto obj = src.object_items(); 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) void start_delete_source(inode_t inode)
{ {
auto source = parent->cli->st_cli.inode_config.find(inode); auto source = parent->cli->st_cli.inode_config.find(inode);