Commit 7bf9ed7e78a3bd0b6179f13cd4d533b3e3f38ed9

Authored by Joe Thornber
Committed by Greg Kroah-Hartman
1 parent 7536e0dce3

dm cache: share cache-metadata object across inactive and active DM tables

commit 9b1cc9f251affdd27f29fe46d0989ba76c33faf6 upstream.

If a DM table is reloaded with an inactive table when the device is not
suspended (normal procedure for LVM2), then there will be two dm-bufio
objects that can diverge.  This can lead to a situation where the
inactive table uses bufio to read metadata at the same time the active
table writes metadata -- resulting in the inactive table having stale
metadata buffers once it is promoted to the active table slot.

Fix this by using reference counting and a global list of cache metadata
objects to ensure there is only one metadata object per metadata device.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 95 additions and 6 deletions Side-by-side Diff

drivers/md/dm-cache-metadata.c
... ... @@ -94,6 +94,9 @@
94 94 } __packed;
95 95  
96 96 struct dm_cache_metadata {
  97 + atomic_t ref_count;
  98 + struct list_head list;
  99 +
97 100 struct block_device *bdev;
98 101 struct dm_block_manager *bm;
99 102 struct dm_space_map *metadata_sm;
... ... @@ -669,10 +672,10 @@
669 672  
670 673 /*----------------------------------------------------------------*/
671 674  
672   -struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
673   - sector_t data_block_size,
674   - bool may_format_device,
675   - size_t policy_hint_size)
  675 +static struct dm_cache_metadata *metadata_open(struct block_device *bdev,
  676 + sector_t data_block_size,
  677 + bool may_format_device,
  678 + size_t policy_hint_size)
676 679 {
677 680 int r;
678 681 struct dm_cache_metadata *cmd;
... ... @@ -683,6 +686,7 @@
683 686 return NULL;
684 687 }
685 688  
  689 + atomic_set(&cmd->ref_count, 1);
686 690 init_rwsem(&cmd->root_lock);
687 691 cmd->bdev = bdev;
688 692 cmd->data_block_size = data_block_size;
689 693  
... ... @@ -705,10 +709,95 @@
705 709 return cmd;
706 710 }
707 711  
  712 +/*
  713 + * We keep a little list of ref counted metadata objects to prevent two
  714 + * different target instances creating separate bufio instances. This is
  715 + * an issue if a table is reloaded before the suspend.
  716 + */
  717 +static DEFINE_MUTEX(table_lock);
  718 +static LIST_HEAD(table);
  719 +
  720 +static struct dm_cache_metadata *lookup(struct block_device *bdev)
  721 +{
  722 + struct dm_cache_metadata *cmd;
  723 +
  724 + list_for_each_entry(cmd, &table, list)
  725 + if (cmd->bdev == bdev) {
  726 + atomic_inc(&cmd->ref_count);
  727 + return cmd;
  728 + }
  729 +
  730 + return NULL;
  731 +}
  732 +
  733 +static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev,
  734 + sector_t data_block_size,
  735 + bool may_format_device,
  736 + size_t policy_hint_size)
  737 +{
  738 + struct dm_cache_metadata *cmd, *cmd2;
  739 +
  740 + mutex_lock(&table_lock);
  741 + cmd = lookup(bdev);
  742 + mutex_unlock(&table_lock);
  743 +
  744 + if (cmd)
  745 + return cmd;
  746 +
  747 + cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size);
  748 + if (cmd) {
  749 + mutex_lock(&table_lock);
  750 + cmd2 = lookup(bdev);
  751 + if (cmd2) {
  752 + mutex_unlock(&table_lock);
  753 + __destroy_persistent_data_objects(cmd);
  754 + kfree(cmd);
  755 + return cmd2;
  756 + }
  757 + list_add(&cmd->list, &table);
  758 + mutex_unlock(&table_lock);
  759 + }
  760 +
  761 + return cmd;
  762 +}
  763 +
  764 +static bool same_params(struct dm_cache_metadata *cmd, sector_t data_block_size)
  765 +{
  766 + if (cmd->data_block_size != data_block_size) {
  767 + DMERR("data_block_size (%llu) different from that in metadata (%llu)\n",
  768 + (unsigned long long) data_block_size,
  769 + (unsigned long long) cmd->data_block_size);
  770 + return false;
  771 + }
  772 +
  773 + return true;
  774 +}
  775 +
  776 +struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
  777 + sector_t data_block_size,
  778 + bool may_format_device,
  779 + size_t policy_hint_size)
  780 +{
  781 + struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size,
  782 + may_format_device, policy_hint_size);
  783 + if (cmd && !same_params(cmd, data_block_size)) {
  784 + dm_cache_metadata_close(cmd);
  785 + return NULL;
  786 + }
  787 +
  788 + return cmd;
  789 +}
  790 +
708 791 void dm_cache_metadata_close(struct dm_cache_metadata *cmd)
709 792 {
710   - __destroy_persistent_data_objects(cmd);
711   - kfree(cmd);
  793 + if (atomic_dec_and_test(&cmd->ref_count)) {
  794 + mutex_lock(&table_lock);
  795 + list_del(&cmd->list);
  796 + mutex_unlock(&table_lock);
  797 +
  798 + __destroy_persistent_data_objects(cmd);
  799 + kfree(cmd);
  800 + }
712 801 }
713 802  
714 803 /*