]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/md/dm-raid.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / drivers / md / dm-raid.c
index 4857fa4a5484ba8e4ae743f2e8d4a48205229875..07c0fa0fa284fbdc9e86673c219f99cd07a35f77 100644 (file)
@@ -789,8 +789,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)
@@ -827,7 +826,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 */
@@ -862,7 +861,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)
@@ -1169,8 +1172,12 @@ static void configure_discard_support(struct dm_target *ti, struct raid_set *rs)
        raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6);
 
        for (i = 0; i < rs->md.raid_disks; i++) {
-               struct request_queue *q = bdev_get_queue(rs->dev[i].rdev.bdev);
+               struct request_queue *q;
+
+               if (!rs->dev[i].rdev.bdev)
+                       continue;
 
+               q = bdev_get_queue(rs->dev[i].rdev.bdev);
                if (!q || !blk_queue_discard(q))
                        return;