Blame view
drivers/md/md-multipath.c
12.6 KB
af1a8899d treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 11 |
/* * multipath.c : Multiple Devices driver for Linux * * Copyright (C) 1999, 2000, 2001 Ingo Molnar, Red Hat * * Copyright (C) 1996, 1997, 1998 Ingo Molnar, Miguel de Icaza, Gadi Oxman * * MULTIPATH management functions. * * derived from raid1.c. |
1da177e4c Linux-2.6.12-rc2 |
12 |
*/ |
bff61975b md: move lots of ... |
13 |
#include <linux/blkdev.h> |
056075c76 md: Add module.h ... |
14 |
#include <linux/module.h> |
bff61975b md: move lots of ... |
15 |
#include <linux/raid/md_u.h> |
bff61975b md: move lots of ... |
16 |
#include <linux/seq_file.h> |
5a0e3ad6a include cleanup: ... |
17 |
#include <linux/slab.h> |
43b2e5d86 md: move md_k.h f... |
18 |
#include "md.h" |
935fe0983 md: rename some d... |
19 |
#include "md-multipath.h" |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 |
#define MAX_WORK_PER_DISK 128 #define NR_RESERVED_BUFS 32 |
69724e28c md/multipath: typ... |
24 |
static int multipath_map (struct mpconf *conf) |
1da177e4c Linux-2.6.12-rc2 |
25 26 27 28 |
{ int i, disks = conf->raid_disks; /* |
f72ffdd68 md: remove unwant... |
29 |
* Later we do read balancing on the read side |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 34 |
* now we use the first available disk. */ rcu_read_lock(); for (i = 0; i < disks; i++) { |
3cb030020 md: removing type... |
35 |
struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev); |
f5b67ae86 md: be extra care... |
36 37 |
if (rdev && test_bit(In_sync, &rdev->flags) && !test_bit(Faulty, &rdev->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 41 42 43 |
atomic_inc(&rdev->nr_pending); rcu_read_unlock(); return i; } } rcu_read_unlock(); |
7279694da md/multipath: rep... |
44 45 |
pr_crit_ratelimited("multipath_map(): no more operational IO paths? "); |
1da177e4c Linux-2.6.12-rc2 |
46 47 48 49 50 51 |
return (-1); } static void multipath_reschedule_retry (struct multipath_bh *mp_bh) { unsigned long flags; |
fd01b88c7 md: remove typede... |
52 |
struct mddev *mddev = mp_bh->mddev; |
69724e28c md/multipath: typ... |
53 |
struct mpconf *conf = mddev->private; |
1da177e4c Linux-2.6.12-rc2 |
54 55 56 57 58 59 |
spin_lock_irqsave(&conf->device_lock, flags); list_add(&mp_bh->retry_list, &conf->retry_list); spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); } |
1da177e4c Linux-2.6.12-rc2 |
60 61 62 63 64 |
/* * multipath_end_bh_io() is called when we have finished servicing a multipathed * operation and are ready to return a success/failure code to the buffer * cache layer. */ |
4e4cbee93 block: switch bio... |
65 |
static void multipath_end_bh_io(struct multipath_bh *mp_bh, blk_status_t status) |
1da177e4c Linux-2.6.12-rc2 |
66 67 |
{ struct bio *bio = mp_bh->master_bio; |
69724e28c md/multipath: typ... |
68 |
struct mpconf *conf = mp_bh->mddev->private; |
1da177e4c Linux-2.6.12-rc2 |
69 |
|
4e4cbee93 block: switch bio... |
70 |
bio->bi_status = status; |
4246a0b63 block: add a bi_e... |
71 |
bio_endio(bio); |
afeee514c md: convert to bi... |
72 |
mempool_free(mp_bh, &conf->pool); |
1da177e4c Linux-2.6.12-rc2 |
73 |
} |
4246a0b63 block: add a bi_e... |
74 |
static void multipath_end_request(struct bio *bio) |
1da177e4c Linux-2.6.12-rc2 |
75 |
{ |
7b92813c3 drivers/md: Remov... |
76 |
struct multipath_bh *mp_bh = bio->bi_private; |
69724e28c md/multipath: typ... |
77 |
struct mpconf *conf = mp_bh->mddev->private; |
3cb030020 md: removing type... |
78 |
struct md_rdev *rdev = conf->multipaths[mp_bh->path].rdev; |
1da177e4c Linux-2.6.12-rc2 |
79 |
|
4e4cbee93 block: switch bio... |
80 |
if (!bio->bi_status) |
1da177e4c Linux-2.6.12-rc2 |
81 |
multipath_end_bh_io(mp_bh, 0); |
1eff9d322 block: rename bio... |
82 |
else if (!(bio->bi_opf & REQ_RAHEAD)) { |
1da177e4c Linux-2.6.12-rc2 |
83 84 85 86 87 |
/* * oops, IO error: */ char b[BDEVNAME_SIZE]; md_error (mp_bh->mddev, rdev); |
7279694da md/multipath: rep... |
88 89 90 91 |
pr_info("multipath: %s: rescheduling sector %llu ", bdevname(rdev->bdev,b), (unsigned long long)bio->bi_iter.bi_sector); |
1da177e4c Linux-2.6.12-rc2 |
92 93 |
multipath_reschedule_retry(mp_bh); } else |
4e4cbee93 block: switch bio... |
94 |
multipath_end_bh_io(mp_bh, bio->bi_status); |
1da177e4c Linux-2.6.12-rc2 |
95 |
rdev_dec_pending(rdev, conf->mddev); |
1da177e4c Linux-2.6.12-rc2 |
96 |
} |
cc27b0c78 md: fix deadlock ... |
97 |
static bool multipath_make_request(struct mddev *mddev, struct bio * bio) |
1da177e4c Linux-2.6.12-rc2 |
98 |
{ |
69724e28c md/multipath: typ... |
99 |
struct mpconf *conf = mddev->private; |
1da177e4c Linux-2.6.12-rc2 |
100 101 |
struct multipath_bh * mp_bh; struct multipath_info *multipath; |
f020809b8 md: improve handl... |
102 103 |
if (unlikely(bio->bi_opf & REQ_PREFLUSH) && md_flush_request(mddev, bio)) |
cc27b0c78 md: fix deadlock ... |
104 |
return true; |
e5dcdd80a [PATCH] md: fail ... |
105 |
|
afeee514c md: convert to bi... |
106 |
mp_bh = mempool_alloc(&conf->pool, GFP_NOIO); |
1da177e4c Linux-2.6.12-rc2 |
107 108 109 |
mp_bh->master_bio = bio; mp_bh->mddev = mddev; |
1da177e4c Linux-2.6.12-rc2 |
110 111 |
mp_bh->path = multipath_map(conf); if (mp_bh->path < 0) { |
4246a0b63 block: add a bi_e... |
112 |
bio_io_error(bio); |
afeee514c md: convert to bi... |
113 |
mempool_free(mp_bh, &conf->pool); |
cc27b0c78 md: fix deadlock ... |
114 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
115 116 |
} multipath = conf->multipaths + mp_bh->path; |
3a83f4677 block: bio: pass ... |
117 |
bio_init(&mp_bh->bio, NULL, 0); |
fafcde3ac md: multipath: do... |
118 |
__bio_clone_fast(&mp_bh->bio, bio); |
4f024f379 block: Abstract o... |
119 |
mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset; |
74d46992e block: replace bi... |
120 |
bio_set_dev(&mp_bh->bio, multipath->rdev->bdev); |
1eff9d322 block: rename bio... |
121 |
mp_bh->bio.bi_opf |= REQ_FAILFAST_TRANSPORT; |
1da177e4c Linux-2.6.12-rc2 |
122 123 |
mp_bh->bio.bi_end_io = multipath_end_request; mp_bh->bio.bi_private = mp_bh; |
26483819f md: disable WRITE... |
124 |
mddev_check_writesame(mddev, &mp_bh->bio); |
3deff1a70 md: support REQ_O... |
125 |
mddev_check_write_zeroes(mddev, &mp_bh->bio); |
1da177e4c Linux-2.6.12-rc2 |
126 |
generic_make_request(&mp_bh->bio); |
cc27b0c78 md: fix deadlock ... |
127 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
128 |
} |
40cf2123c md/multipath: add... |
129 |
static void multipath_status(struct seq_file *seq, struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
130 |
{ |
69724e28c md/multipath: typ... |
131 |
struct mpconf *conf = mddev->private; |
1da177e4c Linux-2.6.12-rc2 |
132 |
int i; |
f72ffdd68 md: remove unwant... |
133 |
|
1da177e4c Linux-2.6.12-rc2 |
134 |
seq_printf (seq, " [%d/%d] [", conf->raid_disks, |
92f861a72 md/multipath: dis... |
135 |
conf->raid_disks - mddev->degraded); |
40cf2123c md/multipath: add... |
136 137 138 139 140 141 |
rcu_read_lock(); for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev); seq_printf (seq, "%s", rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_"); } rcu_read_unlock(); |
3acdb7b51 md-multipath: Use... |
142 |
seq_putc(seq, ']'); |
1da177e4c Linux-2.6.12-rc2 |
143 |
} |
5c675f83c md: make ->conges... |
144 |
static int multipath_congested(struct mddev *mddev, int bits) |
0d1292282 [PATCH] md: defin... |
145 |
{ |
69724e28c md/multipath: typ... |
146 |
struct mpconf *conf = mddev->private; |
0d1292282 [PATCH] md: defin... |
147 148 149 150 |
int i, ret = 0; rcu_read_lock(); for (i = 0; i < mddev->raid_disks ; i++) { |
3cb030020 md: removing type... |
151 |
struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev); |
0d1292282 [PATCH] md: defin... |
152 |
if (rdev && !test_bit(Faulty, &rdev->flags)) { |
165125e1e [BLOCK] Get rid o... |
153 |
struct request_queue *q = bdev_get_queue(rdev->bdev); |
0d1292282 [PATCH] md: defin... |
154 |
|
dc3b17cc8 block: Use pointe... |
155 |
ret |= bdi_congested(q->backing_dev_info, bits); |
0d1292282 [PATCH] md: defin... |
156 157 158 159 160 161 162 163 164 |
/* Just like multipath_map, we just check the * first available device */ break; } } rcu_read_unlock(); return ret; } |
1da177e4c Linux-2.6.12-rc2 |
165 166 167 168 |
/* * Careful, this can execute in IRQ contexts as well! */ |
fd01b88c7 md: remove typede... |
169 |
static void multipath_error (struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
170 |
{ |
69724e28c md/multipath: typ... |
171 |
struct mpconf *conf = mddev->private; |
6f8d0c77c md: make error_ha... |
172 |
char b[BDEVNAME_SIZE]; |
1da177e4c Linux-2.6.12-rc2 |
173 |
|
92f861a72 md/multipath: dis... |
174 |
if (conf->raid_disks - mddev->degraded <= 1) { |
1da177e4c Linux-2.6.12-rc2 |
175 176 177 178 179 |
/* * Uh oh, we can do nothing if this is our last path, but * first check if this is a queued request for a device * which has just failed. */ |
7279694da md/multipath: rep... |
180 181 |
pr_warn("multipath: only one IO path left and IO error. "); |
1da177e4c Linux-2.6.12-rc2 |
182 |
/* leave it active... it's all we have */ |
6f8d0c77c md: make error_ha... |
183 184 185 186 187 188 189 190 191 192 |
return; } /* * Mark disk as unusable */ if (test_and_clear_bit(In_sync, &rdev->flags)) { unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded++; spin_unlock_irqrestore(&conf->device_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
193 |
} |
6f8d0c77c md: make error_ha... |
194 |
set_bit(Faulty, &rdev->flags); |
2953079c6 md: separate flag... |
195 |
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); |
7279694da md/multipath: rep... |
196 197 198 199 |
pr_err("multipath: IO failure on %s, disabling IO path. " "multipath: Operation continuing on %d IO paths. ", |
6f8d0c77c md: make error_ha... |
200 201 |
bdevname(rdev->bdev, b), conf->raid_disks - mddev->degraded); |
1da177e4c Linux-2.6.12-rc2 |
202 |
} |
69724e28c md/multipath: typ... |
203 |
static void print_multipath_conf (struct mpconf *conf) |
1da177e4c Linux-2.6.12-rc2 |
204 205 206 |
{ int i; struct multipath_info *tmp; |
7279694da md/multipath: rep... |
207 208 |
pr_debug("MULTIPATH conf printout: "); |
1da177e4c Linux-2.6.12-rc2 |
209 |
if (!conf) { |
7279694da md/multipath: rep... |
210 211 |
pr_debug("(conf==NULL) "); |
1da177e4c Linux-2.6.12-rc2 |
212 213 |
return; } |
7279694da md/multipath: rep... |
214 215 216 |
pr_debug(" --- wd:%d rd:%d ", conf->raid_disks - conf->mddev->degraded, conf->raid_disks); |
1da177e4c Linux-2.6.12-rc2 |
217 218 219 220 221 |
for (i = 0; i < conf->raid_disks; i++) { char b[BDEVNAME_SIZE]; tmp = conf->multipaths + i; if (tmp->rdev) |
7279694da md/multipath: rep... |
222 223 224 225 |
pr_debug(" disk%d, o:%d, dev:%s ", i,!test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); |
1da177e4c Linux-2.6.12-rc2 |
226 227 |
} } |
fd01b88c7 md: remove typede... |
228 |
static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
229 |
{ |
69724e28c md/multipath: typ... |
230 |
struct mpconf *conf = mddev->private; |
199050ea1 rationalise retur... |
231 |
int err = -EEXIST; |
1da177e4c Linux-2.6.12-rc2 |
232 233 |
int path; struct multipath_info *p; |
6c2fce2ef Support adding a ... |
234 235 236 237 238 |
int first = 0; int last = mddev->raid_disks - 1; if (rdev->raid_disk >= 0) first = last = rdev->raid_disk; |
1da177e4c Linux-2.6.12-rc2 |
239 240 |
print_multipath_conf(conf); |
6c2fce2ef Support adding a ... |
241 |
for (path = first; path <= last; path++) |
1da177e4c Linux-2.6.12-rc2 |
242 |
if ((p=conf->multipaths+path)->rdev == NULL) { |
8f6c2e4b3 md: Use new topol... |
243 244 |
disk_stack_limits(mddev->gendisk, rdev->bdev, rdev->data_offset << 9); |
1da177e4c Linux-2.6.12-rc2 |
245 |
|
1501efadc md/raid: only per... |
246 247 248 |
err = md_integrity_add_rdev(rdev, mddev); if (err) break; |
6f8d0c77c md: make error_ha... |
249 |
spin_lock_irq(&conf->device_lock); |
750a8f3e8 [PATCH] md: fix u... |
250 |
mddev->degraded--; |
1da177e4c Linux-2.6.12-rc2 |
251 |
rdev->raid_disk = path; |
b2d444d7a [PATCH] md: conve... |
252 |
set_bit(In_sync, &rdev->flags); |
6f8d0c77c md: make error_ha... |
253 |
spin_unlock_irq(&conf->device_lock); |
d6065f7bf [PATCH] md: provi... |
254 |
rcu_assign_pointer(p->rdev, rdev); |
199050ea1 rationalise retur... |
255 256 |
err = 0; break; |
1da177e4c Linux-2.6.12-rc2 |
257 258 259 |
} print_multipath_conf(conf); |
199050ea1 rationalise retur... |
260 261 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
262 |
} |
b8321b68d md: change hot_re... |
263 |
static int multipath_remove_disk(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
264 |
{ |
69724e28c md/multipath: typ... |
265 |
struct mpconf *conf = mddev->private; |
1da177e4c Linux-2.6.12-rc2 |
266 |
int err = 0; |
b8321b68d md: change hot_re... |
267 |
int number = rdev->raid_disk; |
1da177e4c Linux-2.6.12-rc2 |
268 269 270 |
struct multipath_info *p = conf->multipaths + number; print_multipath_conf(conf); |
b8321b68d md: change hot_re... |
271 |
if (rdev == p->rdev) { |
b2d444d7a [PATCH] md: conve... |
272 |
if (test_bit(In_sync, &rdev->flags) || |
1da177e4c Linux-2.6.12-rc2 |
273 |
atomic_read(&rdev->nr_pending)) { |
7279694da md/multipath: rep... |
274 275 |
pr_warn("hot-remove-disk, slot %d is identified but is still operational! ", number); |
1da177e4c Linux-2.6.12-rc2 |
276 277 278 279 |
err = -EBUSY; goto abort; } p->rdev = NULL; |
d787be409 md: reduce the nu... |
280 281 282 283 284 285 286 287 |
if (!test_bit(RemoveSynchronized, &rdev->flags)) { synchronize_rcu(); if (atomic_read(&rdev->nr_pending)) { /* lost the race, try later */ err = -EBUSY; p->rdev = rdev; goto abort; } |
1da177e4c Linux-2.6.12-rc2 |
288 |
} |
a91a2785b block: Require su... |
289 |
err = md_integrity_register(mddev); |
1da177e4c Linux-2.6.12-rc2 |
290 291 292 293 294 295 |
} abort: print_multipath_conf(conf); return err; } |
1da177e4c Linux-2.6.12-rc2 |
296 297 298 299 300 301 302 |
/* * This is a kernel thread which: * * 1. Retries failed read operations on working multipaths. * 2. Updates the raid superblock when problems encounter. * 3. Performs writes following reads for array syncronising. */ |
4ed8731d8 MD: change the pa... |
303 |
static void multipathd(struct md_thread *thread) |
1da177e4c Linux-2.6.12-rc2 |
304 |
{ |
4ed8731d8 MD: change the pa... |
305 |
struct mddev *mddev = thread->mddev; |
1da177e4c Linux-2.6.12-rc2 |
306 307 308 |
struct multipath_bh *mp_bh; struct bio *bio; unsigned long flags; |
69724e28c md/multipath: typ... |
309 |
struct mpconf *conf = mddev->private; |
1da177e4c Linux-2.6.12-rc2 |
310 311 312 313 314 315 316 317 318 319 320 321 322 |
struct list_head *head = &conf->retry_list; md_check_recovery(mddev); for (;;) { char b[BDEVNAME_SIZE]; spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) break; mp_bh = list_entry(head->prev, struct multipath_bh, retry_list); list_del(head->prev); spin_unlock_irqrestore(&conf->device_lock, flags); bio = &mp_bh->bio; |
4f024f379 block: Abstract o... |
323 |
bio->bi_iter.bi_sector = mp_bh->master_bio->bi_iter.bi_sector; |
f72ffdd68 md: remove unwant... |
324 |
|
1da177e4c Linux-2.6.12-rc2 |
325 |
if ((mp_bh->path = multipath_map (conf))<0) { |
7279694da md/multipath: rep... |
326 327 |
pr_err("multipath: %s: unrecoverable IO read error for block %llu ", |
74d46992e block: replace bi... |
328 |
bio_devname(bio, b), |
7279694da md/multipath: rep... |
329 |
(unsigned long long)bio->bi_iter.bi_sector); |
4e4cbee93 block: switch bio... |
330 |
multipath_end_bh_io(mp_bh, BLK_STS_IOERR); |
1da177e4c Linux-2.6.12-rc2 |
331 |
} else { |
7279694da md/multipath: rep... |
332 333 |
pr_err("multipath: %s: redirecting sector %llu to another IO path ", |
74d46992e block: replace bi... |
334 |
bio_devname(bio, b), |
7279694da md/multipath: rep... |
335 |
(unsigned long long)bio->bi_iter.bi_sector); |
1da177e4c Linux-2.6.12-rc2 |
336 |
*bio = *(mp_bh->master_bio); |
4f024f379 block: Abstract o... |
337 338 |
bio->bi_iter.bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset; |
74d46992e block: replace bi... |
339 |
bio_set_dev(bio, conf->multipaths[mp_bh->path].rdev->bdev); |
1eff9d322 block: rename bio... |
340 |
bio->bi_opf |= REQ_FAILFAST_TRANSPORT; |
1da177e4c Linux-2.6.12-rc2 |
341 342 343 344 345 346 347 |
bio->bi_end_io = multipath_end_request; bio->bi_private = mp_bh; generic_make_request(bio); } } spin_unlock_irqrestore(&conf->device_lock, flags); } |
fd01b88c7 md: remove typede... |
348 |
static sector_t multipath_size(struct mddev *mddev, sector_t sectors, int raid_disks) |
80c3a6ce4 md: add 'size' as... |
349 350 351 352 353 354 355 |
{ WARN_ONCE(sectors || raid_disks, "%s does not support generic reshape ", __func__); return mddev->dev_sectors; } |
fd01b88c7 md: remove typede... |
356 |
static int multipath_run (struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
357 |
{ |
69724e28c md/multipath: typ... |
358 |
struct mpconf *conf; |
1da177e4c Linux-2.6.12-rc2 |
359 360 |
int disk_idx; struct multipath_info *disk; |
3cb030020 md: removing type... |
361 |
struct md_rdev *rdev; |
92f861a72 md/multipath: dis... |
362 |
int working_disks; |
afeee514c md: convert to bi... |
363 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
364 |
|
0894cc306 md: Move check fo... |
365 366 |
if (md_check_no_bitmap(mddev)) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
367 |
if (mddev->level != LEVEL_MULTIPATH) { |
7279694da md/multipath: rep... |
368 369 370 |
pr_warn("multipath: %s: raid level not set to multipath IO (%d) ", mdname(mddev), mddev->level); |
1da177e4c Linux-2.6.12-rc2 |
371 372 373 374 375 |
goto out; } /* * copy the already verified devices into our private MULTIPATH * bookkeeping area. [whatever we allocate in multipath_run(), |
afa0f557c md: rename ->stop... |
376 |
* should be freed in multipath_free()] |
1da177e4c Linux-2.6.12-rc2 |
377 |
*/ |
69724e28c md/multipath: typ... |
378 |
conf = kzalloc(sizeof(struct mpconf), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
379 |
mddev->private = conf; |
7279694da md/multipath: rep... |
380 |
if (!conf) |
1da177e4c Linux-2.6.12-rc2 |
381 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
382 |
|
6396bb221 treewide: kzalloc... |
383 384 |
conf->multipaths = kcalloc(mddev->raid_disks, sizeof(struct multipath_info), |
1da177e4c Linux-2.6.12-rc2 |
385 |
GFP_KERNEL); |
7279694da md/multipath: rep... |
386 |
if (!conf->multipaths) |
1da177e4c Linux-2.6.12-rc2 |
387 |
goto out_free_conf; |
1da177e4c Linux-2.6.12-rc2 |
388 |
|
92f861a72 md/multipath: dis... |
389 |
working_disks = 0; |
dafb20fa3 md: tidy up rdev_... |
390 |
rdev_for_each(rdev, mddev) { |
1da177e4c Linux-2.6.12-rc2 |
391 392 393 394 395 396 397 |
disk_idx = rdev->raid_disk; if (disk_idx < 0 || disk_idx >= mddev->raid_disks) continue; disk = conf->multipaths + disk_idx; disk->rdev = rdev; |
8f6c2e4b3 md: Use new topol... |
398 399 |
disk_stack_limits(mddev->gendisk, rdev->bdev, rdev->data_offset << 9); |
1da177e4c Linux-2.6.12-rc2 |
400 |
|
b2d444d7a [PATCH] md: conve... |
401 |
if (!test_bit(Faulty, &rdev->flags)) |
92f861a72 md/multipath: dis... |
402 |
working_disks++; |
1da177e4c Linux-2.6.12-rc2 |
403 404 405 |
} conf->raid_disks = mddev->raid_disks; |
1da177e4c Linux-2.6.12-rc2 |
406 407 408 |
conf->mddev = mddev; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); |
92f861a72 md/multipath: dis... |
409 |
if (!working_disks) { |
7279694da md/multipath: rep... |
410 411 |
pr_warn("multipath: no operational IO paths for %s ", |
1da177e4c Linux-2.6.12-rc2 |
412 413 414 |
mdname(mddev)); goto out_free_conf; } |
92f861a72 md/multipath: dis... |
415 |
mddev->degraded = conf->raid_disks - working_disks; |
1da177e4c Linux-2.6.12-rc2 |
416 |
|
afeee514c md: convert to bi... |
417 418 419 |
ret = mempool_init_kmalloc_pool(&conf->pool, NR_RESERVED_BUFS, sizeof(struct multipath_bh)); if (ret) |
1da177e4c Linux-2.6.12-rc2 |
420 |
goto out_free_conf; |
1da177e4c Linux-2.6.12-rc2 |
421 |
|
7279694da md/multipath: rep... |
422 423 424 425 |
mddev->thread = md_register_thread(multipathd, mddev, "multipath"); if (!mddev->thread) goto out_free_conf; |
1da177e4c Linux-2.6.12-rc2 |
426 |
|
7279694da md/multipath: rep... |
427 428 |
pr_info("multipath: array %s active with %d out of %d IO paths ", |
92f861a72 md/multipath: dis... |
429 |
mdname(mddev), conf->raid_disks - mddev->degraded, |
7279694da md/multipath: rep... |
430 |
mddev->raid_disks); |
1da177e4c Linux-2.6.12-rc2 |
431 432 433 |
/* * Ok, everything is just fine now */ |
1f403624b md: centralize ->... |
434 |
md_set_array_sectors(mddev, multipath_size(mddev, 0, 0)); |
7a5febe9f [PATCH] md: set t... |
435 |
|
a91a2785b block: Require su... |
436 437 |
if (md_integrity_register(mddev)) goto out_free_conf; |
1da177e4c Linux-2.6.12-rc2 |
438 439 440 |
return 0; out_free_conf: |
afeee514c md: convert to bi... |
441 |
mempool_exit(&conf->pool); |
990a8baf5 [PATCH] md: remov... |
442 |
kfree(conf->multipaths); |
1da177e4c Linux-2.6.12-rc2 |
443 444 445 446 447 |
kfree(conf); mddev->private = NULL; out: return -EIO; } |
afa0f557c md: rename ->stop... |
448 |
static void multipath_free(struct mddev *mddev, void *priv) |
1da177e4c Linux-2.6.12-rc2 |
449 |
{ |
afa0f557c md: rename ->stop... |
450 |
struct mpconf *conf = priv; |
1da177e4c Linux-2.6.12-rc2 |
451 |
|
afeee514c md: convert to bi... |
452 |
mempool_exit(&conf->pool); |
1da177e4c Linux-2.6.12-rc2 |
453 454 |
kfree(conf->multipaths); kfree(conf); |
1da177e4c Linux-2.6.12-rc2 |
455 |
} |
84fc4b56d md: rename "mdk_p... |
456 |
static struct md_personality multipath_personality = |
1da177e4c Linux-2.6.12-rc2 |
457 458 |
{ .name = "multipath", |
2604b703b [PATCH] md: remov... |
459 |
.level = LEVEL_MULTIPATH, |
1da177e4c Linux-2.6.12-rc2 |
460 461 462 |
.owner = THIS_MODULE, .make_request = multipath_make_request, .run = multipath_run, |
afa0f557c md: rename ->stop... |
463 |
.free = multipath_free, |
1da177e4c Linux-2.6.12-rc2 |
464 465 466 467 |
.status = multipath_status, .error_handler = multipath_error, .hot_add_disk = multipath_add_disk, .hot_remove_disk= multipath_remove_disk, |
80c3a6ce4 md: add 'size' as... |
468 |
.size = multipath_size, |
5c675f83c md: make ->conges... |
469 |
.congested = multipath_congested, |
1da177e4c Linux-2.6.12-rc2 |
470 471 472 473 |
}; static int __init multipath_init (void) { |
2604b703b [PATCH] md: remov... |
474 |
return register_md_personality (&multipath_personality); |
1da177e4c Linux-2.6.12-rc2 |
475 476 477 478 |
} static void __exit multipath_exit (void) { |
2604b703b [PATCH] md: remov... |
479 |
unregister_md_personality (&multipath_personality); |
1da177e4c Linux-2.6.12-rc2 |
480 481 482 483 484 |
} module_init(multipath_init); module_exit(multipath_exit); MODULE_LICENSE("GPL"); |
0efb9e619 md: add MODULE_DE... |
485 |
MODULE_DESCRIPTION("simple multi-path personality for MD"); |
1da177e4c Linux-2.6.12-rc2 |
486 |
MODULE_ALIAS("md-personality-7"); /* MULTIPATH */ |
d9d166c2a [PATCH] md: allow... |
487 |
MODULE_ALIAS("md-multipath"); |
2604b703b [PATCH] md: remov... |
488 |
MODULE_ALIAS("md-level--4"); |