static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
- bool on_wq;
struct r5conf *conf = mddev->private;
- sector_t logical_sector;
- struct stripe_request_ctx ctx = {};
const int rw = bio_data_dir(bi);
+ struct stripe_request_ctx *ctx;
+ sector_t logical_sector;
enum stripe_result res;
int s, stripe_cnt;
+ bool on_wq;
if (unlikely(bi->bi_opf & REQ_PREFLUSH)) {
int ret = log_handle_flush_request(conf, bi);
return true;
}
/* ret == -EAGAIN, fallback */
- /*
- * if r5l_handle_flush_request() didn't clear REQ_PREFLUSH,
- * we need to flush journal device
- */
- ctx.do_flush = bi->bi_opf & REQ_PREFLUSH;
}
md_write_start(mddev, bi);
}
logical_sector = bi->bi_iter.bi_sector & ~((sector_t)RAID5_STRIPE_SECTORS(conf)-1);
- ctx.first_sector = logical_sector;
- ctx.last_sector = bio_end_sector(bi);
bi->bi_next = NULL;
- stripe_cnt = DIV_ROUND_UP_SECTOR_T(ctx.last_sector - logical_sector,
+ ctx = mempool_alloc(conf->ctx_pool, GFP_NOIO);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->first_sector = logical_sector;
+ ctx->last_sector = bio_end_sector(bi);
+ /*
+ * if r5l_handle_flush_request() didn't clear REQ_PREFLUSH,
+ * we need to flush journal device
+ */
+ if (unlikely(bi->bi_opf & REQ_PREFLUSH))
+ ctx->do_flush = true;
+
+ stripe_cnt = DIV_ROUND_UP_SECTOR_T(ctx->last_sector - logical_sector,
RAID5_STRIPE_SECTORS(conf));
- bitmap_set(ctx.sectors_to_do, 0, stripe_cnt);
+ bitmap_set(ctx->sectors_to_do, 0, stripe_cnt);
pr_debug("raid456: %s, logical %llu to %llu\n", __func__,
- bi->bi_iter.bi_sector, ctx.last_sector);
+ bi->bi_iter.bi_sector, ctx->last_sector);
/* Bail out if conflicts with reshape and REQ_NOWAIT is set */
if ((bi->bi_opf & REQ_NOWAIT) &&
bio_wouldblock_error(bi);
if (rw == WRITE)
md_write_end(mddev);
+ mempool_free(ctx, conf->ctx_pool);
return true;
}
md_account_bio(mddev, &bi);
add_wait_queue(&conf->wait_for_reshape, &wait);
on_wq = true;
}
- s = (logical_sector - ctx.first_sector) >> RAID5_STRIPE_SHIFT(conf);
+ s = (logical_sector - ctx->first_sector) >> RAID5_STRIPE_SHIFT(conf);
while (1) {
- res = make_stripe_request(mddev, conf, &ctx, logical_sector,
+ res = make_stripe_request(mddev, conf, ctx, logical_sector,
bi);
if (res == STRIPE_FAIL || res == STRIPE_WAIT_RESHAPE)
break;
* raid5_activate_delayed() from making progress
* and thus deadlocking.
*/
- if (ctx.batch_last) {
- raid5_release_stripe(ctx.batch_last);
- ctx.batch_last = NULL;
+ if (ctx->batch_last) {
+ raid5_release_stripe(ctx->batch_last);
+ ctx->batch_last = NULL;
}
wait_woken(&wait, TASK_UNINTERRUPTIBLE,
continue;
}
- s = find_next_bit_wrap(ctx.sectors_to_do, stripe_cnt, s);
+ s = find_next_bit_wrap(ctx->sectors_to_do, stripe_cnt, s);
if (s == stripe_cnt)
break;
- logical_sector = ctx.first_sector +
+ logical_sector = ctx->first_sector +
(s << RAID5_STRIPE_SHIFT(conf));
}
if (unlikely(on_wq))
remove_wait_queue(&conf->wait_for_reshape, &wait);
- if (ctx.batch_last)
- raid5_release_stripe(ctx.batch_last);
+ if (ctx->batch_last)
+ raid5_release_stripe(ctx->batch_last);
if (rw == WRITE)
md_write_end(mddev);
+
+ mempool_free(ctx, conf->ctx_pool);
if (res == STRIPE_WAIT_RESHAPE) {
md_free_cloned_bio(bi);
return false;
bioset_exit(&conf->bio_split);
kfree(conf->stripe_hashtbl);
kfree(conf->pending_data);
+
+ mempool_destroy(conf->ctx_pool);
+
kfree(conf);
}
goto abort;
}
+ conf->ctx_pool = mempool_create_kmalloc_pool(NR_RAID_BIOS,
+ sizeof(struct stripe_request_ctx));
+ if (!conf->ctx_pool) {
+ ret = -ENOMEM;
+ goto abort;
+ }
+
ret = log_init(conf, journal_dev, raid5_has_ppl(conf));
if (ret)
goto abort;