diff options
author | NeilBrown <neilb@suse.de> | 2011-07-25 21:34:20 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-07-25 21:34:20 -0400 |
commit | c4c1663be46b2ab94e59d3e0c583a8f6b188ff0c (patch) | |
tree | 2e0b6b51c0a55c5f9edad2c832a66c9949ef496d /drivers/md/raid5.h | |
parent | cbe47ec559c33a68b5ee002051b848d1531a8adb (diff) |
md/raid5: replace sh->lock with an 'active' flag.
sh->lock is now mainly used to ensure that two threads aren't running
in the locked part of handle_stripe[56] at the same time.
That can more neatly be achieved with an 'active' flag which we set
while running handle_stripe. If we find the flag is set, we simply
requeue the stripe for later by setting STRIPE_HANDLE.
For safety we take ->device_lock while examining the state of the
stripe and creating a summary in 'stripe_head_state / r6_state'.
This possibly isn't needed but as shared fields like ->toread,
->towrite are checked it is safer for now at least.
We leave the label after the old 'unlock' called "unlock" because it
will disappear in a few patches, so renaming seems pointless.
This leaves the stripe 'locked' for longer as we clear STRIPE_ACTIVE
later, but that is not a problem.
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Namhyung Kim <namhyung@gmail.com>
Diffstat (limited to 'drivers/md/raid5.h')
-rw-r--r-- | drivers/md/raid5.h | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index a33001137bf8..bb246d9e0547 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
@@ -6,11 +6,11 @@ | |||
6 | 6 | ||
7 | /* | 7 | /* |
8 | * | 8 | * |
9 | * Each stripe contains one buffer per disc. Each buffer can be in | 9 | * Each stripe contains one buffer per device. Each buffer can be in |
10 | * one of a number of states stored in "flags". Changes between | 10 | * one of a number of states stored in "flags". Changes between |
11 | * these states happen *almost* exclusively under a per-stripe | 11 | * these states happen *almost* exclusively under the protection of the |
12 | * spinlock. Some very specific changes can happen in bi_end_io, and | 12 | * STRIPE_ACTIVE flag. Some very specific changes can happen in bi_end_io, and |
13 | * these are not protected by the spin lock. | 13 | * these are not protected by STRIPE_ACTIVE. |
14 | * | 14 | * |
15 | * The flag bits that are used to represent these states are: | 15 | * The flag bits that are used to represent these states are: |
16 | * R5_UPTODATE and R5_LOCKED | 16 | * R5_UPTODATE and R5_LOCKED |
@@ -76,12 +76,10 @@ | |||
76 | * block and the cached buffer are successfully written, any buffer on | 76 | * block and the cached buffer are successfully written, any buffer on |
77 | * a written list can be returned with b_end_io. | 77 | * a written list can be returned with b_end_io. |
78 | * | 78 | * |
79 | * The write list and read list both act as fifos. The read list is | 79 | * The write list and read list both act as fifos. The read list, |
80 | * protected by the device_lock. The write and written lists are | 80 | * write list and written list are protected by the device_lock. |
81 | * protected by the stripe lock. The device_lock, which can be | 81 | * The device_lock is only for list manipulations and will only be |
82 | * claimed while the stipe lock is held, is only for list | 82 | * held for a very short time. It can be claimed from interrupts. |
83 | * manipulations and will only be held for a very short time. It can | ||
84 | * be claimed from interrupts. | ||
85 | * | 83 | * |
86 | * | 84 | * |
87 | * Stripes in the stripe cache can be on one of two lists (or on | 85 | * Stripes in the stripe cache can be on one of two lists (or on |
@@ -96,7 +94,6 @@ | |||
96 | * | 94 | * |
97 | * The inactive_list, handle_list and hash bucket lists are all protected by the | 95 | * The inactive_list, handle_list and hash bucket lists are all protected by the |
98 | * device_lock. | 96 | * device_lock. |
99 | * - stripes on the inactive_list never have their stripe_lock held. | ||
100 | * - stripes have a reference counter. If count==0, they are on a list. | 97 | * - stripes have a reference counter. If count==0, they are on a list. |
101 | * - If a stripe might need handling, STRIPE_HANDLE is set. | 98 | * - If a stripe might need handling, STRIPE_HANDLE is set. |
102 | * - When refcount reaches zero, then if STRIPE_HANDLE it is put on | 99 | * - When refcount reaches zero, then if STRIPE_HANDLE it is put on |
@@ -116,10 +113,10 @@ | |||
116 | * attach a request to an active stripe (add_stripe_bh()) | 113 | * attach a request to an active stripe (add_stripe_bh()) |
117 | * lockdev attach-buffer unlockdev | 114 | * lockdev attach-buffer unlockdev |
118 | * handle a stripe (handle_stripe()) | 115 | * handle a stripe (handle_stripe()) |
119 | * lockstripe clrSTRIPE_HANDLE ... | 116 | * setSTRIPE_ACTIVE, clrSTRIPE_HANDLE ... |
120 | * (lockdev check-buffers unlockdev) .. | 117 | * (lockdev check-buffers unlockdev) .. |
121 | * change-state .. | 118 | * change-state .. |
122 | * record io/ops needed unlockstripe schedule io/ops | 119 | * record io/ops needed clearSTRIPE_ACTIVE schedule io/ops |
123 | * release an active stripe (release_stripe()) | 120 | * release an active stripe (release_stripe()) |
124 | * lockdev if (!--cnt) { if STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev | 121 | * lockdev if (!--cnt) { if STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev |
125 | * | 122 | * |
@@ -128,8 +125,7 @@ | |||
128 | * on a cached buffer, and plus one if the stripe is undergoing stripe | 125 | * on a cached buffer, and plus one if the stripe is undergoing stripe |
129 | * operations. | 126 | * operations. |
130 | * | 127 | * |
131 | * Stripe operations are performed outside the stripe lock, | 128 | * The stripe operations are: |
132 | * the stripe operations are: | ||
133 | * -copying data between the stripe cache and user application buffers | 129 | * -copying data between the stripe cache and user application buffers |
134 | * -computing blocks to save a disk access, or to recover a missing block | 130 | * -computing blocks to save a disk access, or to recover a missing block |
135 | * -updating the parity on a write operation (reconstruct write and | 131 | * -updating the parity on a write operation (reconstruct write and |
@@ -159,7 +155,8 @@ | |||
159 | */ | 155 | */ |
160 | 156 | ||
161 | /* | 157 | /* |
162 | * Operations state - intermediate states that are visible outside of sh->lock | 158 | * Operations state - intermediate states that are visible outside of |
159 | * STRIPE_ACTIVE. | ||
163 | * In general _idle indicates nothing is running, _run indicates a data | 160 | * In general _idle indicates nothing is running, _run indicates a data |
164 | * processing operation is active, and _result means the data processing result | 161 | * processing operation is active, and _result means the data processing result |
165 | * is stable and can be acted upon. For simple operations like biofill and | 162 | * is stable and can be acted upon. For simple operations like biofill and |
@@ -209,7 +206,6 @@ struct stripe_head { | |||
209 | short ddf_layout;/* use DDF ordering to calculate Q */ | 206 | short ddf_layout;/* use DDF ordering to calculate Q */ |
210 | unsigned long state; /* state flags */ | 207 | unsigned long state; /* state flags */ |
211 | atomic_t count; /* nr of active thread/requests */ | 208 | atomic_t count; /* nr of active thread/requests */ |
212 | spinlock_t lock; | ||
213 | int bm_seq; /* sequence number for bitmap flushes */ | 209 | int bm_seq; /* sequence number for bitmap flushes */ |
214 | int disks; /* disks in stripe */ | 210 | int disks; /* disks in stripe */ |
215 | enum check_states check_state; | 211 | enum check_states check_state; |
@@ -240,7 +236,7 @@ struct stripe_head { | |||
240 | }; | 236 | }; |
241 | 237 | ||
242 | /* stripe_head_state - collects and tracks the dynamic state of a stripe_head | 238 | /* stripe_head_state - collects and tracks the dynamic state of a stripe_head |
243 | * for handle_stripe. It is only valid under spin_lock(sh->lock); | 239 | * for handle_stripe. |
244 | */ | 240 | */ |
245 | struct stripe_head_state { | 241 | struct stripe_head_state { |
246 | int syncing, expanding, expanded; | 242 | int syncing, expanding, expanded; |
@@ -290,6 +286,7 @@ struct r6_state { | |||
290 | * Stripe state | 286 | * Stripe state |
291 | */ | 287 | */ |
292 | enum { | 288 | enum { |
289 | STRIPE_ACTIVE, | ||
293 | STRIPE_HANDLE, | 290 | STRIPE_HANDLE, |
294 | STRIPE_SYNC_REQUESTED, | 291 | STRIPE_SYNC_REQUESTED, |
295 | STRIPE_SYNCING, | 292 | STRIPE_SYNCING, |
@@ -339,7 +336,7 @@ enum { | |||
339 | * PREREAD_ACTIVE. | 336 | * PREREAD_ACTIVE. |
340 | * In stripe_handle, if we find pre-reading is necessary, we do it if | 337 | * In stripe_handle, if we find pre-reading is necessary, we do it if |
341 | * PREREAD_ACTIVE is set, else we set DELAYED which will send it to the delayed queue. | 338 | * PREREAD_ACTIVE is set, else we set DELAYED which will send it to the delayed queue. |
342 | * HANDLE gets cleared if stripe_handle leave nothing locked. | 339 | * HANDLE gets cleared if stripe_handle leaves nothing locked. |
343 | */ | 340 | */ |
344 | 341 | ||
345 | 342 | ||