diff options
author | Artur Paszkiewicz <artur.paszkiewicz@intel.com> | 2017-03-09 10:00:02 +0100 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-03-16 16:55:56 -0700 |
commit | 6358c239d88c751a9f14152a8d4ad2b69f5be48f (patch) | |
tree | 624a99ba683e1ee7115b2e0c5ac9845436524a09 /drivers/md/raid5-ppl.c | |
parent | 4536bf9ba2d03404655586b07f8830b6f2106242 (diff) | |
download | linux-6358c239d88c751a9f14152a8d4ad2b69f5be48f.tar.bz2 |
raid5-ppl: support disk hot add/remove with PPL
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@intel.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Diffstat (limited to 'drivers/md/raid5-ppl.c')
-rw-r--r-- | drivers/md/raid5-ppl.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index d336c024eef9..4af420f4d8c0 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c @@ -400,6 +400,13 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) struct stripe_head *sh; int i; + bio->bi_private = io; + + if (!log->rdev || test_bit(Faulty, &log->rdev->flags)) { + ppl_log_endio(bio); + return; + } + for (i = 0; i < io->entries_count; i++) { struct ppl_header_entry *e = &pplhdr->entries[i]; @@ -415,7 +422,6 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) pplhdr->entries_count = cpu_to_le32(io->entries_count); pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PPL_HEADER_SIZE)); - bio->bi_private = io; bio->bi_end_io = ppl_log_endio; bio->bi_opf = REQ_OP_WRITE | REQ_FUA; bio->bi_bdev = log->rdev->bdev; @@ -1190,3 +1196,40 @@ err: __ppl_exit_log(ppl_conf); return ret; } + +int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add) +{ + struct ppl_conf *ppl_conf = conf->log_private; + 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, add ? "add" : "remove", + 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 (add) { + ret = ppl_validate_rdev(rdev); + if (!ret) { + log->rdev = rdev; + ret = ppl_write_empty_header(log); + } + } else { + log->rdev = NULL; + } + mutex_unlock(&log->io_mutex); + + return ret; +} |