Compare commits

..

1 Commits

Author SHA1 Message Date
90402ed55b Fix vitastor-cli ls --tree hiding layers whose parent is filtered out
ls --tree built the tree starting from the roots of the selected layers,
so a layer whose parent was left out by a glob, -p or -n was never
reached and not printed at all: ls --tree testimg printed nothing when
testimg had a parent. Show such a layer as a root; its parent is still
shown in the PARENT column.
2026-10-25 16:10:29 +03:00
6 changed files with 75 additions and 42 deletions

View File

@@ -231,8 +231,8 @@ Options:
* `--writers-stopped` allows optimised removal in case of a single 'slim' read-write
child and 'fat' removed parent: the child is merged into parent and parent is renamed
to child in that case. In other cases parent layers are always merged into children.
* `--exact` - remove multiple images with given names.
* `--matching` - remove multiple images with names matching given glob patterns.
* `--exact` - remove multiple images with names matching given glob patterns.
* `--matching` - remove multiple images with given names
* `--down-ok` - continue deletion/merging even if some data will be left on unavailable OSDs.
## flatten
@@ -287,7 +287,7 @@ Describe unclean object locations in the cluster. Options:
## fix
`vitastor-cli fix [--objects <objects>] --bad-osds <osds> [--part <part>] [--check no]`
`vitastor-cli fix [--objects <objects>] [--bad-osds <osds>] [--part <part>] [--check no]`
Fix inconsistent objects in the cluster by deleting some copies.
@@ -298,7 +298,7 @@ Fix inconsistent objects in the cluster by deleting some copies.
Plain text format: 0x<inode>:0x<stripe> <any delimiter> 0x<inode>:0x<stripe> ...
JSON format: [{"inode":"0x...","stripe":"0x..."},...]
--bad-osds <osds>
Required. Remove inconsistent copies/parts of objects from these OSDs, effectively
Remove inconsistent copies/parts of objects from these OSDs, effectively
marking them bad and allowing Vitastor to recover objects from other copies.
--part <number>
Only remove EC part <number> (from 0 to pg_size-1), required for extreme
@@ -316,17 +316,14 @@ Allocate a new OSD number and reserve it by creating empty `/osd/stats/<n>` key.
## rm-osd
`vitastor-cli rm-osd [-f|--force] [--allow-data-loss] [--allow-up] [--dry-run] <osd_id> [osd_id...]`
`vitastor-cli rm-osd [--force] [--allow-data-loss] [--dry-run] <osd_id> [osd_id...]`
Remove metadata and configuration for specified OSD(s) from etcd.
Refuses to remove OSDs that are up or whose removal makes PGs degraded, offline or incomplete.
Refuses to remove OSDs with data without `--force` and `--allow-data-loss`.
* `-f|--force` - remove OSDs even if they are up or PGs become degraded or offline.
* `--allow-data-loss` - remove OSDs even if PGs or objects become incomplete (DATA LOSS). Implies `--force`.
* `--allow-up` - remove OSDs even if they are up.
* `--dry-run` - only check if deletion is possible without data loss and
redundancy degradation.
With `--dry-run` only checks if deletion is possible without data loss and
redundancy degradation.
## osd-tree

View File

