This patch depends on patch 05. Change the type of nr_pending from atomic_t to percpu_ref. Additionally, temporarily switch from percpu mode to atomic mode. This is to reduce the amount of changes from patches 8 to 10. Patches 8 to 10 assume that nr_pending is run in percpu mode. Finally, switch from atomic mode to percpu mode in patch 11. Signed-off-by: Keisuke TADA <keisuke1.tada@xxxxxxxxxx> Signed-off-by: Toshifumi OHTAKE <toshifumi.ootake@xxxxxxxxxx> --- drivers/md/md.c | 13 ++++++++++++- drivers/md/md.h | 18 +++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index df868b315b45..30fbba38ea58 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -998,6 +998,7 @@ void md_rdev_clear(struct md_rdev *rdev) put_page(rdev->bb_page); rdev->bb_page = NULL; } + percpu_ref_exit(&rdev->nr_pending); badblocks_exit(&rdev->badblocks); } EXPORT_SYMBOL_GPL(md_rdev_clear); @@ -3720,8 +3721,14 @@ static const struct kobj_type rdev_ktype = { .default_groups = rdev_default_groups, }; +static void percpu_wakeup_handle_req_pending(struct percpu_ref *ref) +{ +} + int md_rdev_init(struct md_rdev *rdev) { + int ret; + rdev->desc_nr = -1; rdev->saved_raid_disk = -1; rdev->raid_disk = -1; @@ -3732,7 +3739,11 @@ int md_rdev_init(struct md_rdev *rdev) rdev->last_read_error = 0; rdev->sb_loaded = 0; rdev->bb_page = NULL; - atomic_set(&rdev->nr_pending, 0); + ret = percpu_ref_init(&rdev->nr_pending, percpu_wakeup_handle_req_pending, + PERCPU_REF_ALLOW_REINIT, GFP_KERNEL); + WARN_ON(ret); + percpu_ref_switch_to_atomic_sync(&rdev->nr_pending); + nr_pending_dec(rdev); atomic_set(&rdev->read_errors, 0); atomic_set(&rdev->corrected_errors, 0); diff --git a/drivers/md/md.h b/drivers/md/md.h index 724439400ed1..c69e3a0bc4ca 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -107,10 +107,10 @@ struct md_rdev { */ }; - atomic_t nr_pending; /* number of pending requests. - * only maintained for arrays that - * support hot removal - */ + struct percpu_ref nr_pending; /* number of pending requests. + * only maintained for arrays that + * support hot removal + */ atomic_t read_errors; /* number of consecutive read errors that * we have tried to ignore. */ @@ -213,27 +213,27 @@ enum flag_bits { static inline void nr_pending_inc(struct md_rdev *rdev) { - atomic_inc(&rdev->nr_pending); + percpu_ref_get(&rdev->nr_pending); } static inline void nr_pending_dec(struct md_rdev *rdev) { - atomic_dec(&rdev->nr_pending); + percpu_ref_put(&rdev->nr_pending); } static inline bool nr_pending_is_zero(struct md_rdev *rdev) { - return atomic_read(&rdev->nr_pending) == 0; + return percpu_ref_is_zero(&rdev->nr_pending); } static inline bool nr_pending_is_not_zero(struct md_rdev *rdev) { - return atomic_read(&rdev->nr_pending) != 0; + return !percpu_ref_is_zero(&rdev->nr_pending); } static inline unsigned long nr_pending_read(struct md_rdev *rdev) { - return (unsigned long)atomic_read(&rdev->nr_pending); + return atomic_long_read(&rdev->nr_pending.data->count); } static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors, -- 2.34.1