forked from mirrors/linux
		
	md/raid5. Don't write to known bad block on doubtful devices.
If a device has seen write errors, don't write to any known bad blocks on that device. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
		
							parent
							
								
									bc2607f393
								
							
						
					
					
						commit
						73e92e51b7
					
				
					 1 changed files with 30 additions and 1 deletions
				
			
		| 
						 | 
					@ -526,6 +526,36 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 | 
				
			||||||
			atomic_inc(&rdev->nr_pending);
 | 
								atomic_inc(&rdev->nr_pending);
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* We have already checked bad blocks for reads.  Now
 | 
				
			||||||
 | 
							 * need to check for writes.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							while ((rw & WRITE) && rdev &&
 | 
				
			||||||
 | 
							       test_bit(WriteErrorSeen, &rdev->flags)) {
 | 
				
			||||||
 | 
								sector_t first_bad;
 | 
				
			||||||
 | 
								int bad_sectors;
 | 
				
			||||||
 | 
								int bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
 | 
				
			||||||
 | 
										      &first_bad, &bad_sectors);
 | 
				
			||||||
 | 
								if (!bad)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (bad < 0) {
 | 
				
			||||||
 | 
									set_bit(BlockedBadBlocks, &rdev->flags);
 | 
				
			||||||
 | 
									if (!conf->mddev->external &&
 | 
				
			||||||
 | 
									    conf->mddev->flags) {
 | 
				
			||||||
 | 
										/* It is very unlikely, but we might
 | 
				
			||||||
 | 
										 * still need to write out the
 | 
				
			||||||
 | 
										 * bad block log - better give it
 | 
				
			||||||
 | 
										 * a chance*/
 | 
				
			||||||
 | 
										md_check_recovery(conf->mddev);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									md_wait_for_blocked_rdev(rdev, conf->mddev);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									/* Acknowledged bad block - skip the write */
 | 
				
			||||||
 | 
									rdev_dec_pending(rdev, conf->mddev);
 | 
				
			||||||
 | 
									rdev = NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (rdev) {
 | 
							if (rdev) {
 | 
				
			||||||
			if (s->syncing || s->expanding || s->expanded)
 | 
								if (s->syncing || s->expanding || s->expanded)
 | 
				
			||||||
				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 | 
									md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 | 
				
			||||||
| 
						 | 
					@ -3317,7 +3347,6 @@ static void handle_stripe(struct stripe_head *sh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ops_run_io(sh, &s);
 | 
						ops_run_io(sh, &s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (s.dec_preread_active) {
 | 
						if (s.dec_preread_active) {
 | 
				
			||||||
		/* We delay this until after ops_run_io so that if make_request
 | 
							/* We delay this until after ops_run_io so that if make_request
 | 
				
			||||||
		 * is waiting on a flush, it won't continue until the writes
 | 
							 * is waiting on a flush, it won't continue until the writes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue