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: Song Liu <songliubraving@fb.com> Signed-off-by: Shaohua Li <shli@fb.com>
This commit is contained in:
parent
504634f60f
commit
c757ec95c2
|
@ -441,7 +441,6 @@ int r5l_write_stripe(struct r5l_log *log, struct stripe_head *sh)
|
||||||
{
|
{
|
||||||
int write_disks = 0;
|
int write_disks = 0;
|
||||||
int data_pages, parity_pages;
|
int data_pages, parity_pages;
|
||||||
int meta_size;
|
|
||||||
int reserve;
|
int reserve;
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
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);
|
parity_pages = 1 + !!(sh->qd_idx >= 0);
|
||||||
data_pages = write_disks - parity_pages;
|
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);
|
set_bit(STRIPE_LOG_TRAPPED, &sh->state);
|
||||||
/*
|
/*
|
||||||
* The stripe must enter state machine again to finish the write, so
|
* 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)
|
if (PAGE_SIZE != 4096)
|
||||||
return -EINVAL;
|
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);
|
log = kzalloc(sizeof(*log), GFP_KERNEL);
|
||||||
if (!log)
|
if (!log)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
Loading…
Reference in New Issue