Commit 83707237 authored by Artem Bityutskiy's avatar Artem Bityutskiy

UBIFS: fix clean znode counter corruption in error cases

UBIFS maintains per-filesystem and global clean znode counters
('c->clean_zn_cnt' and 'ubifs_clean_zn_cnt'). It is important to maintain
correct values there since the shrinker relies on 'ubifs_clean_zn_cnt'.

However, in case of failures during commit the counters were corrupted. E.g.,
if a failure happens in the middle of 'write_index()', then some nodes in the
commit list ('c->cnext') are marked as clean, and some are marked as dirty. And
the 'ubifs_destroy_tnc_subtree()' frees does not retrun correct count, and we
end up with non-zero 'c->clean_zn_cnt' when unmounting. This means that if we
have 2 file-sytem and one of them fails, and we unmount it,
'ubifs_clean_zn_cnt' stays incorrect and confuses the shrinker.
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 812eb258
...@@ -2876,12 +2876,13 @@ static void tnc_destroy_cnext(struct ubifs_info *c) ...@@ -2876,12 +2876,13 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
*/ */
void ubifs_tnc_close(struct ubifs_info *c) void ubifs_tnc_close(struct ubifs_info *c)
{ {
long clean_freed;
tnc_destroy_cnext(c); tnc_destroy_cnext(c);
if (c->zroot.znode) { if (c->zroot.znode) {
clean_freed = ubifs_destroy_tnc_subtree(c->zroot.znode); long n;
atomic_long_sub(clean_freed, &ubifs_clean_zn_cnt);
ubifs_destroy_tnc_subtree(c->zroot.znode);
n = atomic_long_read(&c->clean_zn_cnt);
atomic_long_sub(n, &ubifs_clean_zn_cnt);
} }
kfree(c->gap_lebs); kfree(c->gap_lebs);
kfree(c->ilebs); kfree(c->ilebs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment