diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 107 |
1 files changed, 23 insertions, 84 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a3d7cd96cfb7..a63a679105ca 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2308,91 +2308,20 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh, | |||
2308 | md_wakeup_thread(conf->mddev->thread); | 2308 | md_wakeup_thread(conf->mddev->thread); |
2309 | } | 2309 | } |
2310 | 2310 | ||
2311 | /* fetch_block5 - checks the given member device to see if its data needs | 2311 | /* fetch_block - checks the given member device to see if its data needs |
2312 | * to be read or computed to satisfy a request. | 2312 | * to be read or computed to satisfy a request. |
2313 | * | 2313 | * |
2314 | * Returns 1 when no more member devices need to be checked, otherwise returns | 2314 | * Returns 1 when no more member devices need to be checked, otherwise returns |
2315 | * 0 to tell the loop in handle_stripe_fill5 to continue | 2315 | * 0 to tell the loop in handle_stripe_fill to continue |
2316 | */ | 2316 | */ |
2317 | static int fetch_block5(struct stripe_head *sh, struct stripe_head_state *s, | 2317 | static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s, |
2318 | int disk_idx, int disks) | 2318 | int disk_idx, int disks) |
2319 | { | ||
2320 | struct r5dev *dev = &sh->dev[disk_idx]; | ||
2321 | struct r5dev *failed_dev = &sh->dev[s->failed_num[0]]; | ||
2322 | |||
2323 | /* is the data in this block needed, and can we get it? */ | ||
2324 | if (!test_bit(R5_LOCKED, &dev->flags) && | ||
2325 | !test_bit(R5_UPTODATE, &dev->flags) && | ||
2326 | (dev->toread || | ||
2327 | (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || | ||
2328 | s->syncing || s->expanding || | ||
2329 | (s->failed && failed_dev->toread) || | ||
2330 | (s->failed && failed_dev->towrite && | ||
2331 | !test_bit(R5_OVERWRITE, &failed_dev->flags)))))) { | ||
2332 | /* We would like to get this block, possibly by computing it, | ||
2333 | * otherwise read it if the backing disk is insync | ||
2334 | */ | ||
2335 | if ((s->uptodate == disks - 1) && | ||
2336 | (s->failed && disk_idx == s->failed_num[0])) { | ||
2337 | set_bit(STRIPE_COMPUTE_RUN, &sh->state); | ||
2338 | set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request); | ||
2339 | set_bit(R5_Wantcompute, &dev->flags); | ||
2340 | sh->ops.target = disk_idx; | ||
2341 | sh->ops.target2 = -1; | ||
2342 | s->req_compute = 1; | ||
2343 | /* Careful: from this point on 'uptodate' is in the eye | ||
2344 | * of raid_run_ops which services 'compute' operations | ||
2345 | * before writes. R5_Wantcompute flags a block that will | ||
2346 | * be R5_UPTODATE by the time it is needed for a | ||
2347 | * subsequent operation. | ||
2348 | */ | ||
2349 | s->uptodate++; | ||
2350 | return 1; /* uptodate + compute == disks */ | ||
2351 | } else if (test_bit(R5_Insync, &dev->flags)) { | ||
2352 | set_bit(R5_LOCKED, &dev->flags); | ||
2353 | set_bit(R5_Wantread, &dev->flags); | ||
2354 | s->locked++; | ||
2355 | pr_debug("Reading block %d (sync=%d)\n", disk_idx, | ||
2356 | s->syncing); | ||
2357 | } | ||
2358 | } | ||
2359 | |||
2360 | return 0; | ||
2361 | } | ||
2362 | |||
2363 | /** | ||
2364 | * handle_stripe_fill5 - read or compute data to satisfy pending requests. | ||
2365 | */ | ||
2366 | static void handle_stripe_fill5(struct stripe_head *sh, | ||
2367 | struct stripe_head_state *s, int disks) | ||
2368 | { | ||
2369 | int i; | ||
2370 | |||
2371 | /* look for blocks to read/compute, skip this if a compute | ||
2372 | * is already in flight, or if the stripe contents are in the | ||
2373 | * midst of changing due to a write | ||
2374 | */ | ||
2375 | if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state && | ||
2376 | !sh->reconstruct_state) | ||
2377 | for (i = disks; i--; ) | ||
2378 | if (fetch_block5(sh, s, i, disks)) | ||
2379 | break; | ||
2380 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2381 | } | ||
2382 | |||
2383 | /* fetch_block6 - checks the given member device to see if its data needs | ||
2384 | * to be read or computed to satisfy a request. | ||
2385 | * | ||
2386 | * Returns 1 when no more member devices need to be checked, otherwise returns | ||
2387 | * 0 to tell the loop in handle_stripe_fill6 to continue | ||
2388 | */ | ||
2389 | static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s, | ||
2390 | int disk_idx, int disks) | ||
2391 | { | 2319 | { |
2392 | struct r5dev *dev = &sh->dev[disk_idx]; | 2320 | struct r5dev *dev = &sh->dev[disk_idx]; |
2393 | struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]], | 2321 | struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]], |
2394 | &sh->dev[s->failed_num[1]] }; | 2322 | &sh->dev[s->failed_num[1]] }; |
2395 | 2323 | ||
2324 | /* is the data in this block needed, and can we get it? */ | ||
2396 | if (!test_bit(R5_LOCKED, &dev->flags) && | 2325 | if (!test_bit(R5_LOCKED, &dev->flags) && |
2397 | !test_bit(R5_UPTODATE, &dev->flags) && | 2326 | !test_bit(R5_UPTODATE, &dev->flags) && |
2398 | (dev->toread || | 2327 | (dev->toread || |
@@ -2400,7 +2329,9 @@ static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s, | |||
2400 | s->syncing || s->expanding || | 2329 | s->syncing || s->expanding || |
2401 | (s->failed >= 1 && fdev[0]->toread) || | 2330 | (s->failed >= 1 && fdev[0]->toread) || |
2402 | (s->failed >= 2 && fdev[1]->toread) || | 2331 | (s->failed >= 2 && fdev[1]->toread) || |
2403 | (s->failed && s->to_write)) { | 2332 | (sh->raid_conf->level <= 5 && s->failed && fdev[0]->towrite && |
2333 | !test_bit(R5_OVERWRITE, &fdev[0]->flags)) || | ||
2334 | (sh->raid_conf->level == 6 && s->failed && s->to_write))) { | ||
2404 | /* we would like to get this block, possibly by computing it, | 2335 | /* we would like to get this block, possibly by computing it, |
2405 | * otherwise read it if the backing disk is insync | 2336 | * otherwise read it if the backing disk is insync |
2406 | */ | 2337 | */ |
@@ -2420,6 +2351,12 @@ static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s, | |||
2420 | sh->ops.target = disk_idx; | 2351 | sh->ops.target = disk_idx; |
2421 | sh->ops.target2 = -1; /* no 2nd target */ | 2352 | sh->ops.target2 = -1; /* no 2nd target */ |
2422 | s->req_compute = 1; | 2353 | s->req_compute = 1; |
2354 | /* Careful: from this point on 'uptodate' is in the eye | ||
2355 | * of raid_run_ops which services 'compute' operations | ||
2356 | * before writes. R5_Wantcompute flags a block that will | ||
2357 | * be R5_UPTODATE by the time it is needed for a | ||
2358 | * subsequent operation. | ||
2359 | */ | ||
2423 | s->uptodate++; | 2360 | s->uptodate++; |
2424 | return 1; | 2361 | return 1; |
2425 | } else if (s->uptodate == disks-2 && s->failed >= 2) { | 2362 | } else if (s->uptodate == disks-2 && s->failed >= 2) { |
@@ -2460,11 +2397,11 @@ static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s, | |||
2460 | } | 2397 | } |
2461 | 2398 | ||
2462 | /** | 2399 | /** |
2463 | * handle_stripe_fill6 - read or compute data to satisfy pending requests. | 2400 | * handle_stripe_fill - read or compute data to satisfy pending requests. |
2464 | */ | 2401 | */ |
2465 | static void handle_stripe_fill6(struct stripe_head *sh, | 2402 | static void handle_stripe_fill(struct stripe_head *sh, |
2466 | struct stripe_head_state *s, | 2403 | struct stripe_head_state *s, |
2467 | int disks) | 2404 | int disks) |
2468 | { | 2405 | { |
2469 | int i; | 2406 | int i; |
2470 | 2407 | ||
@@ -2475,7 +2412,7 @@ static void handle_stripe_fill6(struct stripe_head *sh, | |||
2475 | if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state && | 2412 | if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state && |
2476 | !sh->reconstruct_state) | 2413 | !sh->reconstruct_state) |
2477 | for (i = disks; i--; ) | 2414 | for (i = disks; i--; ) |
2478 | if (fetch_block6(sh, s, i, disks)) | 2415 | if (fetch_block(sh, s, i, disks)) |
2479 | break; | 2416 | break; |
2480 | set_bit(STRIPE_HANDLE, &sh->state); | 2417 | set_bit(STRIPE_HANDLE, &sh->state); |
2481 | } | 2418 | } |
@@ -3122,7 +3059,7 @@ static int handle_stripe5(struct stripe_head *sh, struct stripe_head_state *s) | |||
3122 | */ | 3059 | */ |
3123 | if (s->to_read || s->non_overwrite || | 3060 | if (s->to_read || s->non_overwrite || |
3124 | (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding) | 3061 | (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding) |
3125 | handle_stripe_fill5(sh, s, disks); | 3062 | handle_stripe_fill(sh, s, disks); |
3126 | 3063 | ||
3127 | /* Now we check to see if any write operations have recently | 3064 | /* Now we check to see if any write operations have recently |
3128 | * completed | 3065 | * completed |
@@ -3313,7 +3250,7 @@ static int handle_stripe6(struct stripe_head *sh, struct stripe_head_state *s) | |||
3313 | */ | 3250 | */ |
3314 | if (s->to_read || s->non_overwrite || (s->to_write && s->failed) || | 3251 | if (s->to_read || s->non_overwrite || (s->to_write && s->failed) || |
3315 | (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding) | 3252 | (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding) |
3316 | handle_stripe_fill6(sh, s, disks); | 3253 | handle_stripe_fill(sh, s, disks); |
3317 | 3254 | ||
3318 | /* Now we check to see if any write operations have recently | 3255 | /* Now we check to see if any write operations have recently |
3319 | * completed | 3256 | * completed |
@@ -3397,6 +3334,8 @@ static void handle_stripe(struct stripe_head *sh) | |||
3397 | s.syncing = test_bit(STRIPE_SYNCING, &sh->state); | 3334 | s.syncing = test_bit(STRIPE_SYNCING, &sh->state); |
3398 | s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); | 3335 | s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); |
3399 | s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); | 3336 | s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); |
3337 | s.failed_num[0] = -1; | ||
3338 | s.failed_num[1] = -1; | ||
3400 | 3339 | ||
3401 | if (conf->level == 6) | 3340 | if (conf->level == 6) |
3402 | done = handle_stripe6(sh, &s); | 3341 | done = handle_stripe6(sh, &s); |