diff options
author | Artur Paszkiewicz <artur.paszkiewicz@intel.com> | 2017-03-09 04:00:02 -0500 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-03-16 19:55:56 -0400 |
commit | 6358c239d88c751a9f14152a8d4ad2b69f5be48f (patch) | |
tree | 624a99ba683e1ee7115b2e0c5ac9845436524a09 /drivers/md/raid5-ppl.c | |
parent | 4536bf9ba2d03404655586b07f8830b6f2106242 (diff) |
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) | |||
400 | struct stripe_head *sh; | 400 | struct stripe_head *sh; |
401 | int i; | 401 | int i; |
402 | 402 | ||
403 | bio->bi_private = io; | ||
404 | |||
405 | if (!log->rdev || test_bit(Faulty, &log->rdev->flags)) { | ||
406 | ppl_log_endio(bio); | ||
407 | return; | ||
408 | } | ||
409 | |||
403 | for (i = 0; i < io->entries_count; i++) { | 410 | for (i = 0; i < io->entries_count; i++) { |
404 | struct ppl_header_entry *e = &pplhdr->entries[i]; | 411 | struct ppl_header_entry *e = &pplhdr->entries[i]; |
405 | 412 | ||
@@ -415,7 +422,6 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) | |||
415 | pplhdr->entries_count = cpu_to_le32(io->entries_count); | 422 | pplhdr->entries_count = cpu_to_le32(io->entries_count); |
416 | pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PPL_HEADER_SIZE)); | 423 | pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PPL_HEADER_SIZE)); |
417 | 424 | ||
418 | bio->bi_private = io; | ||
419 | bio->bi_end_io = ppl_log_endio; | 425 | bio->bi_end_io = ppl_log_endio; |
420 | bio->bi_opf = REQ_OP_WRITE | REQ_FUA; | 426 | bio->bi_opf = REQ_OP_WRITE | REQ_FUA; |
421 | bio->bi_bdev = log->rdev->bdev; | 427 | bio->bi_bdev = log->rdev->bdev; |
@@ -1190,3 +1196,40 @@ err: | |||
1190 | __ppl_exit_log(ppl_conf); | 1196 | __ppl_exit_log(ppl_conf); |
1191 | return ret; | 1197 | return ret; |
1192 | } | 1198 | } |
1199 | |||
1200 | int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add) | ||
1201 | { | ||
1202 | struct ppl_conf *ppl_conf = conf->log_private; | ||
1203 | struct ppl_log *log; | ||
1204 | int ret = 0; | ||
1205 | char b[BDEVNAME_SIZE]; | ||
1206 | |||
1207 | if (!rdev) | ||
1208 | return -EINVAL; | ||
1209 | |||
1210 | pr_debug("%s: disk: %d operation: %s dev: %s\n", | ||
1211 | __func__, rdev->raid_disk, add ? "add" : "remove", | ||
1212 | bdevname(rdev->bdev, b)); | ||
1213 | |||
1214 | if (rdev->raid_disk < 0) | ||
1215 | return 0; | ||
1216 | |||
1217 | if (rdev->raid_disk >= ppl_conf->count) | ||
1218 | return -ENODEV; | ||
1219 | |||
1220 | log = &ppl_conf->child_logs[rdev->raid_disk]; | ||
1221 | |||
1222 | mutex_lock(&log->io_mutex); | ||
1223 | if (add) { | ||
1224 | ret = ppl_validate_rdev(rdev); | ||
1225 | if (!ret) { | ||
1226 | log->rdev = rdev; | ||
1227 | ret = ppl_write_empty_header(log); | ||
1228 | } | ||
1229 | } else { | ||
1230 | log->rdev = NULL; | ||
1231 | } | ||
1232 | mutex_unlock(&log->io_mutex); | ||
1233 | |||
1234 | return ret; | ||
1235 | } | ||