aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2014-10-17 07:38:50 -0400
committerMike Snitzer <snitzer@redhat.com>2014-10-21 09:32:15 -0400
commit40d43c4b4cac4c2647bf07110d7b07d35f399a84 (patch)
treec26181aac74dff7571e4c444c957ca8a8ccca9ae /drivers/md
parent9d28eb12447ee08bb5d1e8bb3195cf20e1ecd1c0 (diff)
dm raid: ensure superblock's size matches device's logical block size
The dm-raid superblock (struct dm_raid_superblock) is padded to 512 bytes and that size is being used to read it in from the metadata device into one preallocated page. Reading or writing this on a 512-byte sector device works fine but on a 4096-byte sector device this fails. Set the dm-raid superblock's size to the logical block size of the metadata device, because IO at that size is guaranteed too work. Also add a size check to avoid silent partial metadata loss in case the superblock should ever grow past the logical block size or PAGE_SIZE. [includes pointer math fix from Dan Carpenter] Reported-by: "Liuhua Wang" <lwang@suse.com> Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-raid.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 4857fa4a5484..a7cb9dd5f135 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -789,8 +789,7 @@ struct dm_raid_superblock {
789 __le32 layout; 789 __le32 layout;
790 __le32 stripe_sectors; 790 __le32 stripe_sectors;
791 791
792 __u8 pad[452]; /* Round struct to 512 bytes. */ 792 /* Remainder of a logical block is zero-filled when writing (see super_sync()). */
793 /* Always set to 0 when writing. */
794} __packed; 793} __packed;
795 794
796static int read_disk_sb(struct md_rdev *rdev, int size) 795static int read_disk_sb(struct md_rdev *rdev, int size)
@@ -827,7 +826,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
827 test_bit(Faulty, &(rs->dev[i].rdev.flags))) 826 test_bit(Faulty, &(rs->dev[i].rdev.flags)))
828 failed_devices |= (1ULL << i); 827 failed_devices |= (1ULL << i);
829 828
830 memset(sb, 0, sizeof(*sb)); 829 memset(sb + 1, 0, rdev->sb_size - sizeof(*sb));
831 830
832 sb->magic = cpu_to_le32(DM_RAID_MAGIC); 831 sb->magic = cpu_to_le32(DM_RAID_MAGIC);
833 sb->features = cpu_to_le32(0); /* No features yet */ 832 sb->features = cpu_to_le32(0); /* No features yet */
@@ -862,7 +861,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
862 uint64_t events_sb, events_refsb; 861 uint64_t events_sb, events_refsb;
863 862
864 rdev->sb_start = 0; 863 rdev->sb_start = 0;
865 rdev->sb_size = sizeof(*sb); 864 rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev);
865 if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) {
866 DMERR("superblock size of a logical block is no longer valid");
867 return -EINVAL;
868 }
866 869
867 ret = read_disk_sb(rdev, rdev->sb_size); 870 ret = read_disk_sb(rdev, rdev->sb_size);
868 if (ret) 871 if (ret)