Blame view

drivers/md/raid10.c 92.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * raid10.c : Multiple Devices driver for Linux
   *
   * Copyright (C) 2000-2004 Neil Brown
   *
   * RAID-10 support for md.
   *
25985edce   Lucas De Marchi   Fix common misspe...
8
   * Base on code in raid1.c.  See raid1.c for further copyright information.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
   *
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2, or (at your option)
   * any later version.
   *
   * You should have received a copy of the GNU General Public License
   * (for example /usr/src/linux/COPYING); if not, write to the Free
   * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
255707274   Stephen Rothwell   md: build failure...
21
  #include <linux/delay.h>
bff61975b   NeilBrown   md: move lots of ...
22
  #include <linux/blkdev.h>
056075c76   Paul Gortmaker   md: Add module.h ...
23
  #include <linux/module.h>
bff61975b   NeilBrown   md: move lots of ...
24
  #include <linux/seq_file.h>
8bda470e8   Christian Dietrich   md/raid: use prin...
25
  #include <linux/ratelimit.h>
43b2e5d86   NeilBrown   md: move md_k.h f...
26
  #include "md.h"
ef740c372   Christoph Hellwig   md: move headers ...
27
  #include "raid10.h"
dab8b2924   Trela, Maciej   md: Add support f...
28
  #include "raid0.h"
ef740c372   Christoph Hellwig   md: move headers ...
29
  #include "bitmap.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
  
  /*
   * RAID10 provides a combination of RAID0 and RAID1 functionality.
   * The layout of data is defined by
   *    chunk_size
   *    raid_disks
   *    near_copies (stored in low byte of layout)
   *    far_copies (stored in second byte of layout)
c93983bf5   NeilBrown   [PATCH] md: suppo...
38
   *    far_offset (stored in bit 16 of layout )
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
44
45
   *
   * The data to be stored is divided into chunks using chunksize.
   * Each device is divided into far_copies sections.
   * In each section, chunks are laid out in a style similar to raid0, but
   * near_copies copies of each chunk is stored (each on a different drive).
   * The starting device for each section is offset near_copies from the starting
   * device of the previous section.
c93983bf5   NeilBrown   [PATCH] md: suppo...
46
   * Thus they are (near_copies*far_copies) of each chunk, and each is on a different
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
   * drive.
   * near_copies and far_copies must be at least one, and their product is at most
   * raid_disks.
c93983bf5   NeilBrown   [PATCH] md: suppo...
50
51
52
53
   *
   * If far_offset is true, then the far_copies are handled a bit differently.
   * The copies are still in different stripes, but instead of be very far apart
   * on disk, there are adjacent stripes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
   */
  
  /*
   * Number of guaranteed r10bios in case of extreme VM load:
   */
  #define	NR_RAID10_BIOS 256
34db0cd60   NeilBrown   md: add proper wr...
60
61
62
63
64
  /* When there are this many requests queue to be written by
   * the raid10 thread, we become 'congested' to provide back-pressure
   * for writeback.
   */
  static int max_queued_requests = 1024;
e879a8793   NeilBrown   md/raid10: typede...
65
66
  static void allow_barrier(struct r10conf *conf);
  static void lower_barrier(struct r10conf *conf);
0a27ec96b   NeilBrown   [PATCH] md: impro...
67

