Blame view

drivers/md/raid0.c 19.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  /*
     raid0.c : Multiple Devices driver for Linux
               Copyright (C) 1994-96 Marc ZYNGIER
  	     <zyngier@ufr-info-p7.ibp.fr> or
  	     <maz@gloups.fdn.fr>
               Copyright (C) 1999, 2000 Ingo Molnar, Red Hat
  
  
     RAID-0 management functions.
  
     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.  
  */
bff61975b   NeilBrown   md: move lots of ...
20
  #include <linux/blkdev.h>
bff61975b   NeilBrown   md: move lots of ...
21
  #include <linux/seq_file.h>
056075c76   Paul Gortmaker   md: Add module.h ...
22
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
43b2e5d86   NeilBrown   md: move md_k.h f...
24
  #include "md.h"
ef740c372   Christoph Hellwig   md: move headers ...
25
  #include "raid0.h"
9af204cf7   Trela, Maciej   md: Add support f...
26
  #include "raid5.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

26be34dc3   NeilBrown   [PATCH] md: defin...
28
29
  static int raid0_congested(void *data, int bits)
  {
fd01b88c7   NeilBrown   md: remove typede...
30
  	struct mddev *mddev = data;
e373ab109   NeilBrown   md/raid0: typedef...
31
  	struct r0conf *conf = mddev->private;
3cb030020   NeilBrown   md: removing type...
32
  	struct md_rdev **devlist = conf->devlist;
84707f38e   NeilBrown   md: don't use mdd...
33
  	int raid_disks = conf->strip_zone[0].nb_dev;
26be34dc3   NeilBrown   [PATCH] md: defin...
34
  	int i, ret = 0;
3fa841d7e   NeilBrown   md: report device...
35
36
  	if (mddev_congested(mddev, bits))
  		return 1;
84707f38e   NeilBrown   md: don't use mdd...
37
  	for (i = 0; i < raid_disks && !ret ; i++) {
165125e1e   Jens Axboe   [BLOCK] Get rid o...
38
  		struct request_queue *q = bdev_get_queue(devlist[i]->bdev);
26be34dc3   NeilBrown   [PATCH] md: defin...
39
40
41
42
43
  
  		ret |= bdi_congested(&q->backing_dev_info, bits);
  	}
  	return ret;
  }
46994191a   raz ben yehuda   md: have raid0 re...
44
45
46
  /*
   * inform the user of the raid configuration
  */
fd01b88c7   NeilBrown   md: remove typede...
47
  static void dump_zones(struct mddev *mddev)
