mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
dm raid: ensure superblock's size matches device's logical block size
commit 40d43c4b4c upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
fe30b804a2
commit
513f8da83b
|
|
@ -785,8 +785,7 @@ struct dm_raid_superblock {
|
|||
__le32 layout;
|
||||
__le32 stripe_sectors;
|
||||
|
||||
__u8 pad[452]; /* Round struct to 512 bytes. */
|
||||
/* Always set to 0 when writing. */
|
||||
/* Remainder of a logical block is zero-filled when writing (see super_sync()). */
|
||||
} __packed;
|
||||
|
||||
static int read_disk_sb(struct md_rdev *rdev, int size)
|
||||
|
|
@ -823,7 +822,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
|
|||
test_bit(Faulty, &(rs->dev[i].rdev.flags)))
|
||||
failed_devices |= (1ULL << i);
|
||||
|
||||
memset(sb, 0, sizeof(*sb));
|
||||
memset(sb + 1, 0, rdev->sb_size - sizeof(*sb));
|
||||
|
||||
sb->magic = cpu_to_le32(DM_RAID_MAGIC);
|
||||
sb->features = cpu_to_le32(0); /* No features yet */
|
||||
|
|
@ -858,7 +857,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
|
|||
uint64_t events_sb, events_refsb;
|
||||
|
||||
rdev->sb_start = 0;
|
||||
rdev->sb_size = sizeof(*sb);
|
||||
rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev);
|
||||
if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) {
|
||||
DMERR("superblock size of a logical block is no longer valid");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = read_disk_sb(rdev, rdev->sb_size);
|
||||
if (ret)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user