diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-09-02 14:04:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-09-02 14:04:09 -0400 |
commit | 72a8d129cf5811b77f0d6c8acef9ac34a12bccf4 (patch) | |
tree | 4d508d7c31ad905337be336c1221ba61219c1fa1 | |
parent | 7ed77e804650b9095f862a0cfeecaa955224a73e (diff) | |
parent | b2d2c4ceaddc3098f19637a732f74b820a81a9e7 (diff) |
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md:
Fix problem with waiting while holding rcu read lock in md/bitmap.c
Remove invalidate_partition call from do_md_stop.
-rw-r--r-- | drivers/md/bitmap.c | 45 | ||||
-rw-r--r-- | drivers/md/md.c | 2 |
2 files changed, 38 insertions, 9 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7e65bad522cb..ac89a5deaca2 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -238,15 +238,47 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde | |||
238 | 238 | ||
239 | } | 239 | } |
240 | 240 | ||
241 | static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev) | ||
242 | { | ||
243 | /* Iterate the disks of an mddev, using rcu to protect access to the | ||
244 | * linked list, and raising the refcount of devices we return to ensure | ||
245 | * they don't disappear while in use. | ||
246 | * As devices are only added or removed when raid_disk is < 0 and | ||
247 | * nr_pending is 0 and In_sync is clear, the entries we return will | ||
248 | * still be in the same position on the list when we re-enter | ||
249 | * list_for_each_continue_rcu. | ||
250 | */ | ||
251 | struct list_head *pos; | ||
252 | rcu_read_lock(); | ||
253 | if (rdev == NULL) | ||
254 | /* start at the beginning */ | ||
255 | pos = &mddev->disks; | ||
256 | else { | ||
257 | /* release the previous rdev and start from there. */ | ||
258 | rdev_dec_pending(rdev, mddev); | ||
259 | pos = &rdev->same_set; | ||
260 | } | ||
261 | list_for_each_continue_rcu(pos, &mddev->disks) { | ||
262 | rdev = list_entry(pos, mdk_rdev_t, same_set); | ||
263 | if (rdev->raid_disk >= 0 && | ||
264 | test_bit(In_sync, &rdev->flags) && | ||
265 | !test_bit(Faulty, &rdev->flags)) { | ||
266 | /* this is a usable devices */ | ||
267 | atomic_inc(&rdev->nr_pending); | ||
268 | rcu_read_unlock(); | ||
269 | return rdev; | ||
270 | } | ||
271 | } | ||
272 | rcu_read_unlock(); | ||
273 | return NULL; | ||
274 | } | ||
275 | |||
241 | static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | 276 | static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) |
242 | { | 277 | { |
243 | mdk_rdev_t *rdev; | 278 | mdk_rdev_t *rdev = NULL; |
244 | mddev_t *mddev = bitmap->mddev; | 279 | mddev_t *mddev = bitmap->mddev; |
245 | 280 | ||
246 | rcu_read_lock(); | 281 | while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { |
247 | rdev_for_each_rcu(rdev, mddev) | ||
248 | if (test_bit(In_sync, &rdev->flags) | ||
249 | && !test_bit(Faulty, &rdev->flags)) { | ||
250 | int size = PAGE_SIZE; | 282 | int size = PAGE_SIZE; |
251 | if (page->index == bitmap->file_pages-1) | 283 | if (page->index == bitmap->file_pages-1) |
252 | size = roundup(bitmap->last_page_size, | 284 | size = roundup(bitmap->last_page_size, |
@@ -281,8 +313,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | |||
281 | + page->index * (PAGE_SIZE/512), | 313 | + page->index * (PAGE_SIZE/512), |
282 | size, | 314 | size, |
283 | page); | 315 | page); |
284 | } | 316 | } |
285 | rcu_read_unlock(); | ||
286 | 317 | ||
287 | if (wait) | 318 | if (wait) |
288 | md_super_wait(mddev); | 319 | md_super_wait(mddev); |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 8cfadc5bd2ba..4790c83d78d0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3841,8 +3841,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3841 | 3841 | ||
3842 | del_timer_sync(&mddev->safemode_timer); | 3842 | del_timer_sync(&mddev->safemode_timer); |
3843 | 3843 | ||
3844 | invalidate_partition(disk, 0); | ||
3845 | |||
3846 | switch(mode) { | 3844 | switch(mode) { |
3847 | case 1: /* readonly */ | 3845 | case 1: /* readonly */ |
3848 | err = -ENXIO; | 3846 | err = -ENXIO; |