linux/drivers/md/persistent-data
Joe Thornber cebc2de44d dm space map metadata: fix refcount decrement below 0 which caused corruption
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 5b564d80 ("dm space map: disallow decrementing a reference count
below zero") changed the code to report an error for this temporary
refcount decrement below zero.  So what was previously a harmless
invalid refcount became a hard failure due to the new error path:

 device-mapper: space map common: unable to decrement a reference count below 0
 device-mapper: thin: 253:6: dm_thin_insert_block() failed: error = -22
 device-mapper: thin: 253:6: switching pool to read-only mode

This bug is in dm persistent-data code that is common to the DM thin and
cache targets.  So any users of those targets should apply this fix.

Fix this by applying recursive space map operations in FIFO order rather
than FILO.

Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=68801

Reported-by: Apollon Oikonomopoulos <apoikos@debian.org>
Reported-by: edwillam1007@gmail.com
Reported-by: Teng-Feng Yang <shinrairis@gmail.com>
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org # 3.13+
2014-03-07 12:02:47 -05:00
..
dm-array.c dm array: fix a reference counting bug in shadow_ablock 2013-12-13 14:22:10 -05:00
dm-array.h dm persistent data: add transactional array 2013-03-01 22:45:51 +00:00
dm-bitset.c dm persistent data: add bitset 2013-03-01 22:45:51 +00:00
dm-bitset.h dm persistent data: add bitset 2013-03-01 22:45:51 +00:00
dm-block-manager.c dm persistent data: cleanup dm-thin specific references in text 2014-01-07 10:11:54 -05:00
dm-block-manager.h dm thin: allow pool in read-only mode to transition to read-write mode 2013-12-10 16:35:13 -05:00
dm-btree-internal.h dm persistent data: add btree_walk 2013-03-01 22:45:50 +00:00
dm-btree-remove.c dm thin: fix discard corruption 2013-03-20 17:21:24 +00:00
dm-btree-spine.c dm persistent data: add btree_walk 2013-03-01 22:45:50 +00:00
dm-btree.c dm btree: add dm_btree_find_lowest_key 2014-01-09 16:29:17 -05:00
dm-btree.h dm btree: add dm_btree_find_lowest_key 2014-01-09 16:29:17 -05:00
dm-persistent-data-internal.h
dm-space-map-common.c dm space map common: make sure new space is used during extend 2014-01-07 21:05:17 -05:00
dm-space-map-common.h dm persistent data: only commit space map if index changed 2012-07-27 15:08:06 +01:00
dm-space-map-disk.c dm space map disk: optimise sm_disk_dec_block 2013-11-09 18:20:24 -05:00
dm-space-map-disk.h
dm-space-map-metadata.c dm space map metadata: fix refcount decrement below 0 which caused corruption 2014-03-07 12:02:47 -05:00
dm-space-map-metadata.h dm thin: allow metadata space larger than supported to go unused 2014-02-27 11:49:08 -05:00
dm-space-map.h dm persistent data: add threshold callback to space map 2013-05-10 14:37:20 +01:00
dm-transaction-manager.c hlist: drop the node parameter from iterators 2013-02-27 19:10:24 -08:00
dm-transaction-manager.h dm persistent data: tidy transaction manager creation fns 2012-07-27 15:08:09 +01:00
Kconfig dm: fix Kconfig indentation 2014-03-03 17:31:07 -05:00
Makefile dm persistent data: add bitset 2013-03-01 22:45:51 +00:00