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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, */
|
}, */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user