46994191a   raz ben yehuda   md: have raid0 re...
48
  {
50de8df4a   NeilBrown   md/raid0: convert...
49
  	int j, k;
46994191a   raz ben yehuda   md: have raid0 re...
50
51
52
  	sector_t zone_size = 0;
  	sector_t zone_start = 0;
  	char b[BDEVNAME_SIZE];
e373ab109   NeilBrown   md/raid0: typedef...
53
  	struct r0conf *conf = mddev->private;
84707f38e   NeilBrown   md: don't use mdd...
54
  	int raid_disks = conf->strip_zone[0].nb_dev;
50de8df4a   NeilBrown   md/raid0: convert...
55
56
57
58
  	printk(KERN_INFO "md: RAID0 configuration for %s - %d zone%s
  ",
  	       mdname(mddev),
  	       conf->nr_strip_zones, conf->nr_strip_zones==1?"":"s");
46994191a   raz ben yehuda   md: have raid0 re...
59
  	for (j = 0; j < conf->nr_strip_zones; j++) {
50de8df4a   NeilBrown   md/raid0: convert...
60
  		printk(KERN_INFO "md: zone%d=[", j);
46994191a   raz ben yehuda   md: have raid0 re...
61
  		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
50de8df4a   NeilBrown   md/raid0: convert...
62
  			printk(KERN_CONT "%s%s", k?"/":"",
84707f38e   NeilBrown   md: don't use mdd...
63
  			bdevname(conf->devlist[j*raid_disks
46994191a   raz ben yehuda   md: have raid0 re...
64
  						+ k]->bdev, b));
b5a20961f   NeilBrown   md/raid0: tidy up...
65
66
  		printk(KERN_CONT "]
  ");
46994191a   raz ben yehuda   md: have raid0 re...
67
68
  
  		zone_size  = conf->strip_zone[j].zone_end - zone_start;
50de8df4a   NeilBrown   md/raid0: convert...
69
70
71
  		printk(KERN_INFO "      zone-offset=%10lluKB, "
  				"device-offset=%10lluKB, size=%10lluKB
  ",
46994191a   raz ben yehuda   md: have raid0 re...
72
73
74
75
76
  			(unsigned long long)zone_start>>1,
  			(unsigned long long)conf->strip_zone[j].dev_start>>1,
  			(unsigned long long)zone_size>>1);
  		zone_start = conf->strip_zone[j].zone_end;
  	}
50de8df4a   NeilBrown   md/raid0: convert...
77
78
  	printk(KERN_INFO "
  ");
46994191a   raz ben yehuda   md: have raid0 re...
79
  }
e373ab109   NeilBrown   md/raid0: typedef...
80
  static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  {
a9f326ebf   NeilBrown   md: remove sparse...
82
  	int i, c, err;
49f357a22   NeilBrown   md: raid0: remove...
83
  	sector_t curr_zone_end, sectors;
3cb030020   NeilBrown   md: removing type...
84
  	struct md_rdev *smallest, *rdev1, *rdev2, *rdev, **dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
  	struct strip_zone *zone;
  	int cnt;
  	char b[BDEVNAME_SIZE];
50de8df4a   NeilBrown   md/raid0: convert...
88
  	char b2[BDEVNAME_SIZE];
e373ab109   NeilBrown   md/raid0: typedef...
89
  	struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
c83057a1f   Shaohua Li   md: raid 0 suppor...
90
  	bool discard_supported = false;
ed7b00380   Andre Noll   md: raid0: Alloca...
91
92
93
  
  	if (!conf)
  		return -ENOMEM;
dafb20fa3   NeilBrown   md: tidy up rdev_...
94
  	rdev_for_each(rdev1, mddev) {
50de8df4a   NeilBrown   md/raid0: convert...
95
96
97
98
  		pr_debug("md/raid0:%s: looking at %s
  ",
  			 mdname(mddev),
  			 bdevname(rdev1->bdev, b));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  		c = 0;
13f2682b7   NeilBrown   md: raid0/linear:...
100
101
102
103
104
  
  		/* round size to chunk_size */
  		sectors = rdev1->sectors;
  		sector_div(sectors, mddev->chunk_sectors);
  		rdev1->sectors = sectors * mddev->chunk_sectors;
dafb20fa3   NeilBrown   md: tidy up rdev_...
105
  		rdev_for_each(rdev2, mddev) {
50de8df4a   NeilBrown   md/raid0: convert...
106
107
108
109
110
111
112
113
  			pr_debug("md/raid0:%s:   comparing %s(%llu)"
  				 " with %s(%llu)
  ",
  				 mdname(mddev),
  				 bdevname(rdev1->bdev,b),
  				 (unsigned long long)rdev1->sectors,
  				 bdevname(rdev2->bdev,b2),
  				 (unsigned long long)rdev2->sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  			if (rdev2 == rdev1) {
50de8df4a   NeilBrown   md/raid0: convert...
115
116
117
  				pr_debug("md/raid0:%s:   END
  ",
  					 mdname(mddev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  				break;
  			}
dd8ac336c   Andre Noll   md: Represent rai...
120
  			if (rdev2->sectors == rdev1->sectors) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  				/*
  				 * Not unique, don't count it as a new
  				 * group
  				 */
50de8df4a   NeilBrown   md/raid0: convert...
125
126
127
  				pr_debug("md/raid0:%s:   EQUAL
  ",
  					 mdname(mddev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
  				c = 1;
  				break;
  			}
50de8df4a   NeilBrown   md/raid0: convert...
131
132
133
  			pr_debug("md/raid0:%s:   NOT EQUAL
  ",
  				 mdname(mddev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  		}
  		if (!c) {
50de8df4a   NeilBrown   md/raid0: convert...
136
137
138
  			pr_debug("md/raid0:%s:   ==> UNIQUE
  ",
  				 mdname(mddev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  			conf->nr_strip_zones++;
50de8df4a   NeilBrown   md/raid0: convert...
140
141
142
  			pr_debug("md/raid0:%s: %d zones
  ",
  				 mdname(mddev), conf->nr_strip_zones);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
  		}
  	}
50de8df4a   NeilBrown   md/raid0: convert...
145
146
147
  	pr_debug("md/raid0:%s: FINAL %d zones
  ",
  		 mdname(mddev), conf->nr_strip_zones);
ed7b00380   Andre Noll   md: raid0: Alloca...
148
  	err = -ENOMEM;
9ffae0cf3   NeilBrown   [PATCH] md: conve...
149
  	conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
  				conf->nr_strip_zones, GFP_KERNEL);
  	if (!conf->strip_zone)
ed7b00380   Andre Noll   md: raid0: Alloca...
152
  		goto abort;
3cb030020   NeilBrown   md: removing type...
153
  	conf->devlist = kzalloc(sizeof(struct md_rdev*)*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
  				conf->nr_strip_zones*mddev->raid_disks,
  				GFP_KERNEL);
  	if (!conf->devlist)
ed7b00380   Andre Noll   md: raid0: Alloca...
157
  		goto abort;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
163
164
  	/* The first zone must contain all devices, so here we check that
  	 * there is a proper alignment of slots to devices and find them all
  	 */
  	zone = &conf->strip_zone[0];
  	cnt = 0;
  	smallest = NULL;
b414579f4   NeilBrown   md: raid0: remove...
165
  	dev = conf->devlist;
ed7b00380   Andre Noll   md: raid0: Alloca...
166
  	err = -EINVAL;
dafb20fa3   NeilBrown   md: tidy up rdev_...
167
  	rdev_for_each(rdev1, mddev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  		int j = rdev1->raid_disk;
e93f68a1f   NeilBrown   md: fix handling ...
169
  		if (mddev->level == 10) {
9af204cf7   Trela, Maciej   md: Add support f...
170
171
  			/* taking over a raid10-n2 array */
  			j /= 2;
e93f68a1f   NeilBrown   md: fix handling ...
172
173
  			rdev1->new_raid_disk = j;
  		}
9af204cf7   Trela, Maciej   md: Add support f...
174

fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
175
176
177
178
179
180
181
  		if (mddev->level == 1) {
  			/* taiking over a raid1 array-
  			 * we have only one active disk
  			 */
  			j = 0;
  			rdev1->new_raid_disk = j;
  		}
f96c9f305   NeilBrown   md/raid0: improve...
182
183
184
185
186
187
188
189
  		if (j < 0) {
  			printk(KERN_ERR
  			       "md/raid0:%s: remove inactive devices before converting to RAID0
  ",
  			       mdname(mddev));
  			goto abort;
  		}
  		if (j >= mddev->raid_disks) {
b5a20961f   NeilBrown   md/raid0: tidy up...
190
191
192
  			printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
  			       "aborting!
  ", mdname(mddev), j);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
  			goto abort;
  		}
b414579f4   NeilBrown   md: raid0: remove...
195
  		if (dev[j]) {
b5a20961f   NeilBrown   md/raid0: tidy up...
196
197
198
  			printk(KERN_ERR "md/raid0:%s: multiple devices for %d - "
  			       "aborting!
  ", mdname(mddev), j);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  			goto abort;
  		}
b414579f4   NeilBrown   md: raid0: remove...
201
  		dev[j] = rdev1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202

8f6c2e4b3   Martin K. Petersen   md: Use new topol...
203
204
  		disk_stack_limits(mddev->gendisk, rdev1->bdev,
  				  rdev1->data_offset << 9);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205

ba13da47f   NeilBrown   md: add proper me...
206
207
  		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn)
  			conf->has_merge_bvec = 1;
dd8ac336c   Andre Noll   md: Represent rai...
208
  		if (!smallest || (rdev1->sectors < smallest->sectors))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
  			smallest = rdev1;
  		cnt++;
c83057a1f   Shaohua Li   md: raid 0 suppor...
211
212
213
  
  		if (blk_queue_discard(bdev_get_queue(rdev1->bdev)))
  			discard_supported = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
  	}
  	if (cnt != mddev->raid_disks) {
b5a20961f   NeilBrown   md/raid0: tidy up...
216
217
218
  		printk(KERN_ERR "md/raid0:%s: too few disks (%d of %d) - "
  		       "aborting!
  ", mdname(mddev), cnt, mddev->raid_disks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
  		goto abort;
  	}
  	zone->nb_dev = cnt;
49f357a22   NeilBrown   md: raid0: remove...
222
  	zone->zone_end = smallest->sectors * cnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223

49f357a22   NeilBrown   md: raid0: remove...
224
  	curr_zone_end = zone->zone_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
  
  	/* now do the other zones */
  	for (i = 1; i < conf->nr_strip_zones; i++)
  	{
a9f326ebf   NeilBrown   md: remove sparse...
229
  		int j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  		zone = conf->strip_zone + i;
b414579f4   NeilBrown   md: raid0: remove...
231
  		dev = conf->devlist + i * mddev->raid_disks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

50de8df4a   NeilBrown   md/raid0: convert...
233
234
  		pr_debug("md/raid0:%s: zone %d
  ", mdname(mddev), i);
d27a43abd   NeilBrown   md/raid0: two cle...
235
  		zone->dev_start = smallest->sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
239
  		smallest = NULL;
  		c = 0;
  
  		for (j=0; j<cnt; j++) {
b414579f4   NeilBrown   md: raid0: remove...
240
  			rdev = conf->devlist[j];
d27a43abd   NeilBrown   md/raid0: two cle...
241
  			if (rdev->sectors <= zone->dev_start) {
50de8df4a   NeilBrown   md/raid0: convert...
242
243
244
245
  				pr_debug("md/raid0:%s: checking %s ... nope
  ",
  					 mdname(mddev),
  					 bdevname(rdev->bdev, b));
dd8ac336c   Andre Noll   md: Represent rai...
246
247
  				continue;
  			}
50de8df4a   NeilBrown   md/raid0: convert...
248
249
250
251
252
  			pr_debug("md/raid0:%s: checking %s ..."
  				 " contained as device %d
  ",
  				 mdname(mddev),
  				 bdevname(rdev->bdev, b), c);
b414579f4   NeilBrown   md: raid0: remove...
253
  			dev[c] = rdev;
dd8ac336c   Andre Noll   md: Represent rai...
254
255
256
  			c++;
  			if (!smallest || rdev->sectors < smallest->sectors) {
  				smallest = rdev;
50de8df4a   NeilBrown   md/raid0: convert...
257
258
259
260
  				pr_debug("md/raid0:%s:  (%llu) is smallest!.
  ",
  					 mdname(mddev),
  					 (unsigned long long)rdev->sectors);
dd8ac336c   Andre Noll   md: Represent rai...
261
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
  		}
  
  		zone->nb_dev = c;
49f357a22   NeilBrown   md: raid0: remove...
265
  		sectors = (smallest->sectors - zone->dev_start) * c;
50de8df4a   NeilBrown   md/raid0: convert...
266
267
268
269
  		pr_debug("md/raid0:%s: zone->nb_dev: %d, sectors: %llu
  ",
  			 mdname(mddev),
  			 zone->nb_dev, (unsigned long long)sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270

49f357a22   NeilBrown   md: raid0: remove...
271
  		curr_zone_end += sectors;
d27a43abd   NeilBrown   md/raid0: two cle...
272
  		zone->zone_end = curr_zone_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

50de8df4a   NeilBrown   md/raid0: convert...
274
275
276
277
  		pr_debug("md/raid0:%s: current zone start: %llu
  ",
  			 mdname(mddev),
  			 (unsigned long long)smallest->sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
  	}
26be34dc3   NeilBrown   [PATCH] md: defin...
279
280
  	mddev->queue->backing_dev_info.congested_fn = raid0_congested;
  	mddev->queue->backing_dev_info.congested_data = mddev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281

92e59b6ba   raz ben yehuda   md: raid0: chunk ...
282
283
284
285
  	/*
  	 * now since we have the hard sector sizes, we can make sure
  	 * chunk size is a multiple of that sector size
  	 */
9d8f03636   Andre Noll   md: Make mddev->c...
286
  	if ((mddev->chunk_sectors << 9) % queue_logical_block_size(mddev->queue)) {
b5a20961f   NeilBrown   md/raid0: tidy up...
287
288
  		printk(KERN_ERR "md/raid0:%s: chunk_size of %d not valid
  ",
92e59b6ba   raz ben yehuda   md: raid0: chunk ...
289
  		       mdname(mddev),
9d8f03636   Andre Noll   md: Make mddev->c...
290
  		       mddev->chunk_sectors << 9);
92e59b6ba   raz ben yehuda   md: raid0: chunk ...
291
292
  		goto abort;
  	}
8f6c2e4b3   Martin K. Petersen   md: Use new topol...
293
294
295
296
  
  	blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
  	blk_queue_io_opt(mddev->queue,
  			 (mddev->chunk_sectors << 9) * mddev->raid_disks);
c83057a1f   Shaohua Li   md: raid 0 suppor...
297
298
299
300
  	if (!discard_supported)
  		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
  	else
  		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
50de8df4a   NeilBrown   md/raid0: convert...
301
302
  	pr_debug("md/raid0:%s: done.
  ", mdname(mddev));
9af204cf7   Trela, Maciej   md: Add support f...
303
  	*private_conf = conf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  	return 0;
5568a6035   Andre Noll   md: raid0: Make r...
305
  abort:
ed7b00380   Andre Noll   md: raid0: Alloca...
306
307
308
  	kfree(conf->strip_zone);
  	kfree(conf->devlist);
  	kfree(conf);
58ebb34c4   NeilBrown   md: raid0: fix er...
309
  	*private_conf = ERR_PTR(err);
ed7b00380   Andre Noll   md: raid0: Alloca...
310
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  }
ba13da47f   NeilBrown   md: add proper me...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
  /* Find the zone which holds a particular offset
   * Update *sectorp to be an offset in that zone
   */
  static struct strip_zone *find_zone(struct r0conf *conf,
  				    sector_t *sectorp)
  {
  	int i;
  	struct strip_zone *z = conf->strip_zone;
  	sector_t sector = *sectorp;
  
  	for (i = 0; i < conf->nr_strip_zones; i++)
  		if (sector < z[i].zone_end) {
  			if (i)
  				*sectorp = sector - z[i-1].zone_end;
  			return z + i;
  		}
  	BUG();
  }
  
  /*
   * remaps the bio to the target device. we separate two flows.
   * power 2 flow and a general flow for the sake of perfromance
  */
  static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
  				sector_t sector, sector_t *sector_offset)
  {
  	unsigned int sect_in_chunk;
  	sector_t chunk;
  	struct r0conf *conf = mddev->private;
  	int raid_disks = conf->strip_zone[0].nb_dev;
  	unsigned int chunk_sects = mddev->chunk_sectors;
  
  	if (is_power_of_2(chunk_sects)) {
  		int chunksect_bits = ffz(~chunk_sects);
  		/* find the sector offset inside the chunk */
  		sect_in_chunk  = sector & (chunk_sects - 1);
  		sector >>= chunksect_bits;
  		/* chunk in zone */
  		chunk = *sector_offset;
  		/* quotient is the chunk in real device*/
  		sector_div(chunk, zone->nb_dev << chunksect_bits);
  	} else{
  		sect_in_chunk = sector_div(sector, chunk_sects);
  		chunk = *sector_offset;
  		sector_div(chunk, chunk_sects * zone->nb_dev);
  	}
  	/*
  	*  position the bio over the real device
  	*  real sector = chunk in device + starting of zone
  	*	+ the position in the chunk
  	*/
  	*sector_offset = (chunk * chunk_sects) + sect_in_chunk;
  	return conf->devlist[(zone - conf->strip_zone)*raid_disks
  			     + sector_div(sector, zone->nb_dev)];
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  /**
ba13da47f   NeilBrown   md: add proper me...
368
   *	raid0_mergeable_bvec -- tell bio layer if two requests can be merged
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
   *	@q: request queue
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
370
   *	@bvm: properties of new bio
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
   *	@biovec: the request that could be merged to it.
   *
   *	Return amount of bytes we can accept at this offset
   */
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
375
376
377
  static int raid0_mergeable_bvec(struct request_queue *q,
  				struct bvec_merge_data *bvm,
  				struct bio_vec *biovec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  {
fd01b88c7   NeilBrown   md: remove typede...
379
  	struct mddev *mddev = q->queuedata;
ba13da47f   NeilBrown   md: add proper me...
380
  	struct r0conf *conf = mddev->private;
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
381
  	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
ba13da47f   NeilBrown   md: add proper me...
382
  	sector_t sector_offset = sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  	int max;
9d8f03636   Andre Noll   md: Make mddev->c...
384
  	unsigned int chunk_sectors = mddev->chunk_sectors;
cc371e66e   Alasdair G Kergon   Add bvec_merge_da...
385
  	unsigned int bio_sectors = bvm->bi_size >> 9;
ba13da47f   NeilBrown   md: add proper me...
386
387
388
  	struct strip_zone *zone;
  	struct md_rdev *rdev;
  	struct request_queue *subq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389

d6e412eaa   NeilBrown   md: raid0: chunk_...
390
  	if (is_power_of_2(chunk_sectors))
fbb704efb   raz ben yehuda   md: raid0 :Enable...
391
392
393
394
395
  		max =  (chunk_sectors - ((sector & (chunk_sectors-1))
  						+ bio_sectors)) << 9;
  	else
  		max =  (chunk_sectors - (sector_div(sector, chunk_sectors)
  						+ bio_sectors)) << 9;
ba13da47f   NeilBrown   md: add proper me...
396
397
  	if (max < 0)
  		max = 0; /* bio_add cannot handle a negative return */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
  	if (max <= biovec->bv_len && bio_sectors == 0)
  		return biovec->bv_len;
ba13da47f   NeilBrown   md: add proper me...
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
  	if (max < biovec->bv_len)
  		/* too small already, no need to check further */
  		return max;
  	if (!conf->has_merge_bvec)
  		return max;
  
  	/* May need to check subordinate device */
  	sector = sector_offset;
  	zone = find_zone(mddev->private, &sector_offset);
  	rdev = map_sector(mddev, zone, sector, &sector_offset);
  	subq = bdev_get_queue(rdev->bdev);
  	if (subq->merge_bvec_fn) {
  		bvm->bi_bdev = rdev->bdev;
  		bvm->bi_sector = sector_offset + zone->dev_start +
  			rdev->data_offset;
  		return min(max, subq->merge_bvec_fn(subq, bvm, biovec));
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
  		return max;
  }
fd01b88c7   NeilBrown   md: remove typede...
419
  static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks)
80c3a6ce4   Dan Williams   md: add 'size' as...
420
421
  {
  	sector_t array_sectors = 0;
3cb030020   NeilBrown   md: removing type...
422
  	struct md_rdev *rdev;
80c3a6ce4   Dan Williams   md: add 'size' as...
423
424
425
426
  
  	WARN_ONCE(sectors || raid_disks,
  		  "%s does not support generic reshape
  ", __func__);
dafb20fa3   NeilBrown   md: tidy up rdev_...
427
  	rdev_for_each(rdev, mddev)
a64685399   NeilBrown   md: fix two bugs ...
428
429
  		array_sectors += (rdev->sectors &
  				  ~(sector_t)(mddev->chunk_sectors-1));
80c3a6ce4   Dan Williams   md: add 'size' as...
430
431
432
  
  	return array_sectors;
  }
0366ef847   majianpeng   md/raid0: If md_i...
433
  static int raid0_stop(struct mddev *mddev);
fd01b88c7   NeilBrown   md: remove typede...
434
  static int raid0_run(struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  {
e373ab109   NeilBrown   md/raid0: typedef...
436
  	struct r0conf *conf;
5568a6035   Andre Noll   md: raid0: Make r...
437
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438

9d8f03636   Andre Noll   md: Make mddev->c...
439
  	if (mddev->chunk_sectors == 0) {
b5a20961f   NeilBrown   md/raid0: tidy up...
440
441
442
  		printk(KERN_ERR "md/raid0:%s: chunk size must be set.
  ",
  		       mdname(mddev));
2604b703b   NeilBrown   [PATCH] md: remov...
443
444
  		return -EINVAL;
  	}
0894cc306   Andre Noll   md: Move check fo...
445
446
  	if (md_check_no_bitmap(mddev))
  		return -EINVAL;
086fa5ff0   Martin K. Petersen   block: Rename blk...
447
  	blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
4363ac7c1   Martin K. Petersen   block: Implement ...
448
  	blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
c83057a1f   Shaohua Li   md: raid 0 suppor...
449
  	blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450

9af204cf7   Trela, Maciej   md: Add support f...
451
452
453
454
455
456
457
458
  	/* if private is not null, we are here after takeover */
  	if (mddev->private == NULL) {
  		ret = create_strip_zones(mddev, &conf);
  		if (ret < 0)
  			return ret;
  		mddev->private = conf;
  	}
  	conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
  
  	/* calculate array device size */
1f403624b   Dan Williams   md: centralize ->...
461
  	md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462

b5a20961f   NeilBrown   md/raid0: tidy up...
463
464
465
466
  	printk(KERN_INFO "md/raid0:%s: md_size is %llu sectors.
  ",
  	       mdname(mddev),
  	       (unsigned long long)mddev->array_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
470
471
472
473
474
475
476
  	/* calculate the max read-ahead size.
  	 * For read-ahead of large files to be effective, we need to
  	 * readahead at least twice a whole stripe. i.e. number of devices
  	 * multiplied by chunk size times 2.
  	 * If an individual device has an ra_pages greater than the
  	 * chunk size, then we will not drive that device as hard as it
  	 * wants.  We consider this a configuration error: a larger
  	 * chunksize should be used in that case.
  	 */
  	{
9d8f03636   Andre Noll   md: Make mddev->c...
477
478
  		int stripe = mddev->raid_disks *
  			(mddev->chunk_sectors << 9) / PAGE_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
481
  		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
  			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  	blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
46994191a   raz ben yehuda   md: have raid0 re...
483
  	dump_zones(mddev);
0366ef847   majianpeng   md/raid0: If md_i...
484
485
486
487
488
489
  
  	ret = md_integrity_register(mddev);
  	if (ret)
  		raid0_stop(mddev);
  
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  }
fd01b88c7   NeilBrown   md: remove typede...
491
  static int raid0_stop(struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  {
e373ab109   NeilBrown   md/raid0: typedef...
493
  	struct r0conf *conf = mddev->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
  
  	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
990a8baf5   Jesper Juhl   [PATCH] md: remov...
496
  	kfree(conf->strip_zone);
fb5ab4b5d   Andre Noll   md: raid0: Fix a ...
497
  	kfree(conf->devlist);
990a8baf5   Jesper Juhl   [PATCH] md: remov...
498
  	kfree(conf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  	mddev->private = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
  	return 0;
  }
fbb704efb   raz ben yehuda   md: raid0 :Enable...
502
503
504
  /*
   * Is io distribute over 1 or more chunks ?
  */
fd01b88c7   NeilBrown   md: remove typede...
505
  static inline int is_io_in_chunk_boundary(struct mddev *mddev,
fbb704efb   raz ben yehuda   md: raid0 :Enable...
506
507
  			unsigned int chunk_sects, struct bio *bio)
  {
d6e412eaa   NeilBrown   md: raid0: chunk_...
508
  	if (likely(is_power_of_2(chunk_sects))) {
4f024f379   Kent Overstreet   block: Abstract o...
509
510
  		return chunk_sects >=
  			((bio->bi_iter.bi_sector & (chunk_sects-1))
aa8b57aa3   Kent Overstreet   block: Use bio_se...
511
  					+ bio_sectors(bio));
fbb704efb   raz ben yehuda   md: raid0 :Enable...
512
  	} else{
4f024f379   Kent Overstreet   block: Abstract o...
513
  		sector_t sector = bio->bi_iter.bi_sector;
fbb704efb   raz ben yehuda   md: raid0 :Enable...
514
  		return chunk_sects >= (sector_div(sector, chunk_sects)
aa8b57aa3   Kent Overstreet   block: Use bio_se...
515
  						+ bio_sectors(bio));
fbb704efb   raz ben yehuda   md: raid0 :Enable...
516
517
  	}
  }
b4fdcb02f   Linus Torvalds   Merge branch 'for...
518
  static void raid0_make_request(struct mddev *mddev, struct bio *bio)
fbb704efb   raz ben yehuda   md: raid0 :Enable...
519
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  	struct strip_zone *zone;
3cb030020   NeilBrown   md: removing type...
521
  	struct md_rdev *tmp_dev;
20d0189b1   Kent Overstreet   block: Introduce ...
522
  	struct bio *split;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523

e9c7469bb   Tejun Heo   md: implment REQ_...
524
525
  	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
  		md_flush_request(mddev, bio);
5a7bbad27   Christoph Hellwig   block: remove sup...
526
  		return;
e5dcdd80a   NeilBrown   [PATCH] md: fail ...
527
  	}
20d0189b1   Kent Overstreet   block: Introduce ...
528
  	do {
4f024f379   Kent Overstreet   block: Abstract o...
529
  		sector_t sector = bio->bi_iter.bi_sector;
20d0189b1   Kent Overstreet   block: Introduce ...
530
531
532
533
534
535
536
537
538
539
540
541
542
  		unsigned chunk_sects = mddev->chunk_sectors;
  
  		unsigned sectors = chunk_sects -
  			(likely(is_power_of_2(chunk_sects))
  			 ? (sector & (chunk_sects-1))
  			 : sector_div(sector, chunk_sects));
  
  		if (sectors < bio_sectors(bio)) {
  			split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set);
  			bio_chain(split, bio);
  		} else {
  			split = bio;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543

20d0189b1   Kent Overstreet   block: Introduce ...
544
545
546
547
548
549
550
551
552
553
554
555
556
  		zone = find_zone(mddev->private, &sector);
  		tmp_dev = map_sector(mddev, zone, sector, &sector);
  		split->bi_bdev = tmp_dev->bdev;
  		split->bi_iter.bi_sector = sector + zone->dev_start +
  			tmp_dev->data_offset;
  
  		if (unlikely((split->bi_rw & REQ_DISCARD) &&
  			 !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) {
  			/* Just ignore it */
  			bio_endio(split, 0);
  		} else
  			generic_make_request(split);
  	} while (split != bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  }
8299d7f7c   NeilBrown   md: fix a bug in ...
558

fd01b88c7   NeilBrown   md: remove typede...
559
  static void raid0_status(struct seq_file *seq, struct mddev *mddev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
  {
9d8f03636   Andre Noll   md: Make mddev->c...
561
  	seq_printf(seq, " %dk chunks", mddev->chunk_sectors / 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
  	return;
  }
fd01b88c7   NeilBrown   md: remove typede...
564
  static void *raid0_takeover_raid45(struct mddev *mddev)
9af204cf7   Trela, Maciej   md: Add support f...
565
  {
3cb030020   NeilBrown   md: removing type...
566
  	struct md_rdev *rdev;
e373ab109   NeilBrown   md/raid0: typedef...
567
  	struct r0conf *priv_conf;
9af204cf7   Trela, Maciej   md: Add support f...
568
569
  
  	if (mddev->degraded != 1) {
b5a20961f   NeilBrown   md/raid0: tidy up...
570
571
572
  		printk(KERN_ERR "md/raid0:%s: raid5 must be degraded! Degraded disks: %d
  ",
  		       mdname(mddev),
9af204cf7   Trela, Maciej   md: Add support f...
573
574
575
  		       mddev->degraded);
  		return ERR_PTR(-EINVAL);
  	}
dafb20fa3   NeilBrown   md: tidy up rdev_...
576
  	rdev_for_each(rdev, mddev) {
9af204cf7   Trela, Maciej   md: Add support f...
577
578
  		/* check slot number for a disk */
  		if (rdev->raid_disk == mddev->raid_disks-1) {
b5a20961f   NeilBrown   md/raid0: tidy up...
579
580
581
  			printk(KERN_ERR "md/raid0:%s: raid5 must have missing parity disk!
  ",
  			       mdname(mddev));
9af204cf7   Trela, Maciej   md: Add support f...
582
583
  			return ERR_PTR(-EINVAL);
  		}
eea136d69   NeilBrown   md: fix buglet in...
584
  		rdev->sectors = mddev->dev_sectors;
9af204cf7   Trela, Maciej   md: Add support f...
585
586
587
588
  	}
  
  	/* Set new parameters */
  	mddev->new_level = 0;
001048a31   Maciej Trela   md: clear layout ...
589
  	mddev->new_layout = 0;
9af204cf7   Trela, Maciej   md: Add support f...
590
591
592
593
594
595
596
597
598
  	mddev->new_chunk_sectors = mddev->chunk_sectors;
  	mddev->raid_disks--;
  	mddev->delta_disks = -1;
  	/* make sure it will be not marked as dirty */
  	mddev->recovery_cp = MaxSector;
  
  	create_strip_zones(mddev, &priv_conf);
  	return priv_conf;
  }
fd01b88c7   NeilBrown   md: remove typede...
599
  static void *raid0_takeover_raid10(struct mddev *mddev)
9af204cf7   Trela, Maciej   md: Add support f...
600
  {
e373ab109   NeilBrown   md/raid0: typedef...
601
  	struct r0conf *priv_conf;
9af204cf7   Trela, Maciej   md: Add support f...
602
603
604
605
606
607
608
609
  
  	/* Check layout:
  	 *  - far_copies must be 1
  	 *  - near_copies must be 2
  	 *  - disks number must be even
  	 *  - all mirrors must be already degraded
  	 */
  	if (mddev->layout != ((1 << 8) + 2)) {
b5a20961f   NeilBrown   md/raid0: tidy up...
610
611
612
  		printk(KERN_ERR "md/raid0:%s:: Raid0 cannot takover layout: 0x%x
  ",
  		       mdname(mddev),
9af204cf7   Trela, Maciej   md: Add support f...
613
614
615
616
  		       mddev->layout);
  		return ERR_PTR(-EINVAL);
  	}
  	if (mddev->raid_disks & 1) {
b5a20961f   NeilBrown   md/raid0: tidy up...
617
618
619
  		printk(KERN_ERR "md/raid0:%s: Raid0 cannot takover Raid10 with odd disk number.
  ",
  		       mdname(mddev));
9af204cf7   Trela, Maciej   md: Add support f...
620
621
622
  		return ERR_PTR(-EINVAL);
  	}
  	if (mddev->degraded != (mddev->raid_disks>>1)) {
b5a20961f   NeilBrown   md/raid0: tidy up...
623
624
625
  		printk(KERN_ERR "md/raid0:%s: All mirrors must be already degraded!
  ",
  		       mdname(mddev));
9af204cf7   Trela, Maciej   md: Add support f...
626
627
628
629
630
  		return ERR_PTR(-EINVAL);
  	}
  
  	/* Set new parameters */
  	mddev->new_level = 0;
001048a31   Maciej Trela   md: clear layout ...
631
  	mddev->new_layout = 0;
9af204cf7   Trela, Maciej   md: Add support f...
632
633
634
635
636
637
638
639
  	mddev->new_chunk_sectors = mddev->chunk_sectors;
  	mddev->delta_disks = - mddev->raid_disks / 2;
  	mddev->raid_disks += mddev->delta_disks;
  	mddev->degraded = 0;
  	/* make sure it will be not marked as dirty */
  	mddev->recovery_cp = MaxSector;
  
  	create_strip_zones(mddev, &priv_conf);
9af204cf7   Trela, Maciej   md: Add support f...
640
641
  	return priv_conf;
  }
fd01b88c7   NeilBrown   md: remove typede...
642
  static void *raid0_takeover_raid1(struct mddev *mddev)
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
643
  {
e373ab109   NeilBrown   md/raid0: typedef...
644
  	struct r0conf *priv_conf;
24b961f81   Jes Sorensen   md: Avoid OOPS wh...
645
  	int chunksect;
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
646
647
648
649
650
651
652
653
654
655
  
  	/* Check layout:
  	 *  - (N - 1) mirror drives must be already faulty
  	 */
  	if ((mddev->raid_disks - 1) != mddev->degraded) {
  		printk(KERN_ERR "md/raid0:%s: (N - 1) mirrors drives must be already faulty!
  ",
  		       mdname(mddev));
  		return ERR_PTR(-EINVAL);
  	}
24b961f81   Jes Sorensen   md: Avoid OOPS wh...
656
657
658
659
660
661
662
663
664
665
666
667
668
  	/*
  	 * a raid1 doesn't have the notion of chunk size, so
  	 * figure out the largest suitable size we can use.
  	 */
  	chunksect = 64 * 2; /* 64K by default */
  
  	/* The array must be an exact multiple of chunksize */
  	while (chunksect && (mddev->array_sectors & (chunksect - 1)))
  		chunksect >>= 1;
  
  	if ((chunksect << 9) < PAGE_SIZE)
  		/* array size does not allow a suitable chunk size */
  		return ERR_PTR(-EINVAL);
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
669
670
671
  	/* Set new parameters */
  	mddev->new_level = 0;
  	mddev->new_layout = 0;
24b961f81   Jes Sorensen   md: Avoid OOPS wh...
672
673
  	mddev->new_chunk_sectors = chunksect;
  	mddev->chunk_sectors = chunksect;
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
674
  	mddev->delta_disks = 1 - mddev->raid_disks;
f7bee8094   Krzysztof Wojcik   md: Fix raid1->ra...
675
  	mddev->raid_disks = 1;
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
676
677
678
679
680
681
  	/* make sure it will be not marked as dirty */
  	mddev->recovery_cp = MaxSector;
  
  	create_strip_zones(mddev, &priv_conf);
  	return priv_conf;
  }
fd01b88c7   NeilBrown   md: remove typede...
682
  static void *raid0_takeover(struct mddev *mddev)
9af204cf7   Trela, Maciej   md: Add support f...
683
684
  {
  	/* raid0 can take over:
049d6c1ef   Maciej Trela   md: enable raid4-...
685
  	 *  raid4 - if all data disks are active.
9af204cf7   Trela, Maciej   md: Add support f...
686
687
  	 *  raid5 - providing it is Raid4 layout and one disk is faulty
  	 *  raid10 - assuming we have all necessary active disks
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
688
  	 *  raid1 - with (N -1) mirror drives faulty
9af204cf7   Trela, Maciej   md: Add support f...
689
  	 */
a8461a61c   NeilBrown   md/raid0: check f...
690
691
692
693
694
695
696
  
  	if (mddev->bitmap) {
  		printk(KERN_ERR "md/raid0: %s: cannot takeover array with bitmap
  ",
  		       mdname(mddev));
  		return ERR_PTR(-EBUSY);
  	}
049d6c1ef   Maciej Trela   md: enable raid4-...
697
698
  	if (mddev->level == 4)
  		return raid0_takeover_raid45(mddev);
9af204cf7   Trela, Maciej   md: Add support f...
699
700
  	if (mddev->level == 5) {
  		if (mddev->layout == ALGORITHM_PARITY_N)
049d6c1ef   Maciej Trela   md: enable raid4-...
701
  			return raid0_takeover_raid45(mddev);
9af204cf7   Trela, Maciej   md: Add support f...
702

b5a20961f   NeilBrown   md/raid0: tidy up...
703
704
705
  		printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d
  ",
  		       mdname(mddev), ALGORITHM_PARITY_N);
9af204cf7   Trela, Maciej   md: Add support f...
706
707
708
709
  	}
  
  	if (mddev->level == 10)
  		return raid0_takeover_raid10(mddev);
fc3a08b85   Krzysztof Wojcik   Add raid1->raid0 ...
710
711
712
713
714
715
  	if (mddev->level == 1)
  		return raid0_takeover_raid1(mddev);
  
  	printk(KERN_ERR "Takeover from raid%i to raid0 not supported
  ",
  		mddev->level);
9af204cf7   Trela, Maciej   md: Add support f...
716
717
  	return ERR_PTR(-EINVAL);
  }
fd01b88c7   NeilBrown   md: remove typede...
718
  static void raid0_quiesce(struct mddev *mddev, int state)
9af204cf7   Trela, Maciej   md: Add support f...
719
720
  {
  }
84fc4b56d   NeilBrown   md: rename "mdk_p...
721
  static struct md_personality raid0_personality=
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  {
  	.name		= "raid0",
2604b703b   NeilBrown   [PATCH] md: remov...
724
  	.level		= 0,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
726
727
728
729
  	.owner		= THIS_MODULE,
  	.make_request	= raid0_make_request,
  	.run		= raid0_run,
  	.stop		= raid0_stop,
  	.status		= raid0_status,
80c3a6ce4   Dan Williams   md: add 'size' as...
730
  	.size		= raid0_size,
9af204cf7   Trela, Maciej   md: Add support f...
731
732
  	.takeover	= raid0_takeover,
  	.quiesce	= raid0_quiesce,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
736
  };
  
  static int __init raid0_init (void)
  {
2604b703b   NeilBrown   [PATCH] md: remov...
737
  	return register_md_personality (&raid0_personality);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
739
740
741
  }
  
  static void raid0_exit (void)
  {
2604b703b   NeilBrown   [PATCH] md: remov...
742
  	unregister_md_personality (&raid0_personality);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
747
  }
  
  module_init(raid0_init);
  module_exit(raid0_exit);
  MODULE_LICENSE("GPL");
0efb9e619   NeilBrown   md: add MODULE_DE...
748
  MODULE_DESCRIPTION("RAID0 (striping) personality for MD");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
  MODULE_ALIAS("md-personality-2"); /* RAID0 */
d9d166c2a   NeilBrown   [PATCH] md: allow...
750
  MODULE_ALIAS("md-raid0");
2604b703b   NeilBrown   [PATCH] md: remov...
751
  MODULE_ALIAS("md-level-0");