• Joe Thornber's avatar
    dm space map metadata: fix refcount decrement below 0 which caused corruption · cebc2de4
    Joe Thornber authored
    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=68801Reported-by: default avatarApollon Oikonomopoulos <apoikos@debian.org>
    Reported-by: edwillam1007@gmail.com
    Reported-by: default avatarTeng-Feng Yang <shinrairis@gmail.com>
    Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
    Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
    Cc: stable@vger.kernel.org # 3.13+
    cebc2de4
dm-space-map-metadata.c 16.5 KB