if (!rdev || !rdev->in_sync) { 
if (!rdev || !test_bit(In_sync, &rdev->flags)) { 
static void handle_stripe(struct stripe_head *sh){	raid6_conf_t *conf = sh->raid_conf;	int disks = conf->raid_disks;	struct bio *return_bi= NULL;	struct bio *bi;	int i;	int syncing;	int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;	int non_overwrite = 0;	int failed_num[2] = {0, 0};	struct r5dev *dev, *pdev, *qdev;	int pd_idx = sh->pd_idx;	int qd_idx = raid6_next_disk(pd_idx, disks);	int p_failed, q_failed;	PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",	       (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),	       pd_idx, qd_idx);	spin_lock(&sh->lock);	clear_bit(STRIPE_HANDLE, &sh->state);	clear_bit(STRIPE_DELAYED, &sh->state);	syncing = test_bit(STRIPE_SYNCING, &sh->state);	/* Now to look around and see what can be done */	for (i=disks; i--; ) {		mdk_rdev_t *rdev;		dev = &sh->dev[i];		clear_bit(R5_Insync, &dev->flags);		clear_bit(R5_Syncio, &dev->flags);		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",			i, dev->flags, dev->toread, dev->towrite, dev->written);		/* maybe we can reply to a read */		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {			struct bio *rbi, *rbi2;			PRINTK("Return read for disc %d\n", i);			spin_lock_irq(&conf->device_lock);			rbi = dev->toread;			dev->toread = NULL;			if (test_and_clear_bit(R5_Overlap, &dev->flags))				wake_up(&conf->wait_for_overlap);			spin_unlock_irq(&conf->device_lock);			while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {				copy_data(0, rbi, dev->page, dev->sector);				rbi2 = r5_next_bio(rbi, dev->sector);				spin_lock_irq(&conf->device_lock);				if (--rbi->bi_phys_segments == 0) {					rbi->bi_next = return_bi;					return_bi = rbi;				}				spin_unlock_irq(&conf->device_lock);				rbi = rbi2;			}		}		/* now count some things */		if (test_bit(R5_LOCKED, &dev->flags)) locked++;		if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;		if (dev->toread) to_read++;		if (dev->towrite) {			to_write++;			if (!test_bit(R5_OVERWRITE, &dev->flags))				non_overwrite++;		}		if (dev->written) written++;		rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */		if (!rdev || !rdev->in_sync) {			if ( failed < 2 )				failed_num[failed] = i;			failed++;		} else			set_bit(R5_Insync, &dev->flags);	}	PRINTK("locked=%d uptodate=%d to_read=%d"	       " to_write=%d failed=%d failed_num=%d,%d\n",	       locked, uptodate, to_read, to_write, failed,	       failed_num[0], failed_num[1]);	/* check if the array has lost >2 devices and, if so, some requests might	 * need to be failed	 */	if (failed > 2 && to_read+to_write+written) {		for (i=disks; i--; ) {			int bitmap_end = 0;			spin_lock_irq(&conf->device_lock);			/* fail all writes first */			bi = sh->dev[i].towrite;			sh->dev[i].towrite = NULL;			if (bi) { to_write--; bitmap_end = 1; }			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))				wake_up(&conf->wait_for_overlap);			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){				struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);				clear_bit(BIO_UPTODATE, &bi->bi_flags);				if (--bi->bi_phys_segments == 0) {					md_write_end(conf->mddev);					bi->bi_next = return_bi;					return_bi = bi;				}				bi = nextbi;			}			/* and fail all 'written' */			bi = sh->dev[i].written;			sh->dev[i].written = NULL;			if (bi) bitmap_end = 1;			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);				clear_bit(BIO_UPTODATE, &bi->bi_flags);				if (--bi->bi_phys_segments == 0) {					md_write_end(conf->mddev);					bi->bi_next = return_bi;					return_bi = bi;				}				bi = bi2;			}			/* fail any reads if this device is non-operational */			if (!test_bit(R5_Insync, &sh->dev[i].flags)) {				bi = sh->dev[i].toread;				sh->dev[i].toread = NULL;				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))					wake_up(&conf->wait_for_overlap);				if (bi) to_read--;				while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){					struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);					clear_bit(BIO_UPTODATE, &bi->bi_flags);					if (--bi->bi_phys_segments == 0) {						bi->bi_next = return_bi;						return_bi = bi;					}					bi = nextbi;				}			}			spin_unlock_irq(&conf->device_lock);			if (bitmap_end)				bitmap_endwrite(conf->mddev->bitmap, sh->sector,						STRIPE_SECTORS, 0, 0);		}	}	if (failed > 2 && syncing) {		md_done_sync(conf->mddev, STRIPE_SECTORS,0);		clear_bit(STRIPE_SYNCING, &sh->state);		syncing = 0;	}	/*	 * might be able to return some write requests if the parity blocks	 * are safe, or on a failed drive	 */	pdev = &sh->dev[pd_idx];	p_failed = (failed >= 1 && failed_num[0] == pd_idx)		|| (failed >= 2 && failed_num[1] == pd_idx);	qdev = &sh->dev[qd_idx];	q_failed = (failed >= 1 && failed_num[0] == qd_idx)		|| (failed >= 2 && failed_num[1] == qd_idx);	if ( written &&	     ( p_failed || ((test_bit(R5_Insync, &pdev->flags)			     && !test_bit(R5_LOCKED, &pdev->flags)			     && test_bit(R5_UPTODATE, &pdev->flags))) ) &&	     ( q_failed || ((test_bit(R5_Insync, &qdev->flags)			     && !test_bit(R5_LOCKED, &qdev->flags)			     && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {		/* any written block on an uptodate or failed drive can be		 * returned.  Note that if we 'wrote' to a failed drive,		 * it will be UPTODATE, but never LOCKED, so we don't need		 * to test 'failed' directly.		 */		for (i=disks; i--; )			if (sh->dev[i].written) {				dev = &sh->dev[i];				if (!test_bit(R5_LOCKED, &dev->flags) &&				    test_bit(R5_UPTODATE, &dev->flags) ) {					/* We can return any write requests */					int bitmap_end = 0;					struct bio *wbi, *wbi2;					PRINTK("Return write for stripe %llu disc %d\n",					       (unsigned long long)sh->sector, i);					spin_lock_irq(&conf->device_lock);					wbi = dev->written;					dev->written = NULL;					while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {						wbi2 = r5_next_bio(wbi, dev->sector);						if (--wbi->bi_phys_segments == 0) {							md_write_end(conf->mddev);							wbi->bi_next = return_bi;							return_bi = wbi;						}						wbi = wbi2;					}					if (dev->towrite == NULL)						bitmap_end = 1;					spin_unlock_irq(&conf->device_lock);					if (bitmap_end)						bitmap_endwrite(conf->mddev->bitmap, sh->sector,								STRIPE_SECTORS,								!test_bit(STRIPE_DEGRADED, &sh->state), 0);				}			}	}	/* Now we might consider reading some blocks, either to check/generate	 * parity, or to satisfy requests	 * or to load a block that is being partially written.	 */	if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) {		for (i=disks; i--;) {			dev = &sh->dev[i];			if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&			    (dev->toread ||			     (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||			     syncing ||			     (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||			     (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))				    )				) {				/* we would like to get this block, possibly				 * by computing it, but we might not be able to				 */				if (uptodate == disks-1) {					PRINTK("Computing stripe %llu block %d\n",					       (unsigned long long)sh->sector, i);					compute_block_1(sh, i);					uptodate++;				} else if ( uptodate == disks-2 && failed >= 2 ) {					/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */					int other;					for (other=disks; other--;) {						if ( other == i )							continue;						if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )							break;					}					BUG_ON(other < 0);					PRINTK("Computing stripe %llu blocks %d,%d\n",					       (unsigned long long)sh->sector, i, other);					compute_block_2(sh, i, other);					uptodate += 2;				} else if (test_bit(R5_Insync, &dev->flags)) {					set_bit(R5_LOCKED, &dev->flags);					set_bit(R5_Wantread, &dev->flags);#if 0					/* if I am just reading this block and we don't have					   a failed drive, or any pending writes then sidestep the cache */					if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&					    ! syncing && !failed && !to_write) {						sh->bh_cache[i]->b_page =  sh->bh_read[i]->b_page;						sh->bh_cache[i]->b_data =  sh->bh_read[i]->b_data;					}#endif					locked++;					PRINTK("Reading block %d (sync=%d)\n",						i, syncing);					if (syncing)						md_sync_acct(conf->disks[i].rdev->bdev,							     STRIPE_SECTORS);				}			}		}		set_bit(STRIPE_HANDLE, &sh->state);	}	/* now to consider writing and what else, if anything should be read */	if (to_write) {		int rcw=0, must_compute=0;		for (i=disks ; i--;) {			dev = &sh->dev[i];			/* Would I have to read this buffer for reconstruct_write */			if (!test_bit(R5_OVERWRITE, &dev->flags)			    && i != pd_idx && i != qd_idx			    && (!test_bit(R5_LOCKED, &dev->flags)#if 0				|| sh->bh_page[i] != bh->b_page#endif				    ) &&			    !test_bit(R5_UPTODATE, &dev->flags)) {				if (test_bit(R5_Insync, &dev->flags)) rcw++;				else {					PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);					must_compute++;				}			}		}		PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",		       (unsigned long long)sh->sector, rcw, must_compute);		set_bit(STRIPE_HANDLE, &sh->state);		if (rcw > 0)			/* want reconstruct write, but need to get some data */			for (i=disks; i--;) {				dev = &sh->dev[i];				if (!test_bit(R5_OVERWRITE, &dev->flags)				    && !(failed == 0 && (i == pd_idx || i == qd_idx))				    && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&				    test_bit(R5_Insync, &dev->flags)) {					if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))					{						PRINTK("Read_old stripe %llu block %d for Reconstruct\n",						       (unsigned long long)sh->sector, i);						set_bit(R5_LOCKED, &dev->flags);						set_bit(R5_Wantread, &dev->flags);						locked++;					} else {						PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",						       (unsigned long long)sh->sector, i);						set_bit(STRIPE_DELAYED, &sh->state);						set_bit(STRIPE_HANDLE, &sh->state);					}				}			}		/* now if nothing is locked, and if we have enough data, we can start a write request */		if (locked == 0 && rcw == 0 &&		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {			if ( must_compute > 0 ) {				/* We have failed blocks and need to compute them */				switch ( failed ) {				case 0:	BUG();				case 1: compute_block_1(sh, failed_num[0]); break;				case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;				default: BUG();	/* This request should have been failed? */				}			}			PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);			compute_parity(sh, RECONSTRUCT_WRITE);			/* now every locked buffer is ready to be written */			for (i=disks; i--;)				if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {					PRINTK("Writing stripe %llu block %d\n",					       (unsigned long long)sh->sector, i);					locked++;					set_bit(R5_Wantwrite, &sh->dev[i].flags);#if 0 /**** FIX: I don't understand the logic here... ****/					if (!test_bit(R5_Insync, &sh->dev[i].flags)					    || ((i==pd_idx || i==qd_idx) && failed == 0)) /* FIX? */						set_bit(STRIPE_INSYNC, &sh->state);#endif				}			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {				atomic_dec(&conf->preread_active_stripes);				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)					md_wakeup_thread(conf->mddev->thread);			}		}	}	/* maybe we need to check and possibly fix the parity for this stripe	 * Any reads will already have been scheduled, so we just see if enough data	 * is available	 */	if (syncing && locked == 0 &&	    !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 2) {		set_bit(STRIPE_HANDLE, &sh->state);#if 0 /* RAID-6: Don't support CHECK PARITY yet */		if (failed == 0) {			char *pagea;			if (uptodate != disks)				BUG();			compute_parity(sh, CHECK_PARITY);			uptodate--;			pagea = page_address(sh->dev[pd_idx].page);			if ((*(u32*)pagea) == 0 &&			    !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) {				/* parity is correct (on disc, not in buffer any more) */				set_bit(STRIPE_INSYNC, &sh->state);			}		}#endif		if (!test_bit(STRIPE_INSYNC, &sh->state)) {			int failed_needupdate[2];			struct r5dev *adev, *bdev;			if ( failed < 1 )				failed_num[0] = pd_idx;			if ( failed < 2 )				failed_num[1] = (failed_num[0] == qd_idx) ? pd_idx : qd_idx;			failed_needupdate[0] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[0]].flags);			failed_needupdate[1] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[1]].flags);			PRINTK("sync: failed=%d num=%d,%d fnu=%u%u\n",			       failed, failed_num[0], failed_num[1], failed_needupdate[0], failed_needupdate[1]);#if 0  /* RAID-6: This code seems to require that CHECK_PARITY destroys the uptodateness of the parity */			/* should be able to compute the missing block(s) and write to spare */			if ( failed_needupdate[0] ^ failed_needupdate[1] ) {				if (uptodate+1 != disks)					BUG();				compute_block_1(sh, failed_needupdate[0] ? failed_num[0] : failed_num[1]);				uptodate++;			} else if ( failed_needupdate[0] & failed_needupdate[1] ) {				if (uptodate+2 != disks)					BUG();				compute_block_2(sh, failed_num[0], failed_num[1]);				uptodate += 2;			}#else			compute_block_2(sh, failed_num[0], failed_num[1]);			uptodate += failed_needupdate[0] + failed_needupdate[1];#endif			if (uptodate != disks)				BUG();			PRINTK("Marking for sync stripe %llu blocks %d,%d\n",			       (unsigned long long)sh->sector, failed_num[0], failed_num[1]);			/**** FIX: Should we really do both of these unconditionally? ****/			adev = &sh->dev[failed_num[0]];			locked += !test_bit(R5_LOCKED, &adev->flags);			set_bit(R5_LOCKED, &adev->flags);			set_bit(R5_Wantwrite, &adev->flags);			bdev = &sh->dev[failed_num[1]];			locked += !test_bit(R5_LOCKED, &bdev->flags);			set_bit(R5_LOCKED, &bdev->flags);			clear_bit(STRIPE_DEGRADED, &sh->state);			set_bit(R5_Wantwrite, &bdev->flags);			set_bit(STRIPE_INSYNC, &sh->state);			set_bit(R5_Syncio, &adev->flags);			set_bit(R5_Syncio, &bdev->flags);		}	}	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {		md_done_sync(conf->mddev, STRIPE_SECTORS,1);		clear_bit(STRIPE_SYNCING, &sh->state);	}	spin_unlock(&sh->lock);	while ((bi=return_bi)) {		int bytes = bi->bi_size;		return_bi = bi->bi_next;		bi->bi_next = NULL;		bi->bi_size = 0;		bi->bi_end_io(bi, bytes, 0);	}	for (i=disks; i-- ;) {		int rw;		struct bio *bi;		mdk_rdev_t *rdev;		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))			rw = 1;		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))			rw = 0;		else			continue;		bi = &sh->dev[i].req;		bi->bi_rw = rw;		if (rw)			bi->bi_end_io = raid6_end_write_request;		else			bi->bi_end_io = raid6_end_read_request;		rcu_read_lock();		rdev = rcu_dereference(conf->disks[i].rdev);		if (rdev && rdev->faulty)			rdev = NULL;		if (rdev)			atomic_inc(&rdev->nr_pending);		rcu_read_unlock();		if (rdev) {			if (test_bit(R5_Syncio, &sh->dev[i].flags))				md_sync_acct(rdev->bdev, STRIPE_SECTORS);			bi->bi_bdev = rdev->bdev;			PRINTK("for %llu schedule op %ld on disc %d\n",				(unsigned long long)sh->sector, bi->bi_rw, i);			atomic_inc(&sh->count);			bi->bi_sector = sh->sector + rdev->data_offset;			bi->bi_flags = 1 << BIO_UPTODATE;			bi->bi_vcnt = 1;			bi->bi_max_vecs = 1;			bi->bi_idx = 0;			bi->bi_io_vec = &sh->dev[i].vec;			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;			bi->bi_io_vec[0].bv_offset = 0;			bi->bi_size = STRIPE_SIZE;			bi->bi_next = NULL;			generic_make_request(bi);		} else {			if (rw == 1)				set_bit(STRIPE_DEGRADED, &sh->state);			PRINTK("skip op %ld on disc %d for sector %llu\n",				bi->bi_rw, i, (unsigned long long)sh->sector);			clear_bit(R5_LOCKED, &sh->dev[i].flags);			set_bit(STRIPE_HANDLE, &sh->state);		}	}}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/b2d444d7ad975d555bb919601bcdc0e58975a40e/raid6main.c/clean/drivers/md/raid6main.c