summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/raid5-cache.c17
-rw-r--r--drivers/md/raid5-log.h81
-rw-r--r--drivers/md/raid5.c48
-rw-r--r--drivers/md/raid5.h30
4 files changed, 107 insertions, 69 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 5c8640c86b90..5f82dabdda6f 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -344,6 +344,8 @@ void r5c_handle_cached_data_endio(struct r5conf *conf,
344 } 344 }
345} 345}
346 346
347void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
348
347/* Check whether we should flush some stripes to free up stripe cache */ 349/* Check whether we should flush some stripes to free up stripe cache */
348void r5c_check_stripe_cache_usage(struct r5conf *conf) 350void r5c_check_stripe_cache_usage(struct r5conf *conf)
349{ 351{
@@ -2749,9 +2751,7 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
2749 } 2751 }
2750} 2752}
2751 2753
2752int 2754int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
2753r5c_cache_data(struct r5l_log *log, struct stripe_head *sh,
2754 struct stripe_head_state *s)
2755{ 2755{
2756 struct r5conf *conf = sh->raid_conf; 2756 struct r5conf *conf = sh->raid_conf;
2757 int pages = 0; 2757 int pages = 0;
@@ -2914,6 +2914,10 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
2914{ 2914{
2915 struct request_queue *q = bdev_get_queue(rdev->bdev); 2915 struct request_queue *q = bdev_get_queue(rdev->bdev);
2916 struct r5l_log *log; 2916 struct r5l_log *log;
2917 char b[BDEVNAME_SIZE];
2918
2919 pr_debug("md/raid:%s: using device %s as journal\n",
2920 mdname(conf->mddev), bdevname(rdev->bdev, b));
2917 2921
2918 if (PAGE_SIZE != 4096) 2922 if (PAGE_SIZE != 4096)
2919 return -EINVAL; 2923 return -EINVAL;
@@ -3016,8 +3020,13 @@ io_kc:
3016 return -EINVAL; 3020 return -EINVAL;
3017} 3021}
3018 3022
3019void r5l_exit_log(struct r5l_log *log) 3023void r5l_exit_log(struct r5conf *conf)
3020{ 3024{
3025 struct r5l_log *log = conf->log;
3026
3027 conf->log = NULL;
3028 synchronize_rcu();
3029
3021 flush_work(&log->disable_writeback_work); 3030 flush_work(&log->disable_writeback_work);
3022 md_unregister_thread(&log->reclaim_thread); 3031 md_unregister_thread(&log->reclaim_thread);
3023 mempool_destroy(log->meta_pool); 3032 mempool_destroy(log->meta_pool);
diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h
new file mode 100644
index 000000000000..2da4bd3bbd79
--- /dev/null
+++ b/drivers/md/raid5-log.h
@@ -0,0 +1,81 @@
1#ifndef _RAID5_LOG_H
2#define _RAID5_LOG_H
3
4extern int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev);
5extern void r5l_exit_log(struct r5conf *conf);
6extern int r5l_write_stripe(struct r5l_log *log, struct stripe_head *head_sh);
7extern void r5l_write_stripe_run(struct r5l_log *log);
8extern void r5l_flush_stripe_to_raid(struct r5l_log *log);
9extern void r5l_stripe_write_finished(struct stripe_head *sh);
10extern int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio);
11extern void r5l_quiesce(struct r5l_log *log, int state);
12extern bool r5l_log_disk_error(struct r5conf *conf);
13extern bool r5c_is_writeback(struct r5l_log *log);
14extern int
15r5c_try_caching_write(struct r5conf *conf, struct stripe_head *sh,
16 struct stripe_head_state *s, int disks);
17extern void
18r5c_finish_stripe_write_out(struct r5conf *conf, struct stripe_head *sh,
19 struct stripe_head_state *s);
20extern void r5c_release_extra_page(struct stripe_head *sh);
21extern void r5c_use_extra_page(struct stripe_head *sh);
22extern void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
23extern void r5c_handle_cached_data_endio(struct r5conf *conf,
24 struct stripe_head *sh, int disks, struct bio_list *return_bi);
25extern int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh);
26extern void r5c_make_stripe_write_out(struct stripe_head *sh);
27extern void r5c_flush_cache(struct r5conf *conf, int num);
28extern void r5c_check_stripe_cache_usage(struct r5conf *conf);
29extern void r5c_check_cached_full_stripe(struct r5conf *conf);
30extern struct md_sysfs_entry r5c_journal_mode;
31extern void r5c_update_on_rdev_error(struct mddev *mddev);
32extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
33
34static inline int log_stripe(struct stripe_head *sh, struct stripe_head_state *s)
35{
36 struct r5conf *conf = sh->raid_conf;
37
38 if (conf->log) {
39 if (!test_bit(STRIPE_R5C_CACHING, &sh->state)) {
40 /* writing out phase */
41 if (s->waiting_extra_page)
42 return 0;
43 return r5l_write_stripe(conf->log, sh);
44 } else if (test_bit(STRIPE_LOG_TRAPPED, &sh->state)) {
45 /* caching phase */
46 return r5c_cache_data(conf->log, sh);
47 }
48 }
49
50 return -EAGAIN;
51}
52
53static inline void log_stripe_write_finished(struct stripe_head *sh)
54{
55 struct r5conf *conf = sh->raid_conf;
56
57 if (conf->log)
58 r5l_stripe_write_finished(sh);
59}
60
61static inline void log_write_stripe_run(struct r5conf *conf)
62{
63 if (conf->log)
64 r5l_write_stripe_run(conf->log);
65}
66
67static inline void log_exit(struct r5conf *conf)
68{
69 if (conf->log)
70 r5l_exit_log(conf);
71}
72
73static inline int log_init(struct r5conf *conf, struct md_rdev *journal_dev)
74{
75 if (journal_dev)
76 return r5l_init_log(conf, journal_dev);
77
78 return 0;
79}
80
81#endif
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 013398ce2080..f575f40d2acb 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -64,6 +64,7 @@
64#include "raid5.h" 64#include "raid5.h"
65#include "raid0.h" 65#include "raid0.h"
66#include "bitmap.h" 66#include "bitmap.h"
67#include "raid5-log.h"
67 68
68#define UNSUPPORTED_MDDEV_FLAGS (1L << MD_FAILFAST_SUPPORTED) 69#define UNSUPPORTED_MDDEV_FLAGS (1L << MD_FAILFAST_SUPPORTED)
69 70
@@ -997,18 +998,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
997 998
998 might_sleep(); 999 might_sleep();
999 1000
1000 if (!test_bit(STRIPE_R5C_CACHING, &sh->state)) { 1001 if (log_stripe(sh, s) == 0)
1001 /* writing out phase */ 1002 return;
1002 if (s->waiting_extra_page)
1003 return;
1004 if (r5l_write_stripe(conf->log, sh) == 0)
1005 return;
1006 } else { /* caching phase */
1007 if (test_bit(STRIPE_LOG_TRAPPED, &sh->state)) {
1008 r5c_cache_data(conf->log, sh, s);
1009 return;
1010 }
1011 }
1012 1003
1013 should_defer = conf->batch_bio_dispatch && conf->group_cnt; 1004 should_defer = conf->batch_bio_dispatch && conf->group_cnt;
1014 1005
@@ -3345,7 +3336,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
3345 if (bi) 3336 if (bi)
3346 bitmap_end = 1; 3337 bitmap_end = 1;
3347 3338
3348 r5l_stripe_write_finished(sh); 3339 log_stripe_write_finished(sh);
3349 3340
3350 if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) 3341 if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
3351 wake_up(&conf->wait_for_overlap); 3342 wake_up(&conf->wait_for_overlap);
@@ -3764,7 +3755,7 @@ returnbi:
3764 discard_pending = 1; 3755 discard_pending = 1;
3765 } 3756 }
3766 3757
3767 r5l_stripe_write_finished(sh); 3758 log_stripe_write_finished(sh);
3768 3759
3769 if (!discard_pending && 3760 if (!discard_pending &&
3770 test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) { 3761 test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
@@ -4754,7 +4745,7 @@ static void handle_stripe(struct stripe_head *sh)
4754 4745
4755 if (s.just_cached) 4746 if (s.just_cached)
4756 r5c_handle_cached_data_endio(conf, sh, disks, &s.return_bi); 4747 r5c_handle_cached_data_endio(conf, sh, disks, &s.return_bi);
4757 r5l_stripe_write_finished(sh); 4748 log_stripe_write_finished(sh);
4758 4749
4759 /* Now we might consider reading some blocks, either to check/generate 4750 /* Now we might consider reading some blocks, either to check/generate
4760 * parity, or to satisfy requests 4751 * parity, or to satisfy requests
@@ -6168,7 +6159,7 @@ static int handle_active_stripes(struct r5conf *conf, int group,
6168 6159
6169 for (i = 0; i < batch_size; i++) 6160 for (i = 0; i < batch_size; i++)
6170 handle_stripe(batch[i]); 6161 handle_stripe(batch[i]);
6171 r5l_write_stripe_run(conf->log); 6162 log_write_stripe_run(conf);
6172 6163
6173 cond_resched(); 6164 cond_resched();
6174 6165
@@ -6745,8 +6736,8 @@ static void free_conf(struct r5conf *conf)
6745{ 6736{
6746 int i; 6737 int i;
6747 6738
6748 if (conf->log) 6739 log_exit(conf);
6749 r5l_exit_log(conf->log); 6740
6750 if (conf->shrinker.nr_deferred) 6741 if (conf->shrinker.nr_deferred)
6751 unregister_shrinker(&conf->shrinker); 6742 unregister_shrinker(&conf->shrinker);
6752 6743
@@ -7436,14 +7427,8 @@ static int raid5_run(struct mddev *mddev)
7436 blk_queue_max_hw_sectors(mddev->queue, UINT_MAX); 7427 blk_queue_max_hw_sectors(mddev->queue, UINT_MAX);
7437 } 7428 }
7438 7429
7439 if (journal_dev) { 7430 if (log_init(conf, journal_dev))
7440 char b[BDEVNAME_SIZE]; 7431 goto abort;
7441
7442 pr_debug("md/raid:%s: using device %s as journal\n",
7443 mdname(mddev), bdevname(journal_dev->bdev, b));
7444 if (r5l_init_log(conf, journal_dev))
7445 goto abort;
7446 }
7447 7432
7448 return 0; 7433 return 0;
7449abort: 7434abort:
@@ -7557,17 +7542,13 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
7557 7542
7558 print_raid5_conf(conf); 7543 print_raid5_conf(conf);
7559 if (test_bit(Journal, &rdev->flags) && conf->log) { 7544 if (test_bit(Journal, &rdev->flags) && conf->log) {
7560 struct r5l_log *log;
7561 /* 7545 /*
7562 * we can't wait pending write here, as this is called in 7546 * we can't wait pending write here, as this is called in
7563 * raid5d, wait will deadlock. 7547 * raid5d, wait will deadlock.
7564 */ 7548 */
7565 if (atomic_read(&mddev->writes_pending)) 7549 if (atomic_read(&mddev->writes_pending))
7566 return -EBUSY; 7550 return -EBUSY;
7567 log = conf->log; 7551 log_exit(conf);
7568 conf->log = NULL;
7569 synchronize_rcu();
7570 r5l_exit_log(log);
7571 return 0; 7552 return 0;
7572 } 7553 }
7573 if (rdev == p->rdev) 7554 if (rdev == p->rdev)
@@ -7636,7 +7617,6 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
7636 int last = conf->raid_disks - 1; 7617 int last = conf->raid_disks - 1;
7637 7618
7638 if (test_bit(Journal, &rdev->flags)) { 7619 if (test_bit(Journal, &rdev->flags)) {
7639 char b[BDEVNAME_SIZE];
7640 if (conf->log) 7620 if (conf->log)
7641 return -EBUSY; 7621 return -EBUSY;
7642 7622
@@ -7645,9 +7625,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
7645 * The array is in readonly mode if journal is missing, so no 7625 * The array is in readonly mode if journal is missing, so no
7646 * write requests running. We should be safe 7626 * write requests running. We should be safe
7647 */ 7627 */
7648 r5l_init_log(conf, rdev); 7628 log_init(conf, rdev);
7649 pr_debug("md/raid:%s: using device %s as journal\n",
7650 mdname(mddev), bdevname(rdev->bdev, b));
7651 return 0; 7629 return 0;
7652 } 7630 }
7653 if (mddev->recovery_disabled == conf->recovery_disabled) 7631 if (mddev->recovery_disabled == conf->recovery_disabled)
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 985cdc4850c2..6dd295a80ee1 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -779,34 +779,4 @@ extern struct stripe_head *
779raid5_get_active_stripe(struct r5conf *conf, sector_t sector, 779raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
780 int previous, int noblock, int noquiesce); 780 int previous, int noblock, int noquiesce);
781extern int raid5_calc_degraded(struct r5conf *conf); 781extern int raid5_calc_degraded(struct r5conf *conf);
782extern int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev);
783extern void r5l_exit_log(struct r5l_log *log);
784extern int r5l_write_stripe(struct r5l_log *log, struct stripe_head *head_sh);
785extern void r5l_write_stripe_run(struct r5l_log *log);
786extern void r5l_flush_stripe_to_raid(struct r5l_log *log);
787extern void r5l_stripe_write_finished(struct stripe_head *sh);
788extern int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio);
789extern void r5l_quiesce(struct r5l_log *log, int state);
790extern bool r5l_log_disk_error(struct r5conf *conf);
791extern bool r5c_is_writeback(struct r5l_log *log);
792extern int
793r5c_try_caching_write(struct r5conf *conf, struct stripe_head *sh,
794 struct stripe_head_state *s, int disks);
795extern void
796r5c_finish_stripe_write_out(struct r5conf *conf, struct stripe_head *sh,
797 struct stripe_head_state *s);
798extern void r5c_release_extra_page(struct stripe_head *sh);
799extern void r5c_use_extra_page(struct stripe_head *sh);
800extern void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
801extern void r5c_handle_cached_data_endio(struct r5conf *conf,
802 struct stripe_head *sh, int disks, struct bio_list *return_bi);
803extern int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh,
804 struct stripe_head_state *s);
805extern void r5c_make_stripe_write_out(struct stripe_head *sh);
806extern void r5c_flush_cache(struct r5conf *conf, int num);
807extern void r5c_check_stripe_cache_usage(struct r5conf *conf);
808extern void r5c_check_cached_full_stripe(struct r5conf *conf);
809extern struct md_sysfs_entry r5c_journal_mode;
810extern void r5c_update_on_rdev_error(struct mddev *mddev);
811extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
812#endif 782#endif