@@ -239,8 +239,8 @@ vitastor-cli dd [iimg=<image> | if=<file>] [oimg=<image> | of=<file>] [bs=1M] \
у удаляемой цепочки есть только один дочерний образ, содержащий небольшой объём данных.
В этом случае дочерний образ вливается в родительский и удаляется, а родительский
переименовывается в дочерний.
* `--exact` - удалить все образы с точно заданными именами.
* `--matching` - удалить все образы с именами, подходящими под переданные glob-шаблоны.
* `--exact` - удалить все образы с именами, подходящими под переданные glob-шаблоны.
* `--matching` - удалить все образы с точно заданными именами.
* `--down-ok` - продолжать удаление/слияние, даже если часть данных останется неудалённой на недоступных OSD.
## flatten
@@ -302,7 +302,7 @@ vitastor-cli dd [iimg=<image> | if=<file>] [oimg=<image> | of=<file>] [bs=1M] \
## fix
`vitastor-cli fix [--objects <объекты>] --bad-osds <osds> [--part <номер>] [--check no]`
`vitastor-cli fix [--objects <объекты>] [--bad-osds <osds>] [--part <номер>] [--check no]`
Исправить неконсистентные (неоднозначные) объекты путём удаления части копий.
@@ -313,9 +313,9 @@ vitastor-cli dd [iimg=<image> | if=<file>] [oimg=<image> | of=<file>] [bs=1M] \
Простой формат: 0x<инод>:0x<смещение> <любой разделитель> 0x<инод>:0x<смещение> ...
Формат JSON: [{"inode":"0x<инод>","stripe":"0x<смещение>"},...]
--bad-osds <osds>
Обязательная опция. Удалить неконсистентные копии/части объектов с данных
OSD, таким образом признавая потерю этих копий и позволяя Vitastor-у
восстановить объекты из других копий.
Удалить неконсистентные копии/части объектов с данных OSD, таким образом
признавая потерю этих копий и позволяя Vitastor-у восстановить объекты из
других копий.
--part <номер>
Удалить только части EC с заданным номером (от 0 до pg_size-1). Нужно только
в редких граничных случаях, когда один и тот же OSD содержит несколько частей
@@ -334,19 +334,14 @@ vitastor-cli dd [iimg=<image> | if=<file>] [oimg=<image> | of=<file>] [bs=1M] \
## rm-osd
`vitastor-cli rm-osd [-f|--force] [--allow-data-loss] [--allow-up] [--dry-run] <osd_id> [osd_id...]`
`vitastor-cli rm-osd [--force] [--allow-data-loss] [--dry-run] <osd_id> [osd_id...]`
Удалить метаданные и конфигурацию для заданных OSD из etcd.
Отказывается удалять работающие OSD, а также OSD, после удаления которых PG станут
деградированными, недоступными (offline) или неполными (incomplete).
Отказывается удалять OSD с данными без опций `--force` и `--allow-data-loss`.
* `-f|--force` - удалить OSD, даже если они работают или PG станут деградированными или недоступными.
* `--allow-data-loss` - удалить OSD, даже если PG или объекты станут неполными (ПОТЕРЯ ДАННЫХ).
Включает действие `--force`.
* `--allow-up` - удалить OSD, даже если они работают.
* `--dry-run` - только проверить, возможно ли удаление без потери данных и деградации
избыточности.
С опцией `--dry-run` только проверяет, возможно ли удаление без потери данных и деградации
избыточности.
## osd-tree

View File

@@ -108,8 +108,8 @@ static const char* help_text =
" --writers-stopped allows optimised removal in case of a single 'slim' read-write\n"
" child and 'fat' removed parent: the child is merged into parent and parent is renamed\n"
" to child in that case. In other cases parent layers are always merged into children.\n"
" --exact Remove multiple images with given names.\n"
" --matching Remove multiple images with names matching given glob patterns.\n"
" --exact Remove multiple images with names matching given glob patterns.\n"
" --matching Remove multiple images with given names\n"
" --writers-stopped Allow renaming inodes over their read/write children.\n"
" --down-ok Continue deletion/merging even if some data will be left on unavailable OSDs.\n"
"\n"
@@ -145,15 +145,12 @@ static const char* help_text =
" --min-offset, --max-offset\n"
" Restrict listing to specific offsets inside inodes.\n"
"\n"
"vitastor-cli raw-ls --pool_id ID (--pg_num NUM|--offset NUM) [OPTIONS]\n"
"vitastor-cli raw-ls [OPTIONS]\n"
" Find object(s) in the cluster using raw secondary listing operations. Options:\n"
" [--min_inode NUM] [--max_inode NUM] [--offset NUM] [--pg_num NUM] [--pg_count COUNT]\n"
" [--pg_stripe_size NUM] [--osds 1,2,3,...]\n"
" --pool_id (numeric pool ID) is required. --pg_num is required unless --offset is given,\n"
" in which case the PG is calculated from the offset. --pg_count, --pg_stripe_size and\n"
" --osds default to the pool configuration and are required if the pool does not exist.\n"
"\n"
"vitastor-cli fix [--objects <objects>] --bad-osds <osds> [--part <part>] [--check no]\n"
"vitastor-cli fix [--objects <objects>] [--bad-osds <osds>] [--part <part>] [--check no]\n"
" Fix inconsistent objects in the cluster by deleting some copies.\n"
" --objects <objects>\n"
" Objects to fix, either in plain text or JSON format. If not specified,\n"
@@ -161,7 +158,7 @@ static const char* help_text =
" Plain text format: 0x<inode>:0x<stripe> <any delimiter> 0x<inode>:0x<stripe> ...\n"
" JSON format: [{\"inode\":\"0x...\",\"stripe\":\"0x...\"},...]\n"
" --bad-osds <osds>\n"
" Required. Remove inconsistent copies/parts of objects from these OSDs, effectively\n"
" Remove inconsistent copies/parts of objects from these OSDs, effectively\n"
" marking them bad and allowing Vitastor to recover objects from other copies.\n"
" --part <number>\n"
" Only remove EC part <number> (from 0 to pg_size-1), required for extreme\n"
@@ -173,14 +170,11 @@ static const char* help_text =
"vitastor-cli alloc-osd\n"
" Allocate a new OSD number and reserve it by creating empty /osd/stats/<n> key.\n"
"\n"
"vitastor-cli rm-osd [-f|--force] [--allow-data-loss] [--allow-up] [--dry-run] <osd_id> [osd_id...]\n"
"vitastor-cli rm-osd [--force] [--allow-data-loss] [--dry-run] <osd_id> [osd_id...]\n"
" Remove metadata and configuration for specified OSD(s) from etcd.\n"
" Refuses to remove OSDs that are up or whose removal makes PGs degraded, offline or incomplete.\n"
" -f|--force Remove OSDs even if they are up or PGs become degraded or offline.\n"
" --allow-data-loss Remove OSDs even if PGs or objects become incomplete (DATA LOSS). Implies --force.\n"
" --allow-up Remove OSDs even if they are up.\n"
" --dry-run Only check if deletion is possible without data loss and\n"
" redundancy degradation.\n"
" Refuses to remove OSDs with data without --force and --allow-data-loss.\n"
" With --dry-run only checks if deletion is possible without data loss and\n"
" redundancy degradation.\n"
"\n"
"vitastor-cli osd-tree [-l|--long]\n"
" Show current OSD tree, optionally with I/O statistics if -l is specified.\n"

