Add a function to modify the log by removing an rdev when a drive fails or adding when a spare/replacement is activated as a raid member. Removing a disk just clears the child log rdev pointer. No new stripes will be accepted for this child log in ppl_write_stripe() and running io units will be processed without writing PPL to the device. Adding a disk sets the child log rdev pointer and writes an empty PPL header. Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@xxxxxxxxx> --- drivers/md/raid5-ppl.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/md/raid5.c | 15 +++++++++++++++ drivers/md/raid5.h | 8 ++++++++ 3 files changed, 70 insertions(+) diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index a7693353243a..c2070d124849 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c @@ -319,6 +319,12 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, ppl_conf->bs); bio->bi_private = io; + + if (!log->rdev || test_bit(Faulty, &log->rdev->flags)) { + ppl_log_endio(bio); + return; + } + bio->bi_end_io = ppl_log_endio; bio->bi_opf = REQ_OP_WRITE | REQ_FUA; bio->bi_bdev = log->rdev->bdev; @@ -1098,3 +1104,44 @@ int ppl_init_log(struct r5conf *conf) ppl_exit_log(ppl_conf); return ret; } + +int ppl_modify_log(struct ppl_conf *ppl_conf, struct md_rdev *rdev, + enum ppl_modify_log_operation operation) +{ + struct ppl_log *log; + int ret = 0; + char b[BDEVNAME_SIZE]; + + if (!rdev) + return -EINVAL; + + pr_debug("%s: disk: %d operation: %s dev: %s\n", + __func__, rdev->raid_disk, + operation == PPL_MODIFY_LOG_DISK_REMOVE ? "remove" : + (operation == PPL_MODIFY_LOG_DISK_ADD ? "add" : "?"), + bdevname(rdev->bdev, b)); + + if (rdev->raid_disk < 0) + return 0; + + if (rdev->raid_disk >= ppl_conf->count) + return -ENODEV; + + log = &ppl_conf->child_logs[rdev->raid_disk]; + + mutex_lock(&log->io_mutex); + if (operation == PPL_MODIFY_LOG_DISK_REMOVE) { + log->rdev = NULL; + } else if (operation == PPL_MODIFY_LOG_DISK_ADD) { + ret = ppl_validate_rdev(rdev); + if (!ret) { + log->rdev = rdev; + ret = ppl_write_empty_header(log); + } + } else { + ret = -EINVAL; + } + mutex_unlock(&log->io_mutex); + + return ret; +} diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 8b52392457d8..b17e90f06f19 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -7623,6 +7623,12 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev) *rdevp = rdev; } } + if (conf->ppl) { + err = ppl_modify_log(conf->ppl, rdev, + PPL_MODIFY_LOG_DISK_REMOVE); + if (err) + goto abort; + } if (p->replacement) { /* We must have just cleared 'rdev' */ p->rdev = p->replacement; @@ -7632,6 +7638,10 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev) */ p->replacement = NULL; clear_bit(WantReplacement, &rdev->flags); + + if (conf->ppl) + err = ppl_modify_log(conf->ppl, p->rdev, + PPL_MODIFY_LOG_DISK_ADD); } else /* We might have just removed the Replacement as faulty- * clear the bit just in case @@ -7695,6 +7705,11 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) if (rdev->saved_raid_disk != disk) conf->fullsync = 1; rcu_assign_pointer(p->rdev, rdev); + + if (conf->ppl) + err = ppl_modify_log(conf->ppl, rdev, + PPL_MODIFY_LOG_DISK_ADD); + goto out; } } diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index f915a7a0e752..43cfa5fa71b3 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -806,4 +806,12 @@ extern void ppl_exit_log(struct ppl_conf *log); extern int ppl_write_stripe(struct ppl_conf *log, struct stripe_head *sh); extern void ppl_write_stripe_run(struct ppl_conf *log); extern void ppl_stripe_write_finished(struct stripe_head *sh); + +enum ppl_modify_log_operation { + PPL_MODIFY_LOG_DISK_REMOVE, + PPL_MODIFY_LOG_DISK_ADD, +}; +extern int ppl_modify_log(struct ppl_conf *log, struct md_rdev *rdev, + enum ppl_modify_log_operation operation); + #endif -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html