diff options
Diffstat (limited to 'drivers/md/raid5-ppl.c')
| -rw-r--r-- | drivers/md/raid5-ppl.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index 0b096ddc9c1e..17e9e7d51097 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/raid/md_p.h> | 20 | #include <linux/raid/md_p.h> |
| 21 | #include "md.h" | 21 | #include "md.h" |
| 22 | #include "raid5.h" | 22 | #include "raid5.h" |
| 23 | #include "raid5-log.h" | ||
| 23 | 24 | ||
| 24 | /* | 25 | /* |
| 25 | * PPL consists of a 4KB header (struct ppl_header) and at least 128KB for | 26 | * PPL consists of a 4KB header (struct ppl_header) and at least 128KB for |
| @@ -115,6 +116,8 @@ struct ppl_conf { | |||
| 115 | /* stripes to retry if failed to allocate io_unit */ | 116 | /* stripes to retry if failed to allocate io_unit */ |
| 116 | struct list_head no_mem_stripes; | 117 | struct list_head no_mem_stripes; |
| 117 | spinlock_t no_mem_stripes_lock; | 118 | spinlock_t no_mem_stripes_lock; |
| 119 | |||
| 120 | unsigned short write_hint; | ||
| 118 | }; | 121 | }; |
| 119 | 122 | ||
| 120 | struct ppl_log { | 123 | struct ppl_log { |
| @@ -474,6 +477,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) | |||
| 474 | bio_set_dev(bio, log->rdev->bdev); | 477 | bio_set_dev(bio, log->rdev->bdev); |
| 475 | bio->bi_iter.bi_sector = log->next_io_sector; | 478 | bio->bi_iter.bi_sector = log->next_io_sector; |
| 476 | bio_add_page(bio, io->header_page, PAGE_SIZE, 0); | 479 | bio_add_page(bio, io->header_page, PAGE_SIZE, 0); |
| 480 | bio->bi_write_hint = ppl_conf->write_hint; | ||
| 477 | 481 | ||
| 478 | pr_debug("%s: log->current_io_sector: %llu\n", __func__, | 482 | pr_debug("%s: log->current_io_sector: %llu\n", __func__, |
| 479 | (unsigned long long)log->next_io_sector); | 483 | (unsigned long long)log->next_io_sector); |
| @@ -503,6 +507,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) | |||
| 503 | bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, | 507 | bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, |
| 504 | &ppl_conf->bs); | 508 | &ppl_conf->bs); |
| 505 | bio->bi_opf = prev->bi_opf; | 509 | bio->bi_opf = prev->bi_opf; |
| 510 | bio->bi_write_hint = prev->bi_write_hint; | ||
| 506 | bio_copy_dev(bio, prev); | 511 | bio_copy_dev(bio, prev); |
| 507 | bio->bi_iter.bi_sector = bio_end_sector(prev); | 512 | bio->bi_iter.bi_sector = bio_end_sector(prev); |
| 508 | bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); | 513 | bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); |
| @@ -1407,6 +1412,7 @@ int ppl_init_log(struct r5conf *conf) | |||
| 1407 | atomic64_set(&ppl_conf->seq, 0); | 1412 | atomic64_set(&ppl_conf->seq, 0); |
| 1408 | INIT_LIST_HEAD(&ppl_conf->no_mem_stripes); | 1413 | INIT_LIST_HEAD(&ppl_conf->no_mem_stripes); |
| 1409 | spin_lock_init(&ppl_conf->no_mem_stripes_lock); | 1414 | spin_lock_init(&ppl_conf->no_mem_stripes_lock); |
| 1415 | ppl_conf->write_hint = RWF_WRITE_LIFE_NOT_SET; | ||
| 1410 | 1416 | ||
| 1411 | if (!mddev->external) { | 1417 | if (!mddev->external) { |
| 1412 | ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid)); | 1418 | ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid)); |
| @@ -1501,3 +1507,60 @@ int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add) | |||
| 1501 | 1507 | ||
| 1502 | return ret; | 1508 | return ret; |
| 1503 | } | 1509 | } |
| 1510 | |||
| 1511 | static ssize_t | ||
| 1512 | ppl_write_hint_show(struct mddev *mddev, char *buf) | ||
| 1513 | { | ||
| 1514 | size_t ret = 0; | ||
| 1515 | struct r5conf *conf; | ||
| 1516 | struct ppl_conf *ppl_conf = NULL; | ||
| 1517 | |||
| 1518 | spin_lock(&mddev->lock); | ||
| 1519 | conf = mddev->private; | ||
| 1520 | if (conf && raid5_has_ppl(conf)) | ||
| 1521 | ppl_conf = conf->log_private; | ||
| 1522 | ret = sprintf(buf, "%d\n", ppl_conf ? ppl_conf->write_hint : 0); | ||
| 1523 | spin_unlock(&mddev->lock); | ||
| 1524 | |||
| 1525 | return ret; | ||
| 1526 | } | ||
| 1527 | |||
| 1528 | static ssize_t | ||
| 1529 | ppl_write_hint_store(struct mddev *mddev, const char *page, size_t len) | ||
| 1530 | { | ||
| 1531 | struct r5conf *conf; | ||
| 1532 | struct ppl_conf *ppl_conf; | ||
| 1533 | int err = 0; | ||
| 1534 | unsigned short new; | ||
| 1535 | |||
| 1536 | if (len >= PAGE_SIZE) | ||
| 1537 | return -EINVAL; | ||
| 1538 | if (kstrtou16(page, 10, &new)) | ||
| 1539 | return -EINVAL; | ||
| 1540 | |||
| 1541 | err = mddev_lock(mddev); | ||
| 1542 | if (err) | ||
| 1543 | return err; | ||
| 1544 | |||
| 1545 | conf = mddev->private; | ||
| 1546 | if (!conf) { | ||
| 1547 | err = -ENODEV; | ||
| 1548 | } else if (raid5_has_ppl(conf)) { | ||
| 1549 | ppl_conf = conf->log_private; | ||
| 1550 | if (!ppl_conf) | ||
| 1551 | err = -EINVAL; | ||
| 1552 | else | ||
| 1553 | ppl_conf->write_hint = new; | ||
| 1554 | } else { | ||
| 1555 | err = -EINVAL; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | mddev_unlock(mddev); | ||
| 1559 | |||
| 1560 | return err ?: len; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | struct md_sysfs_entry | ||
| 1564 | ppl_write_hint = __ATTR(ppl_write_hint, S_IRUGO | S_IWUSR, | ||
| 1565 | ppl_write_hint_show, | ||
| 1566 | ppl_write_hint_store); | ||