View File

@@ -250,11 +250,17 @@ resume_1:
json11::Json::array to_tree(const json11::Json::array & array)
{
std::set<uint64_t> listed;
for (const auto & item: array)
{
listed.insert(item["inode_id"].uint64_value());
}
std::map<uint64_t, json11::Json::array> children;
for (const auto & item: array)
{
uint64_t parent_id = item["parent_inode_id"].uint64_value();
children[parent_id].push_back(item);
// Layers with a filtered out parent are shown as roots
children[listed.find(parent_id) != listed.end() ? parent_id : 0].push_back(item);
}
json11::Json::array tree;
std::function<void(uint64_t, const std::string &)> add_children = [&](uint64_t parent_id, const std::string & prefix)

View File

@@ -122,6 +122,7 @@ OLD=1 ./test_corrupt_all.sh
./test_reweight_half.sh
./test_snapshot_pool2.sh
./test_ls_tree.sh
./test_snapshot_read_bitmap.sh
TEST_NAME=csum_32k_dmj OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_metadata false --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh

40
tests/test_ls_tree.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/bash -ex
# Test vitastor-cli ls --tree with filters which leave out parent layers
. `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 128M testimg
$VITASTOR_CLI snap-create testimg@snap1
$VITASTOR_CLI create --parent testimg@snap1 testclone
$VITASTOR_CLI create-pool testpool2 -s 3 -n 4 --failure_domain osd
wait_pool_up 30 2 3 4
$VITASTOR_CLI create --parent testimg@snap1 -p testpool2 testclone2
# First column of each row without the header
check_tree()
{
local expected=$1
shift
local rows=$($VITASTOR_CLI ls --tree "$@" | tail -n +2 | sed 's/ .*//' | tr '\n' ';')
if [[ "$rows" != "$expected" ]]; then
format_error "ls --tree $* shows '$rows', expected '$expected'"
fi
}
$VITASTOR_CLI ls --tree
check_tree 'testimg@snap1;├─ testclone;├─ testclone2;└─ testimg;'
check_tree 'testimg@snap1;└─ testimg;' 'testimg*'
# Layers whose parent is filtered out are shown as roots
check_tree 'testimg;' testimg
check_tree 'testclone;testimg;' testclone testimg
check_tree 'testclone;' -n 1
check_tree 'testclone2;' -p testpool2
if ! $VITASTOR_CLI ls --tree testimg | grep -q ' testimg@snap1 *$'; then
format_error "ls --tree testimg should show testimg@snap1 as the parent"
fi
format_green OK