osd: Roll back unstable writes of removed pools in the old store #106
Open
koolkhel
wants to merge 1 commits from
koolkhel/vitastor:removed-pools-v1 into master
pull from: koolkhel/vitastor:removed-pools-v1
merge into: vitalif:master
vitalif:master
vitalif:fatal-error-hook
vitalif:primary-stickiness
vitalif:libvfn
vitalif:canceling
vitalif:immediate-repeering
vitalif:rdma-close-tcp
vitalif:use-degraded-writes
vitalif:fix-write-delete-flow
vitalif:openssl-3.0.12
vitalif:openssl-capture-secrets
vitalif:ignore-small-rdma-end
vitalif:encrypt-batch
vitalif:faster-peering-calc
vitalif:http-hello
vitalif:xxh3-bench
vitalif:create-user-etcd-based
vitalif:aesxts_streaming_nosupport
vitalif:refactor-heap-continue-write
vitalif:ston3lu-patch-0127
vitalif:rdma-credits
vitalif:heap-meta
vitalif:sendmsg-zc-no-more-error
vitalif:fix-clear-refs
vitalif:veeam-trick
vitalif:test-etcd-schizo
vitalif:test
vitalif:test1
vitalif:test2
vitalif:cow-meta
vitalif:kv-readahead
vitalif:qemu-fix-crash-idea
vitalif:eventloop-auto-init-trigger
vitalif:hugo-docs
vitalif:node-mutex-and-postpone
vitalif:check-writeback
vitalif:msgr-iothreads-v2
vitalif:antietcd
vitalif:rel-1.4
vitalif:test-fix-ec-unknown-state-51
vitalif:kv-update
vitalif:kv-debug
vitalif:hotfix-1.2.0
vitalif:rdma-simple-nodp
vitalif:zerocopy-tcp-send
vitalif:csi-staging
vitalif:hotfix-1.1.0
vitalif:hotfix-1.0.0
vitalif:fsync-feedback
vitalif:cached-reads
vitalif:qemu-send-loop
vitalif:test-double-alloc
vitalif:hier-failure-domains
vitalif:mon-self-restart
vitalif:epoch-deletions
vitalif:rdma-flow-control
vitalif:csi-use-vitastor-cli
vitalif:rdma-v2
vitalif:etcd-hide-base64
vitalif:lrc-matrix
vitalif:rm-left-on-dead
vitalif:nfs-proxy-old
vitalif:non-odp-rdma
vitalif:test-zctr
vitalif:separate-data-connections
vitalif:sec_osd_msgr
vitalif:test-assert
vitalif:nbd-vmsplice
vitalif:allow-etcd-address-option
vitalif:rdma-zerocopy
vitalif:rel-0.5
vitalif:openonload
vitalif:sync-io-test
vitalif:trace-sync
vitalif:trace-sqes
vitalif:test-submit-and-wait
vitalif:test-sq-poll
vitalif:blocking-uring-test
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
No description provided.
Delete Branch "koolkhel/vitastor:removed-pools-v1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Nothing stabilizes or rolls back unstable writes of a removed pool, its PGs are never peered again. The old store can't trim its journal past them, so the journal fills up and writes to all other pools on the same OSDs fail with -EAGAIN forever, restarts don't help.
Add a synchronous
get_unstable_objects()which walksdirty_dbof the old store, and roll back unstable writes of removed pools with it. The OSD only picks up a pool when it disappears from the pool configuration, or on start when the store has unstable writes of a pool that doesn't exist, and lists the store once the pool's PGs are removed and stopped. In normal operation it does nothing: PG changes only check that the set of removed pools is empty. The new store keeps such writes in its metadata without harm, so the OSD does nothing for it (blockstore_i::is_new()).Tested:
test_blockstore_v1: newtest_get_unstable_objectsosd_test: newtest_rollback_removed_pool_on_start,test_rollback_removed_pool_online,test_rollback_removed_pool_idle(ordinary pool and PG changes don't list the store, the new store is never listed)tests/test_rm_pool_unstable.sh(old store): removes a pool with unstable writes online and while OSDs are down, then writes 4x the journal size to another pool. Without the patch it fails with "Pool removed online: writes to another pool got stuck"; with it every OSD logs "Rolled back 8 unstable object versions of removed pools" in both phases.Not covered: an OSD whose journal is already completely full can't be healed, the rollback itself needs a journal sector.
Contributor Name
Yury Luneff (MIND Software LLC, https://mindsw.io)
CLA
@@ -505,6 +505,10 @@ void osd_t::on_change_etcd_state_hook(std::map<std::string, etcd_kv_t> & changes}apply_pg_config();}if (pools || changes.find(st_cli->etcd_prefix+"/pg/config") != changes.end())тут два раза чтоб не делать pgs =, можно выше pgs = 1 раз присвоить а тут только проверять
@@ -728,6 +732,7 @@ void osd_t::on_load_pgs_hook(bool success)apply_pg_count();apply_pg_config();}rollback_removed_pools();тут делается rollback_(), а выше только check_(). как будто не совсем сбалансированно, надо по идее одно и то же триггерить, ну либо в одном месте где-то триггерить
@@ -476,0 +482,4 @@{for (auto & pc: st_cli->pool_config){if (pc.second.exists)а я чот не понял, т.е. это не срабатывает, если есть вообще хотя бы 1 живой пул? так это бессмысленно, нужно-то чтобы срабатывало для удалённых
@@ -476,0 +486,4 @@{continue;}// Wait until PGs are removed too, so that their primaries stop sending writesа тут можно сделать как-то без перебора всех PG, в конце концов этот check на каждом изменении конфигурации пулов или PG гоняется. просто как-нибудь находить одну, если есть то выходить
@@ -476,0 +506,4 @@void osd_t::rollback_removed_pools(){if (!bs)вот тут хочется, чтобы этот rollback вообще не вызывался даже, если стор новый. можно хоть даже флаг какой-то добавить, типа if !bs || !bs->is_new() -> не вызывать.
причём делать это не даже не тут на rollback(), а прям на check(), если он будет основной точкой входа.
@@ -476,0 +515,4 @@{return;}for (auto & pp: pgs)аналогично, перебирать конфигурации всех активных PG - это прям стрём, нужно как-то лёгенько по какому-нибудь std::set ID пулов (имеющих unstable версии, вероятно) проходиться, находить если любая 1 pg есть в pgs, то не трогать его пока, как-то так.
короче надо так, чтобы: при обычной работе оно вообще ничего не делало и проверка была O(1), делать начинало только а) при старте б) при изменении конфигурации пулов, когда из неё пропадает пул, а в остальное время не смотрело на изменения PG. ну и да как выше уже написал - чтоб это вообще было только для старого стора. а то стрёмно мне чтобы это не полезло роллбэкать что-то когда не надо, хочется максимально ограничить кейсы.
причём теоретически в момент когда пропадает пул, если уж мы пытаемся красиво обработать кейс, когда злобный админ грохает пул не удалив данные и не остановив клиентов (а я так понимаю это как раз кейс который ты хочешь обработать в этом ПР...), unstable-ов может быть больше, а когда уже реально пропадут PG и пулы и мы реально пойдём всё уже удалять, их будет меньше, т.е. список-то объектов перезапрашивать конечно
5ddaaaefc9toc216e4929fПеределал, запушил в ту же ветку.
check_removed_pools()вызывается при загрузке PG (старт или перезагрузка из etcd) и при изменении/config/pools. Первой строкой тамif (!bs || bs->is_new()) return;,is_new()добавил вblockstore_i(true в новом сторе). Для нового стора не вызывается вообще ничего, в том числеget_unstable_objects().std::set<pool_id_t> rm_pools: удалённые пулы, по которым ещё надо откатить. Обычно он пустой, и измененияpg/configи остановка PG проверяют только его:rm_pools.size()в хуке иrm_pools.find(pg.pool_id)вfinish_stop_pg. Перебора всех PG больше нет./config/poolsпрохожуpool_config(пулы, не PG) и сравниваю с набором пулов, которые были в конфиге раньше. Тот, который был и пропал, попадает вrm_pools. На старте вrm_poolsпопадают несуществующие пулы из списка unstable-объектов стора: пул могли удалить, пока OSD лежал.rm_poolsсмотрю только его PG:pgs.lower_bound({ pool_id, 0 })до первой не-OFFLINE и егоpg_configдо первой сconfig_exists. Если что-то есть, пул остаётся вrm_poolsдо следующего измененияpg/configили остановки его PG.pgsв хуке теперь вычисляется один раз.rm_poolsбез отката.Про
osd_flush.cpp:485: там былcontinueдля существующих пулов, а не выход, то есть срабатывало для любого удалённого пула, у которого уже не было PG. Но этого кода теперь нет.Тесты:
osd_test(test_rollback_removed_pool_on_start,_online, и новый_idle: при обычных изменениях пулов и PG стор не листится, а для нового стора не листится вообще),test_blockstore_v1,OLD=1 tests/test_rm_pool_unstable.sh(все OSD пишут "Rolled back 8 …" в обеих фазах). Ветка перебазирована на текущий master.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.