Implement "deleted" flag
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ vitastor-cli snap-create [-p|--pool <id|name>] <image>@<snapshot>
|
||||
Если новый размер меньше старого, "лишние" данные будут удалены, поэтому перед уменьшением
|
||||
образа сначала уменьшите файловую систему в нём.
|
||||
|
||||
* `--deleted 1|0` - Установить/снять флаг "образ удалён" (устанавливается при незавершённом удалении).
|
||||
* `-f|--force` - Разрешить уменьшение или перевод в чтение-запись образа, у которого есть клоны.
|
||||
* `--down-ok` - Разрешить уменьшение, даже если часть данных останется неудалённой на недоступных OSD.
|
||||
|
||||
|
||||
@@ -216,6 +216,7 @@ const etcd_tree = {
|
||||
parent_pool?: <pool_id>,
|
||||
parent_id?: <inode_t>,
|
||||
readonly?: boolean,
|
||||
deleted?: boolean,
|
||||
}
|
||||
}
|
||||
}, */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user