dd0fc66fb   Al Viro   [PATCH] gfp flags...
68
  static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  {
e879a8793   NeilBrown   md/raid10: typede...
70
  	struct r10conf *conf = data;
9f2c9d12b   NeilBrown   md: remove typede...
71
  	int size = offsetof(struct r10bio, devs[conf->copies]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

69335ef3b   NeilBrown   md/raid10: prepar...
73
74
  	/* allocate a r10bio with room for raid_disks entries in the
  	 * bios array */
7eaceacca   Jens Axboe   block: remove per...
75
  	return kzalloc(size, gfp_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
  }
  
  static void r10bio_pool_free(void *r10_bio, void *data)
  {
  	kfree(r10_bio);
  }
0310fa216   NeilBrown   Allow raid10 resy...
82
  /* Maximum size of each resync request */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  #define RESYNC_BLOCK_SIZE (64*1024)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
0310fa216   NeilBrown   Allow raid10 resy...
85
86
87
88
  /* amount of memory to reserve for resync requests */
  #define RESYNC_WINDOW (1024*1024)
  /* maximum number of concurrent requests, memory permitting */
  #define RESYNC_DEPTH (32*1024*1024/RESYNC_BLOCK_SIZE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
95
96
  
  /*
   * When performing a resync, we need to read and compare, so
   * we need as many pages are there are copies.
   * When performing a recovery, we need 2 bios, one for read,
   * one for write (we recover only one drive per r10buf)
   *
   */
dd0fc66fb   Al Viro   [PATCH] gfp flags...
97
  static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  {
e879a8793   NeilBrown   md/raid10: typede...
99
  	struct r10conf *conf = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  	struct page *page;
9f2c9d12b   NeilBrown   md: remove typede...
101
  	struct r10bio *r10_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
106
  	struct bio *bio;
  	int i, j;
  	int nalloc;
  
  	r10_bio = r10bio_pool_alloc(gfp_flags, conf);
7eaceacca   Jens Axboe   block: remove per...
107
  	if (!r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
117
118
  
  	if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
  		nalloc = conf->copies; /* resync */
  	else
  		nalloc = 2; /* recovery */
  
  	/*
  	 * Allocate bios.
  	 */
  	for (j = nalloc ; j-- ; ) {
6746557f0   NeilBrown   md: use bio_kmall...
119
  		bio = bio_kmalloc(gfp_flags, RESYNC_PAGES);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
  		if (!bio)
  			goto out_free_bio;
  		r10_bio->devs[j].bio = bio;
69335ef3b   NeilBrown   md/raid10: prepar...
123
124
125
126
127
128
  		if (!conf->have_replacement)
  			continue;
  		bio = bio_kmalloc(gfp_flags, RESYNC_PAGES);
  		if (!bio)
  			goto out_free_bio;
  		r10_bio->devs[j].repl_bio = bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
134
  	}
  	/*
  	 * Allocate RESYNC_PAGES data pages and attach them
  	 * where needed.
  	 */
  	for (j = 0 ; j < nalloc; j++) {
69335ef3b   NeilBrown   md/raid10: prepar...
135
  		struct bio *rbio = r10_bio->devs[j].repl_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  		bio = r10_bio->devs[j].bio;
  		for (i = 0; i < RESYNC_PAGES; i++) {
c65060ad4   Namhyung Kim   md/raid10: share ...
138
139
140
141
142
143
144
145
  			if (j == 1 && !test_bit(MD_RECOVERY_SYNC,
  						&conf->mddev->recovery)) {
  				/* we can share bv_page's during recovery */
  				struct bio *rbio = r10_bio->devs[0].bio;
  				page = rbio->bi_io_vec[i].bv_page;
  				get_page(page);
  			} else
  				page = alloc_page(gfp_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
  			if (unlikely(!page))
  				goto out_free_pages;
  
  			bio->bi_io_vec[i].bv_page = page;
69335ef3b   NeilBrown   md/raid10: prepar...
150
151
  			if (rbio)
  				rbio->bi_io_vec[i].bv_page = page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
  		}
  	}
  
  	return r10_bio;
  
  out_free_pages:
  	for ( ; i > 0 ; i--)
1345b1d8a   NeilBrown   [PATCH] md: defin...
159
  		safe_put_page(bio->bi_io_vec[i-1].bv_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  	while (j--)
  		for (i = 0; i < RESYNC_PAGES ; i++)
1345b1d8a   NeilBrown   [PATCH] md: defin...
162
  			safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  	j = -1;
  out_free_bio:
69335ef3b   NeilBrown   md/raid10: prepar...
165
  	while (++j < nalloc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  		bio_put(r10_bio->devs[j].bio);
69335ef3b   NeilBrown   md/raid10: prepar...
167
168
169
  		if (r10_bio->devs[j].repl_bio)
  			bio_put(r10_bio->devs[j].repl_bio);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
176
  	r10bio_pool_free(r10_bio, conf);
  	return NULL;
  }
  
  static void r10buf_pool_free(void *__r10_bio, void *data)
  {
  	int i;
e879a8793   NeilBrown   md/raid10: typede...
177
  	struct r10conf *conf = data;
9f2c9d12b   NeilBrown   md: remove typede...
178
  	struct r10bio *r10bio = __r10_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
  	int j;
  
  	for (j=0; j < conf->copies; j++) {
  		struct bio *bio = r10bio->devs[j].bio;
  		if (bio) {
  			for (i = 0; i < RESYNC_PAGES; i++) {
1345b1d8a   NeilBrown   [PATCH] md: defin...
185
  				safe_put_page(bio->bi_io_vec[i].bv_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
  				bio->bi_io_vec[i].bv_page = NULL;
  			}
  			bio_put(bio);
  		}
69335ef3b   NeilBrown   md/raid10: prepar...
190
191
192
  		bio = r10bio->devs[j].repl_bio;
  		if (bio)
  			bio_put(bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
  	}
  	r10bio_pool_free(r10bio, conf);
  }
e879a8793   NeilBrown   md/raid10: typede...
196
  static void put_all_bios(struct r10conf *conf, struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
200
201
  {
  	int i;
  
  	for (i = 0; i < conf->copies; i++) {
  		struct bio **bio = & r10_bio->devs[i].bio;
749c55e94   NeilBrown   md/raid10: clear ...
202
  		if (!BIO_SPECIAL(*bio))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
  			bio_put(*bio);
  		*bio = NULL;
69335ef3b   NeilBrown   md/raid10: prepar...
205
206
207
208
  		bio = &r10_bio->devs[i].repl_bio;
  		if (r10_bio->read_slot < 0 && !BIO_SPECIAL(*bio))
  			bio_put(*bio);
  		*bio = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
  	}
  }
9f2c9d12b   NeilBrown   md: remove typede...
211
  static void free_r10bio(struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  {
e879a8793   NeilBrown   md/raid10: typede...
213
  	struct r10conf *conf = r10_bio->mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
  	put_all_bios(conf, r10_bio);
  	mempool_free(r10_bio, conf->r10bio_pool);
  }
9f2c9d12b   NeilBrown   md: remove typede...
218
  static void put_buf(struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  {
e879a8793   NeilBrown   md/raid10: typede...
220
  	struct r10conf *conf = r10_bio->mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  
  	mempool_free(r10_bio, conf->r10buf_pool);
0a27ec96b   NeilBrown   [PATCH] md: impro...
223
  	lower_barrier(conf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  }
9f2c9d12b   NeilBrown   md: remove typede...
225
  static void reschedule_retry(struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
  {
  	unsigned long flags;
fd01b88c7   NeilBrown   md: remove typede...
228
  	struct mddev *mddev = r10_bio->mddev;
e879a8793   NeilBrown   md/raid10: typede...
229
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  
  	spin_lock_irqsave(&conf->device_lock, flags);
  	list_add(&r10_bio->retry_list, &conf->retry_list);
4443ae10c   NeilBrown   [PATCH] md: auto-...
233
  	conf->nr_queued ++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	spin_unlock_irqrestore(&conf->device_lock, flags);
388667bed   Arthur Jones   md: raid10: wake ...
235
236
  	/* wake up frozen array... */
  	wake_up(&conf->wait_barrier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
  	md_wakeup_thread(mddev->thread);
  }
  
  /*
   * raid_end_bio_io() is called when we have finished servicing a mirrored
   * operation and are ready to return a success/failure code to the buffer
   * cache layer.
   */
9f2c9d12b   NeilBrown   md: remove typede...
245
  static void raid_end_bio_io(struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  {
  	struct bio *bio = r10_bio->master_bio;
856e08e23   NeilBrown   md/raid10: avoid ...
248
  	int done;
e879a8793   NeilBrown   md/raid10: typede...
249
  	struct r10conf *conf = r10_bio->mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250

856e08e23   NeilBrown   md/raid10: avoid ...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  	if (bio->bi_phys_segments) {
  		unsigned long flags;
  		spin_lock_irqsave(&conf->device_lock, flags);
  		bio->bi_phys_segments--;
  		done = (bio->bi_phys_segments == 0);
  		spin_unlock_irqrestore(&conf->device_lock, flags);
  	} else
  		done = 1;
  	if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
  		clear_bit(BIO_UPTODATE, &bio->bi_flags);
  	if (done) {
  		bio_endio(bio, 0);
  		/*
  		 * Wake up any possible resync thread that waits for the device
  		 * to go idle.
  		 */
  		allow_barrier(conf);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
  	free_r10bio(r10_bio);
  }
  
  /*
   * Update disk head position estimator based on IRQ completion info.
   */
9f2c9d12b   NeilBrown   md: remove typede...
275
  static inline void update_head_pos(int slot, struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  {
e879a8793   NeilBrown   md/raid10: typede...
277
  	struct r10conf *conf = r10_bio->mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
  
  	conf->mirrors[r10_bio->devs[slot].devnum].head_position =
  		r10_bio->devs[slot].addr + (r10_bio->sectors);
  }
778ca0185   Namhyung Kim   md/raid10: factor...
282
283
284
  /*
   * Find the disk number which triggered given bio
   */
e879a8793   NeilBrown   md/raid10: typede...
285
  static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio,
69335ef3b   NeilBrown   md/raid10: prepar...
286
  			 struct bio *bio, int *slotp, int *replp)
778ca0185   Namhyung Kim   md/raid10: factor...
287
288
  {
  	int slot;
69335ef3b   NeilBrown   md/raid10: prepar...
289
  	int repl = 0;
778ca0185   Namhyung Kim   md/raid10: factor...
290

69335ef3b   NeilBrown   md/raid10: prepar...
291
  	for (slot = 0; slot < conf->copies; slot++) {
778ca0185   Namhyung Kim   md/raid10: factor...
292
293
  		if (r10_bio->devs[slot].bio == bio)
  			break;
69335ef3b   NeilBrown   md/raid10: prepar...
294
295
296
297
298
  		if (r10_bio->devs[slot].repl_bio == bio) {
  			repl = 1;
  			break;
  		}
  	}
778ca0185   Namhyung Kim   md/raid10: factor...
299
300
301
  
  	BUG_ON(slot == conf->copies);
  	update_head_pos(slot, r10_bio);
749c55e94   NeilBrown   md/raid10: clear ...
302
303
  	if (slotp)
  		*slotp = slot;
69335ef3b   NeilBrown   md/raid10: prepar...
304
305
  	if (replp)
  		*replp = repl;
778ca0185   Namhyung Kim   md/raid10: factor...
306
307
  	return r10_bio->devs[slot].devnum;
  }
6712ecf8f   NeilBrown   Drop 'size' argum...
308
  static void raid10_end_read_request(struct bio *bio, int error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
  {
  	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
9f2c9d12b   NeilBrown   md: remove typede...
311
  	struct r10bio *r10_bio = bio->bi_private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  	int slot, dev;
abbf098e6   NeilBrown   md/raid10: prefer...
313
  	struct md_rdev *rdev;
e879a8793   NeilBrown   md/raid10: typede...
314
  	struct r10conf *conf = r10_bio->mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
  
  	slot = r10_bio->read_slot;
  	dev = r10_bio->devs[slot].devnum;
abbf098e6   NeilBrown   md/raid10: prefer...
319
  	rdev = r10_bio->devs[slot].rdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
  	/*
  	 * this branch is our 'one mirror IO has finished' event handler:
  	 */
4443ae10c   NeilBrown   [PATCH] md: auto-...
323
324
325
  	update_head_pos(slot, r10_bio);
  
  	if (uptodate) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
328
329
330
331
332
333
334
335
  		/*
  		 * Set R10BIO_Uptodate in our master bio, so that
  		 * we will return a good error code to the higher
  		 * levels even if IO on some other mirrored buffer fails.
  		 *
  		 * The 'master' represents the composite IO operation to
  		 * user-side. So if something waits for IO, then it will
  		 * wait for the 'master' bio.
  		 */
  		set_bit(R10BIO_Uptodate, &r10_bio->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  		raid_end_bio_io(r10_bio);
abbf098e6   NeilBrown   md/raid10: prefer...
337
  		rdev_dec_pending(rdev, conf->mddev);
4443ae10c   NeilBrown   [PATCH] md: auto-...
338
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  		/*
7c4e06ff2   NeilBrown   md/raid10: some t...
340
  		 * oops, read error - keep the refcount on the rdev
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  		 */
  		char b[BDEVNAME_SIZE];
8bda470e8   Christian Dietrich   md/raid: use prin...
343
344
345
346
  		printk_ratelimited(KERN_ERR
  				   "md/raid10:%s: %s: rescheduling sector %llu
  ",
  				   mdname(conf->mddev),
abbf098e6   NeilBrown   md/raid10: prefer...
347
  				   bdevname(rdev->bdev, b),
8bda470e8   Christian Dietrich   md/raid: use prin...
348
  				   (unsigned long long)r10_bio->sector);
856e08e23   NeilBrown   md/raid10: avoid ...
349
  		set_bit(R10BIO_ReadError, &r10_bio->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
  		reschedule_retry(r10_bio);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  }
9f2c9d12b   NeilBrown   md: remove typede...
353
  static void close_write(struct r10bio *r10_bio)
bd870a16c   NeilBrown   md/raid10: Handl...
354
355
356
357
358
359
360
361
  {
  	/* clear the bitmap if all writes complete successfully */
  	bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
  			r10_bio->sectors,
  			!test_bit(R10BIO_Degraded, &r10_bio->state),
  			0);
  	md_write_end(r10_bio->mddev);
  }
9f2c9d12b   NeilBrown   md: remove typede...
362
  static void one_write_done(struct r10bio *r10_bio)
19d5f834d   NeilBrown   md/raid10: unify ...
363
364
365
366
367
368
369
370
371
372
373
374
375
  {
  	if (atomic_dec_and_test(&r10_bio->remaining)) {
  		if (test_bit(R10BIO_WriteError, &r10_bio->state))
  			reschedule_retry(r10_bio);
  		else {
  			close_write(r10_bio);
  			if (test_bit(R10BIO_MadeGood, &r10_bio->state))
  				reschedule_retry(r10_bio);
  			else
  				raid_end_bio_io(r10_bio);
  		}
  	}
  }
6712ecf8f   NeilBrown   Drop 'size' argum...
376
  static void raid10_end_write_request(struct bio *bio, int error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
  {
  	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
9f2c9d12b   NeilBrown   md: remove typede...
379
  	struct r10bio *r10_bio = bio->bi_private;
778ca0185   Namhyung Kim   md/raid10: factor...
380
  	int dev;
749c55e94   NeilBrown   md/raid10: clear ...
381
  	int dec_rdev = 1;
e879a8793   NeilBrown   md/raid10: typede...
382
  	struct r10conf *conf = r10_bio->mddev->private;
475b0321a   NeilBrown   md/raid10: writes...
383
  	int slot, repl;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
384
  	struct md_rdev *rdev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385

475b0321a   NeilBrown   md/raid10: writes...
386
  	dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387

475b0321a   NeilBrown   md/raid10: writes...
388
389
  	if (repl)
  		rdev = conf->mirrors[dev].replacement;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
390
391
392
  	if (!rdev) {
  		smp_rmb();
  		repl = 0;
475b0321a   NeilBrown   md/raid10: writes...
393
  		rdev = conf->mirrors[dev].rdev;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
394
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
  	/*
  	 * this branch is our 'one mirror IO has finished' event handler:
  	 */
6cce3b23f   NeilBrown   [PATCH] md: write...
398
  	if (!uptodate) {
475b0321a   NeilBrown   md/raid10: writes...
399
400
401
402
403
404
405
  		if (repl)
  			/* Never record new bad blocks to replacement,
  			 * just fail it.
  			 */
  			md_error(rdev->mddev, rdev);
  		else {
  			set_bit(WriteErrorSeen,	&rdev->flags);
b7044d41b   NeilBrown   md/raid10: If the...
406
407
408
  			if (!test_and_set_bit(WantReplacement, &rdev->flags))
  				set_bit(MD_RECOVERY_NEEDED,
  					&rdev->mddev->recovery);
475b0321a   NeilBrown   md/raid10: writes...
409
410
411
  			set_bit(R10BIO_WriteError, &r10_bio->state);
  			dec_rdev = 0;
  		}
749c55e94   NeilBrown   md/raid10: clear ...
412
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
419
420
421
  		/*
  		 * Set R10BIO_Uptodate in our master bio, so that
  		 * we will return a good error code for to the higher
  		 * levels even if IO on some other mirrored buffer fails.
  		 *
  		 * The 'master' represents the composite IO operation to
  		 * user-side. So if something waits for IO, then it will
  		 * wait for the 'master' bio.
  		 */
749c55e94   NeilBrown   md/raid10: clear ...
422
423
  		sector_t first_bad;
  		int bad_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  		set_bit(R10BIO_Uptodate, &r10_bio->state);
749c55e94   NeilBrown   md/raid10: clear ...
425
  		/* Maybe we can clear some bad blocks. */
475b0321a   NeilBrown   md/raid10: writes...
426
  		if (is_badblock(rdev,
749c55e94   NeilBrown   md/raid10: clear ...
427
428
429
430
  				r10_bio->devs[slot].addr,
  				r10_bio->sectors,
  				&first_bad, &bad_sectors)) {
  			bio_put(bio);
475b0321a   NeilBrown   md/raid10: writes...
431
432
433
434
  			if (repl)
  				r10_bio->devs[slot].repl_bio = IO_MADE_GOOD;
  			else
  				r10_bio->devs[slot].bio = IO_MADE_GOOD;
749c55e94   NeilBrown   md/raid10: clear ...
435
436
437
438
  			dec_rdev = 0;
  			set_bit(R10BIO_MadeGood, &r10_bio->state);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
443
  	/*
  	 *
  	 * Let's see if all mirrored write operations have finished
  	 * already.
  	 */
19d5f834d   NeilBrown   md/raid10: unify ...
444
  	one_write_done(r10_bio);
749c55e94   NeilBrown   md/raid10: clear ...
445
446
  	if (dec_rdev)
  		rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
  /*
   * RAID10 layout manager
25985edce   Lucas De Marchi   Fix common misspe...
450
   * As well as the chunksize and raid_disks count, there are two
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
455
456
   * parameters: near_copies and far_copies.
   * near_copies * far_copies must be <= raid_disks.
   * Normally one of these will be 1.
   * If both are 1, we get raid0.
   * If near_copies == raid_disks, we get raid1.
   *
25985edce   Lucas De Marchi   Fix common misspe...
457
   * Chunks are laid out in raid0 style with near_copies copies of the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
465
466
   * first chunk, followed by near_copies copies of the next chunk and
   * so on.
   * If far_copies > 1, then after 1/far_copies of the array has been assigned
   * as described above, we start again with a device offset of near_copies.
   * So we effectively have another copy of the whole array further down all
   * the drives, but with blocks on different drives.
   * With this layout, and block is never stored twice on the one device.
   *
   * raid10_find_phys finds the sector offset of a given virtual sector
c93983bf5   NeilBrown   [PATCH] md: suppo...
467
   * on each device that it is on.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
   *
   * raid10_find_virt does the reverse mapping, from a device and a
   * sector offset to a virtual address
   */
e879a8793   NeilBrown   md/raid10: typede...
472
  static void raid10_find_phys(struct r10conf *conf, struct r10bio *r10bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  {
  	int n,f;
  	sector_t sector;
  	sector_t chunk;
  	sector_t stripe;
  	int dev;
  
  	int slot = 0;
  
  	/* now calculate first sector/dev */
  	chunk = r10bio->sector >> conf->chunk_shift;
  	sector = r10bio->sector & conf->chunk_mask;
  
  	chunk *= conf->near_copies;
  	stripe = chunk;
  	dev = sector_div(stripe, conf->raid_disks);
c93983bf5   NeilBrown   [PATCH] md: suppo...
489
490
  	if (conf->far_offset)
  		stripe *= conf->far_copies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
  
  	sector += stripe << conf->chunk_shift;
  
  	/* and calculate all the others */
  	for (n=0; n < conf->near_copies; n++) {
  		int d = dev;
  		sector_t s = sector;
  		r10bio->devs[slot].addr = sector;
  		r10bio->devs[slot].devnum = d;
  		slot++;
  
  		for (f = 1; f < conf->far_copies; f++) {
  			d += conf->near_copies;
  			if (d >= conf->raid_disks)
  				d -= conf->raid_disks;
  			s += conf->stride;
  			r10bio->devs[slot].devnum = d;
  			r10bio->devs[slot].addr = s;
  			slot++;
  		}
  		dev++;
  		if (dev >= conf->raid_disks) {
  			dev = 0;
  			sector += (conf->chunk_mask + 1);
  		}
  	}
  	BUG_ON(slot != conf->copies);
  }
e879a8793   NeilBrown   md/raid10: typede...
519
  static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
  {
  	sector_t offset, chunk, vchunk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  	offset = sector & conf->chunk_mask;
c93983bf5   NeilBrown   [PATCH] md: suppo...
523
524
525
526
527
528
529
530
  	if (conf->far_offset) {
  		int fc;
  		chunk = sector >> conf->chunk_shift;
  		fc = sector_div(chunk, conf->far_copies);
  		dev -= fc * conf->near_copies;
  		if (dev < 0)
  			dev += conf->raid_disks;
  	} else {
64a742bc6   NeilBrown   [PATCH] md: fix r...
531
  		while (sector >= conf->stride) {
c93983bf5   NeilBrown   [PATCH] md: suppo...
532
533
534
535
536
537
538
539
  			sector -= conf->stride;
  			if (dev < conf->near_copies)
  				dev += conf->raid_disks - conf->near_copies;
  			else
  				dev -= conf->near_copies;
  		}
  		chunk = sector >> conf->chunk_shift;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
545
546
547
  	vchunk = chunk * conf->raid_disks + dev;
  	sector_div(vchunk, conf->near_copies);
  	return (vchunk << conf->chunk_shift) + offset;
  }
  
  /**
   *	raid10_mergeable_bvec -- tell bio layer if a two requests can be merged
   *	@q: request queue
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
548
   *	@bvm: properties of new bio
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
553
554
   *	@biovec: the request that could be merged to it.
   *
   *	Return amount of bytes we can accept at this offset
   *      If near_copies == raid_disk, there are no striping issues,
   *      but in that case, the function isn't called at all.
   */
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
555
556
557
  static int raid10_mergeable_bvec(struct request_queue *q,
  				 struct bvec_merge_data *bvm,
  				 struct bio_vec *biovec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  {
fd01b88c7   NeilBrown   md: remove typede...
559
  	struct mddev *mddev = q->queuedata;
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
560
  	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
  	int max;
9d8f03636   Andre Noll   md: Make mddev->c...
562
  	unsigned int chunk_sectors = mddev->chunk_sectors;
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
563
  	unsigned int bio_sectors = bvm->bi_size >> 9;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
566
  
  	max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
  	if (max < 0) max = 0; /* bio_add cannot handle a negative return */
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
567
568
  	if (max <= biovec->bv_len && bio_sectors == 0)
  		return biovec->bv_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  	else
  		return max;
  }
  
  /*
   * This routine returns the disk from which the requested read should
   * be done. There is a per-array 'next expected sequential IO' sector
   * number - if this matches on the next IO then we use the last disk.
   * There is also a per-disk 'last know head position' sector that is
   * maintained from IRQ contexts, both the normal and the resync IO
   * completion handlers update this position correctly. If there is no
   * perfect sequential match then we pick the disk whose head is closest.
   *
   * If there are 2 mirrors in the same 2 devices, performance degrades
   * because position is mirror, not device based.
   *
   * The rdev for the device selected will have nr_pending incremented.
   */
  
  /*
   * FIXME: possibly should rethink readbalancing and do it differently
   * depending on near_copies / far_copies geometry.
   */
96c3fd1f3   NeilBrown   md/raid10: chang...
592
593
594
  static struct md_rdev *read_balance(struct r10conf *conf,
  				    struct r10bio *r10_bio,
  				    int *max_sectors)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  {
af3a2cd6b   NeilBrown   md: Fix read bala...
596
  	const sector_t this_sector = r10_bio->sector;
56d991210   NeilBrown   md: simplify raid...
597
  	int disk, slot;
856e08e23   NeilBrown   md/raid10: avoid ...
598
599
  	int sectors = r10_bio->sectors;
  	int best_good_sectors;
56d991210   NeilBrown   md: simplify raid...
600
  	sector_t new_distance, best_dist;
abbf098e6   NeilBrown   md/raid10: prefer...
601
  	struct md_rdev *rdev, *best_rdev;
56d991210   NeilBrown   md: simplify raid...
602
603
  	int do_balance;
  	int best_slot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
606
  
  	raid10_find_phys(conf, r10_bio);
  	rcu_read_lock();
56d991210   NeilBrown   md: simplify raid...
607
  retry:
856e08e23   NeilBrown   md/raid10: avoid ...
608
  	sectors = r10_bio->sectors;
56d991210   NeilBrown   md: simplify raid...
609
  	best_slot = -1;
abbf098e6   NeilBrown   md/raid10: prefer...
610
  	best_rdev = NULL;
56d991210   NeilBrown   md: simplify raid...
611
  	best_dist = MaxSector;
856e08e23   NeilBrown   md/raid10: avoid ...
612
  	best_good_sectors = 0;
56d991210   NeilBrown   md: simplify raid...
613
  	do_balance = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
  	/*
  	 * Check if we can balance. We can balance on the whole
6cce3b23f   NeilBrown   [PATCH] md: write...
616
617
618
  	 * device if no resync is going on (recovery is ok), or below
  	 * the resync window. We take the first readable disk when
  	 * above the resync window.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
  	 */
  	if (conf->mddev->recovery_cp < MaxSector
56d991210   NeilBrown   md: simplify raid...
621
622
  	    && (this_sector + sectors >= conf->next_resync))
  		do_balance = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623

56d991210   NeilBrown   md: simplify raid...
624
  	for (slot = 0; slot < conf->copies ; slot++) {
856e08e23   NeilBrown   md/raid10: avoid ...
625
626
627
  		sector_t first_bad;
  		int bad_sectors;
  		sector_t dev_sector;
56d991210   NeilBrown   md: simplify raid...
628
629
  		if (r10_bio->devs[slot].bio == IO_BLOCKED)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  		disk = r10_bio->devs[slot].devnum;
abbf098e6   NeilBrown   md/raid10: prefer...
631
632
633
634
  		rdev = rcu_dereference(conf->mirrors[disk].replacement);
  		if (rdev == NULL || test_bit(Faulty, &rdev->flags) ||
  		    r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
  			rdev = rcu_dereference(conf->mirrors[disk].rdev);
56d991210   NeilBrown   md: simplify raid...
635
  		if (rdev == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
  			continue;
abbf098e6   NeilBrown   md/raid10: prefer...
637
638
639
640
  		if (test_bit(Faulty, &rdev->flags))
  			continue;
  		if (!test_bit(In_sync, &rdev->flags) &&
  		    r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
56d991210   NeilBrown   md: simplify raid...
641
  			continue;
856e08e23   NeilBrown   md/raid10: avoid ...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
  		dev_sector = r10_bio->devs[slot].addr;
  		if (is_badblock(rdev, dev_sector, sectors,
  				&first_bad, &bad_sectors)) {
  			if (best_dist < MaxSector)
  				/* Already have a better slot */
  				continue;
  			if (first_bad <= dev_sector) {
  				/* Cannot read here.  If this is the
  				 * 'primary' device, then we must not read
  				 * beyond 'bad_sectors' from another device.
  				 */
  				bad_sectors -= (dev_sector - first_bad);
  				if (!do_balance && sectors > bad_sectors)
  					sectors = bad_sectors;
  				if (best_good_sectors > sectors)
  					best_good_sectors = sectors;
  			} else {
  				sector_t good_sectors =
  					first_bad - dev_sector;
  				if (good_sectors > best_good_sectors) {
  					best_good_sectors = good_sectors;
  					best_slot = slot;
abbf098e6   NeilBrown   md/raid10: prefer...
664
  					best_rdev = rdev;
856e08e23   NeilBrown   md/raid10: avoid ...
665
666
667
668
669
670
671
672
  				}
  				if (!do_balance)
  					/* Must read from here */
  					break;
  			}
  			continue;
  		} else
  			best_good_sectors = sectors;
56d991210   NeilBrown   md: simplify raid...
673
674
  		if (!do_balance)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675

22dfdf521   NeilBrown   [PATCH] md: impro...
676
677
678
679
  		/* This optimisation is debatable, and completely destroys
  		 * sequential read speed for 'far copies' arrays.  So only
  		 * keep it for 'near' arrays, and review those later.
  		 */
56d991210   NeilBrown   md: simplify raid...
680
  		if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  			break;
8ed3a1956   Keld Simonsen   md: don't attempt...
682
683
684
  
  		/* for far > 1 always use the lowest address */
  		if (conf->far_copies > 1)
56d991210   NeilBrown   md: simplify raid...
685
  			new_distance = r10_bio->devs[slot].addr;
8ed3a1956   Keld Simonsen   md: don't attempt...
686
  		else
56d991210   NeilBrown   md: simplify raid...
687
688
689
690
691
  			new_distance = abs(r10_bio->devs[slot].addr -
  					   conf->mirrors[disk].head_position);
  		if (new_distance < best_dist) {
  			best_dist = new_distance;
  			best_slot = slot;
abbf098e6   NeilBrown   md/raid10: prefer...
692
  			best_rdev = rdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
  		}
  	}
abbf098e6   NeilBrown   md/raid10: prefer...
695
  	if (slot >= conf->copies) {
56d991210   NeilBrown   md: simplify raid...
696
  		slot = best_slot;
abbf098e6   NeilBrown   md/raid10: prefer...
697
698
  		rdev = best_rdev;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699

56d991210   NeilBrown   md: simplify raid...
700
  	if (slot >= 0) {
56d991210   NeilBrown   md: simplify raid...
701
702
703
704
705
706
707
708
709
710
  		atomic_inc(&rdev->nr_pending);
  		if (test_bit(Faulty, &rdev->flags)) {
  			/* Cannot risk returning a device that failed
  			 * before we inc'ed nr_pending
  			 */
  			rdev_dec_pending(rdev, conf->mddev);
  			goto retry;
  		}
  		r10_bio->read_slot = slot;
  	} else
96c3fd1f3   NeilBrown   md/raid10: chang...
711
  		rdev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
  	rcu_read_unlock();
856e08e23   NeilBrown   md/raid10: avoid ...
713
  	*max_sectors = best_good_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714

96c3fd1f3   NeilBrown   md/raid10: chang...
715
  	return rdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  }
0d1292282   NeilBrown   [PATCH] md: defin...
717
718
  static int raid10_congested(void *data, int bits)
  {
fd01b88c7   NeilBrown   md: remove typede...
719
  	struct mddev *mddev = data;
e879a8793   NeilBrown   md/raid10: typede...
720
  	struct r10conf *conf = mddev->private;
0d1292282   NeilBrown   [PATCH] md: defin...
721
  	int i, ret = 0;
34db0cd60   NeilBrown   md: add proper wr...
722
723
724
  	if ((bits & (1 << BDI_async_congested)) &&
  	    conf->pending_count >= max_queued_requests)
  		return 1;
3fa841d7e   NeilBrown   md: report device...
725
726
  	if (mddev_congested(mddev, bits))
  		return 1;
0d1292282   NeilBrown   [PATCH] md: defin...
727
  	rcu_read_lock();
84707f38e   NeilBrown   md: don't use mdd...
728
  	for (i = 0; i < conf->raid_disks && ret == 0; i++) {
3cb030020   NeilBrown   md: removing type...
729
  		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
0d1292282   NeilBrown   [PATCH] md: defin...
730
  		if (rdev && !test_bit(Faulty, &rdev->flags)) {
165125e1e   Jens Axboe   [BLOCK] Get rid o...
731
  			struct request_queue *q = bdev_get_queue(rdev->bdev);
0d1292282   NeilBrown   [PATCH] md: defin...
732
733
734
735
736
737
738
  
  			ret |= bdi_congested(&q->backing_dev_info, bits);
  		}
  	}
  	rcu_read_unlock();
  	return ret;
  }
e879a8793   NeilBrown   md/raid10: typede...
739
  static void flush_pending_writes(struct r10conf *conf)
a35e63efa   NeilBrown   md: fix deadlock ...
740
741
742
  {
  	/* Any writes that have been queued but are awaiting
  	 * bitmap updates get flushed here.
a35e63efa   NeilBrown   md: fix deadlock ...
743
  	 */
a35e63efa   NeilBrown   md: fix deadlock ...
744
745
746
747
748
  	spin_lock_irq(&conf->device_lock);
  
  	if (conf->pending_bio_list.head) {
  		struct bio *bio;
  		bio = bio_list_get(&conf->pending_bio_list);
34db0cd60   NeilBrown   md: add proper wr...
749
  		conf->pending_count = 0;
a35e63efa   NeilBrown   md: fix deadlock ...
750
751
752
753
  		spin_unlock_irq(&conf->device_lock);
  		/* flush any pending bitmap writes to disk
  		 * before proceeding w/ I/O */
  		bitmap_unplug(conf->mddev->bitmap);
34db0cd60   NeilBrown   md: add proper wr...
754
  		wake_up(&conf->wait_barrier);
a35e63efa   NeilBrown   md: fix deadlock ...
755
756
757
758
759
760
761
  
  		while (bio) { /* submit pending writes */
  			struct bio *next = bio->bi_next;
  			bio->bi_next = NULL;
  			generic_make_request(bio);
  			bio = next;
  		}
a35e63efa   NeilBrown   md: fix deadlock ...
762
763
  	} else
  		spin_unlock_irq(&conf->device_lock);
a35e63efa   NeilBrown   md: fix deadlock ...
764
  }
7eaceacca   Jens Axboe   block: remove per...
765

0a27ec96b   NeilBrown   [PATCH] md: impro...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  /* Barriers....
   * Sometimes we need to suspend IO while we do something else,
   * either some resync/recovery, or reconfigure the array.
   * To do this we raise a 'barrier'.
   * The 'barrier' is a counter that can be raised multiple times
   * to count how many activities are happening which preclude
   * normal IO.
   * We can only raise the barrier if there is no pending IO.
   * i.e. if nr_pending == 0.
   * We choose only to raise the barrier if no-one is waiting for the
   * barrier to go down.  This means that as soon as an IO request
   * is ready, no other operations which require a barrier will start
   * until the IO request has had a chance.
   *
   * So: regular IO calls 'wait_barrier'.  When that returns there
   *    is no backgroup IO happening,  It must arrange to call
   *    allow_barrier when it has finished its IO.
   * backgroup IO calls must call raise_barrier.  Once that returns
   *    there is no normal IO happeing.  It must arrange to call
   *    lower_barrier when the particular background IO completes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787

e879a8793   NeilBrown   md/raid10: typede...
788
  static void raise_barrier(struct r10conf *conf, int force)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  {
6cce3b23f   NeilBrown   [PATCH] md: write...
790
  	BUG_ON(force && !conf->barrier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  	spin_lock_irq(&conf->resync_lock);
0a27ec96b   NeilBrown   [PATCH] md: impro...
792

6cce3b23f   NeilBrown   [PATCH] md: write...
793
794
  	/* Wait until no block IO is waiting (unless 'force') */
  	wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
c3b328ac8   NeilBrown   md: fix up raid1/...
795
  			    conf->resync_lock, );
0a27ec96b   NeilBrown   [PATCH] md: impro...
796
797
798
  
  	/* block any new IO from starting */
  	conf->barrier++;
c3b328ac8   NeilBrown   md: fix up raid1/...
799
  	/* Now wait for all pending IO to complete */
0a27ec96b   NeilBrown   [PATCH] md: impro...
800
801
  	wait_event_lock_irq(conf->wait_barrier,
  			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
c3b328ac8   NeilBrown   md: fix up raid1/...
802
  			    conf->resync_lock, );
0a27ec96b   NeilBrown   [PATCH] md: impro...
803
804
805
  
  	spin_unlock_irq(&conf->resync_lock);
  }
e879a8793   NeilBrown   md/raid10: typede...
806
  static void lower_barrier(struct r10conf *conf)
0a27ec96b   NeilBrown   [PATCH] md: impro...
807
808
809
810
811
812
813
  {
  	unsigned long flags;
  	spin_lock_irqsave(&conf->resync_lock, flags);
  	conf->barrier--;
  	spin_unlock_irqrestore(&conf->resync_lock, flags);
  	wake_up(&conf->wait_barrier);
  }
e879a8793   NeilBrown   md/raid10: typede...
814
  static void wait_barrier(struct r10conf *conf)
0a27ec96b   NeilBrown   [PATCH] md: impro...
815
816
817
818
819
820
  {
  	spin_lock_irq(&conf->resync_lock);
  	if (conf->barrier) {
  		conf->nr_waiting++;
  		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
  				    conf->resync_lock,
c3b328ac8   NeilBrown   md: fix up raid1/...
821
  				    );
0a27ec96b   NeilBrown   [PATCH] md: impro...
822
  		conf->nr_waiting--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  	}
0a27ec96b   NeilBrown   [PATCH] md: impro...
824
  	conf->nr_pending++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
826
  	spin_unlock_irq(&conf->resync_lock);
  }
e879a8793   NeilBrown   md/raid10: typede...
827
  static void allow_barrier(struct r10conf *conf)
0a27ec96b   NeilBrown   [PATCH] md: impro...
828
829
830
831
832
833
834
  {
  	unsigned long flags;
  	spin_lock_irqsave(&conf->resync_lock, flags);
  	conf->nr_pending--;
  	spin_unlock_irqrestore(&conf->resync_lock, flags);
  	wake_up(&conf->wait_barrier);
  }
e879a8793   NeilBrown   md/raid10: typede...
835
  static void freeze_array(struct r10conf *conf)
4443ae10c   NeilBrown   [PATCH] md: auto-...
836
837
  {
  	/* stop syncio and normal IO and wait for everything to
f188593ee   NeilBrown   [PATCH] md: fix t...
838
  	 * go quiet.
4443ae10c   NeilBrown   [PATCH] md: auto-...
839
  	 * We increment barrier and nr_waiting, and then
1c830532f   NeilBrown   md: fix possible ...
840
841
842
843
844
845
846
847
  	 * wait until nr_pending match nr_queued+1
  	 * This is called in the context of one normal IO request
  	 * that has failed. Thus any sync request that might be pending
  	 * will be blocked by nr_pending, and we need to wait for
  	 * pending IO requests to complete or be queued for re-try.
  	 * Thus the number queued (nr_queued) plus this request (1)
  	 * must match the number of pending IOs (nr_pending) before
  	 * we continue.
4443ae10c   NeilBrown   [PATCH] md: auto-...
848
849
850
851
852
  	 */
  	spin_lock_irq(&conf->resync_lock);
  	conf->barrier++;
  	conf->nr_waiting++;
  	wait_event_lock_irq(conf->wait_barrier,
1c830532f   NeilBrown   md: fix possible ...
853
  			    conf->nr_pending == conf->nr_queued+1,
4443ae10c   NeilBrown   [PATCH] md: auto-...
854
  			    conf->resync_lock,
c3b328ac8   NeilBrown   md: fix up raid1/...
855
  			    flush_pending_writes(conf));
4443ae10c   NeilBrown   [PATCH] md: auto-...
856
857
  	spin_unlock_irq(&conf->resync_lock);
  }
e879a8793   NeilBrown   md/raid10: typede...
858
  static void unfreeze_array(struct r10conf *conf)
4443ae10c   NeilBrown   [PATCH] md: auto-...
859
860
861
862
863
864
865
866
  {
  	/* reverse the effect of the freeze */
  	spin_lock_irq(&conf->resync_lock);
  	conf->barrier--;
  	conf->nr_waiting--;
  	wake_up(&conf->wait_barrier);
  	spin_unlock_irq(&conf->resync_lock);
  }
b4fdcb02f   Linus Torvalds   Merge branch 'for...
867
  static void make_request(struct mddev *mddev, struct bio * bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  {
e879a8793   NeilBrown   md/raid10: typede...
869
  	struct r10conf *conf = mddev->private;
9f2c9d12b   NeilBrown   md: remove typede...
870
  	struct r10bio *r10_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
872
873
  	struct bio *read_bio;
  	int i;
  	int chunk_sects = conf->chunk_mask + 1;
a362357b6   Jens Axboe   [BLOCK] Unify the...
874
  	const int rw = bio_data_dir(bio);
2c7d46ec1   NeilBrown   md raid-1/10 Fix ...
875
  	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
e9c7469bb   Tejun Heo   md: implment REQ_...
876
  	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
6cce3b23f   NeilBrown   [PATCH] md: write...
877
  	unsigned long flags;
3cb030020   NeilBrown   md: removing type...
878
  	struct md_rdev *blocked_rdev;
c3b328ac8   NeilBrown   md: fix up raid1/...
879
  	int plugged;
d4432c23b   NeilBrown   md/raid10: avoid ...
880
881
  	int sectors_handled;
  	int max_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882

e9c7469bb   Tejun Heo   md: implment REQ_...
883
884
  	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
  		md_flush_request(mddev, bio);
5a7bbad27   Christoph Hellwig   block: remove sup...
885
  		return;
e5dcdd80a   NeilBrown   [PATCH] md: fail ...
886
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  	/* If this request crosses a chunk boundary, we need to
  	 * split it.  This will only happen for 1 PAGE (or less) requests.
  	 */
  	if (unlikely( (bio->bi_sector & conf->chunk_mask) + (bio->bi_size >> 9)
  		      > chunk_sects &&
  		    conf->near_copies < conf->raid_disks)) {
  		struct bio_pair *bp;
  		/* Sanity check -- queue functions should prevent this happening */
  		if (bio->bi_vcnt != 1 ||
  		    bio->bi_idx != 0)
  			goto bad_map;
  		/* This is a one page bio that upper layers
  		 * refuse to split for us, so we need to split it.
  		 */
6feef531f   Denis ChengRq   block: mark bio_s...
901
  		bp = bio_split(bio,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  			       chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
51e9ac770   NeilBrown   md/raid10: fix de...
903
904
905
906
907
908
909
910
911
912
913
914
  
  		/* Each of these 'make_request' calls will call 'wait_barrier'.
  		 * If the first succeeds but the second blocks due to the resync
  		 * thread raising the barrier, we will deadlock because the
  		 * IO to the underlying device will be queued in generic_make_request
  		 * and will never complete, so will never reduce nr_pending.
  		 * So increment nr_waiting here so no new raise_barriers will
  		 * succeed, and so the second wait_barrier cannot block.
  		 */
  		spin_lock_irq(&conf->resync_lock);
  		conf->nr_waiting++;
  		spin_unlock_irq(&conf->resync_lock);
5a7bbad27   Christoph Hellwig   block: remove sup...
915
916
  		make_request(mddev, &bp->bio1);
  		make_request(mddev, &bp->bio2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917

51e9ac770   NeilBrown   md/raid10: fix de...
918
919
920
921
  		spin_lock_irq(&conf->resync_lock);
  		conf->nr_waiting--;
  		wake_up(&conf->wait_barrier);
  		spin_unlock_irq(&conf->resync_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
  		bio_pair_release(bp);
5a7bbad27   Christoph Hellwig   block: remove sup...
923
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  	bad_map:
128595ed6   NeilBrown   md/raid10: tidy u...
925
926
927
  		printk("md/raid10:%s: make_request bug: can't convert block across chunks"
  		       " or bigger than %dk %llu %d
  ", mdname(mddev), chunk_sects/2,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  		       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
6712ecf8f   NeilBrown   Drop 'size' argum...
929
  		bio_io_error(bio);
5a7bbad27   Christoph Hellwig   block: remove sup...
930
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
  	}
3d310eb7b   NeilBrown   [PATCH] md: fix d...
932
  	md_write_start(mddev, bio);
06d91a5fe   NeilBrown   [PATCH] md: impro...
933

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
938
  	/*
  	 * Register the new request and wait if the reconstruction
  	 * thread has put up a bar for new requests.
  	 * Continue immediately if no resync is active currently.
  	 */
0a27ec96b   NeilBrown   [PATCH] md: impro...
939
  	wait_barrier(conf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
944
945
946
947
  	r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
  
  	r10_bio->master_bio = bio;
  	r10_bio->sectors = bio->bi_size >> 9;
  
  	r10_bio->mddev = mddev;
  	r10_bio->sector = bio->bi_sector;
6cce3b23f   NeilBrown   [PATCH] md: write...
948
  	r10_bio->state = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949

856e08e23   NeilBrown   md/raid10: avoid ...
950
951
952
953
954
955
956
957
958
  	/* We might need to issue multiple reads to different
  	 * devices if there are bad blocks around, so we keep
  	 * track of the number of reads in bio->bi_phys_segments.
  	 * If this is 0, there is only one r10_bio and no locking
  	 * will be needed when the request completes.  If it is
  	 * non-zero, then it is the number of not-completed requests.
  	 */
  	bio->bi_phys_segments = 0;
  	clear_bit(BIO_SEG_VALID, &bio->bi_flags);
a362357b6   Jens Axboe   [BLOCK] Unify the...
959
  	if (rw == READ) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
  		/*
  		 * read balancing logic:
  		 */
96c3fd1f3   NeilBrown   md/raid10: chang...
963
  		struct md_rdev *rdev;
856e08e23   NeilBrown   md/raid10: avoid ...
964
965
966
  		int slot;
  
  read_again:
96c3fd1f3   NeilBrown   md/raid10: chang...
967
968
  		rdev = read_balance(conf, r10_bio, &max_sectors);
  		if (!rdev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
  			raid_end_bio_io(r10_bio);
5a7bbad27   Christoph Hellwig   block: remove sup...
970
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
  		}
96c3fd1f3   NeilBrown   md/raid10: chang...
972
  		slot = r10_bio->read_slot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973

a167f6632   NeilBrown   md: use separate ...
974
  		read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
856e08e23   NeilBrown   md/raid10: avoid ...
975
976
  		md_trim_bio(read_bio, r10_bio->sector - bio->bi_sector,
  			    max_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
  
  		r10_bio->devs[slot].bio = read_bio;
abbf098e6   NeilBrown   md/raid10: prefer...
979
  		r10_bio->devs[slot].rdev = rdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
  
  		read_bio->bi_sector = r10_bio->devs[slot].addr +
96c3fd1f3   NeilBrown   md/raid10: chang...
982
983
  			rdev->data_offset;
  		read_bio->bi_bdev = rdev->bdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
  		read_bio->bi_end_io = raid10_end_read_request;
7b6d91dae   Christoph Hellwig   block: unify flag...
985
  		read_bio->bi_rw = READ | do_sync;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
  		read_bio->bi_private = r10_bio;
856e08e23   NeilBrown   md/raid10: avoid ...
987
988
989
990
  		if (max_sectors < r10_bio->sectors) {
  			/* Could not read all from this device, so we will
  			 * need another r10_bio.
  			 */
856e08e23   NeilBrown   md/raid10: avoid ...
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  			sectors_handled = (r10_bio->sectors + max_sectors
  					   - bio->bi_sector);
  			r10_bio->sectors = max_sectors;
  			spin_lock_irq(&conf->device_lock);
  			if (bio->bi_phys_segments == 0)
  				bio->bi_phys_segments = 2;
  			else
  				bio->bi_phys_segments++;
  			spin_unlock(&conf->device_lock);
  			/* Cannot call generic_make_request directly
  			 * as that will be queued in __generic_make_request
  			 * and subsequent mempool_alloc might block
  			 * waiting for it.  so hand bio over to raid10d.
  			 */
  			reschedule_retry(r10_bio);
  
  			r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
  
  			r10_bio->master_bio = bio;
  			r10_bio->sectors = ((bio->bi_size >> 9)
  					    - sectors_handled);
  			r10_bio->state = 0;
  			r10_bio->mddev = mddev;
  			r10_bio->sector = bio->bi_sector + sectors_handled;
  			goto read_again;
  		} else
  			generic_make_request(read_bio);
5a7bbad27   Christoph Hellwig   block: remove sup...
1018
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
1020
1021
1022
1023
  	}
  
  	/*
  	 * WRITE:
  	 */
34db0cd60   NeilBrown   md: add proper wr...
1024
1025
1026
1027
1028
  	if (conf->pending_count >= max_queued_requests) {
  		md_wakeup_thread(mddev->thread);
  		wait_event(conf->wait_barrier,
  			   conf->pending_count < max_queued_requests);
  	}
6bfe0b499   Dan Williams   md: support block...
1029
  	/* first select target devices under rcu_lock and
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
  	 * inc refcount on their rdev.  Record them by setting
  	 * bios[x] to bio
d4432c23b   NeilBrown   md/raid10: avoid ...
1032
1033
1034
1035
1036
1037
1038
  	 * If there are known/acknowledged bad blocks on any device
  	 * on which we have seen a write error, we want to avoid
  	 * writing to those blocks.  This potentially requires several
  	 * writes to write around the bad blocks.  Each set of writes
  	 * gets its own r10_bio with a set of bios attached.  The number
  	 * of r10_bios is recored in bio->bi_phys_segments just as with
  	 * the read case.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  	 */
c3b328ac8   NeilBrown   md: fix up raid1/...
1040
  	plugged = mddev_check_plugged(mddev);
69335ef3b   NeilBrown   md/raid10: prepar...
1041
  	r10_bio->read_slot = -1; /* make sure repl_bio gets freed */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
  	raid10_find_phys(conf, r10_bio);
d4432c23b   NeilBrown   md/raid10: avoid ...
1043
  retry_write:
cb6969e8c   Harvey Harrison   misc: fix integer...
1044
  	blocked_rdev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
  	rcu_read_lock();
d4432c23b   NeilBrown   md/raid10: avoid ...
1046
  	max_sectors = r10_bio->sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
  	for (i = 0;  i < conf->copies; i++) {
  		int d = r10_bio->devs[i].devnum;
3cb030020   NeilBrown   md: removing type...
1049
  		struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
475b0321a   NeilBrown   md/raid10: writes...
1050
1051
  		struct md_rdev *rrdev = rcu_dereference(
  			conf->mirrors[d].replacement);
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1052
1053
  		if (rdev == rrdev)
  			rrdev = NULL;
6bfe0b499   Dan Williams   md: support block...
1054
1055
1056
1057
1058
  		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
  			atomic_inc(&rdev->nr_pending);
  			blocked_rdev = rdev;
  			break;
  		}
475b0321a   NeilBrown   md/raid10: writes...
1059
1060
1061
1062
1063
1064
1065
  		if (rrdev && unlikely(test_bit(Blocked, &rrdev->flags))) {
  			atomic_inc(&rrdev->nr_pending);
  			blocked_rdev = rrdev;
  			break;
  		}
  		if (rrdev && test_bit(Faulty, &rrdev->flags))
  			rrdev = NULL;
d4432c23b   NeilBrown   md/raid10: avoid ...
1066
  		r10_bio->devs[i].bio = NULL;
475b0321a   NeilBrown   md/raid10: writes...
1067
  		r10_bio->devs[i].repl_bio = NULL;
d4432c23b   NeilBrown   md/raid10: avoid ...
1068
  		if (!rdev || test_bit(Faulty, &rdev->flags)) {
6cce3b23f   NeilBrown   [PATCH] md: write...
1069
  			set_bit(R10BIO_Degraded, &r10_bio->state);
d4432c23b   NeilBrown   md/raid10: avoid ...
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  			continue;
  		}
  		if (test_bit(WriteErrorSeen, &rdev->flags)) {
  			sector_t first_bad;
  			sector_t dev_sector = r10_bio->devs[i].addr;
  			int bad_sectors;
  			int is_bad;
  
  			is_bad = is_badblock(rdev, dev_sector,
  					     max_sectors,
  					     &first_bad, &bad_sectors);
  			if (is_bad < 0) {
  				/* Mustn't write here until the bad block
  				 * is acknowledged
  				 */
  				atomic_inc(&rdev->nr_pending);
  				set_bit(BlockedBadBlocks, &rdev->flags);
  				blocked_rdev = rdev;
  				break;
  			}
  			if (is_bad && first_bad <= dev_sector) {
  				/* Cannot write here at all */
  				bad_sectors -= (dev_sector - first_bad);
  				if (bad_sectors < max_sectors)
  					/* Mustn't write more than bad_sectors
  					 * to other devices yet
  					 */
  					max_sectors = bad_sectors;
  				/* We don't set R10BIO_Degraded as that
  				 * only applies if the disk is missing,
  				 * so it might be re-added, and we want to
  				 * know to recover this chunk.
  				 * In this case the device is here, and the
  				 * fact that this chunk is not in-sync is
  				 * recorded in the bad block log.
  				 */
  				continue;
  			}
  			if (is_bad) {
  				int good_sectors = first_bad - dev_sector;
  				if (good_sectors < max_sectors)
  					max_sectors = good_sectors;
  			}
6cce3b23f   NeilBrown   [PATCH] md: write...
1113
  		}
d4432c23b   NeilBrown   md/raid10: avoid ...
1114
1115
  		r10_bio->devs[i].bio = bio;
  		atomic_inc(&rdev->nr_pending);
475b0321a   NeilBrown   md/raid10: writes...
1116
1117
1118
1119
  		if (rrdev) {
  			r10_bio->devs[i].repl_bio = bio;
  			atomic_inc(&rrdev->nr_pending);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
  	}
  	rcu_read_unlock();
6bfe0b499   Dan Williams   md: support block...
1122
1123
1124
1125
  	if (unlikely(blocked_rdev)) {
  		/* Have to wait for this device to get unblocked, then retry */
  		int j;
  		int d;
475b0321a   NeilBrown   md/raid10: writes...
1126
  		for (j = 0; j < i; j++) {
6bfe0b499   Dan Williams   md: support block...
1127
1128
1129
1130
  			if (r10_bio->devs[j].bio) {
  				d = r10_bio->devs[j].devnum;
  				rdev_dec_pending(conf->mirrors[d].rdev, mddev);
  			}
475b0321a   NeilBrown   md/raid10: writes...
1131
  			if (r10_bio->devs[j].repl_bio) {
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1132
  				struct md_rdev *rdev;
475b0321a   NeilBrown   md/raid10: writes...
1133
  				d = r10_bio->devs[j].devnum;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1134
1135
1136
1137
1138
1139
1140
  				rdev = conf->mirrors[d].replacement;
  				if (!rdev) {
  					/* Race with remove_disk */
  					smp_mb();
  					rdev = conf->mirrors[d].rdev;
  				}
  				rdev_dec_pending(rdev, mddev);
475b0321a   NeilBrown   md/raid10: writes...
1141
1142
  			}
  		}
6bfe0b499   Dan Williams   md: support block...
1143
1144
1145
1146
1147
  		allow_barrier(conf);
  		md_wait_for_blocked_rdev(blocked_rdev, mddev);
  		wait_barrier(conf);
  		goto retry_write;
  	}
d4432c23b   NeilBrown   md/raid10: avoid ...
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
  	if (max_sectors < r10_bio->sectors) {
  		/* We are splitting this into multiple parts, so
  		 * we need to prepare for allocating another r10_bio.
  		 */
  		r10_bio->sectors = max_sectors;
  		spin_lock_irq(&conf->device_lock);
  		if (bio->bi_phys_segments == 0)
  			bio->bi_phys_segments = 2;
  		else
  			bio->bi_phys_segments++;
  		spin_unlock_irq(&conf->device_lock);
  	}
  	sectors_handled = r10_bio->sector + max_sectors - bio->bi_sector;
4e78064f4   NeilBrown   md: Fix possible ...
1161
  	atomic_set(&r10_bio->remaining, 1);
d4432c23b   NeilBrown   md/raid10: avoid ...
1162
  	bitmap_startwrite(mddev->bitmap, r10_bio->sector, r10_bio->sectors, 0);
06d91a5fe   NeilBrown   [PATCH] md: impro...
1163

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
1165
1166
1167
1168
  	for (i = 0; i < conf->copies; i++) {
  		struct bio *mbio;
  		int d = r10_bio->devs[i].devnum;
  		if (!r10_bio->devs[i].bio)
  			continue;
a167f6632   NeilBrown   md: use separate ...
1169
  		mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
d4432c23b   NeilBrown   md/raid10: avoid ...
1170
1171
  		md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
  			    max_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
  		r10_bio->devs[i].bio = mbio;
d4432c23b   NeilBrown   md/raid10: avoid ...
1173
1174
  		mbio->bi_sector	= (r10_bio->devs[i].addr+
  				   conf->mirrors[d].rdev->data_offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
  		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
  		mbio->bi_end_io	= raid10_end_write_request;
e9c7469bb   Tejun Heo   md: implment REQ_...
1177
  		mbio->bi_rw = WRITE | do_sync | do_fua;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
1179
1180
  		mbio->bi_private = r10_bio;
  
  		atomic_inc(&r10_bio->remaining);
4e78064f4   NeilBrown   md: Fix possible ...
1181
1182
  		spin_lock_irqsave(&conf->device_lock, flags);
  		bio_list_add(&conf->pending_bio_list, mbio);
34db0cd60   NeilBrown   md: add proper wr...
1183
  		conf->pending_count++;
4e78064f4   NeilBrown   md: Fix possible ...
1184
  		spin_unlock_irqrestore(&conf->device_lock, flags);
475b0321a   NeilBrown   md/raid10: writes...
1185
1186
1187
1188
1189
1190
1191
1192
  
  		if (!r10_bio->devs[i].repl_bio)
  			continue;
  
  		mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
  		md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
  			    max_sectors);
  		r10_bio->devs[i].repl_bio = mbio;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1193
1194
1195
1196
  		/* We are actively writing to the original device
  		 * so it cannot disappear, so the replacement cannot
  		 * become NULL here
  		 */
475b0321a   NeilBrown   md/raid10: writes...
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
  		mbio->bi_sector	= (r10_bio->devs[i].addr+
  				   conf->mirrors[d].replacement->data_offset);
  		mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
  		mbio->bi_end_io	= raid10_end_write_request;
  		mbio->bi_rw = WRITE | do_sync | do_fua;
  		mbio->bi_private = r10_bio;
  
  		atomic_inc(&r10_bio->remaining);
  		spin_lock_irqsave(&conf->device_lock, flags);
  		bio_list_add(&conf->pending_bio_list, mbio);
  		conf->pending_count++;
  		spin_unlock_irqrestore(&conf->device_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
  	}
079fa166a   NeilBrown   md/raid1,10: Remo...
1210
1211
1212
  	/* Don't remove the bias on 'remaining' (one_write_done) until
  	 * after checking if we need to go around again.
  	 */
a35e63efa   NeilBrown   md: fix deadlock ...
1213

d4432c23b   NeilBrown   md/raid10: avoid ...
1214
  	if (sectors_handled < (bio->bi_size >> 9)) {
079fa166a   NeilBrown   md/raid1,10: Remo...
1215
  		one_write_done(r10_bio);
5e5702898   NeilBrown   md/raid10: Handle...
1216
  		/* We need another r10_bio.  It has already been counted
d4432c23b   NeilBrown   md/raid10: avoid ...
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  		 * in bio->bi_phys_segments.
  		 */
  		r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
  
  		r10_bio->master_bio = bio;
  		r10_bio->sectors = (bio->bi_size >> 9) - sectors_handled;
  
  		r10_bio->mddev = mddev;
  		r10_bio->sector = bio->bi_sector + sectors_handled;
  		r10_bio->state = 0;
  		goto retry_write;
  	}
079fa166a   NeilBrown   md/raid1,10: Remo...
1229
1230
1231
1232
  	one_write_done(r10_bio);
  
  	/* In case raid10d snuck in to freeze_array */
  	wake_up(&conf->wait_barrier);
d4432c23b   NeilBrown   md/raid10: avoid ...
1233

c3b328ac8   NeilBrown   md: fix up raid1/...
1234
  	if (do_sync || !mddev->bitmap || !plugged)
e3881a681   Lars Ellenberg   [PATCH] md: pass ...
1235
  		md_wakeup_thread(mddev->thread);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  }
fd01b88c7   NeilBrown   md: remove typede...
1237
  static void status(struct seq_file *seq, struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
  {
e879a8793   NeilBrown   md/raid10: typede...
1239
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
1241
1242
  	int i;
  
  	if (conf->near_copies < conf->raid_disks)
9d8f03636   Andre Noll   md: Make mddev->c...
1243
  		seq_printf(seq, " %dK chunks", mddev->chunk_sectors / 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
  	if (conf->near_copies > 1)
  		seq_printf(seq, " %d near-copies", conf->near_copies);
c93983bf5   NeilBrown   [PATCH] md: suppo...
1246
1247
1248
1249
1250
1251
  	if (conf->far_copies > 1) {
  		if (conf->far_offset)
  			seq_printf(seq, " %d offset-copies", conf->far_copies);
  		else
  			seq_printf(seq, " %d far-copies", conf->far_copies);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
  	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
76186dd8b   NeilBrown   [PATCH] md: remov...
1253
  					conf->raid_disks - mddev->degraded);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
  	for (i = 0; i < conf->raid_disks; i++)
  		seq_printf(seq, "%s",
  			      conf->mirrors[i].rdev &&
b2d444d7a   NeilBrown   [PATCH] md: conve...
1257
  			      test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
  	seq_printf(seq, "]");
  }
700c72138   NeilBrown   md/raid10: Improv...
1260
1261
1262
1263
1264
  /* check if there are enough drives for
   * every block to appear on atleast one.
   * Don't consider the device numbered 'ignore'
   * as we might be about to remove it.
   */
e879a8793   NeilBrown   md/raid10: typede...
1265
  static int enough(struct r10conf *conf, int ignore)
700c72138   NeilBrown   md/raid10: Improv...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
  {
  	int first = 0;
  
  	do {
  		int n = conf->copies;
  		int cnt = 0;
  		while (n--) {
  			if (conf->mirrors[first].rdev &&
  			    first != ignore)
  				cnt++;
  			first = (first+1) % conf->raid_disks;
  		}
  		if (cnt == 0)
  			return 0;
  	} while (first != 0);
  	return 1;
  }
fd01b88c7   NeilBrown   md: remove typede...
1283
  static void error(struct mddev *mddev, struct md_rdev *rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
  {
  	char b[BDEVNAME_SIZE];
e879a8793   NeilBrown   md/raid10: typede...
1286
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
1288
1289
1290
1291
1292
1293
  
  	/*
  	 * If it is not operational, then we have already marked it as dead
  	 * else if it is the last working disks, ignore the error, let the
  	 * next level up know.
  	 * else mark the drive as failed
  	 */
b2d444d7a   NeilBrown   [PATCH] md: conve...
1294
  	if (test_bit(In_sync, &rdev->flags)
700c72138   NeilBrown   md/raid10: Improv...
1295
  	    && !enough(conf, rdev->raid_disk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296
1297
  		/*
  		 * Don't fail the drive, just return an IO error.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
1299
  		 */
  		return;
c04be0aa8   NeilBrown   [PATCH] md: Impro...
1300
1301
1302
  	if (test_and_clear_bit(In_sync, &rdev->flags)) {
  		unsigned long flags;
  		spin_lock_irqsave(&conf->device_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
  		mddev->degraded++;
c04be0aa8   NeilBrown   [PATCH] md: Impro...
1304
  		spin_unlock_irqrestore(&conf->device_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
1306
1307
  		/*
  		 * if recovery is running, make sure it aborts.
  		 */
dfc706450   NeilBrown   md: restart recov...
1308
  		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
  	}
de393cdea   NeilBrown   md: make it easie...
1310
  	set_bit(Blocked, &rdev->flags);
b2d444d7a   NeilBrown   [PATCH] md: conve...
1311
  	set_bit(Faulty, &rdev->flags);
850b2b420   NeilBrown   [PATCH] md: repla...
1312
  	set_bit(MD_CHANGE_DEVS, &mddev->flags);
067032bc6   Joe Perches   md: Fix single pr...
1313
1314
1315
1316
1317
  	printk(KERN_ALERT
  	       "md/raid10:%s: Disk failure on %s, disabling device.
  "
  	       "md/raid10:%s: Operation continuing on %d devices.
  ",
128595ed6   NeilBrown   md/raid10: tidy u...
1318
1319
  	       mdname(mddev), bdevname(rdev->bdev, b),
  	       mdname(mddev), conf->raid_disks - mddev->degraded);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  }
e879a8793   NeilBrown   md/raid10: typede...
1321
  static void print_conf(struct r10conf *conf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
1323
  {
  	int i;
0f6d02d58   NeilBrown   md: remove typede...
1324
  	struct mirror_info *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325

128595ed6   NeilBrown   md/raid10: tidy u...
1326
1327
  	printk(KERN_DEBUG "RAID10 conf printout:
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
  	if (!conf) {
128595ed6   NeilBrown   md/raid10: tidy u...
1329
1330
  		printk(KERN_DEBUG "(!conf)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
1332
  		return;
  	}
128595ed6   NeilBrown   md/raid10: tidy u...
1333
1334
  	printk(KERN_DEBUG " --- wd:%d rd:%d
  ", conf->raid_disks - conf->mddev->degraded,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
1338
1339
1340
  		conf->raid_disks);
  
  	for (i = 0; i < conf->raid_disks; i++) {
  		char b[BDEVNAME_SIZE];
  		tmp = conf->mirrors + i;
  		if (tmp->rdev)
128595ed6   NeilBrown   md/raid10: tidy u...
1341
1342
  			printk(KERN_DEBUG " disk %d, wo:%d, o:%d, dev:%s
  ",
b2d444d7a   NeilBrown   [PATCH] md: conve...
1343
1344
  				i, !test_bit(In_sync, &tmp->rdev->flags),
  			        !test_bit(Faulty, &tmp->rdev->flags),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
1346
1347
  				bdevname(tmp->rdev->bdev,b));
  	}
  }
e879a8793   NeilBrown   md/raid10: typede...
1348
  static void close_sync(struct r10conf *conf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
  {
0a27ec96b   NeilBrown   [PATCH] md: impro...
1350
1351
  	wait_barrier(conf);
  	allow_barrier(conf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
1354
1355
  
  	mempool_destroy(conf->r10buf_pool);
  	conf->r10buf_pool = NULL;
  }
fd01b88c7   NeilBrown   md: remove typede...
1356
  static int raid10_spare_active(struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
  {
  	int i;
e879a8793   NeilBrown   md/raid10: typede...
1359
  	struct r10conf *conf = mddev->private;
0f6d02d58   NeilBrown   md: remove typede...
1360
  	struct mirror_info *tmp;
6b9656205   NeilBrown   md: provide appro...
1361
1362
  	int count = 0;
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
1367
1368
1369
  
  	/*
  	 * Find all non-in_sync disks within the RAID10 configuration
  	 * and mark them in_sync
  	 */
  	for (i = 0; i < conf->raid_disks; i++) {
  		tmp = conf->mirrors + i;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
  		if (tmp->replacement
  		    && tmp->replacement->recovery_offset == MaxSector
  		    && !test_bit(Faulty, &tmp->replacement->flags)
  		    && !test_and_set_bit(In_sync, &tmp->replacement->flags)) {
  			/* Replacement has just become active */
  			if (!tmp->rdev
  			    || !test_and_clear_bit(In_sync, &tmp->rdev->flags))
  				count++;
  			if (tmp->rdev) {
  				/* Replaced device not technically faulty,
  				 * but we need to be sure it gets removed
  				 * and never re-added.
  				 */
  				set_bit(Faulty, &tmp->rdev->flags);
  				sysfs_notify_dirent_safe(
  					tmp->rdev->sysfs_state);
  			}
  			sysfs_notify_dirent_safe(tmp->replacement->sysfs_state);
  		} else if (tmp->rdev
  			   && !test_bit(Faulty, &tmp->rdev->flags)
  			   && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
6b9656205   NeilBrown   md: provide appro...
1391
  			count++;
e6ffbcb6c   Adrian Drzewiecki   md: Notify sysfs ...
1392
  			sysfs_notify_dirent(tmp->rdev->sysfs_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
1394
  		}
  	}
6b9656205   NeilBrown   md: provide appro...
1395
1396
1397
  	spin_lock_irqsave(&conf->device_lock, flags);
  	mddev->degraded -= count;
  	spin_unlock_irqrestore(&conf->device_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
1399
  
  	print_conf(conf);
6b9656205   NeilBrown   md: provide appro...
1400
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
  }
fd01b88c7   NeilBrown   md: remove typede...
1402
  static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
  {
e879a8793   NeilBrown   md/raid10: typede...
1404
  	struct r10conf *conf = mddev->private;
199050ea1   Neil Brown   rationalise retur...
1405
  	int err = -EEXIST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
  	int mirror;
6c2fce2ef   Neil Brown   Support adding a ...
1407
  	int first = 0;
84707f38e   NeilBrown   md: don't use mdd...
1408
  	int last = conf->raid_disks - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
1410
1411
1412
1413
  
  	if (mddev->recovery_cp < MaxSector)
  		/* only hot-add to in-sync arrays, as recovery is
  		 * very different from resync
  		 */
199050ea1   Neil Brown   rationalise retur...
1414
  		return -EBUSY;
700c72138   NeilBrown   md/raid10: Improv...
1415
  	if (!enough(conf, -1))
199050ea1   Neil Brown   rationalise retur...
1416
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417

a53a6c857   NeilBrown   md: fix bug in ra...
1418
  	if (rdev->raid_disk >= 0)
6c2fce2ef   Neil Brown   Support adding a ...
1419
  		first = last = rdev->raid_disk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420

2c4193df3   Namhyung Kim   md/raid10: get ri...
1421
  	if (rdev->saved_raid_disk >= first &&
6cce3b23f   NeilBrown   [PATCH] md: write...
1422
1423
1424
  	    conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
  		mirror = rdev->saved_raid_disk;
  	else
6c2fce2ef   Neil Brown   Support adding a ...
1425
  		mirror = first;
2bb77736a   NeilBrown   md/raid10: Make u...
1426
  	for ( ; mirror <= last ; mirror++) {
0f6d02d58   NeilBrown   md: remove typede...
1427
  		struct mirror_info *p = &conf->mirrors[mirror];
2bb77736a   NeilBrown   md/raid10: Make u...
1428
1429
  		if (p->recovery_disabled == mddev->recovery_disabled)
  			continue;
b7044d41b   NeilBrown   md/raid10: If the...
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
  		if (p->rdev) {
  			if (!test_bit(WantReplacement, &p->rdev->flags) ||
  			    p->replacement != NULL)
  				continue;
  			clear_bit(In_sync, &rdev->flags);
  			set_bit(Replacement, &rdev->flags);
  			rdev->raid_disk = mirror;
  			err = 0;
  			disk_stack_limits(mddev->gendisk, rdev->bdev,
  					  rdev->data_offset << 9);
  			if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
  				blk_queue_max_segments(mddev->queue, 1);
  				blk_queue_segment_boundary(mddev->queue,
  							   PAGE_CACHE_SIZE - 1);
  			}
  			conf->fullsync = 1;
  			rcu_assign_pointer(p->replacement, rdev);
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449

2bb77736a   NeilBrown   md/raid10: Make u...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  		disk_stack_limits(mddev->gendisk, rdev->bdev,
  				  rdev->data_offset << 9);
  		/* as we don't honour merge_bvec_fn, we must
  		 * never risk violating it, so limit
  		 * ->max_segments to one lying with a single
  		 * page, as a one page request is never in
  		 * violation.
  		 */
  		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
  			blk_queue_max_segments(mddev->queue, 1);
  			blk_queue_segment_boundary(mddev->queue,
  						   PAGE_CACHE_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
  		}
2bb77736a   NeilBrown   md/raid10: Make u...
1463
  		p->head_position = 0;
d890fa2b0   NeilBrown   md: Fix some bugs...
1464
  		p->recovery_disabled = mddev->recovery_disabled - 1;
2bb77736a   NeilBrown   md/raid10: Make u...
1465
1466
1467
1468
1469
1470
1471
  		rdev->raid_disk = mirror;
  		err = 0;
  		if (rdev->saved_raid_disk != mirror)
  			conf->fullsync = 1;
  		rcu_assign_pointer(p->rdev, rdev);
  		break;
  	}
ac5e7113e   Andre Noll   md: Push down dat...
1472
  	md_integrity_add_rdev(rdev, mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
  	print_conf(conf);
199050ea1   Neil Brown   rationalise retur...
1474
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
  }
b8321b68d   NeilBrown   md: change hot_re...
1476
  static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1477
  {
e879a8793   NeilBrown   md/raid10: typede...
1478
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  	int err = 0;
b8321b68d   NeilBrown   md: change hot_re...
1480
  	int number = rdev->raid_disk;
c8ab903ea   NeilBrown   md/raid10: allow ...
1481
1482
  	struct md_rdev **rdevp;
  	struct mirror_info *p = conf->mirrors + number;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
  
  	print_conf(conf);
c8ab903ea   NeilBrown   md/raid10: allow ...
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
  	if (rdev == p->rdev)
  		rdevp = &p->rdev;
  	else if (rdev == p->replacement)
  		rdevp = &p->replacement;
  	else
  		return 0;
  
  	if (test_bit(In_sync, &rdev->flags) ||
  	    atomic_read(&rdev->nr_pending)) {
  		err = -EBUSY;
  		goto abort;
  	}
  	/* Only remove faulty devices if recovery
  	 * is not possible.
  	 */
  	if (!test_bit(Faulty, &rdev->flags) &&
  	    mddev->recovery_disabled != p->recovery_disabled &&
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1502
  	    (!p->replacement || p->replacement == rdev) &&
c8ab903ea   NeilBrown   md/raid10: allow ...
1503
1504
1505
  	    enough(conf, -1)) {
  		err = -EBUSY;
  		goto abort;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1506
  	}
c8ab903ea   NeilBrown   md/raid10: allow ...
1507
1508
1509
1510
1511
1512
1513
  	*rdevp = NULL;
  	synchronize_rcu();
  	if (atomic_read(&rdev->nr_pending)) {
  		/* lost the race, try later */
  		err = -EBUSY;
  		*rdevp = rdev;
  		goto abort;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
  	} else if (p->replacement) {
  		/* We must have just cleared 'rdev' */
  		p->rdev = p->replacement;
  		clear_bit(Replacement, &p->replacement->flags);
  		smp_mb(); /* Make sure other CPUs may see both as identical
  			   * but will never see neither -- if they are careful.
  			   */
  		p->replacement = NULL;
  		clear_bit(WantReplacement, &rdev->flags);
  	} else
  		/* We might have just remove the Replacement as faulty
  		 * Clear the flag just in case
  		 */
  		clear_bit(WantReplacement, &rdev->flags);
c8ab903ea   NeilBrown   md/raid10: allow ...
1528
  	err = md_integrity_register(mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1529
1530
1531
1532
1533
  abort:
  
  	print_conf(conf);
  	return err;
  }
6712ecf8f   NeilBrown   Drop 'size' argum...
1534
  static void end_sync_read(struct bio *bio, int error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1535
  {
9f2c9d12b   NeilBrown   md: remove typede...
1536
  	struct r10bio *r10_bio = bio->bi_private;
e879a8793   NeilBrown   md/raid10: typede...
1537
  	struct r10conf *conf = r10_bio->mddev->private;
778ca0185   Namhyung Kim   md/raid10: factor...
1538
  	int d;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1539

69335ef3b   NeilBrown   md/raid10: prepar...
1540
  	d = find_bio_disk(conf, r10_bio, bio, NULL, NULL);
0eb3ff12a   NeilBrown   [PATCH] md: raid1...
1541
1542
1543
  
  	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
  		set_bit(R10BIO_Uptodate, &r10_bio->state);
e684e41db   NeilBrown   md/raid10: simpli...
1544
1545
1546
1547
  	else
  		/* The write handler will notice the lack of
  		 * R10BIO_Uptodate and record any errors etc
  		 */
4dbcdc751   NeilBrown   [PATCH] md: count...
1548
1549
  		atomic_add(r10_bio->sectors,
  			   &conf->mirrors[d].rdev->corrected_errors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
1552
1553
  
  	/* for reconstruct, we always reschedule after a read.
  	 * for resync, only after all reads
  	 */
73d5c38a9   NeilBrown   md: avoid races w...
1554
  	rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555
1556
1557
1558
1559
1560
1561
  	if (test_bit(R10BIO_IsRecover, &r10_bio->state) ||
  	    atomic_dec_and_test(&r10_bio->remaining)) {
  		/* we have read all the blocks,
  		 * do the comparison in process context in raid10d
  		 */
  		reschedule_retry(r10_bio);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
  }
9f2c9d12b   NeilBrown   md: remove typede...
1563
  static void end_sync_request(struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564
  {
fd01b88c7   NeilBrown   md: remove typede...
1565
  	struct mddev *mddev = r10_bio->mddev;
dfc706450   NeilBrown   md: restart recov...
1566

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
1568
1569
  	while (atomic_dec_and_test(&r10_bio->remaining)) {
  		if (r10_bio->master_bio == NULL) {
  			/* the primary of several recovery bios */
73d5c38a9   NeilBrown   md: avoid races w...
1570
  			sector_t s = r10_bio->sectors;
1a0b7cd82   NeilBrown   md/raid10: record...
1571
1572
  			if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
  			    test_bit(R10BIO_WriteError, &r10_bio->state))
749c55e94   NeilBrown   md/raid10: clear ...
1573
1574
1575
  				reschedule_retry(r10_bio);
  			else
  				put_buf(r10_bio);
73d5c38a9   NeilBrown   md: avoid races w...
1576
  			md_done_sync(mddev, s, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
1578
  			break;
  		} else {
9f2c9d12b   NeilBrown   md: remove typede...
1579
  			struct r10bio *r10_bio2 = (struct r10bio *)r10_bio->master_bio;
1a0b7cd82   NeilBrown   md/raid10: record...
1580
1581
  			if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
  			    test_bit(R10BIO_WriteError, &r10_bio->state))
749c55e94   NeilBrown   md/raid10: clear ...
1582
1583
1584
  				reschedule_retry(r10_bio);
  			else
  				put_buf(r10_bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585
1586
1587
  			r10_bio = r10_bio2;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1588
  }
5e5702898   NeilBrown   md/raid10: Handle...
1589
1590
1591
  static void end_sync_write(struct bio *bio, int error)
  {
  	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
9f2c9d12b   NeilBrown   md: remove typede...
1592
  	struct r10bio *r10_bio = bio->bi_private;
fd01b88c7   NeilBrown   md: remove typede...
1593
  	struct mddev *mddev = r10_bio->mddev;
e879a8793   NeilBrown   md/raid10: typede...
1594
  	struct r10conf *conf = mddev->private;
5e5702898   NeilBrown   md/raid10: Handle...
1595
1596
1597
1598
  	int d;
  	sector_t first_bad;
  	int bad_sectors;
  	int slot;
9ad1aefc8   NeilBrown   md/raid10: Handl...
1599
  	int repl;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1600
  	struct md_rdev *rdev = NULL;
5e5702898   NeilBrown   md/raid10: Handle...
1601

9ad1aefc8   NeilBrown   md/raid10: Handl...
1602
1603
1604
  	d = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
  	if (repl)
  		rdev = conf->mirrors[d].replacement;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1605
1606
  	if (!rdev) {
  		smp_mb();
9ad1aefc8   NeilBrown   md/raid10: Handl...
1607
  		rdev = conf->mirrors[d].rdev;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
1608
  	}
5e5702898   NeilBrown   md/raid10: Handle...
1609
1610
  
  	if (!uptodate) {
9ad1aefc8   NeilBrown   md/raid10: Handl...
1611
1612
1613
1614
  		if (repl)
  			md_error(mddev, rdev);
  		else {
  			set_bit(WriteErrorSeen, &rdev->flags);
b7044d41b   NeilBrown   md/raid10: If the...
1615
1616
1617
  			if (!test_and_set_bit(WantReplacement, &rdev->flags))
  				set_bit(MD_RECOVERY_NEEDED,
  					&rdev->mddev->recovery);
9ad1aefc8   NeilBrown   md/raid10: Handl...
1618
1619
1620
  			set_bit(R10BIO_WriteError, &r10_bio->state);
  		}
  	} else if (is_badblock(rdev,
5e5702898   NeilBrown   md/raid10: Handle...
1621
1622
1623
1624
  			     r10_bio->devs[slot].addr,
  			     r10_bio->sectors,
  			     &first_bad, &bad_sectors))
  		set_bit(R10BIO_MadeGood, &r10_bio->state);
9ad1aefc8   NeilBrown   md/raid10: Handl...
1625
  	rdev_dec_pending(rdev, mddev);
5e5702898   NeilBrown   md/raid10: Handle...
1626
1627
1628
  
  	end_sync_request(r10_bio);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
  /*
   * Note: sync and recover and handled very differently for raid10
   * This code is for resync.
   * For resync, we read through virtual addresses and read all blocks.
   * If there is any error, we schedule a write.  The lowest numbered
   * drive is authoritative.
   * However requests come for physical address, so we need to map.
   * For every physical address there are raid_disks/copies virtual addresses,
   * which is always are least one, but is not necessarly an integer.
   * This means that a physical address can span multiple chunks, so we may
   * have to submit multiple io requests for a single sync request.
   */
  /*
   * We check if all blocks are in-sync and only write to blocks that
   * aren't in sync
   */
9f2c9d12b   NeilBrown   md: remove typede...
1645
  static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  {
e879a8793   NeilBrown   md/raid10: typede...
1647
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
  	int i, first;
  	struct bio *tbio, *fbio;
  
  	atomic_set(&r10_bio->remaining, 1);
  
  	/* find the first device with a block */
  	for (i=0; i<conf->copies; i++)
  		if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
  			break;
  
  	if (i == conf->copies)
  		goto done;
  
  	first = i;
  	fbio = r10_bio->devs[i].bio;
  
  	/* now find blocks with errors */
0eb3ff12a   NeilBrown   [PATCH] md: raid1...
1665
1666
1667
  	for (i=0 ; i < conf->copies ; i++) {
  		int  j, d;
  		int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
  		tbio = r10_bio->devs[i].bio;
0eb3ff12a   NeilBrown   [PATCH] md: raid1...
1670
1671
1672
1673
  
  		if (tbio->bi_end_io != end_sync_read)
  			continue;
  		if (i == first)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  			continue;
0eb3ff12a   NeilBrown   [PATCH] md: raid1...
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
  		if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) {
  			/* We know that the bi_io_vec layout is the same for
  			 * both 'first' and 'i', so we just compare them.
  			 * All vec entries are PAGE_SIZE;
  			 */
  			for (j = 0; j < vcnt; j++)
  				if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
  					   page_address(tbio->bi_io_vec[j].bv_page),
  					   PAGE_SIZE))
  					break;
  			if (j == vcnt)
  				continue;
  			mddev->resync_mismatches += r10_bio->sectors;
f84ee364d   NeilBrown   md/raid10: attem...
1688
1689
1690
  			if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
  				/* Don't fix anything. */
  				continue;
0eb3ff12a   NeilBrown   [PATCH] md: raid1...
1691
  		}
f84ee364d   NeilBrown   md/raid10: attem...
1692
1693
  		/* Ok, we need to write this bio, either to correct an
  		 * inconsistency or to correct an unreadable block.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694
1695
1696
1697
1698
1699
1700
  		 * First we need to fixup bv_offset, bv_len and
  		 * bi_vecs, as the read request might have corrupted these
  		 */
  		tbio->bi_vcnt = vcnt;
  		tbio->bi_size = r10_bio->sectors << 9;
  		tbio->bi_idx = 0;
  		tbio->bi_phys_segments = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
  		tbio->bi_flags &= ~(BIO_POOL_MASK - 1);
  		tbio->bi_flags |= 1 << BIO_UPTODATE;
  		tbio->bi_next = NULL;
  		tbio->bi_rw = WRITE;
  		tbio->bi_private = r10_bio;
  		tbio->bi_sector = r10_bio->devs[i].addr;
  
  		for (j=0; j < vcnt ; j++) {
  			tbio->bi_io_vec[j].bv_offset = 0;
  			tbio->bi_io_vec[j].bv_len = PAGE_SIZE;
  
  			memcpy(page_address(tbio->bi_io_vec[j].bv_page),
  			       page_address(fbio->bi_io_vec[j].bv_page),
  			       PAGE_SIZE);
  		}
  		tbio->bi_end_io = end_sync_write;
  
  		d = r10_bio->devs[i].devnum;
  		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
  		atomic_inc(&r10_bio->remaining);
  		md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
  
  		tbio->bi_sector += conf->mirrors[d].rdev->data_offset;
  		tbio->bi_bdev = conf->mirrors[d].rdev->bdev;
  		generic_make_request(tbio);
  	}
9ad1aefc8   NeilBrown   md/raid10: Handl...
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
  	/* Now write out to any replacement devices
  	 * that are active
  	 */
  	for (i = 0; i < conf->copies; i++) {
  		int j, d;
  		int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
  
  		tbio = r10_bio->devs[i].repl_bio;
  		if (!tbio || !tbio->bi_end_io)
  			continue;
  		if (r10_bio->devs[i].bio->bi_end_io != end_sync_write
  		    && r10_bio->devs[i].bio != fbio)
  			for (j = 0; j < vcnt; j++)
  				memcpy(page_address(tbio->bi_io_vec[j].bv_page),
  				       page_address(fbio->bi_io_vec[j].bv_page),
  				       PAGE_SIZE);
  		d = r10_bio->devs[i].devnum;
  		atomic_inc(&r10_bio->remaining);
  		md_sync_acct(conf->mirrors[d].replacement->bdev,
  			     tbio->bi_size >> 9);
  		generic_make_request(tbio);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
  done:
  	if (atomic_dec_and_test(&r10_bio->remaining)) {
  		md_done_sync(mddev, r10_bio->sectors, 1);
  		put_buf(r10_bio);
  	}
  }
  
  /*
   * Now for the recovery code.
   * Recovery happens across physical sectors.
   * We recover all non-is_sync drives by finding the virtual address of
   * each, and then choose a working drive that also has that virt address.
   * There is a separate r10_bio for each non-in_sync drive.
   * Only the first two slots are in use. The first for reading,
   * The second for writing.
   *
   */
9f2c9d12b   NeilBrown   md: remove typede...
1766
  static void fix_recovery_read_error(struct r10bio *r10_bio)
5e5702898   NeilBrown   md/raid10: Handle...
1767
1768
1769
1770
1771
1772
1773
1774
  {
  	/* We got a read error during recovery.
  	 * We repeat the read in smaller page-sized sections.
  	 * If a read succeeds, write it to the new device or record
  	 * a bad block if we cannot.
  	 * If a read fails, record a bad block on both old and
  	 * new devices.
  	 */
fd01b88c7   NeilBrown   md: remove typede...
1775
  	struct mddev *mddev = r10_bio->mddev;
e879a8793   NeilBrown   md/raid10: typede...
1776
  	struct r10conf *conf = mddev->private;
5e5702898   NeilBrown   md/raid10: Handle...
1777
1778
1779
1780
1781
1782
1783
1784
1785
  	struct bio *bio = r10_bio->devs[0].bio;
  	sector_t sect = 0;
  	int sectors = r10_bio->sectors;
  	int idx = 0;
  	int dr = r10_bio->devs[0].devnum;
  	int dw = r10_bio->devs[1].devnum;
  
  	while (sectors) {
  		int s = sectors;
3cb030020   NeilBrown   md: removing type...
1786
  		struct md_rdev *rdev;
5e5702898   NeilBrown   md/raid10: Handle...
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
  		sector_t addr;
  		int ok;
  
  		if (s > (PAGE_SIZE>>9))
  			s = PAGE_SIZE >> 9;
  
  		rdev = conf->mirrors[dr].rdev;
  		addr = r10_bio->devs[0].addr + sect,
  		ok = sync_page_io(rdev,
  				  addr,
  				  s << 9,
  				  bio->bi_io_vec[idx].bv_page,
  				  READ, false);
  		if (ok) {
  			rdev = conf->mirrors[dw].rdev;
  			addr = r10_bio->devs[1].addr + sect;
  			ok = sync_page_io(rdev,
  					  addr,
  					  s << 9,
  					  bio->bi_io_vec[idx].bv_page,
  					  WRITE, false);
b7044d41b   NeilBrown   md/raid10: If the...
1808
  			if (!ok) {
5e5702898   NeilBrown   md/raid10: Handle...
1809
  				set_bit(WriteErrorSeen, &rdev->flags);
b7044d41b   NeilBrown   md/raid10: If the...
1810
1811
1812
1813
1814
  				if (!test_and_set_bit(WantReplacement,
  						      &rdev->flags))
  					set_bit(MD_RECOVERY_NEEDED,
  						&rdev->mddev->recovery);
  			}
5e5702898   NeilBrown   md/raid10: Handle...
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
  		}
  		if (!ok) {
  			/* We don't worry if we cannot set a bad block -
  			 * it really is bad so there is no loss in not
  			 * recording it yet
  			 */
  			rdev_set_badblocks(rdev, addr, s, 0);
  
  			if (rdev != conf->mirrors[dw].rdev) {
  				/* need bad block on destination too */
3cb030020   NeilBrown   md: removing type...
1825
  				struct md_rdev *rdev2 = conf->mirrors[dw].rdev;
5e5702898   NeilBrown   md/raid10: Handle...
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
  				addr = r10_bio->devs[1].addr + sect;
  				ok = rdev_set_badblocks(rdev2, addr, s, 0);
  				if (!ok) {
  					/* just abort the recovery */
  					printk(KERN_NOTICE
  					       "md/raid10:%s: recovery aborted"
  					       " due to read error
  ",
  					       mdname(mddev));
  
  					conf->mirrors[dw].recovery_disabled
  						= mddev->recovery_disabled;
  					set_bit(MD_RECOVERY_INTR,
  						&mddev->recovery);
  					break;
  				}
  			}
  		}
  
  		sectors -= s;
  		sect += s;
  		idx++;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1850

9f2c9d12b   NeilBrown   md: remove typede...
1851
  static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  {
e879a8793   NeilBrown   md/raid10: typede...
1853
  	struct r10conf *conf = mddev->private;
c65060ad4   Namhyung Kim   md/raid10: share ...
1854
  	int d;
24afd80d9   NeilBrown   md/raid10: handle...
1855
  	struct bio *wbio, *wbio2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856

5e5702898   NeilBrown   md/raid10: Handle...
1857
1858
1859
1860
1861
  	if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) {
  		fix_recovery_read_error(r10_bio);
  		end_sync_request(r10_bio);
  		return;
  	}
c65060ad4   Namhyung Kim   md/raid10: share ...
1862
1863
  	/*
  	 * share the pages with the first bio
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1864
1865
  	 * and submit the write request
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
  	d = r10_bio->devs[1].devnum;
24afd80d9   NeilBrown   md/raid10: handle...
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
  	wbio = r10_bio->devs[1].bio;
  	wbio2 = r10_bio->devs[1].repl_bio;
  	if (wbio->bi_end_io) {
  		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
  		md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
  		generic_make_request(wbio);
  	}
  	if (wbio2 && wbio2->bi_end_io) {
  		atomic_inc(&conf->mirrors[d].replacement->nr_pending);
  		md_sync_acct(conf->mirrors[d].replacement->bdev,
  			     wbio2->bi_size >> 9);
  		generic_make_request(wbio2);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
1881
1882
1883
  }
  
  
  /*
1e50915fe   Robert Becker   raid: improve MD/...
1884
1885
1886
1887
1888
   * Used by fix_read_error() to decay the per rdev read_errors.
   * We halve the read error count for every hour that has elapsed
   * since the last recorded read error.
   *
   */
fd01b88c7   NeilBrown   md: remove typede...
1889
  static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev)
1e50915fe   Robert Becker   raid: improve MD/...
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
  {
  	struct timespec cur_time_mon;
  	unsigned long hours_since_last;
  	unsigned int read_errors = atomic_read(&rdev->read_errors);
  
  	ktime_get_ts(&cur_time_mon);
  
  	if (rdev->last_read_error.tv_sec == 0 &&
  	    rdev->last_read_error.tv_nsec == 0) {
  		/* first time we've seen a read error */
  		rdev->last_read_error = cur_time_mon;
  		return;
  	}
  
  	hours_since_last = (cur_time_mon.tv_sec -
  			    rdev->last_read_error.tv_sec) / 3600;
  
  	rdev->last_read_error = cur_time_mon;
  
  	/*
  	 * if hours_since_last is > the number of bits in read_errors
  	 * just set read errors to 0. We do this to avoid
  	 * overflowing the shift of read_errors by hours_since_last.
  	 */
  	if (hours_since_last >= 8 * sizeof(read_errors))
  		atomic_set(&rdev->read_errors, 0);
  	else
  		atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
  }
3cb030020   NeilBrown   md: removing type...
1919
  static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector,
58c54fcca   NeilBrown   md/raid10: handle...
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
  			    int sectors, struct page *page, int rw)
  {
  	sector_t first_bad;
  	int bad_sectors;
  
  	if (is_badblock(rdev, sector, sectors, &first_bad, &bad_sectors)
  	    && (rw == READ || test_bit(WriteErrorSeen, &rdev->flags)))
  		return -1;
  	if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
  		/* success */
  		return 1;
b7044d41b   NeilBrown   md/raid10: If the...
1931
  	if (rw == WRITE) {
58c54fcca   NeilBrown   md/raid10: handle...
1932
  		set_bit(WriteErrorSeen, &rdev->flags);
b7044d41b   NeilBrown   md/raid10: If the...
1933
1934
1935
1936
  		if (!test_and_set_bit(WantReplacement, &rdev->flags))
  			set_bit(MD_RECOVERY_NEEDED,
  				&rdev->mddev->recovery);
  	}
58c54fcca   NeilBrown   md/raid10: handle...
1937
1938
1939
1940
1941
  	/* need to record an error - either for the block or the device */
  	if (!rdev_set_badblocks(rdev, sector, sectors, 0))
  		md_error(rdev->mddev, rdev);
  	return 0;
  }
1e50915fe   Robert Becker   raid: improve MD/...
1942
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1943
1944
1945
1946
   * This is a kernel thread which:
   *
   *	1.	Retries failed read operations on working mirrors.
   *	2.	Updates the raid superblock when problems encounter.
6814d5368   NeilBrown   [PATCH] md: facto...
1947
   *	3.	Performs writes following reads for array synchronising.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
   */
e879a8793   NeilBrown   md/raid10: typede...
1949
  static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10bio *r10_bio)
6814d5368   NeilBrown   [PATCH] md: facto...
1950
1951
1952
  {
  	int sect = 0; /* Offset from r10_bio->sector */
  	int sectors = r10_bio->sectors;
3cb030020   NeilBrown   md: removing type...
1953
  	struct md_rdev*rdev;
1e50915fe   Robert Becker   raid: improve MD/...
1954
  	int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
0544a21db   Prasanna S. Panchamukhi   md: raid10: Fix n...
1955
  	int d = r10_bio->devs[r10_bio->read_slot].devnum;
1e50915fe   Robert Becker   raid: improve MD/...
1956

7c4e06ff2   NeilBrown   md/raid10: some t...
1957
1958
1959
1960
  	/* still own a reference to this rdev, so it cannot
  	 * have been cleared recently.
  	 */
  	rdev = conf->mirrors[d].rdev;
1e50915fe   Robert Becker   raid: improve MD/...
1961

7c4e06ff2   NeilBrown   md/raid10: some t...
1962
1963
1964
1965
  	if (test_bit(Faulty, &rdev->flags))
  		/* drive has already been failed, just ignore any
  		   more fix_read_error() attempts */
  		return;
1e50915fe   Robert Becker   raid: improve MD/...
1966

7c4e06ff2   NeilBrown   md/raid10: some t...
1967
1968
1969
1970
1971
  	check_decay_read_errors(mddev, rdev);
  	atomic_inc(&rdev->read_errors);
  	if (atomic_read(&rdev->read_errors) > max_read_errors) {
  		char b[BDEVNAME_SIZE];
  		bdevname(rdev->bdev, b);
1e50915fe   Robert Becker   raid: improve MD/...
1972

7c4e06ff2   NeilBrown   md/raid10: some t...
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
  		printk(KERN_NOTICE
  		       "md/raid10:%s: %s: Raid device exceeded "
  		       "read_error threshold [cur %d:max %d]
  ",
  		       mdname(mddev), b,
  		       atomic_read(&rdev->read_errors), max_read_errors);
  		printk(KERN_NOTICE
  		       "md/raid10:%s: %s: Failing raid device
  ",
  		       mdname(mddev), b);
  		md_error(mddev, conf->mirrors[d].rdev);
  		return;
1e50915fe   Robert Becker   raid: improve MD/...
1985
  	}
1e50915fe   Robert Becker   raid: improve MD/...
1986

6814d5368   NeilBrown   [PATCH] md: facto...
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
  	while(sectors) {
  		int s = sectors;
  		int sl = r10_bio->read_slot;
  		int success = 0;
  		int start;
  
  		if (s > (PAGE_SIZE>>9))
  			s = PAGE_SIZE >> 9;
  
  		rcu_read_lock();
  		do {
8dbed5ceb   NeilBrown   md/raid10 - avoid...
1998
1999
  			sector_t first_bad;
  			int bad_sectors;
0544a21db   Prasanna S. Panchamukhi   md: raid10: Fix n...
2000
  			d = r10_bio->devs[sl].devnum;
6814d5368   NeilBrown   [PATCH] md: facto...
2001
2002
  			rdev = rcu_dereference(conf->mirrors[d].rdev);
  			if (rdev &&
8dbed5ceb   NeilBrown   md/raid10 - avoid...
2003
2004
2005
  			    test_bit(In_sync, &rdev->flags) &&
  			    is_badblock(rdev, r10_bio->devs[sl].addr + sect, s,
  					&first_bad, &bad_sectors) == 0) {
6814d5368   NeilBrown   [PATCH] md: facto...
2006
2007
  				atomic_inc(&rdev->nr_pending);
  				rcu_read_unlock();
2b193363e   NeilBrown   md: change type o...
2008
  				success = sync_page_io(rdev,
6814d5368   NeilBrown   [PATCH] md: facto...
2009
  						       r10_bio->devs[sl].addr +
ccebd4c41   Jonathan Brassow   md-new-param-to_s...
2010
  						       sect,
6814d5368   NeilBrown   [PATCH] md: facto...
2011
  						       s<<9,
ccebd4c41   Jonathan Brassow   md-new-param-to_s...
2012
  						       conf->tmppage, READ, false);
6814d5368   NeilBrown   [PATCH] md: facto...
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
  				rdev_dec_pending(rdev, mddev);
  				rcu_read_lock();
  				if (success)
  					break;
  			}
  			sl++;
  			if (sl == conf->copies)
  				sl = 0;
  		} while (!success && sl != r10_bio->read_slot);
  		rcu_read_unlock();
  
  		if (!success) {
58c54fcca   NeilBrown   md/raid10: handle...
2025
2026
2027
2028
  			/* Cannot read from anywhere, just mark the block
  			 * as bad on the first device to discourage future
  			 * reads.
  			 */
6814d5368   NeilBrown   [PATCH] md: facto...
2029
  			int dn = r10_bio->devs[r10_bio->read_slot].devnum;
58c54fcca   NeilBrown   md/raid10: handle...
2030
2031
2032
2033
2034
2035
2036
2037
  			rdev = conf->mirrors[dn].rdev;
  
  			if (!rdev_set_badblocks(
  				    rdev,
  				    r10_bio->devs[r10_bio->read_slot].addr
  				    + sect,
  				    s, 0))
  				md_error(mddev, rdev);
6814d5368   NeilBrown   [PATCH] md: facto...
2038
2039
2040
2041
2042
2043
2044
  			break;
  		}
  
  		start = sl;
  		/* write it back and re-read */
  		rcu_read_lock();
  		while (sl != r10_bio->read_slot) {
67b8dc4b0   Robert Becker   md/raid10: print ...
2045
  			char b[BDEVNAME_SIZE];
0544a21db   Prasanna S. Panchamukhi   md: raid10: Fix n...
2046

6814d5368   NeilBrown   [PATCH] md: facto...
2047
2048
2049
2050
2051
  			if (sl==0)
  				sl = conf->copies;
  			sl--;
  			d = r10_bio->devs[sl].devnum;
  			rdev = rcu_dereference(conf->mirrors[d].rdev);
1294b9c97   NeilBrown   md/raid10: simpli...
2052
2053
2054
2055
2056
2057
  			if (!rdev ||
  			    !test_bit(In_sync, &rdev->flags))
  				continue;
  
  			atomic_inc(&rdev->nr_pending);
  			rcu_read_unlock();
58c54fcca   NeilBrown   md/raid10: handle...
2058
2059
2060
2061
  			if (r10_sync_page_io(rdev,
  					     r10_bio->devs[sl].addr +
  					     sect,
  					     s<<9, conf->tmppage, WRITE)
1294b9c97   NeilBrown   md/raid10: simpli...
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
  			    == 0) {
  				/* Well, this device is dead */
  				printk(KERN_NOTICE
  				       "md/raid10:%s: read correction "
  				       "write failed"
  				       " (%d sectors at %llu on %s)
  ",
  				       mdname(mddev), s,
  				       (unsigned long long)(
  					       sect + rdev->data_offset),
  				       bdevname(rdev->bdev, b));
  				printk(KERN_NOTICE "md/raid10:%s: %s: failing "
  				       "drive
  ",
  				       mdname(mddev),
  				       bdevname(rdev->bdev, b));
6814d5368   NeilBrown   [PATCH] md: facto...
2078
  			}
1294b9c97   NeilBrown   md/raid10: simpli...
2079
2080
  			rdev_dec_pending(rdev, mddev);
  			rcu_read_lock();
6814d5368   NeilBrown   [PATCH] md: facto...
2081
2082
2083
  		}
  		sl = start;
  		while (sl != r10_bio->read_slot) {
1294b9c97   NeilBrown   md/raid10: simpli...
2084
  			char b[BDEVNAME_SIZE];
0544a21db   Prasanna S. Panchamukhi   md: raid10: Fix n...
2085

6814d5368   NeilBrown   [PATCH] md: facto...
2086
2087
2088
2089
2090
  			if (sl==0)
  				sl = conf->copies;
  			sl--;
  			d = r10_bio->devs[sl].devnum;
  			rdev = rcu_dereference(conf->mirrors[d].rdev);
1294b9c97   NeilBrown   md/raid10: simpli...
2091
2092
2093
  			if (!rdev ||
  			    !test_bit(In_sync, &rdev->flags))
  				continue;
6814d5368   NeilBrown   [PATCH] md: facto...
2094

1294b9c97   NeilBrown   md/raid10: simpli...
2095
2096
  			atomic_inc(&rdev->nr_pending);
  			rcu_read_unlock();
58c54fcca   NeilBrown   md/raid10: handle...
2097
2098
2099
2100
2101
2102
  			switch (r10_sync_page_io(rdev,
  					     r10_bio->devs[sl].addr +
  					     sect,
  					     s<<9, conf->tmppage,
  						 READ)) {
  			case 0:
1294b9c97   NeilBrown   md/raid10: simpli...
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
  				/* Well, this device is dead */
  				printk(KERN_NOTICE
  				       "md/raid10:%s: unable to read back "
  				       "corrected sectors"
  				       " (%d sectors at %llu on %s)
  ",
  				       mdname(mddev), s,
  				       (unsigned long long)(
  					       sect + rdev->data_offset),
  				       bdevname(rdev->bdev, b));
  				printk(KERN_NOTICE "md/raid10:%s: %s: failing "
  				       "drive
  ",
  				       mdname(mddev),
  				       bdevname(rdev->bdev, b));
58c54fcca   NeilBrown   md/raid10: handle...
2118
2119
  				break;
  			case 1:
1294b9c97   NeilBrown   md/raid10: simpli...
2120
2121
2122
2123
2124
2125
2126
2127
2128
  				printk(KERN_INFO
  				       "md/raid10:%s: read error corrected"
  				       " (%d sectors at %llu on %s)
  ",
  				       mdname(mddev), s,
  				       (unsigned long long)(
  					       sect + rdev->data_offset),
  				       bdevname(rdev->bdev, b));
  				atomic_add(s, &rdev->corrected_errors);
6814d5368   NeilBrown   [PATCH] md: facto...
2129
  			}
1294b9c97   NeilBrown   md/raid10: simpli...
2130
2131
2132
  
  			rdev_dec_pending(rdev, mddev);
  			rcu_read_lock();
6814d5368   NeilBrown   [PATCH] md: facto...
2133
2134
2135
2136
2137
2138
2139
  		}
  		rcu_read_unlock();
  
  		sectors -= s;
  		sect += s;
  	}
  }
bd870a16c   NeilBrown   md/raid10: Handl...
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
  static void bi_complete(struct bio *bio, int error)
  {
  	complete((struct completion *)bio->bi_private);
  }
  
  static int submit_bio_wait(int rw, struct bio *bio)
  {
  	struct completion event;
  	rw |= REQ_SYNC;
  
  	init_completion(&event);
  	bio->bi_private = &event;
  	bio->bi_end_io = bi_complete;
  	submit_bio(rw, bio);
  	wait_for_completion(&event);
  
  	return test_bit(BIO_UPTODATE, &bio->bi_flags);
  }
9f2c9d12b   NeilBrown   md: remove typede...
2158
  static int narrow_write_error(struct r10bio *r10_bio, int i)
bd870a16c   NeilBrown   md/raid10: Handl...
2159
2160
  {
  	struct bio *bio = r10_bio->master_bio;
fd01b88c7   NeilBrown   md: remove typede...
2161
  	struct mddev *mddev = r10_bio->mddev;
e879a8793   NeilBrown   md/raid10: typede...
2162
  	struct r10conf *conf = mddev->private;
3cb030020   NeilBrown   md: removing type...
2163
  	struct md_rdev *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
bd870a16c   NeilBrown   md/raid10: Handl...
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
  	/* bio has the data to be written to slot 'i' where
  	 * we just recently had a write error.
  	 * We repeatedly clone the bio and trim down to one block,
  	 * then try the write.  Where the write fails we record
  	 * a bad block.
  	 * It is conceivable that the bio doesn't exactly align with
  	 * blocks.  We must handle this.
  	 *
  	 * We currently own a reference to the rdev.
  	 */
  
  	int block_sectors;
  	sector_t sector;
  	int sectors;
  	int sect_to_write = r10_bio->sectors;
  	int ok = 1;
  
  	if (rdev->badblocks.shift < 0)
  		return 0;
  
  	block_sectors = 1 << rdev->badblocks.shift;
  	sector = r10_bio->sector;
  	sectors = ((r10_bio->sector + block_sectors)
  		   & ~(sector_t)(block_sectors - 1))
  		- sector;
  
  	while (sect_to_write) {
  		struct bio *wbio;
  		if (sectors > sect_to_write)
  			sectors = sect_to_write;
  		/* Write at 'sector' for 'sectors' */
  		wbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
  		md_trim_bio(wbio, sector - bio->bi_sector, sectors);
  		wbio->bi_sector = (r10_bio->devs[i].addr+
  				   rdev->data_offset+
  				   (sector - r10_bio->sector));
  		wbio->bi_bdev = rdev->bdev;
  		if (submit_bio_wait(WRITE, wbio) == 0)
  			/* Failure! */
  			ok = rdev_set_badblocks(rdev, sector,
  						sectors, 0)
  				&& ok;
  
  		bio_put(wbio);
  		sect_to_write -= sectors;
  		sector += sectors;
  		sectors = block_sectors;
  	}
  	return ok;
  }
9f2c9d12b   NeilBrown   md: remove typede...
2214
  static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio)
560f8e553   NeilBrown   md/raid10: Split ...
2215
2216
  {
  	int slot = r10_bio->read_slot;
560f8e553   NeilBrown   md/raid10: Split ...
2217
  	struct bio *bio;
e879a8793   NeilBrown   md/raid10: typede...
2218
  	struct r10conf *conf = mddev->private;
abbf098e6   NeilBrown   md/raid10: prefer...
2219
  	struct md_rdev *rdev = r10_bio->devs[slot].rdev;
560f8e553   NeilBrown   md/raid10: Split ...
2220
2221
  	char b[BDEVNAME_SIZE];
  	unsigned long do_sync;
856e08e23   NeilBrown   md/raid10: avoid ...
2222
  	int max_sectors;
560f8e553   NeilBrown   md/raid10: Split ...
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
  
  	/* we got a read error. Maybe the drive is bad.  Maybe just
  	 * the block and we can fix it.
  	 * We freeze all other IO, and try reading the block from
  	 * other devices.  When we find one, we re-write
  	 * and check it that fixes the read error.
  	 * This is all done synchronously while the array is
  	 * frozen.
  	 */
  	if (mddev->ro == 0) {
  		freeze_array(conf);
  		fix_read_error(conf, mddev, r10_bio);
  		unfreeze_array(conf);
  	}
abbf098e6   NeilBrown   md/raid10: prefer...
2237
  	rdev_dec_pending(rdev, mddev);
560f8e553   NeilBrown   md/raid10: Split ...
2238
2239
  
  	bio = r10_bio->devs[slot].bio;
7399c31bc   NeilBrown   md/raid10: avoid ...
2240
  	bdevname(bio->bi_bdev, b);
560f8e553   NeilBrown   md/raid10: Split ...
2241
2242
  	r10_bio->devs[slot].bio =
  		mddev->ro ? IO_BLOCKED : NULL;
7399c31bc   NeilBrown   md/raid10: avoid ...
2243
  read_more:
96c3fd1f3   NeilBrown   md/raid10: chang...
2244
2245
  	rdev = read_balance(conf, r10_bio, &max_sectors);
  	if (rdev == NULL) {
560f8e553   NeilBrown   md/raid10: Split ...
2246
2247
2248
  		printk(KERN_ALERT "md/raid10:%s: %s: unrecoverable I/O"
  		       " read error for block %llu
  ",
7399c31bc   NeilBrown   md/raid10: avoid ...
2249
  		       mdname(mddev), b,
560f8e553   NeilBrown   md/raid10: Split ...
2250
2251
2252
2253
2254
2255
2256
  		       (unsigned long long)r10_bio->sector);
  		raid_end_bio_io(r10_bio);
  		bio_put(bio);
  		return;
  	}
  
  	do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC);
7399c31bc   NeilBrown   md/raid10: avoid ...
2257
2258
  	if (bio)
  		bio_put(bio);
560f8e553   NeilBrown   md/raid10: Split ...
2259
  	slot = r10_bio->read_slot;
560f8e553   NeilBrown   md/raid10: Split ...
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
  	printk_ratelimited(
  		KERN_ERR
  		"md/raid10:%s: %s: redirecting"
  		"sector %llu to another mirror
  ",
  		mdname(mddev),
  		bdevname(rdev->bdev, b),
  		(unsigned long long)r10_bio->sector);
  	bio = bio_clone_mddev(r10_bio->master_bio,
  			      GFP_NOIO, mddev);
7399c31bc   NeilBrown   md/raid10: avoid ...
2270
2271
2272
  	md_trim_bio(bio,
  		    r10_bio->sector - bio->bi_sector,
  		    max_sectors);
560f8e553   NeilBrown   md/raid10: Split ...
2273
  	r10_bio->devs[slot].bio = bio;
abbf098e6   NeilBrown   md/raid10: prefer...
2274
  	r10_bio->devs[slot].rdev = rdev;
560f8e553   NeilBrown   md/raid10: Split ...
2275
2276
2277
2278
2279
2280
  	bio->bi_sector = r10_bio->devs[slot].addr
  		+ rdev->data_offset;
  	bio->bi_bdev = rdev->bdev;
  	bio->bi_rw = READ | do_sync;
  	bio->bi_private = r10_bio;
  	bio->bi_end_io = raid10_end_read_request;
7399c31bc   NeilBrown   md/raid10: avoid ...
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
  	if (max_sectors < r10_bio->sectors) {
  		/* Drat - have to split this up more */
  		struct bio *mbio = r10_bio->master_bio;
  		int sectors_handled =
  			r10_bio->sector + max_sectors
  			- mbio->bi_sector;
  		r10_bio->sectors = max_sectors;
  		spin_lock_irq(&conf->device_lock);
  		if (mbio->bi_phys_segments == 0)
  			mbio->bi_phys_segments = 2;
  		else
  			mbio->bi_phys_segments++;
  		spin_unlock_irq(&conf->device_lock);
  		generic_make_request(bio);
  		bio = NULL;
  
  		r10_bio = mempool_alloc(conf->r10bio_pool,
  					GFP_NOIO);
  		r10_bio->master_bio = mbio;
  		r10_bio->sectors = (mbio->bi_size >> 9)
  			- sectors_handled;
  		r10_bio->state = 0;
  		set_bit(R10BIO_ReadError,
  			&r10_bio->state);
  		r10_bio->mddev = mddev;
  		r10_bio->sector = mbio->bi_sector
  			+ sectors_handled;
  
  		goto read_more;
  	} else
  		generic_make_request(bio);
560f8e553   NeilBrown   md/raid10: Split ...
2312
  }
e879a8793   NeilBrown   md/raid10: typede...
2313
  static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
749c55e94   NeilBrown   md/raid10: clear ...
2314
2315
2316
2317
  {
  	/* Some sort of write request has finished and it
  	 * succeeded in writing where we thought there was a
  	 * bad block.  So forget the bad block.
1a0b7cd82   NeilBrown   md/raid10: record...
2318
2319
  	 * Or possibly if failed and we need to record
  	 * a bad block.
749c55e94   NeilBrown   md/raid10: clear ...
2320
2321
  	 */
  	int m;
3cb030020   NeilBrown   md: removing type...
2322
  	struct md_rdev *rdev;
749c55e94   NeilBrown   md/raid10: clear ...
2323
2324
2325
  
  	if (test_bit(R10BIO_IsSync, &r10_bio->state) ||
  	    test_bit(R10BIO_IsRecover, &r10_bio->state)) {
1a0b7cd82   NeilBrown   md/raid10: record...
2326
2327
2328
2329
2330
2331
  		for (m = 0; m < conf->copies; m++) {
  			int dev = r10_bio->devs[m].devnum;
  			rdev = conf->mirrors[dev].rdev;
  			if (r10_bio->devs[m].bio == NULL)
  				continue;
  			if (test_bit(BIO_UPTODATE,
749c55e94   NeilBrown   md/raid10: clear ...
2332
  				     &r10_bio->devs[m].bio->bi_flags)) {
749c55e94   NeilBrown   md/raid10: clear ...
2333
2334
2335
2336
  				rdev_clear_badblocks(
  					rdev,
  					r10_bio->devs[m].addr,
  					r10_bio->sectors);
1a0b7cd82   NeilBrown   md/raid10: record...
2337
2338
2339
2340
2341
2342
  			} else {
  				if (!rdev_set_badblocks(
  					    rdev,
  					    r10_bio->devs[m].addr,
  					    r10_bio->sectors, 0))
  					md_error(conf->mddev, rdev);
749c55e94   NeilBrown   md/raid10: clear ...
2343
  			}
9ad1aefc8   NeilBrown   md/raid10: Handl...
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
  			rdev = conf->mirrors[dev].replacement;
  			if (r10_bio->devs[m].repl_bio == NULL)
  				continue;
  			if (test_bit(BIO_UPTODATE,
  				     &r10_bio->devs[m].repl_bio->bi_flags)) {
  				rdev_clear_badblocks(
  					rdev,
  					r10_bio->devs[m].addr,
  					r10_bio->sectors);
  			} else {
  				if (!rdev_set_badblocks(
  					    rdev,
  					    r10_bio->devs[m].addr,
  					    r10_bio->sectors, 0))
  					md_error(conf->mddev, rdev);
  			}
1a0b7cd82   NeilBrown   md/raid10: record...
2360
  		}
749c55e94   NeilBrown   md/raid10: clear ...
2361
2362
  		put_buf(r10_bio);
  	} else {
bd870a16c   NeilBrown   md/raid10: Handl...
2363
2364
2365
2366
2367
  		for (m = 0; m < conf->copies; m++) {
  			int dev = r10_bio->devs[m].devnum;
  			struct bio *bio = r10_bio->devs[m].bio;
  			rdev = conf->mirrors[dev].rdev;
  			if (bio == IO_MADE_GOOD) {
749c55e94   NeilBrown   md/raid10: clear ...
2368
2369
2370
2371
2372
  				rdev_clear_badblocks(
  					rdev,
  					r10_bio->devs[m].addr,
  					r10_bio->sectors);
  				rdev_dec_pending(rdev, conf->mddev);
bd870a16c   NeilBrown   md/raid10: Handl...
2373
2374
2375
2376
2377
2378
2379
2380
  			} else if (bio != NULL &&
  				   !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
  				if (!narrow_write_error(r10_bio, m)) {
  					md_error(conf->mddev, rdev);
  					set_bit(R10BIO_Degraded,
  						&r10_bio->state);
  				}
  				rdev_dec_pending(rdev, conf->mddev);
749c55e94   NeilBrown   md/raid10: clear ...
2381
  			}
475b0321a   NeilBrown   md/raid10: writes...
2382
2383
  			bio = r10_bio->devs[m].repl_bio;
  			rdev = conf->mirrors[dev].replacement;
4ca40c2ce   NeilBrown   md/raid10: Allow ...
2384
  			if (rdev && bio == IO_MADE_GOOD) {
475b0321a   NeilBrown   md/raid10: writes...
2385
2386
2387
2388
2389
2390
  				rdev_clear_badblocks(
  					rdev,
  					r10_bio->devs[m].addr,
  					r10_bio->sectors);
  				rdev_dec_pending(rdev, conf->mddev);
  			}
bd870a16c   NeilBrown   md/raid10: Handl...
2391
2392
2393
2394
  		}
  		if (test_bit(R10BIO_WriteError,
  			     &r10_bio->state))
  			close_write(r10_bio);
749c55e94   NeilBrown   md/raid10: clear ...
2395
2396
2397
  		raid_end_bio_io(r10_bio);
  	}
  }
fd01b88c7   NeilBrown   md: remove typede...
2398
  static void raid10d(struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2399
  {
9f2c9d12b   NeilBrown   md: remove typede...
2400
  	struct r10bio *r10_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2401
  	unsigned long flags;
e879a8793   NeilBrown   md/raid10: typede...
2402
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2403
  	struct list_head *head = &conf->retry_list;
e1dfa0a29   NeilBrown   md: use new plugg...
2404
  	struct blk_plug plug;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2405
2406
  
  	md_check_recovery(mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2407

e1dfa0a29   NeilBrown   md: use new plugg...
2408
  	blk_start_plug(&plug);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2409
  	for (;;) {
6cce3b23f   NeilBrown   [PATCH] md: write...
2410

7eaceacca   Jens Axboe   block: remove per...
2411
  		flush_pending_writes(conf);
6cce3b23f   NeilBrown   [PATCH] md: write...
2412

a35e63efa   NeilBrown   md: fix deadlock ...
2413
2414
2415
  		spin_lock_irqsave(&conf->device_lock, flags);
  		if (list_empty(head)) {
  			spin_unlock_irqrestore(&conf->device_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2416
  			break;
a35e63efa   NeilBrown   md: fix deadlock ...
2417
  		}
9f2c9d12b   NeilBrown   md: remove typede...
2418
  		r10_bio = list_entry(head->prev, struct r10bio, retry_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2419
  		list_del(head->prev);
4443ae10c   NeilBrown   [PATCH] md: auto-...
2420
  		conf->nr_queued--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2421
2422
2423
  		spin_unlock_irqrestore(&conf->device_lock, flags);
  
  		mddev = r10_bio->mddev;
070ec55d0   NeilBrown   md: remove mddev_...
2424
  		conf = mddev->private;
bd870a16c   NeilBrown   md/raid10: Handl...
2425
2426
  		if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
  		    test_bit(R10BIO_WriteError, &r10_bio->state))
749c55e94   NeilBrown   md/raid10: clear ...
2427
2428
  			handle_write_completed(conf, r10_bio);
  		else if (test_bit(R10BIO_IsSync, &r10_bio->state))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
  			sync_request_write(mddev, r10_bio);
7eaceacca   Jens Axboe   block: remove per...
2430
  		else if (test_bit(R10BIO_IsRecover, &r10_bio->state))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2431
  			recovery_request_write(mddev, r10_bio);
856e08e23   NeilBrown   md/raid10: avoid ...
2432
  		else if (test_bit(R10BIO_ReadError, &r10_bio->state))
560f8e553   NeilBrown   md/raid10: Split ...
2433
  			handle_read_error(mddev, r10_bio);
856e08e23   NeilBrown   md/raid10: avoid ...
2434
2435
2436
2437
2438
2439
2440
  		else {
  			/* just a partial read to be scheduled from a
  			 * separate context
  			 */
  			int slot = r10_bio->read_slot;
  			generic_make_request(r10_bio->devs[slot].bio);
  		}
560f8e553   NeilBrown   md/raid10: Split ...
2441

1d9d52416   NeilBrown   md/raid1/raid10: ...
2442
  		cond_resched();
de393cdea   NeilBrown   md: make it easie...
2443
2444
  		if (mddev->flags & ~(1<<MD_CHANGE_PENDING))
  			md_check_recovery(mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
  	}
e1dfa0a29   NeilBrown   md: use new plugg...
2446
  	blk_finish_plug(&plug);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2447
  }
e879a8793   NeilBrown   md/raid10: typede...
2448
  static int init_resync(struct r10conf *conf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2449
2450
  {
  	int buffs;
69335ef3b   NeilBrown   md/raid10: prepar...
2451
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2452
2453
  
  	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
b63854838   Eric Sesterhenn   BUG_ON() Conversi...
2454
  	BUG_ON(conf->r10buf_pool);
69335ef3b   NeilBrown   md/raid10: prepar...
2455
2456
2457
2458
  	conf->have_replacement = 0;
  	for (i = 0; i < conf->raid_disks; i++)
  		if (conf->mirrors[i].replacement)
  			conf->have_replacement = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
  	conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
  	if (!conf->r10buf_pool)
  		return -ENOMEM;
  	conf->next_resync = 0;
  	return 0;
  }
  
  /*
   * perform a "sync" on one "block"
   *
   * We need to make sure that no normal I/O request - particularly write
   * requests - conflict with active sync requests.
   *
   * This is achieved by tracking pending requests and a 'barrier' concept
   * that can be installed to exclude normal IO requests.
   *
   * Resync and recovery are handled very differently.
   * We differentiate by looking at MD_RECOVERY_SYNC in mddev->recovery.
   *
   * For resync, we iterate over virtual addresses, read all copies,
   * and update if there are differences.  If only one copy is live,
   * skip it.
   * For recovery, we iterate over physical addresses, read a good
   * value for each non-in_sync drive, and over-write.
   *
   * So, for recovery we may have several outstanding complex requests for a
   * given address, one for each out-of-sync device.  We model this by allocating
   * a number of r10_bio structures, one for each out-of-sync device.
   * As we setup these structures, we collect all bio's together into a list
   * which we then process collectively to add pages, and then process again
   * to pass to generic_make_request.
   *
   * The r10_bio structures are linked using a borrowed master_bio pointer.
   * This link is counted in ->remaining.  When the r10_bio that points to NULL
   * has its remaining count decremented to 0, the whole complex operation
   * is complete.
   *
   */
fd01b88c7   NeilBrown   md: remove typede...
2497
  static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
ab9d47e99   NeilBrown   md/raid10: refor...
2498
  			     int *skipped, int go_faster)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2499
  {
e879a8793   NeilBrown   md/raid10: typede...
2500
  	struct r10conf *conf = mddev->private;
9f2c9d12b   NeilBrown   md: remove typede...
2501
  	struct r10bio *r10_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2502
2503
  	struct bio *biolist = NULL, *bio;
  	sector_t max_sector, nr_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2504
  	int i;
6cce3b23f   NeilBrown   [PATCH] md: write...
2505
  	int max_sync;
57dab0bdf   NeilBrown   md: use sector_t ...
2506
  	sector_t sync_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2507
2508
2509
2510
2511
  	sector_t sectors_skipped = 0;
  	int chunks_skipped = 0;
  
  	if (!conf->r10buf_pool)
  		if (init_resync(conf))
57afd89f9   NeilBrown   [PATCH] md: impro...
2512
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2513
2514
  
   skipped:
58c0fed40   Andre Noll   md: Make mddev->s...
2515
  	max_sector = mddev->dev_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2516
2517
2518
  	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
  		max_sector = mddev->resync_max_sectors;
  	if (sector_nr >= max_sector) {
6cce3b23f   NeilBrown   [PATCH] md: write...
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
  		/* If we aborted, we need to abort the
  		 * sync on the 'current' bitmap chucks (there can
  		 * be several when recovering multiple devices).
  		 * as we may have started syncing it but not finished.
  		 * We can find the current address in
  		 * mddev->curr_resync, but for recovery,
  		 * we need to convert that to several
  		 * virtual addresses.
  		 */
  		if (mddev->curr_resync < max_sector) { /* aborted */
  			if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
  				bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
  						&sync_blocks, 1);
  			else for (i=0; i<conf->raid_disks; i++) {
  				sector_t sect =
  					raid10_find_virt(conf, mddev->curr_resync, i);
  				bitmap_end_sync(mddev->bitmap, sect,
  						&sync_blocks, 1);
  			}
9ad1aefc8   NeilBrown   md/raid10: Handl...
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
  		} else {
  			/* completed sync */
  			if ((!mddev->bitmap || conf->fullsync)
  			    && conf->have_replacement
  			    && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
  				/* Completed a full sync so the replacements
  				 * are now fully recovered.
  				 */
  				for (i = 0; i < conf->raid_disks; i++)
  					if (conf->mirrors[i].replacement)
  						conf->mirrors[i].replacement
  							->recovery_offset
  							= MaxSector;
  			}
6cce3b23f   NeilBrown   [PATCH] md: write...
2552
  			conf->fullsync = 0;
9ad1aefc8   NeilBrown   md/raid10: Handl...
2553
  		}
6cce3b23f   NeilBrown   [PATCH] md: write...
2554
  		bitmap_close_sync(mddev->bitmap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2555
  		close_sync(conf);
57afd89f9   NeilBrown   [PATCH] md: impro...
2556
  		*skipped = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2557
2558
2559
2560
2561
2562
  		return sectors_skipped;
  	}
  	if (chunks_skipped >= conf->raid_disks) {
  		/* if there has been nothing to do on any drive,
  		 * then there is nothing to do at all..
  		 */
57afd89f9   NeilBrown   [PATCH] md: impro...
2563
2564
  		*skipped = 1;
  		return (max_sector - sector_nr) + sectors_skipped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2565
  	}
c62072777   NeilBrown   md: allow a maxim...
2566
2567
  	if (max_sector > mddev->resync_max)
  		max_sector = mddev->resync_max; /* Don't do IO beyond here */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
  	/* make sure whole request will fit in a chunk - if chunks
  	 * are meaningful
  	 */
  	if (conf->near_copies < conf->raid_disks &&
  	    max_sector > (sector_nr | conf->chunk_mask))
  		max_sector = (sector_nr | conf->chunk_mask) + 1;
  	/*
  	 * If there is non-resync activity waiting for us then
  	 * put in a delay to throttle resync.
  	 */
0a27ec96b   NeilBrown   [PATCH] md: impro...
2578
  	if (!go_faster && conf->nr_waiting)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2579
  		msleep_interruptible(1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
  
  	/* Again, very different code for resync and recovery.
  	 * Both must result in an r10bio with a list of bios that
  	 * have bi_end_io, bi_sector, bi_bdev set,
  	 * and bi_private set to the r10bio.
  	 * For recovery, we may actually create several r10bios
  	 * with 2 bios in each, that correspond to the bios in the main one.
  	 * In this case, the subordinate r10bios link back through a
  	 * borrowed master_bio pointer, and the counter in the master
  	 * includes a ref from each subordinate.
  	 */
  	/* First, we decide what to do and set ->bi_end_io
  	 * To end_sync_read if we want to read, and
  	 * end_sync_write if we will want to write.
  	 */
6cce3b23f   NeilBrown   [PATCH] md: write...
2595
  	max_sync = RESYNC_PAGES << (PAGE_SHIFT-9);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596
2597
  	if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
  		/* recovery... the complicated one */
e875ecea2   NeilBrown   md/raid10 record ...
2598
  		int j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2599
  		r10_bio = NULL;
ab9d47e99   NeilBrown   md/raid10: refor...
2600
2601
  		for (i=0 ; i<conf->raid_disks; i++) {
  			int still_degraded;
9f2c9d12b   NeilBrown   md: remove typede...
2602
  			struct r10bio *rb2;
ab9d47e99   NeilBrown   md/raid10: refor...
2603
2604
  			sector_t sect;
  			int must_sync;
e875ecea2   NeilBrown   md/raid10 record ...
2605
  			int any_working;
24afd80d9   NeilBrown   md/raid10: handle...
2606
2607
2608
2609
2610
2611
2612
2613
  			struct mirror_info *mirror = &conf->mirrors[i];
  
  			if ((mirror->rdev == NULL ||
  			     test_bit(In_sync, &mirror->rdev->flags))
  			    &&
  			    (mirror->replacement == NULL ||
  			     test_bit(Faulty,
  				      &mirror->replacement->flags)))
ab9d47e99   NeilBrown   md/raid10: refor...
2614
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2615

ab9d47e99   NeilBrown   md/raid10: refor...
2616
2617
2618
2619
  			still_degraded = 0;
  			/* want to reconstruct this device */
  			rb2 = r10_bio;
  			sect = raid10_find_virt(conf, sector_nr, i);
24afd80d9   NeilBrown   md/raid10: handle...
2620
2621
2622
  			/* Unless we are doing a full sync, or a replacement
  			 * we only need to recover the block if it is set in
  			 * the bitmap
ab9d47e99   NeilBrown   md/raid10: refor...
2623
2624
2625
2626
2627
2628
  			 */
  			must_sync = bitmap_start_sync(mddev->bitmap, sect,
  						      &sync_blocks, 1);
  			if (sync_blocks < max_sync)
  				max_sync = sync_blocks;
  			if (!must_sync &&
24afd80d9   NeilBrown   md/raid10: handle...
2629
  			    mirror->replacement == NULL &&
ab9d47e99   NeilBrown   md/raid10: refor...
2630
2631
2632
2633
2634
2635
2636
  			    !conf->fullsync) {
  				/* yep, skip the sync_blocks here, but don't assume
  				 * that there will never be anything to do here
  				 */
  				chunks_skipped = -1;
  				continue;
  			}
6cce3b23f   NeilBrown   [PATCH] md: write...
2637

ab9d47e99   NeilBrown   md/raid10: refor...
2638
2639
2640
  			r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
  			raise_barrier(conf, rb2 != NULL);
  			atomic_set(&r10_bio->remaining, 0);
180555691   NeilBrown   md/raid10: don't ...
2641

ab9d47e99   NeilBrown   md/raid10: refor...
2642
2643
2644
2645
2646
2647
  			r10_bio->master_bio = (struct bio*)rb2;
  			if (rb2)
  				atomic_inc(&rb2->remaining);
  			r10_bio->mddev = mddev;
  			set_bit(R10BIO_IsRecover, &r10_bio->state);
  			r10_bio->sector = sect;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2648

ab9d47e99   NeilBrown   md/raid10: refor...
2649
2650
2651
2652
2653
2654
2655
2656
2657
  			raid10_find_phys(conf, r10_bio);
  
  			/* Need to check if the array will still be
  			 * degraded
  			 */
  			for (j=0; j<conf->raid_disks; j++)
  				if (conf->mirrors[j].rdev == NULL ||
  				    test_bit(Faulty, &conf->mirrors[j].rdev->flags)) {
  					still_degraded = 1;
87fc767b8   NeilBrown   [PATCH] md: fix B...
2658
  					break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2659
  				}
ab9d47e99   NeilBrown   md/raid10: refor...
2660
2661
2662
  
  			must_sync = bitmap_start_sync(mddev->bitmap, sect,
  						      &sync_blocks, still_degraded);
e875ecea2   NeilBrown   md/raid10 record ...
2663
  			any_working = 0;
ab9d47e99   NeilBrown   md/raid10: refor...
2664
  			for (j=0; j<conf->copies;j++) {
e875ecea2   NeilBrown   md/raid10 record ...
2665
  				int k;
ab9d47e99   NeilBrown   md/raid10: refor...
2666
  				int d = r10_bio->devs[j].devnum;
5e5702898   NeilBrown   md/raid10: Handle...
2667
  				sector_t from_addr, to_addr;
3cb030020   NeilBrown   md: removing type...
2668
  				struct md_rdev *rdev;
40c356ce5   NeilBrown   md/raid10: avoid ...
2669
2670
  				sector_t sector, first_bad;
  				int bad_sectors;
ab9d47e99   NeilBrown   md/raid10: refor...
2671
2672
2673
2674
  				if (!conf->mirrors[d].rdev ||
  				    !test_bit(In_sync, &conf->mirrors[d].rdev->flags))
  					continue;
  				/* This is where we read from */
e875ecea2   NeilBrown   md/raid10 record ...
2675
  				any_working = 1;
40c356ce5   NeilBrown   md/raid10: avoid ...
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
  				rdev = conf->mirrors[d].rdev;
  				sector = r10_bio->devs[j].addr;
  
  				if (is_badblock(rdev, sector, max_sync,
  						&first_bad, &bad_sectors)) {
  					if (first_bad > sector)
  						max_sync = first_bad - sector;
  					else {
  						bad_sectors -= (sector
  								- first_bad);
  						if (max_sync > bad_sectors)
  							max_sync = bad_sectors;
  						continue;
  					}
  				}
ab9d47e99   NeilBrown   md/raid10: refor...
2691
2692
2693
2694
2695
2696
  				bio = r10_bio->devs[0].bio;
  				bio->bi_next = biolist;
  				biolist = bio;
  				bio->bi_private = r10_bio;
  				bio->bi_end_io = end_sync_read;
  				bio->bi_rw = READ;
5e5702898   NeilBrown   md/raid10: Handle...
2697
  				from_addr = r10_bio->devs[j].addr;
24afd80d9   NeilBrown   md/raid10: handle...
2698
2699
2700
2701
  				bio->bi_sector = from_addr + rdev->data_offset;
  				bio->bi_bdev = rdev->bdev;
  				atomic_inc(&rdev->nr_pending);
  				/* and we write to 'i' (if not in_sync) */
ab9d47e99   NeilBrown   md/raid10: refor...
2702
2703
2704
2705
2706
  
  				for (k=0; k<conf->copies; k++)
  					if (r10_bio->devs[k].devnum == i)
  						break;
  				BUG_ON(k == conf->copies);
5e5702898   NeilBrown   md/raid10: Handle...
2707
  				to_addr = r10_bio->devs[k].addr;
ab9d47e99   NeilBrown   md/raid10: refor...
2708
  				r10_bio->devs[0].devnum = d;
5e5702898   NeilBrown   md/raid10: Handle...
2709
  				r10_bio->devs[0].addr = from_addr;
ab9d47e99   NeilBrown   md/raid10: refor...
2710
  				r10_bio->devs[1].devnum = i;
5e5702898   NeilBrown   md/raid10: Handle...
2711
  				r10_bio->devs[1].addr = to_addr;
ab9d47e99   NeilBrown   md/raid10: refor...
2712

24afd80d9   NeilBrown   md/raid10: handle...
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
  				rdev = mirror->rdev;
  				if (!test_bit(In_sync, &rdev->flags)) {
  					bio = r10_bio->devs[1].bio;
  					bio->bi_next = biolist;
  					biolist = bio;
  					bio->bi_private = r10_bio;
  					bio->bi_end_io = end_sync_write;
  					bio->bi_rw = WRITE;
  					bio->bi_sector = to_addr
  						+ rdev->data_offset;
  					bio->bi_bdev = rdev->bdev;
  					atomic_inc(&r10_bio->remaining);
  				} else
  					r10_bio->devs[1].bio->bi_end_io = NULL;
  
  				/* and maybe write to replacement */
  				bio = r10_bio->devs[1].repl_bio;
  				if (bio)
  					bio->bi_end_io = NULL;
  				rdev = mirror->replacement;
  				/* Note: if rdev != NULL, then bio
  				 * cannot be NULL as r10buf_pool_alloc will
  				 * have allocated it.
  				 * So the second test here is pointless.
  				 * But it keeps semantic-checkers happy, and
  				 * this comment keeps human reviewers
  				 * happy.
  				 */
  				if (rdev == NULL || bio == NULL ||
  				    test_bit(Faulty, &rdev->flags))
  					break;
  				bio->bi_next = biolist;
  				biolist = bio;
  				bio->bi_private = r10_bio;
  				bio->bi_end_io = end_sync_write;
  				bio->bi_rw = WRITE;
  				bio->bi_sector = to_addr + rdev->data_offset;
  				bio->bi_bdev = rdev->bdev;
  				atomic_inc(&r10_bio->remaining);
ab9d47e99   NeilBrown   md/raid10: refor...
2752
2753
2754
  				break;
  			}
  			if (j == conf->copies) {
e875ecea2   NeilBrown   md/raid10 record ...
2755
2756
  				/* Cannot recover, so abort the recovery or
  				 * record a bad block */
ab9d47e99   NeilBrown   md/raid10: refor...
2757
2758
2759
2760
  				put_buf(r10_bio);
  				if (rb2)
  					atomic_dec(&rb2->remaining);
  				r10_bio = rb2;
e875ecea2   NeilBrown   md/raid10 record ...
2761
2762
2763
2764
2765
2766
2767
2768
  				if (any_working) {
  					/* problem is that there are bad blocks
  					 * on other device(s)
  					 */
  					int k;
  					for (k = 0; k < conf->copies; k++)
  						if (r10_bio->devs[k].devnum == i)
  							break;
24afd80d9   NeilBrown   md/raid10: handle...
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
  					if (!test_bit(In_sync,
  						      &mirror->rdev->flags)
  					    && !rdev_set_badblocks(
  						    mirror->rdev,
  						    r10_bio->devs[k].addr,
  						    max_sync, 0))
  						any_working = 0;
  					if (mirror->replacement &&
  					    !rdev_set_badblocks(
  						    mirror->replacement,
e875ecea2   NeilBrown   md/raid10 record ...
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
  						    r10_bio->devs[k].addr,
  						    max_sync, 0))
  						any_working = 0;
  				}
  				if (!any_working)  {
  					if (!test_and_set_bit(MD_RECOVERY_INTR,
  							      &mddev->recovery))
  						printk(KERN_INFO "md/raid10:%s: insufficient "
  						       "working devices for recovery.
  ",
  						       mdname(mddev));
24afd80d9   NeilBrown   md/raid10: handle...
2790
  					mirror->recovery_disabled
e875ecea2   NeilBrown   md/raid10 record ...
2791
2792
  						= mddev->recovery_disabled;
  				}
ab9d47e99   NeilBrown   md/raid10: refor...
2793
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2794
  			}
ab9d47e99   NeilBrown   md/raid10: refor...
2795
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2796
2797
  		if (biolist == NULL) {
  			while (r10_bio) {
9f2c9d12b   NeilBrown   md: remove typede...
2798
2799
  				struct r10bio *rb2 = r10_bio;
  				r10_bio = (struct r10bio*) rb2->master_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2800
2801
2802
2803
2804
2805
2806
2807
  				rb2->master_bio = NULL;
  				put_buf(rb2);
  			}
  			goto giveup;
  		}
  	} else {
  		/* resync. Schedule a read for every block at this virt offset */
  		int count = 0;
6cce3b23f   NeilBrown   [PATCH] md: write...
2808

78200d45c   NeilBrown   md/raid10: Don't...
2809
  		bitmap_cond_end_sync(mddev->bitmap, sector_nr);
6cce3b23f   NeilBrown   [PATCH] md: write...
2810
2811
  		if (!bitmap_start_sync(mddev->bitmap, sector_nr,
  				       &sync_blocks, mddev->degraded) &&
ab9d47e99   NeilBrown   md/raid10: refor...
2812
2813
  		    !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED,
  						 &mddev->recovery)) {
6cce3b23f   NeilBrown   [PATCH] md: write...
2814
2815
2816
2817
2818
2819
  			/* We can skip this block */
  			*skipped = 1;
  			return sync_blocks + sectors_skipped;
  		}
  		if (sync_blocks < max_sync)
  			max_sync = sync_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2820
  		r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2821
2822
  		r10_bio->mddev = mddev;
  		atomic_set(&r10_bio->remaining, 0);
6cce3b23f   NeilBrown   [PATCH] md: write...
2823
2824
  		raise_barrier(conf, 0);
  		conf->next_resync = sector_nr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2825
2826
2827
2828
2829
2830
2831
2832
2833
  
  		r10_bio->master_bio = NULL;
  		r10_bio->sector = sector_nr;
  		set_bit(R10BIO_IsSync, &r10_bio->state);
  		raid10_find_phys(conf, r10_bio);
  		r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1;
  
  		for (i=0; i<conf->copies; i++) {
  			int d = r10_bio->devs[i].devnum;
40c356ce5   NeilBrown   md/raid10: avoid ...
2834
2835
  			sector_t first_bad, sector;
  			int bad_sectors;
9ad1aefc8   NeilBrown   md/raid10: Handl...
2836
2837
  			if (r10_bio->devs[i].repl_bio)
  				r10_bio->devs[i].repl_bio->bi_end_io = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2838
2839
  			bio = r10_bio->devs[i].bio;
  			bio->bi_end_io = NULL;
af03b8e4e   NeilBrown   md: fix two raid1...
2840
  			clear_bit(BIO_UPTODATE, &bio->bi_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2841
  			if (conf->mirrors[d].rdev == NULL ||
b2d444d7a   NeilBrown   [PATCH] md: conve...
2842
  			    test_bit(Faulty, &conf->mirrors[d].rdev->flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2843
  				continue;
40c356ce5   NeilBrown   md/raid10: avoid ...
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
  			sector = r10_bio->devs[i].addr;
  			if (is_badblock(conf->mirrors[d].rdev,
  					sector, max_sync,
  					&first_bad, &bad_sectors)) {
  				if (first_bad > sector)
  					max_sync = first_bad - sector;
  				else {
  					bad_sectors -= (sector - first_bad);
  					if (max_sync > bad_sectors)
  						max_sync = max_sync;
  					continue;
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2857
2858
2859
2860
2861
2862
  			atomic_inc(&conf->mirrors[d].rdev->nr_pending);
  			atomic_inc(&r10_bio->remaining);
  			bio->bi_next = biolist;
  			biolist = bio;
  			bio->bi_private = r10_bio;
  			bio->bi_end_io = end_sync_read;
802ba064c   NeilBrown   [PATCH] md: Don't...
2863
  			bio->bi_rw = READ;
40c356ce5   NeilBrown   md/raid10: avoid ...
2864
  			bio->bi_sector = sector +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2865
2866
2867
  				conf->mirrors[d].rdev->data_offset;
  			bio->bi_bdev = conf->mirrors[d].rdev->bdev;
  			count++;
9ad1aefc8   NeilBrown   md/raid10: Handl...
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
  
  			if (conf->mirrors[d].replacement == NULL ||
  			    test_bit(Faulty,
  				     &conf->mirrors[d].replacement->flags))
  				continue;
  
  			/* Need to set up for writing to the replacement */
  			bio = r10_bio->devs[i].repl_bio;
  			clear_bit(BIO_UPTODATE, &bio->bi_flags);
  
  			sector = r10_bio->devs[i].addr;
  			atomic_inc(&conf->mirrors[d].rdev->nr_pending);
  			bio->bi_next = biolist;
  			biolist = bio;
  			bio->bi_private = r10_bio;
  			bio->bi_end_io = end_sync_write;
  			bio->bi_rw = WRITE;
  			bio->bi_sector = sector +
  				conf->mirrors[d].replacement->data_offset;
  			bio->bi_bdev = conf->mirrors[d].replacement->bdev;
  			count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2889
2890
2891
2892
2893
2894
  		}
  
  		if (count < 2) {
  			for (i=0; i<conf->copies; i++) {
  				int d = r10_bio->devs[i].devnum;
  				if (r10_bio->devs[i].bio->bi_end_io)
ab9d47e99   NeilBrown   md/raid10: refor...
2895
2896
  					rdev_dec_pending(conf->mirrors[d].rdev,
  							 mddev);
9ad1aefc8   NeilBrown   md/raid10: Handl...
2897
2898
2899
2900
2901
  				if (r10_bio->devs[i].repl_bio &&
  				    r10_bio->devs[i].repl_bio->bi_end_io)
  					rdev_dec_pending(
  						conf->mirrors[d].replacement,
  						mddev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
  			}
  			put_buf(r10_bio);
  			biolist = NULL;
  			goto giveup;
  		}
  	}
  
  	for (bio = biolist; bio ; bio=bio->bi_next) {
  
  		bio->bi_flags &= ~(BIO_POOL_MASK - 1);
  		if (bio->bi_end_io)
  			bio->bi_flags |= 1 << BIO_UPTODATE;
  		bio->bi_vcnt = 0;
  		bio->bi_idx = 0;
  		bio->bi_phys_segments = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2917
2918
2919
2920
  		bio->bi_size = 0;
  	}
  
  	nr_sectors = 0;
6cce3b23f   NeilBrown   [PATCH] md: write...
2921
2922
  	if (sector_nr + max_sync < max_sector)
  		max_sector = sector_nr + max_sync;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2923
2924
2925
  	do {
  		struct page *page;
  		int len = PAGE_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2926
2927
2928
2929
2930
  		if (sector_nr + (len>>9) > max_sector)
  			len = (max_sector - sector_nr) << 9;
  		if (len == 0)
  			break;
  		for (bio= biolist ; bio ; bio=bio->bi_next) {
ab9d47e99   NeilBrown   md/raid10: refor...
2931
  			struct bio *bio2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2932
  			page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
ab9d47e99   NeilBrown   md/raid10: refor...
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
  			if (bio_add_page(bio, page, len, 0))
  				continue;
  
  			/* stop here */
  			bio->bi_io_vec[bio->bi_vcnt].bv_page = page;
  			for (bio2 = biolist;
  			     bio2 && bio2 != bio;
  			     bio2 = bio2->bi_next) {
  				/* remove last page from this bio */
  				bio2->bi_vcnt--;
  				bio2->bi_size -= len;
  				bio2->bi_flags &= ~(1<< BIO_SEG_VALID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2945
  			}
ab9d47e99   NeilBrown   md/raid10: refor...
2946
  			goto bio_full;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
  		}
  		nr_sectors += len>>9;
  		sector_nr += len>>9;
  	} while (biolist->bi_vcnt < RESYNC_PAGES);
   bio_full:
  	r10_bio->sectors = nr_sectors;
  
  	while (biolist) {
  		bio = biolist;
  		biolist = biolist->bi_next;
  
  		bio->bi_next = NULL;
  		r10_bio = bio->bi_private;
  		r10_bio->sectors = nr_sectors;
  
  		if (bio->bi_end_io == end_sync_read) {
  			md_sync_acct(bio->bi_bdev, nr_sectors);
  			generic_make_request(bio);
  		}
  	}
57afd89f9   NeilBrown   [PATCH] md: impro...
2967
2968
2969
2970
2971
  	if (sectors_skipped)
  		/* pretend they weren't skipped, it makes
  		 * no important difference in this case
  		 */
  		md_done_sync(mddev, sectors_skipped, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2972
2973
2974
  	return sectors_skipped + nr_sectors;
   giveup:
  	/* There is nowhere to write, so all non-sync
e875ecea2   NeilBrown   md/raid10 record ...
2975
2976
  	 * drives must be failed or in resync, all drives
  	 * have a bad block, so try the next chunk...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2977
  	 */
09b4068a7   NeilBrown   md/raid10: Don't...
2978
2979
2980
2981
  	if (sector_nr + max_sync < max_sector)
  		max_sector = sector_nr + max_sync;
  
  	sectors_skipped += (max_sector - sector_nr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2982
2983
  	chunks_skipped ++;
  	sector_nr = max_sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2984
  	goto skipped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2985
  }
80c3a6ce4   Dan Williams   md: add 'size' as...
2986
  static sector_t
fd01b88c7   NeilBrown   md: remove typede...
2987
  raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
80c3a6ce4   Dan Williams   md: add 'size' as...
2988
2989
  {
  	sector_t size;
e879a8793   NeilBrown   md/raid10: typede...
2990
  	struct r10conf *conf = mddev->private;
80c3a6ce4   Dan Williams   md: add 'size' as...
2991
2992
  
  	if (!raid_disks)
84707f38e   NeilBrown   md: don't use mdd...
2993
  		raid_disks = conf->raid_disks;
80c3a6ce4   Dan Williams   md: add 'size' as...
2994
  	if (!sectors)
dab8b2924   Trela, Maciej   md: Add support f...
2995
  		sectors = conf->dev_sectors;
80c3a6ce4   Dan Williams   md: add 'size' as...
2996
2997
2998
2999
3000
3001
3002
3003
  
  	size = sectors >> conf->chunk_shift;
  	sector_div(size, conf->far_copies);
  	size = size * raid_disks;
  	sector_div(size, conf->near_copies);
  
  	return size << conf->chunk_shift;
  }
dab8b2924   Trela, Maciej   md: Add support f...
3004

e879a8793   NeilBrown   md/raid10: typede...
3005
  static struct r10conf *setup_conf(struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3006
  {
e879a8793   NeilBrown   md/raid10: typede...
3007
  	struct r10conf *conf = NULL;
c93983bf5   NeilBrown   [PATCH] md: suppo...
3008
  	int nc, fc, fo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3009
  	sector_t stride, size;
dab8b2924   Trela, Maciej   md: Add support f...
3010
  	int err = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3011

f73ea8737   Maciej Trela   md: fix raid10 ta...
3012
3013
  	if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
  	    !is_power_of_2(mddev->new_chunk_sectors)) {
128595ed6   NeilBrown   md/raid10: tidy u...
3014
3015
3016
3017
  		printk(KERN_ERR "md/raid10:%s: chunk size must be "
  		       "at least PAGE_SIZE(%ld) and be a power of 2.
  ",
  		       mdname(mddev), PAGE_SIZE);
dab8b2924   Trela, Maciej   md: Add support f...
3018
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3019
  	}
2604b703b   NeilBrown   [PATCH] md: remov...
3020

f73ea8737   Maciej Trela   md: fix raid10 ta...
3021
3022
3023
  	nc = mddev->new_layout & 255;
  	fc = (mddev->new_layout >> 8) & 255;
  	fo = mddev->new_layout & (1<<16);
dab8b2924   Trela, Maciej   md: Add support f...
3024

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3025
  	if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
f73ea8737   Maciej Trela   md: fix raid10 ta...
3026
  	    (mddev->new_layout >> 17)) {
128595ed6   NeilBrown   md/raid10: tidy u...
3027
3028
  		printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x
  ",
f73ea8737   Maciej Trela   md: fix raid10 ta...
3029
  		       mdname(mddev), mddev->new_layout);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3030
3031
  		goto out;
  	}
dab8b2924   Trela, Maciej   md: Add support f...
3032
3033
  
  	err = -ENOMEM;
e879a8793   NeilBrown   md/raid10: typede...
3034
  	conf = kzalloc(sizeof(struct r10conf), GFP_KERNEL);
dab8b2924   Trela, Maciej   md: Add support f...
3035
  	if (!conf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3036
  		goto out;
dab8b2924   Trela, Maciej   md: Add support f...
3037

4443ae10c   NeilBrown   [PATCH] md: auto-...
3038
  	conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
dab8b2924   Trela, Maciej   md: Add support f...
3039
3040
3041
  				GFP_KERNEL);
  	if (!conf->mirrors)
  		goto out;
4443ae10c   NeilBrown   [PATCH] md: auto-...
3042
3043
3044
  
  	conf->tmppage = alloc_page(GFP_KERNEL);
  	if (!conf->tmppage)
dab8b2924   Trela, Maciej   md: Add support f...
3045
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3046

64a742bc6   NeilBrown   [PATCH] md: fix r...
3047
  	conf->raid_disks = mddev->raid_disks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3048
3049
3050
  	conf->near_copies = nc;
  	conf->far_copies = fc;
  	conf->copies = nc*fc;
c93983bf5   NeilBrown   [PATCH] md: suppo...
3051
  	conf->far_offset = fo;
dab8b2924   Trela, Maciej   md: Add support f...
3052
3053
3054
3055
3056
3057
3058
  	conf->chunk_mask = mddev->new_chunk_sectors - 1;
  	conf->chunk_shift = ffz(~mddev->new_chunk_sectors);
  
  	conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
  					   r10bio_pool_free, conf);
  	if (!conf->r10bio_pool)
  		goto out;
58c0fed40   Andre Noll   md: Make mddev->s...
3059
  	size = mddev->dev_sectors >> conf->chunk_shift;
64a742bc6   NeilBrown   [PATCH] md: fix r...
3060
3061
3062
3063
3064
3065
  	sector_div(size, fc);
  	size = size * conf->raid_disks;
  	sector_div(size, nc);
  	/* 'size' is now the number of chunks in the array */
  	/* calculate "used chunks per device" in 'stride' */
  	stride = size * conf->copies;
af03b8e4e   NeilBrown   md: fix two raid1...
3066
3067
3068
3069
3070
  
  	/* We need to round up when dividing by raid_disks to
  	 * get the stride size.
  	 */
  	stride += conf->raid_disks - 1;
64a742bc6   NeilBrown   [PATCH] md: fix r...
3071
  	sector_div(stride, conf->raid_disks);
dab8b2924   Trela, Maciej   md: Add support f...
3072
3073
  
  	conf->dev_sectors = stride << conf->chunk_shift;
64a742bc6   NeilBrown   [PATCH] md: fix r...
3074

c93983bf5   NeilBrown   [PATCH] md: suppo...
3075
  	if (fo)
64a742bc6   NeilBrown   [PATCH] md: fix r...
3076
3077
  		stride = 1;
  	else
c93983bf5   NeilBrown   [PATCH] md: suppo...
3078
  		sector_div(stride, fc);
64a742bc6   NeilBrown   [PATCH] md: fix r...
3079
  	conf->stride = stride << conf->chunk_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3080

e7e72bf64   Neil Brown   Remove blkdev war...
3081
  	spin_lock_init(&conf->device_lock);
dab8b2924   Trela, Maciej   md: Add support f...
3082
3083
3084
3085
3086
3087
3088
3089
  	INIT_LIST_HEAD(&conf->retry_list);
  
  	spin_lock_init(&conf->resync_lock);
  	init_waitqueue_head(&conf->wait_barrier);
  
  	conf->thread = md_register_thread(raid10d, mddev, NULL);
  	if (!conf->thread)
  		goto out;
dab8b2924   Trela, Maciej   md: Add support f...
3090
3091
3092
3093
  	conf->mddev = mddev;
  	return conf;
  
   out:
128595ed6   NeilBrown   md/raid10: tidy u...
3094
3095
  	printk(KERN_ERR "md/raid10:%s: couldn't allocate memory.
  ",
dab8b2924   Trela, Maciej   md: Add support f...
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
  	       mdname(mddev));
  	if (conf) {
  		if (conf->r10bio_pool)
  			mempool_destroy(conf->r10bio_pool);
  		kfree(conf->mirrors);
  		safe_put_page(conf->tmppage);
  		kfree(conf);
  	}
  	return ERR_PTR(err);
  }
fd01b88c7   NeilBrown   md: remove typede...
3106
  static int run(struct mddev *mddev)
dab8b2924   Trela, Maciej   md: Add support f...
3107
  {
e879a8793   NeilBrown   md/raid10: typede...
3108
  	struct r10conf *conf;
dab8b2924   Trela, Maciej   md: Add support f...
3109
  	int i, disk_idx, chunk_size;
0f6d02d58   NeilBrown   md: remove typede...
3110
  	struct mirror_info *disk;
3cb030020   NeilBrown   md: removing type...
3111
  	struct md_rdev *rdev;
dab8b2924   Trela, Maciej   md: Add support f...
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
  	sector_t size;
  
  	/*
  	 * copy the already verified devices into our private RAID10
  	 * bookkeeping area. [whatever we allocate in run(),
  	 * should be freed in stop()]
  	 */
  
  	if (mddev->private == NULL) {
  		conf = setup_conf(mddev);
  		if (IS_ERR(conf))
  			return PTR_ERR(conf);
  		mddev->private = conf;
  	}
  	conf = mddev->private;
  	if (!conf)
  		goto out;
dab8b2924   Trela, Maciej   md: Add support f...
3129
3130
  	mddev->thread = conf->thread;
  	conf->thread = NULL;
8f6c2e4b3   Martin K. Petersen   md: Use new topol...
3131
3132
3133
3134
3135
3136
3137
  	chunk_size = mddev->chunk_sectors << 9;
  	blk_queue_io_min(mddev->queue, chunk_size);
  	if (conf->raid_disks % conf->near_copies)
  		blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks);
  	else
  		blk_queue_io_opt(mddev->queue, chunk_size *
  				 (conf->raid_disks / conf->near_copies));
159ec1fc0   Cheng Renquan   md: use list_for_...
3138
  	list_for_each_entry(rdev, &mddev->disks, same_set) {
34b343cff   NeilBrown   md: don't allow a...
3139

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3140
  		disk_idx = rdev->raid_disk;
84707f38e   NeilBrown   md: don't use mdd...
3141
  		if (disk_idx >= conf->raid_disks
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3142
3143
3144
  		    || disk_idx < 0)
  			continue;
  		disk = conf->mirrors + disk_idx;
56a2559bb   NeilBrown   md/raid10: recogn...
3145
3146
3147
3148
3149
3150
3151
3152
3153
  		if (test_bit(Replacement, &rdev->flags)) {
  			if (disk->replacement)
  				goto out_free_conf;
  			disk->replacement = rdev;
  		} else {
  			if (disk->rdev)
  				goto out_free_conf;
  			disk->rdev = rdev;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3154
  		disk->rdev = rdev;
8f6c2e4b3   Martin K. Petersen   md: Use new topol...
3155
3156
  		disk_stack_limits(mddev->gendisk, rdev->bdev,
  				  rdev->data_offset << 9);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3157
  		/* as we don't honour merge_bvec_fn, we must never risk
627a2d3c2   NeilBrown   md: deal with mer...
3158
3159
  		 * violating it, so limit max_segments to 1 lying
  		 * within a single page.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3160
  		 */
627a2d3c2   NeilBrown   md: deal with mer...
3161
3162
3163
3164
3165
  		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
  			blk_queue_max_segments(mddev->queue, 1);
  			blk_queue_segment_boundary(mddev->queue,
  						   PAGE_CACHE_SIZE - 1);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3166
3167
  
  		disk->head_position = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3168
  	}
6d508242b   NeilBrown   [PATCH] md: fix r...
3169
  	/* need to check that every block has at least one working mirror */
700c72138   NeilBrown   md/raid10: Improv...
3170
  	if (!enough(conf, -1)) {
128595ed6   NeilBrown   md/raid10: tidy u...
3171
3172
  		printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.
  ",
6d508242b   NeilBrown   [PATCH] md: fix r...
3173
  		       mdname(mddev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3174
3175
3176
3177
3178
3179
3180
  		goto out_free_conf;
  	}
  
  	mddev->degraded = 0;
  	for (i = 0; i < conf->raid_disks; i++) {
  
  		disk = conf->mirrors + i;
56a2559bb   NeilBrown   md/raid10: recogn...
3181
3182
3183
3184
3185
3186
  		if (!disk->rdev && disk->replacement) {
  			/* The replacement is all we have - use it */
  			disk->rdev = disk->replacement;
  			disk->replacement = NULL;
  			clear_bit(Replacement, &disk->rdev->flags);
  		}
5fd6c1dce   NeilBrown   [PATCH] md: allow...
3187
  		if (!disk->rdev ||
2e333e898   NeilBrown   [PATCH] md: fix c...
3188
  		    !test_bit(In_sync, &disk->rdev->flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3189
3190
  			disk->head_position = 0;
  			mddev->degraded++;
8c2e870a6   Neil Brown   Ensure interrupte...
3191
3192
  			if (disk->rdev)
  				conf->fullsync = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3193
  		}
d890fa2b0   NeilBrown   md: Fix some bugs...
3194
  		disk->recovery_disabled = mddev->recovery_disabled - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3195
  	}
8c6ac868b   Andre Noll   md: Push down rec...
3196
  	if (mddev->recovery_cp != MaxSector)
128595ed6   NeilBrown   md/raid10: tidy u...
3197
  		printk(KERN_NOTICE "md/raid10:%s: not clean"
8c6ac868b   Andre Noll   md: Push down rec...
3198
3199
3200
  		       " -- starting background reconstruction
  ",
  		       mdname(mddev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3201
  	printk(KERN_INFO
128595ed6   NeilBrown   md/raid10: tidy u...
3202
3203
  		"md/raid10:%s: active with %d out of %d devices
  ",
84707f38e   NeilBrown   md: don't use mdd...
3204
3205
  		mdname(mddev), conf->raid_disks - mddev->degraded,
  		conf->raid_disks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3206
3207
3208
  	/*
  	 * Ok, everything is just fine now
  	 */
dab8b2924   Trela, Maciej   md: Add support f...
3209
3210
3211
3212
  	mddev->dev_sectors = conf->dev_sectors;
  	size = raid10_size(mddev, 0, 0);
  	md_set_array_sectors(mddev, size);
  	mddev->resync_max_sectors = size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3213

0d1292282   NeilBrown   [PATCH] md: defin...
3214
3215
  	mddev->queue->backing_dev_info.congested_fn = raid10_congested;
  	mddev->queue->backing_dev_info.congested_data = mddev;
7a5febe9f   NeilBrown   [PATCH] md: set t...
3216

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3217
3218
3219
3220
3221
  	/* Calculate max read-ahead size.
  	 * We need to readahead at least twice a whole stripe....
  	 * maybe...
  	 */
  	{
9d8f03636   Andre Noll   md: Make mddev->c...
3222
3223
  		int stripe = conf->raid_disks *
  			((mddev->chunk_sectors << 9) / PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3224
3225
3226
3227
  		stripe /= conf->near_copies;
  		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
  			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
  	}
84707f38e   NeilBrown   md: don't use mdd...
3228
  	if (conf->near_copies < conf->raid_disks)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3229
  		blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
a91a2785b   Martin K. Petersen   block: Require su...
3230
3231
3232
  
  	if (md_integrity_register(mddev))
  		goto out_free_conf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3233
3234
3235
  	return 0;
  
  out_free_conf:
01f96c0a9   NeilBrown   md: Avoid waking ...
3236
  	md_unregister_thread(&mddev->thread);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3237
3238
  	if (conf->r10bio_pool)
  		mempool_destroy(conf->r10bio_pool);
1345b1d8a   NeilBrown   [PATCH] md: defin...
3239
  	safe_put_page(conf->tmppage);
990a8baf5   Jesper Juhl   [PATCH] md: remov...
3240
  	kfree(conf->mirrors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3241
3242
3243
3244
3245
  	kfree(conf);
  	mddev->private = NULL;
  out:
  	return -EIO;
  }
fd01b88c7   NeilBrown   md: remove typede...
3246
  static int stop(struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3247
  {
e879a8793   NeilBrown   md/raid10: typede...
3248
  	struct r10conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3249

409c57f38   NeilBrown   md: enable suspen...
3250
3251
  	raise_barrier(conf, 0);
  	lower_barrier(conf);
01f96c0a9   NeilBrown   md: Avoid waking ...
3252
  	md_unregister_thread(&mddev->thread);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3253
3254
3255
  	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
  	if (conf->r10bio_pool)
  		mempool_destroy(conf->r10bio_pool);
990a8baf5   Jesper Juhl   [PATCH] md: remov...
3256
  	kfree(conf->mirrors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3257
3258
3259
3260
  	kfree(conf);
  	mddev->private = NULL;
  	return 0;
  }
fd01b88c7   NeilBrown   md: remove typede...
3261
  static void raid10_quiesce(struct mddev *mddev, int state)
6cce3b23f   NeilBrown   [PATCH] md: write...
3262
  {
e879a8793   NeilBrown   md/raid10: typede...
3263
  	struct r10conf *conf = mddev->private;
6cce3b23f   NeilBrown   [PATCH] md: write...
3264
3265
3266
3267
3268
3269
3270
3271
3272
  
  	switch(state) {
  	case 1:
  		raise_barrier(conf, 0);
  		break;
  	case 0:
  		lower_barrier(conf);
  		break;
  	}
6cce3b23f   NeilBrown   [PATCH] md: write...
3273
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3274

fd01b88c7   NeilBrown   md: remove typede...
3275
  static void *raid10_takeover_raid0(struct mddev *mddev)
dab8b2924   Trela, Maciej   md: Add support f...
3276
  {
3cb030020   NeilBrown   md: removing type...
3277
  	struct md_rdev *rdev;
e879a8793   NeilBrown   md/raid10: typede...
3278
  	struct r10conf *conf;
dab8b2924   Trela, Maciej   md: Add support f...
3279
3280
  
  	if (mddev->degraded > 0) {
128595ed6   NeilBrown   md/raid10: tidy u...
3281
3282
3283
  		printk(KERN_ERR "md/raid10:%s: Error: degraded raid0!
  ",
  		       mdname(mddev));
dab8b2924   Trela, Maciej   md: Add support f...
3284
3285
  		return ERR_PTR(-EINVAL);
  	}
dab8b2924   Trela, Maciej   md: Add support f...
3286
3287
3288
3289
3290
3291
  	/* Set new parameters */
  	mddev->new_level = 10;
  	/* new layout: far_copies = 1, near_copies = 2 */
  	mddev->new_layout = (1<<8) + 2;
  	mddev->new_chunk_sectors = mddev->chunk_sectors;
  	mddev->delta_disks = mddev->raid_disks;
dab8b2924   Trela, Maciej   md: Add support f...
3292
3293
3294
3295
3296
  	mddev->raid_disks *= 2;
  	/* make sure it will be not marked as dirty */
  	mddev->recovery_cp = MaxSector;
  
  	conf = setup_conf(mddev);
02214dc54   Krzysztof Wojcik   FIX: md: process ...
3297
  	if (!IS_ERR(conf)) {
e93f68a1f   NeilBrown   md: fix handling ...
3298
3299
3300
  		list_for_each_entry(rdev, &mddev->disks, same_set)
  			if (rdev->raid_disk >= 0)
  				rdev->new_raid_disk = rdev->raid_disk * 2;
02214dc54   Krzysztof Wojcik   FIX: md: process ...
3301
3302
  		conf->barrier = 1;
  	}
dab8b2924   Trela, Maciej   md: Add support f...
3303
3304
  	return conf;
  }
fd01b88c7   NeilBrown   md: remove typede...
3305
  static void *raid10_takeover(struct mddev *mddev)
dab8b2924   Trela, Maciej   md: Add support f...
3306
  {
e373ab109   NeilBrown   md/raid0: typedef...
3307
  	struct r0conf *raid0_conf;
dab8b2924   Trela, Maciej   md: Add support f...
3308
3309
3310
3311
3312
3313
  
  	/* raid10 can take over:
  	 *  raid0 - providing it has only two drives
  	 */
  	if (mddev->level == 0) {
  		/* for raid0 takeover only one zone is supported */
e373ab109   NeilBrown   md/raid0: typedef...
3314
3315
  		raid0_conf = mddev->private;
  		if (raid0_conf->nr_strip_zones > 1) {
128595ed6   NeilBrown   md/raid10: tidy u...
3316
3317
3318
3319
  			printk(KERN_ERR "md/raid10:%s: cannot takeover raid 0"
  			       " with more than one zone.
  ",
  			       mdname(mddev));
dab8b2924   Trela, Maciej   md: Add support f...
3320
3321
3322
3323
3324
3325
  			return ERR_PTR(-EINVAL);
  		}
  		return raid10_takeover_raid0(mddev);
  	}
  	return ERR_PTR(-EINVAL);
  }
84fc4b56d   NeilBrown   md: rename "mdk_p...
3326
  static struct md_personality raid10_personality =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3327
3328
  {
  	.name		= "raid10",
2604b703b   NeilBrown   [PATCH] md: remov...
3329
  	.level		= 10,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
  	.owner		= THIS_MODULE,
  	.make_request	= make_request,
  	.run		= run,
  	.stop		= stop,
  	.status		= status,
  	.error_handler	= error,
  	.hot_add_disk	= raid10_add_disk,
  	.hot_remove_disk= raid10_remove_disk,
  	.spare_active	= raid10_spare_active,
  	.sync_request	= sync_request,
6cce3b23f   NeilBrown   [PATCH] md: write...
3340
  	.quiesce	= raid10_quiesce,
80c3a6ce4   Dan Williams   md: add 'size' as...
3341
  	.size		= raid10_size,
dab8b2924   Trela, Maciej   md: Add support f...
3342
  	.takeover	= raid10_takeover,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3343
3344
3345
3346
  };
  
  static int __init raid_init(void)
  {
2604b703b   NeilBrown   [PATCH] md: remov...
3347
  	return register_md_personality(&raid10_personality);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3348
3349
3350
3351
  }
  
  static void raid_exit(void)
  {
2604b703b   NeilBrown   [PATCH] md: remov...
3352
  	unregister_md_personality(&raid10_personality);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3353
3354
3355
3356
3357
  }
  
  module_init(raid_init);
  module_exit(raid_exit);
  MODULE_LICENSE("GPL");
0efb9e619   NeilBrown   md: add MODULE_DE...
3358
  MODULE_DESCRIPTION("RAID10 (striped mirror) personality for MD");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3359
  MODULE_ALIAS("md-personality-9"); /* RAID10 */
d9d166c2a   NeilBrown   [PATCH] md: allow...
3360
  MODULE_ALIAS("md-raid10");
2604b703b   NeilBrown   [PATCH] md: remov...
3361
  MODULE_ALIAS("md-level-10");
34db0cd60   NeilBrown   md: add proper wr...
3362
3363
  
  module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);