cebc2de44d
This has been a relatively long-standing issue that wasn't nailed down
until Teng-Feng Yang's meticulous bug report to dm-devel on 3/7/2014,
see: http://www.redhat.com/archives/dm-devel/2014-March/msg00021.html
From that report:
"When decreasing the reference count of a metadata block with its
reference count equals 3, we will call dm_btree_remove() to remove
this enrty from the B+tree which keeps the reference count info in
metadata device.
The B+tree will try to rebalance the entry of the child nodes in each
node it traversed, and the rebalance process contains the following
steps.
(1) Finding the corresponding children in current node (shadow_current(s))
(2) Shadow the children block (issue BOP_INC)
(3) redistribute keys among children, and free children if necessary (issue BOP_DEC)
Since the update of a metadata block's reference count could be
recursive, we will stash these reference count update operations in
smm->uncommitted and then process them in a FILO fashion.
The problem is that step(3) could free the children which is created
in step(2), so the BOP_DEC issued in step(3) will be carried out
before the BOP_INC issued in step(2) since these BOPs will be
processed in FILO fashion. Once the BOP_DEC from step(3) tries to
decrease the reference count of newly shadow block, it will report
failure for its reference equals 0 before decreasing. It looks like we
can solve this issue by processing these BOPs in a FIFO fashion
instead of FILO."
Commit
|
||
---|---|---|
.. | ||
dm-array.c | ||
dm-array.h | ||
dm-bitset.c | ||
dm-bitset.h | ||
dm-block-manager.c | ||
dm-block-manager.h | ||
dm-btree-internal.h | ||
dm-btree-remove.c | ||
dm-btree-spine.c | ||
dm-btree.c | ||
dm-btree.h | ||
dm-persistent-data-internal.h | ||
dm-space-map-common.c | ||
dm-space-map-common.h | ||
dm-space-map-disk.c | ||
dm-space-map-disk.h | ||
dm-space-map-metadata.c | ||
dm-space-map-metadata.h | ||
dm-space-map.h | ||
dm-transaction-manager.c | ||
dm-transaction-manager.h | ||
Kconfig | ||
Makefile |