|
@@ -2850,7 +2850,11 @@ struct meta_data_on_disk {
|
|
|
u32 bm_bytes_per_bit; /* BM_BLOCK_SIZE */
|
|
|
u32 la_peer_max_bio_size; /* last peer max_bio_size */
|
|
|
|
|
|
- u8 reserved_u8[4096 - (7*8 + 8*4)];
|
|
|
+ /* see al_tr_number_to_on_disk_sector() */
|
|
|
+ u32 al_stripes;
|
|
|
+ u32 al_stripe_size_4k;
|
|
|
+
|
|
|
+ u8 reserved_u8[4096 - (7*8 + 10*4)];
|
|
|
} __packed;
|
|
|
|
|
|
/**
|
|
@@ -2898,7 +2902,10 @@ void drbd_md_sync(struct drbd_conf *mdev)
|
|
|
buffer->bm_offset = cpu_to_be32(mdev->ldev->md.bm_offset);
|
|
|
buffer->la_peer_max_bio_size = cpu_to_be32(mdev->peer_max_bio_size);
|
|
|
|
|
|
- D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset);
|
|
|
+ buffer->al_stripes = cpu_to_be32(mdev->ldev->md.al_stripes);
|
|
|
+ buffer->al_stripe_size_4k = cpu_to_be32(mdev->ldev->md.al_stripe_size_4k);
|
|
|
+
|
|
|
+ D_ASSERT(drbd_md_ss(mdev->ldev) == mdev->ldev->md.md_offset);
|
|
|
sector = mdev->ldev->md.md_offset;
|
|
|
|
|
|
if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
|
|
@@ -2916,13 +2923,60 @@ out:
|
|
|
put_ldev(mdev);
|
|
|
}
|
|
|
|
|
|
+static int check_activity_log_stripe_size(struct drbd_conf *mdev,
|
|
|
+ struct meta_data_on_disk *on_disk,
|
|
|
+ struct drbd_md *in_core)
|
|
|
+{
|
|
|
+ u32 al_stripes = be32_to_cpu(on_disk->al_stripes);
|
|
|
+ u32 al_stripe_size_4k = be32_to_cpu(on_disk->al_stripe_size_4k);
|
|
|
+ u64 al_size_4k;
|
|
|
+
|
|
|
+ /* both not set: default to old fixed size activity log */
|
|
|
+ if (al_stripes == 0 && al_stripe_size_4k == 0) {
|
|
|
+ al_stripes = 1;
|
|
|
+ al_stripe_size_4k = MD_32kB_SECT/8;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* some paranoia plausibility checks */
|
|
|
+
|
|
|
+ /* we need both values to be set */
|
|
|
+ if (al_stripes == 0 || al_stripe_size_4k == 0)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ al_size_4k = (u64)al_stripes * al_stripe_size_4k;
|
|
|
+
|
|
|
+ /* Upper limit of activity log area, to avoid potential overflow
|
|
|
+ * problems in al_tr_number_to_on_disk_sector(). As right now, more
|
|
|
+ * than 72 * 4k blocks total only increases the amount of history,
|
|
|
+ * limiting this arbitrarily to 16 GB is not a real limitation ;-) */
|
|
|
+ if (al_size_4k > (16 * 1024 * 1024/4))
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ /* Lower limit: we need at least 8 transaction slots (32kB)
|
|
|
+ * to not break existing setups */
|
|
|
+ if (al_size_4k < MD_32kB_SECT/8)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ in_core->al_stripe_size_4k = al_stripe_size_4k;
|
|
|
+ in_core->al_stripes = al_stripes;
|
|
|
+ in_core->al_size_4k = al_size_4k;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ dev_err(DEV, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
|
|
|
+ al_stripes, al_stripe_size_4k);
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* drbd_md_read() - Reads in the meta data super block
|
|
|
* @mdev: DRBD device.
|
|
|
* @bdev: Device from which the meta data should be read in.
|
|
|
*
|
|
|
- * Return 0 (NO_ERROR) on success, and an enum drbd_ret_code in case
|
|
|
+ * Return NO_ERROR on success, and an enum drbd_ret_code in case
|
|
|
* something goes wrong.
|
|
|
+ *
|
|
|
+ * Called exactly once during drbd_adm_attach()
|
|
|
*/
|
|
|
int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
|
|
|
{
|
|
@@ -2937,6 +2991,10 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
|
|
|
if (!buffer)
|
|
|
goto out;
|
|
|
|
|
|
+ /* First, figure out where our meta data superblock is located. */
|
|
|
+ bdev->md.meta_dev_idx = bdev->disk_conf->meta_dev_idx;
|
|
|
+ bdev->md.md_offset = drbd_md_ss(bdev);
|
|
|
+
|
|
|
if (drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) {
|
|
|
/* NOTE: can't do normal error processing here as this is
|
|
|
called BEFORE disk is attached */
|
|
@@ -2954,40 +3012,43 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
|
|
|
rv = ERR_MD_UNCLEAN;
|
|
|
goto err;
|
|
|
}
|
|
|
+
|
|
|
+ rv = ERR_MD_INVALID;
|
|
|
if (magic != DRBD_MD_MAGIC_08) {
|
|
|
if (magic == DRBD_MD_MAGIC_07)
|
|
|
dev_err(DEV, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
|
|
|
else
|
|
|
dev_err(DEV, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
|
|
|
- rv = ERR_MD_INVALID;
|
|
|
goto err;
|
|
|
}
|
|
|
+
|
|
|
+ if (check_activity_log_stripe_size(mdev, buffer, &bdev->md))
|
|
|
+ goto err;
|
|
|
+
|
|
|
if (be32_to_cpu(buffer->al_offset) != bdev->md.al_offset) {
|
|
|
dev_err(DEV, "unexpected al_offset: %d (expected %d)\n",
|
|
|
be32_to_cpu(buffer->al_offset), bdev->md.al_offset);
|
|
|
- rv = ERR_MD_INVALID;
|
|
|
goto err;
|
|
|
}
|
|
|
if (be32_to_cpu(buffer->bm_offset) != bdev->md.bm_offset) {
|
|
|
dev_err(DEV, "unexpected bm_offset: %d (expected %d)\n",
|
|
|
be32_to_cpu(buffer->bm_offset), bdev->md.bm_offset);
|
|
|
- rv = ERR_MD_INVALID;
|
|
|
goto err;
|
|
|
}
|
|
|
if (be32_to_cpu(buffer->md_size_sect) != bdev->md.md_size_sect) {
|
|
|
dev_err(DEV, "unexpected md_size: %u (expected %u)\n",
|
|
|
be32_to_cpu(buffer->md_size_sect), bdev->md.md_size_sect);
|
|
|
- rv = ERR_MD_INVALID;
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) {
|
|
|
dev_err(DEV, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
|
|
|
be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE);
|
|
|
- rv = ERR_MD_INVALID;
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
+ rv = NO_ERROR;
|
|
|
+
|
|
|
bdev->md.la_size_sect = be64_to_cpu(buffer->la_size);
|
|
|
for (i = UI_CURRENT; i < UI_SIZE; i++)
|
|
|
bdev->md.uuid[i] = be64_to_cpu(buffer->uuid[i]);
|