From: Joe Thornber dm transaction manager: stop using dm_bm_unlock_move when shadowing blocks Optimisation. Some code, such as the space maps, keep using on disk data structures from the previous transaction. They can do this because blocks wont be reallocated until the subsequent transaction. Using dm_bm_unlock_move to copy blocks sounds like a win, but it forces a synchronous read should the old block be accessed. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer --- drivers/md/persistent-data/dm-transaction-manager.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) Index: linux-3.5-rc7/drivers/md/persistent-data/dm-transaction-manager.c =================================================================== --- linux-3.5-rc7.orig/drivers/md/persistent-data/dm-transaction-manager.c +++ linux-3.5-rc7/drivers/md/persistent-data/dm-transaction-manager.c @@ -219,13 +219,24 @@ static int __shadow_block(struct dm_tran if (r < 0) return r; - r = dm_bm_unlock_move(orig_block, new); - if (r < 0) { + /* + * It would be tempting to use dm_bm_unlock_move here. But some + * code, such as the space maps, keep using the old data structures + * - secure in the knowledge they wont be changed until the next + * transaction. Using unlock_move would force a synchronous read + * since the old block would no longer be in the cache. + */ + r = dm_bm_write_lock_zero(tm->bm, new, v, result); + if (r) { dm_bm_unlock(orig_block); return r; } - return dm_bm_write_lock(tm->bm, new, v, result); + memcpy(dm_block_data(*result), dm_block_data(orig_block), + dm_bm_block_size(tm->bm)); + + dm_bm_unlock(orig_block); + return r; } int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,