Commit ea9694b2 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] md: remove possible oops in md/raid1

When we get a pointer and check it is non-null, we should not get the pointer
again but should instead use the pointer we got in the first place...
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 93c944b2
...@@ -338,6 +338,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) ...@@ -338,6 +338,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
int new_disk = conf->last_used, disk = new_disk; int new_disk = conf->last_used, disk = new_disk;
const int sectors = r1_bio->sectors; const int sectors = r1_bio->sectors;
sector_t new_distance, current_distance; sector_t new_distance, current_distance;
mdk_rdev_t *new_rdev, *rdev;
rcu_read_lock(); rcu_read_lock();
/* /*
...@@ -345,13 +346,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) ...@@ -345,13 +346,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
* device if no resync is going on, or below the resync window. * device if no resync is going on, or below the resync window.
* We take the first readable disk when above the resync window. * We take the first readable disk when above the resync window.
*/ */
retry:
if (conf->mddev->recovery_cp < MaxSector && if (conf->mddev->recovery_cp < MaxSector &&
(this_sector + sectors >= conf->next_resync)) { (this_sector + sectors >= conf->next_resync)) {
/* Choose the first operation device, for consistancy */ /* Choose the first operation device, for consistancy */
new_disk = 0; new_disk = 0;
while (!conf->mirrors[new_disk].rdev || while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
!conf->mirrors[new_disk].rdev->in_sync) { !new_rdev->in_sync) {
new_disk++; new_disk++;
if (new_disk == conf->raid_disks) { if (new_disk == conf->raid_disks) {
new_disk = -1; new_disk = -1;
...@@ -363,8 +365,8 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) ...@@ -363,8 +365,8 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* make sure the disk is operational */ /* make sure the disk is operational */
while (!conf->mirrors[new_disk].rdev || while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
!conf->mirrors[new_disk].rdev->in_sync) { !new_rdev->in_sync) {
if (new_disk <= 0) if (new_disk <= 0)
new_disk = conf->raid_disks; new_disk = conf->raid_disks;
new_disk--; new_disk--;
...@@ -393,18 +395,20 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) ...@@ -393,18 +395,20 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
disk = conf->raid_disks; disk = conf->raid_disks;
disk--; disk--;
if (!conf->mirrors[disk].rdev || if ((rdev=conf->mirrors[disk].rdev) == NULL ||
!conf->mirrors[disk].rdev->in_sync) !rdev->in_sync)
continue; continue;
if (!atomic_read(&conf->mirrors[disk].rdev->nr_pending)) { if (!atomic_read(&rdev->nr_pending)) {
new_disk = disk; new_disk = disk;
new_rdev = rdev;
break; break;
} }
new_distance = abs(this_sector - conf->mirrors[disk].head_position); new_distance = abs(this_sector - conf->mirrors[disk].head_position);
if (new_distance < current_distance) { if (new_distance < current_distance) {
current_distance = new_distance; current_distance = new_distance;
new_disk = disk; new_disk = disk;
new_rdev = rdev;
} }
} while (disk != conf->last_used); } while (disk != conf->last_used);
...@@ -414,7 +418,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) ...@@ -414,7 +418,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
if (new_disk >= 0) { if (new_disk >= 0) {
conf->next_seq_sect = this_sector + sectors; conf->next_seq_sect = this_sector + sectors;
conf->last_used = new_disk; conf->last_used = new_disk;
atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending); atomic_inc(&new_rdev->nr_pending);
if (!new_rdev->in_sync) {
/* cannot risk returning a device that failed
* before we inc'ed nr_pending
*/
atomic_dec(&new_rdev->nr_pending);
goto retry;
}
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -512,6 +523,7 @@ static int make_request(request_queue_t *q, struct bio * bio) ...@@ -512,6 +523,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1bio_t *r1_bio; r1bio_t *r1_bio;
struct bio *read_bio; struct bio *read_bio;
int i, disks; int i, disks;
mdk_rdev_t *rdev;
/* /*
* Register the new request and wait if the reconstruction * Register the new request and wait if the reconstruction
...@@ -585,9 +597,13 @@ static int make_request(request_queue_t *q, struct bio * bio) ...@@ -585,9 +597,13 @@ static int make_request(request_queue_t *q, struct bio * bio)
disks = conf->raid_disks; disks = conf->raid_disks;
rcu_read_lock(); rcu_read_lock();
for (i = 0; i < disks; i++) { for (i = 0; i < disks; i++) {
if (conf->mirrors[i].rdev && if ((rdev=conf->mirrors[i].rdev) != NULL &&
!conf->mirrors[i].rdev->faulty) { !rdev->faulty) {
atomic_inc(&conf->mirrors[i].rdev->nr_pending); atomic_inc(&rdev->nr_pending);
if (rdev->faulty) {
atomic_dec(&rdev->nr_pending);
r1_bio->bios[i] = NULL;
} else
r1_bio->bios[i] = bio; r1_bio->bios[i] = bio;
} else } else
r1_bio->bios[i] = NULL; r1_bio->bios[i] = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment