md/raid5-cache: use READ_ONCE/WRITE_ONCE for 'conf->log'
[linux-2.6-microblaze.git] / drivers / md / raid5-cache.c
index 518b7cf..889bba6 100644 (file)
@@ -327,8 +327,9 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
 void r5c_check_stripe_cache_usage(struct r5conf *conf)
 {
        int total_cached;
+       struct r5l_log *log = READ_ONCE(conf->log);
 
-       if (!r5c_is_writeback(conf->log))
+       if (!r5c_is_writeback(log))
                return;
 
        total_cached = atomic_read(&conf->r5c_cached_partial_stripes) +
@@ -344,7 +345,7 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)
         */
        if (total_cached > conf->min_nr_stripes * 1 / 2 ||
            atomic_read(&conf->empty_inactive_list_nr) > 0)
-               r5l_wake_reclaim(conf->log, 0);
+               r5l_wake_reclaim(log, 0);
 }
 
 /*
@@ -353,7 +354,9 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)
  */
 void r5c_check_cached_full_stripe(struct r5conf *conf)
 {
-       if (!r5c_is_writeback(conf->log))
+       struct r5l_log *log = READ_ONCE(conf->log);
+
+       if (!r5c_is_writeback(log))
                return;
 
        /*
@@ -363,7 +366,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)
        if (atomic_read(&conf->r5c_cached_full_stripes) >=
            min(R5C_FULL_STRIPE_FLUSH_BATCH(conf),
                conf->chunk_sectors >> RAID5_STRIPE_SHIFT(conf)))
-               r5l_wake_reclaim(conf->log, 0);
+               r5l_wake_reclaim(log, 0);
 }
 
 /*
@@ -396,7 +399,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)
  */
 static sector_t r5c_log_required_to_flush_cache(struct r5conf *conf)
 {
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
 
        if (!r5c_is_writeback(log))
                return 0;
@@ -449,7 +452,7 @@ static inline void r5c_update_log_state(struct r5l_log *log)
 void r5c_make_stripe_write_out(struct stripe_head *sh)
 {
        struct r5conf *conf = sh->raid_conf;
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
 
        BUG_ON(!r5c_is_writeback(log));
 
@@ -491,7 +494,7 @@ static void r5c_handle_parity_cached(struct stripe_head *sh)
  */
 static void r5c_finish_cache_stripe(struct stripe_head *sh)
 {
-       struct r5l_log *log = sh->raid_conf->log;
+       struct r5l_log *log = READ_ONCE(sh->raid_conf->log);
 
        if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
                BUG_ON(test_bit(STRIPE_R5C_CACHING, &sh->state));
@@ -692,7 +695,7 @@ static void r5c_disable_writeback_async(struct work_struct *work)
 
        /* wait superblock change before suspend */
        wait_event(mddev->sb_wait,
-                  conf->log == NULL ||
+                  !READ_ONCE(conf->log) ||
                   (!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) &&
                    (locked = mddev_trylock(mddev))));
        if (locked) {
@@ -1151,7 +1154,7 @@ static void r5l_run_no_space_stripes(struct r5l_log *log)
 static sector_t r5c_calculate_new_cp(struct r5conf *conf)
 {
        struct stripe_head *sh;
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
        sector_t new_cp;
        unsigned long flags;
 
@@ -1159,12 +1162,12 @@ static sector_t r5c_calculate_new_cp(struct r5conf *conf)
                return log->next_checkpoint;
 
        spin_lock_irqsave(&log->stripe_in_journal_lock, flags);
-       if (list_empty(&conf->log->stripe_in_journal_list)) {
+       if (list_empty(&log->stripe_in_journal_list)) {
                /* all stripes flushed */
                spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
                return log->next_checkpoint;
        }
-       sh = list_first_entry(&conf->log->stripe_in_journal_list,
+       sh = list_first_entry(&log->stripe_in_journal_list,
                              struct stripe_head, r5c);
        new_cp = sh->log_start;
        spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
@@ -1399,7 +1402,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)
        struct stripe_head *sh, *next;
 
        lockdep_assert_held(&conf->device_lock);
-       if (!conf->log)
+       if (!READ_ONCE(conf->log))
                return;
 
        count = 0;
@@ -1420,7 +1423,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)
 
 static void r5c_do_reclaim(struct r5conf *conf)
 {
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
        struct stripe_head *sh;
        int count = 0;
        unsigned long flags;
@@ -1549,7 +1552,7 @@ static void r5l_reclaim_thread(struct md_thread *thread)
 {
        struct mddev *mddev = thread->mddev;
        struct r5conf *conf = mddev->private;
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
 
        if (!log)
                return;
@@ -1591,7 +1594,7 @@ void r5l_quiesce(struct r5l_log *log, int quiesce)
 
 bool r5l_log_disk_error(struct r5conf *conf)
 {
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
 
        /* don't allow write if journal disk is missing */
        if (!log)
@@ -2635,7 +2638,7 @@ int r5c_try_caching_write(struct r5conf *conf,
                          struct stripe_head_state *s,
                          int disks)
 {
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
        int i;
        struct r5dev *dev;
        int to_cache = 0;
@@ -2802,7 +2805,7 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
                                 struct stripe_head *sh,
                                 struct stripe_head_state *s)
 {
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
        int i;
        int do_wakeup = 0;
        sector_t tree_index;
@@ -2941,7 +2944,7 @@ int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
 /* check whether this big stripe is in write back cache. */
 bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect)
 {
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
        sector_t tree_index;
        void *slot;
 
@@ -3049,14 +3052,14 @@ int r5l_start(struct r5l_log *log)
 void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
 {
        struct r5conf *conf = mddev->private;
-       struct r5l_log *log = conf->log;
+       struct r5l_log *log = READ_ONCE(conf->log);
 
        if (!log)
                return;
 
        if ((raid5_calc_degraded(conf) > 0 ||
             test_bit(Journal, &rdev->flags)) &&
-           conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
+           log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
                schedule_work(&log->disable_writeback_work);
 }
 
@@ -3145,7 +3148,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
        spin_lock_init(&log->stripe_in_journal_lock);
        atomic_set(&log->stripe_in_journal_count, 0);
 
-       conf->log = log;
+       WRITE_ONCE(conf->log, log);
 
        set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
        return 0;
@@ -3173,7 +3176,7 @@ void r5l_exit_log(struct r5conf *conf)
         * 'reconfig_mutex' is held by caller, set 'confg->log' to NULL to
         * ensure disable_writeback_work wakes up and exits.
         */
-       conf->log = NULL;
+       WRITE_ONCE(conf->log, NULL);
        wake_up(&conf->mddev->sb_wait);
        flush_work(&log->disable_writeback_work);