Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1532d9e8 authored by Tomasz Majchrzak's avatar Tomasz Majchrzak Committed by Shaohua Li
Browse files

raid5-ppl: PPL support for disks with write-back cache enabled



In order to provide data consistency with PPL for disks with write-back
cache enabled all data has to be flushed to disks before next PPL
entry. The disks to be flushed are marked in the bitmap. It's modified
under a mutex and it's only read after PPL io unit is submitted.

A limitation of 64 disks in the array has been introduced to keep data
structures and implementation simple. RAID5 arrays with so many disks are
not likely due to high risk of multiple disks failure. Such restriction
should not be a real life limitation.

With write-back cache disabled next PPL entry is submitted when data write
for current one completes. Data flush defers next log submission so trigger
it when there are no stripes for handling found.

As PPL assures all data is flushed to disk at request completion, just
acknowledge flush request when PPL is enabled.

Signed-off-by: default avatarTomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: default avatarShaohua Li <sh.li@alibaba-inc.com>
parent 92e6245d
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@ case the behavior is the same as in plain raid5.
PPL is available for md version-1 metadata and external (specifically IMSM)
PPL is available for md version-1 metadata and external (specifically IMSM)
metadata arrays. It can be enabled using mdadm option --consistency-policy=ppl.
metadata arrays. It can be enabled using mdadm option --consistency-policy=ppl.


Currently, volatile write-back cache should be disabled on all member drives
There is a limitation of maximum 64 disks in the array for PPL. It allows to
when using PPL. Otherwise it cannot guarantee consistency in case of power
keep data structures and implementation simple. RAID5 arrays with so many disks
failure.
are not likely due to high risk of multiple disks failure. Such restriction
should not be a real life limitation.
+3 −2
Original line number Original line Diff line number Diff line
@@ -711,7 +711,7 @@ static struct md_rdev *find_rdev(struct mddev *mddev, dev_t dev)
	return NULL;
	return NULL;
}
}


static struct md_rdev *find_rdev_rcu(struct mddev *mddev, dev_t dev)
struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev)
{
{
	struct md_rdev *rdev;
	struct md_rdev *rdev;


@@ -721,6 +721,7 @@ static struct md_rdev *find_rdev_rcu(struct mddev *mddev, dev_t dev)


	return NULL;
	return NULL;
}
}
EXPORT_SYMBOL_GPL(md_find_rdev_rcu);


static struct md_personality *find_pers(int level, char *clevel)
static struct md_personality *find_pers(int level, char *clevel)
{
{
@@ -7010,7 +7011,7 @@ static int set_disk_faulty(struct mddev *mddev, dev_t dev)
		return -ENODEV;
		return -ENODEV;


	rcu_read_lock();
	rcu_read_lock();
	rdev = find_rdev_rcu(mddev, dev);
	rdev = md_find_rdev_rcu(mddev, dev);
	if (!rdev)
	if (!rdev)
		err =  -ENODEV;
		err =  -ENODEV;
	else {
	else {
+1 −0
Original line number Original line Diff line number Diff line
@@ -710,6 +710,7 @@ extern void md_reload_sb(struct mddev *mddev, int raid_disk);
extern void md_update_sb(struct mddev *mddev, int force);
extern void md_update_sb(struct mddev *mddev, int force);
extern void md_kick_rdev_from_array(struct md_rdev * rdev);
extern void md_kick_rdev_from_array(struct md_rdev * rdev);
struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr);
struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr);
struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev);


static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
{
{
+0 −5
Original line number Original line Diff line number Diff line
@@ -1111,9 +1111,6 @@ void r5l_write_stripe_run(struct r5l_log *log)


int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio)
int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio)
{
{
	if (!log)
		return -ENODEV;

	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
		/*
		/*
		 * in write through (journal only)
		 * in write through (journal only)
@@ -1592,8 +1589,6 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space)
void r5l_quiesce(struct r5l_log *log, int quiesce)
void r5l_quiesce(struct r5l_log *log, int quiesce)
{
{
	struct mddev *mddev;
	struct mddev *mddev;
	if (!log)
		return;


	if (quiesce) {
	if (quiesce) {
		/* make sure r5l_write_super_and_discard_space exits */
		/* make sure r5l_write_super_and_discard_space exits */
+29 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ extern int ppl_write_stripe(struct r5conf *conf, struct stripe_head *sh);
extern void ppl_write_stripe_run(struct r5conf *conf);
extern void ppl_write_stripe_run(struct r5conf *conf);
extern void ppl_stripe_write_finished(struct stripe_head *sh);
extern void ppl_stripe_write_finished(struct stripe_head *sh);
extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add);
extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add);
extern void ppl_quiesce(struct r5conf *conf, int quiesce);


static inline bool raid5_has_ppl(struct r5conf *conf)
static inline bool raid5_has_ppl(struct r5conf *conf)
{
{
@@ -88,6 +89,34 @@ static inline void log_write_stripe_run(struct r5conf *conf)
		ppl_write_stripe_run(conf);
		ppl_write_stripe_run(conf);
}
}


static inline void log_flush_stripe_to_raid(struct r5conf *conf)
{
	if (conf->log)
		r5l_flush_stripe_to_raid(conf->log);
	else if (raid5_has_ppl(conf))
		ppl_write_stripe_run(conf);
}

static inline int log_handle_flush_request(struct r5conf *conf, struct bio *bio)
{
	int ret = -ENODEV;

	if (conf->log)
		ret = r5l_handle_flush_request(conf->log, bio);
	else if (raid5_has_ppl(conf))
		ret = 0;

	return ret;
}

static inline void log_quiesce(struct r5conf *conf, int quiesce)
{
	if (conf->log)
		r5l_quiesce(conf->log, quiesce);
	else if (raid5_has_ppl(conf))
		ppl_quiesce(conf, quiesce);
}

static inline void log_exit(struct r5conf *conf)
static inline void log_exit(struct r5conf *conf)
{
{
	if (conf->log)
	if (conf->log)
Loading