Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c757ec95 authored by Song Liu's avatar Song Liu Committed by Shaohua Li
Browse files

md/r5cache: Check array size in r5l_init_log



Currently, r5l_write_stripe checks meta size for each stripe write,
which is not necessary.

With this patch, r5l_init_log checks maximal meta size of the array,
which is (r5l_meta_block + raid_disks x r5l_payload_data_parity).
If this is too big to fit in one page, r5l_init_log aborts.

With current meta data, r5l_log support raid_disks up to 203.

Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent 504634f6
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -441,7 +441,6 @@ int r5l_write_stripe(struct r5l_log *log, struct stripe_head *sh)
{
	int write_disks = 0;
	int data_pages, parity_pages;
	int meta_size;
	int reserve;
	int i;
	int ret = 0;
@@ -473,15 +472,6 @@ int r5l_write_stripe(struct r5l_log *log, struct stripe_head *sh)
	parity_pages = 1 + !!(sh->qd_idx >= 0);
	data_pages = write_disks - parity_pages;

	meta_size =
		((sizeof(struct r5l_payload_data_parity) + sizeof(__le32))
		 * data_pages) +
		sizeof(struct r5l_payload_data_parity) +
		sizeof(__le32) * parity_pages;
	/* Doesn't work with very big raid array */
	if (meta_size + sizeof(struct r5l_meta_block) > PAGE_SIZE)
		return -EINVAL;

	set_bit(STRIPE_LOG_TRAPPED, &sh->state);
	/*
	 * The stripe must enter state machine again to finish the write, so
@@ -1197,6 +1187,22 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)

	if (PAGE_SIZE != 4096)
		return -EINVAL;

	/*
	 * The PAGE_SIZE must be big enough to hold 1 r5l_meta_block and
	 * raid_disks r5l_payload_data_parity.
	 *
	 * Write journal and cache does not work for very big array
	 * (raid_disks > 203)
	 */
	if (sizeof(struct r5l_meta_block) +
	    ((sizeof(struct r5l_payload_data_parity) + sizeof(__le32)) *
	     conf->raid_disks) > PAGE_SIZE) {
		pr_err("md/raid:%s: write journal/cache doesn't work for array with %d disks\n",
		       mdname(conf->mddev), conf->raid_disks);
		return -EINVAL;
	}

	log = kzalloc(sizeof(*log), GFP_KERNEL);
	if (!log)
		return -ENOMEM;