diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-10 08:35:40 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-10 08:35:40 +0200 |
commit | 429b022af41108f6942d72547592b1d30e9a51f0 (patch) | |
tree | 7d68355529718018cdad1241285816c6f64620b2 /drivers/md/bitmap.c | |
parent | 0cd418ddb1ee88df7d16d5df06cb2da68eceb9e4 (diff) | |
parent | adee14b2e1557d0a8559f29681732d05a89dfc35 (diff) | |
download | op-kernel-dev-429b022af41108f6942d72547592b1d30e9a51f0.zip op-kernel-dev-429b022af41108f6942d72547592b1d30e9a51f0.tar.gz |
Merge commit 'v2.6.27-rc6' into core/rcu
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r-- | drivers/md/bitmap.c | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7e65bad..ac89a5d 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 } +static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev) +{ + /* Iterate the disks of an mddev, using rcu to protect access to the + * linked list, and raising the refcount of devices we return to ensure + * they don't disappear while in use. + * As devices are only added or removed when raid_disk is < 0 and + * nr_pending is 0 and In_sync is clear, the entries we return will + * still be in the same position on the list when we re-enter + * list_for_each_continue_rcu. + */ + struct list_head *pos; + rcu_read_lock(); + if (rdev == NULL) + /* start at the beginning */ + pos = &mddev->disks; + else { + /* release the previous rdev and start from there. */ + rdev_dec_pending(rdev, mddev); + pos = &rdev->same_set; + } + list_for_each_continue_rcu(pos, &mddev->disks) { + rdev = list_entry(pos, mdk_rdev_t, same_set); + if (rdev->raid_disk >= 0 && + test_bit(In_sync, &rdev->flags) && + !test_bit(Faulty, &rdev->flags)) { + /* this is a usable devices */ + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + return rdev; + } + } + rcu_read_unlock(); + return NULL; +} + static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) { - mdk_rdev_t *rdev; + mdk_rdev_t *rdev = NULL; mddev_t *mddev = bitmap->mddev; - rcu_read_lock(); - rdev_for_each_rcu(rdev, mddev) - if (test_bit(In_sync, &rdev->flags) - && !test_bit(Faulty, &rdev->flags)) { + while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { int size = PAGE_SIZE; if (page->index == bitmap->file_pages-1) size = roundup(bitmap->last_page_size, @@ -281,8 +313,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) + page->index * (PAGE_SIZE/512), size, page); - } - rcu_read_unlock(); + } if (wait) md_super_wait(mddev); |