From 845b9e229fe0716ab6b4d94b4364c99069667b59 Mon Sep 17 00:00:00 2001 From: Artur Paszkiewicz Date: Tue, 4 Apr 2017 13:13:57 +0200 Subject: raid5-ppl: use resize_stripes() when enabling or disabling ppl Use resize_stripes() instead of raid5_reset_stripe_cache() to allocate or free sh->ppl_page at runtime for all stripes in the stripe cache. raid5_reset_stripe_cache() required suspending the mddev and could deadlock because of GFP_KERNEL allocations. Move the 'newsize' check to check_reshape() to allow reallocating the stripes with the same number of disks. Allocate sh->ppl_page in alloc_stripe() instead of grow_buffers(). Pass 'struct r5conf *conf' as a parameter to alloc_stripe() because it is needed to check whether to allocate ppl_page. Add free_stripe() and use it to free stripes rather than directly call kmem_cache_free(). Also free sh->ppl_page in free_stripe(). Set MD_HAS_PPL at the end of ppl_init_log() instead of explicitly setting it in advance and add another parameter to log_init() to allow calling ppl_init_log() without the bit set. Don't try to calculate partial parity or add a stripe to log if it does not have ppl_page set. Enabling ppl can now be performed without suspending the mddev, because the log won't be used until new stripes are allocated with ppl_page. Calling mddev_suspend/resume is still necessary when disabling ppl, because we want all stripes to finish before stopping the log, but resize_stripes() can be called after mddev_resume() when ppl is no longer active. Suggested-by: NeilBrown Signed-off-by: Artur Paszkiewicz Signed-off-by: Shaohua Li --- drivers/md/raid5-ppl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/md/raid5-ppl.c') diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index 355cf3581ef8..71968cf47d7d 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c @@ -328,7 +328,7 @@ int ppl_write_stripe(struct r5conf *conf, struct stripe_head *sh) struct ppl_io_unit *io = sh->ppl_io; struct ppl_log *log; - if (io || test_bit(STRIPE_SYNCING, &sh->state) || + if (io || test_bit(STRIPE_SYNCING, &sh->state) || !sh->ppl_page || !test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags) || !test_bit(R5_Insync, &sh->dev[sh->pd_idx].flags)) { clear_bit(STRIPE_LOG_TRAPPED, &sh->state); @@ -1204,6 +1204,7 @@ int ppl_init_log(struct r5conf *conf) } conf->log_private = ppl_conf; + set_bit(MD_HAS_PPL, &ppl_conf->mddev->flags); return 0; err: -- cgit v1.2.3