md/raid5: Remove use of sh->lock in sync_request
authorNeilBrown <neilb@suse.de>
Tue, 26 Jul 2011 01:19:49 +0000 (11:19 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 26 Jul 2011 01:19:49 +0000 (11:19 +1000)
This is the start of a series of patches to remove sh->lock.

sync_request takes sh->lock before setting STRIPE_SYNCING to ensure
there is no race with testing it in handle_stripe[56].

Instead, use a new flag STRIPE_SYNC_REQUESTED and test it early
in handle_stripe[56] (after getting the same lock) and perform the
same set/clear operations if it was set.

Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Namhyung Kim <namhyung@gmail.com>
drivers/md/raid5.c
drivers/md/raid5.h

index 71480646a4596a9e6a36a426ab24666c4e3b642c..f2f2ab329690ae6beb52dc5d141f3ff8a168810b 100644 (file)
@@ -3022,6 +3022,10 @@ static void handle_stripe5(struct stripe_head *sh)
                 sh->reconstruct_state);
 
        spin_lock(&sh->lock);
+       if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+               set_bit(STRIPE_SYNCING, &sh->state);
+               clear_bit(STRIPE_INSYNC, &sh->state);
+       }
        clear_bit(STRIPE_HANDLE, &sh->state);
        clear_bit(STRIPE_DELAYED, &sh->state);
 
@@ -3313,6 +3317,10 @@ static void handle_stripe6(struct stripe_head *sh)
        memset(&s, 0, sizeof(s));
 
        spin_lock(&sh->lock);
+       if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+               set_bit(STRIPE_SYNCING, &sh->state);
+               clear_bit(STRIPE_INSYNC, &sh->state);
+       }
        clear_bit(STRIPE_HANDLE, &sh->state);
        clear_bit(STRIPE_DELAYED, &sh->state);
 
@@ -4373,10 +4381,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
 
        bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
 
-       spin_lock(&sh->lock);
-       set_bit(STRIPE_SYNCING, &sh->state);
-       clear_bit(STRIPE_INSYNC, &sh->state);
-       spin_unlock(&sh->lock);
+       set_bit(STRIPE_SYNC_REQUESTED, &sh->state);
 
        handle_stripe(sh);
        release_stripe(sh);
index 3ca77a2613ba0a544ffa9c4aca4e12122d77cc96..a33001137bf8dac95cf68fe61c074d1d2fb2c7f1 100644 (file)
@@ -289,21 +289,24 @@ struct r6_state {
 /*
  * Stripe state
  */
-#define STRIPE_HANDLE          2
-#define        STRIPE_SYNCING          3
-#define        STRIPE_INSYNC           4
-#define        STRIPE_PREREAD_ACTIVE   5
-#define        STRIPE_DELAYED          6
-#define        STRIPE_DEGRADED         7
-#define        STRIPE_BIT_DELAY        8
-#define        STRIPE_EXPANDING        9
-#define        STRIPE_EXPAND_SOURCE    10
-#define        STRIPE_EXPAND_READY     11
-#define        STRIPE_IO_STARTED       12 /* do not count towards 'bypass_count' */
-#define        STRIPE_FULL_WRITE       13 /* all blocks are set to be overwritten */
-#define        STRIPE_BIOFILL_RUN      14
-#define        STRIPE_COMPUTE_RUN      15
-#define        STRIPE_OPS_REQ_PENDING  16
+enum {
+       STRIPE_HANDLE,
+       STRIPE_SYNC_REQUESTED,
+       STRIPE_SYNCING,
+       STRIPE_INSYNC,
+       STRIPE_PREREAD_ACTIVE,
+       STRIPE_DELAYED,
+       STRIPE_DEGRADED,
+       STRIPE_BIT_DELAY,
+       STRIPE_EXPANDING,
+       STRIPE_EXPAND_SOURCE,
+       STRIPE_EXPAND_READY,
+       STRIPE_IO_STARTED,      /* do not count towards 'bypass_count' */
+       STRIPE_FULL_WRITE,      /* all blocks are set to be overwritten */
+       STRIPE_BIOFILL_RUN,
+       STRIPE_COMPUTE_RUN,
+       STRIPE_OPS_REQ_PENDING,
+};
 
 /*
  * Operation request flags