Blame view
drivers/md/md.c
214 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* md.c : Multiple Devices driver for Linux Copyright (C) 1998, 1999, 2000 Ingo Molnar completely rewritten, based on the MD driver code from Marc Zyngier Changes: - RAID-1/RAID-5 extensions by Miguel de Icaza, Gadi Oxman, Ingo Molnar - RAID-6 extensions by H. Peter Anvin <hpa@zytor.com> - boot support for linear and striped mode by Harald Hoyer <HarryH@Royal.Net> - kerneld support by Boris Tobotras <boris@xtalk.msk.su> - kmod support by: Cyrus Durgin - RAID0 bugfixes: Mark Anthony Lisher <markal@iname.com> - Devfs support by Richard Gooch <rgooch@atnf.csiro.au> - lots of fixes and improvements to the RAID1/RAID5 and generic RAID code (such as request based resynchronization): Neil Brown <neilb@cse.unsw.edu.au>. |
32a7627cf [PATCH] md: optim... |
21 22 |
- persistent bitmap code Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc. |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 27 28 29 30 31 |
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. */ |
a6fb0934f [PATCH] md: use k... |
32 |
#include <linux/kthread.h> |
bff61975b md: move lots of ... |
33 |
#include <linux/blkdev.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#include <linux/sysctl.h> |
bff61975b md: move lots of ... |
35 |
#include <linux/seq_file.h> |
2a48fc0ab block: autoconver... |
36 |
#include <linux/mutex.h> |
1da177e4c Linux-2.6.12-rc2 |
37 |
#include <linux/buffer_head.h> /* for invalidate_bdev */ |
d7603b7e3 [PATCH] md: make ... |
38 |
#include <linux/poll.h> |
16f17b39f [PATCH] md: incre... |
39 |
#include <linux/ctype.h> |
e7d2860b6 tree-wide: conver... |
40 |
#include <linux/string.h> |
fb4d8c76e md: Remove unnece... |
41 42 43 |
#include <linux/hdreg.h> #include <linux/proc_fs.h> #include <linux/random.h> |
056075c76 md: Add module.h ... |
44 |
#include <linux/module.h> |
fb4d8c76e md: Remove unnece... |
45 |
#include <linux/reboot.h> |
32a7627cf [PATCH] md: optim... |
46 |
#include <linux/file.h> |
aa98aa319 md: move compat_i... |
47 |
#include <linux/compat.h> |
255707274 md: build failure... |
48 |
#include <linux/delay.h> |
bff61975b md: move lots of ... |
49 50 |
#include <linux/raid/md_p.h> #include <linux/raid/md_u.h> |
5a0e3ad6a include cleanup: ... |
51 |
#include <linux/slab.h> |
43b2e5d86 md: move md_k.h f... |
52 |
#include "md.h" |
ef740c372 md: move headers ... |
53 |
#include "bitmap.h" |
1da177e4c Linux-2.6.12-rc2 |
54 |
|
1da177e4c Linux-2.6.12-rc2 |
55 |
#ifndef MODULE |
d710e1381 md: remove space ... |
56 |
static void autostart_arrays(int part); |
1da177e4c Linux-2.6.12-rc2 |
57 |
#endif |
01f96c0a9 md: Avoid waking ... |
58 59 60 61 62 |
/* pers_list is a list of registered personalities protected * by pers_lock. * pers_lock does extra service to protect accesses to * mddev->thread when the mutex cannot be held. */ |
2604b703b [PATCH] md: remov... |
63 |
static LIST_HEAD(pers_list); |
1da177e4c Linux-2.6.12-rc2 |
64 |
static DEFINE_SPINLOCK(pers_lock); |
5e56341d0 [PATCH] md: make ... |
65 |
static void md_print_devices(void); |
90b08710e md: allow paralle... |
66 |
static DECLARE_WAIT_QUEUE_HEAD(resync_wait); |
e804ac780 md: fix and updat... |
67 68 |
static struct workqueue_struct *md_wq; static struct workqueue_struct *md_misc_wq; |
90b08710e md: allow paralle... |
69 |
|
5e56341d0 [PATCH] md: make ... |
70 71 |
#define MD_BUG(x...) { printk("md: bug in file %s, line %d ", __FILE__, __LINE__); md_print_devices(); } |
1da177e4c Linux-2.6.12-rc2 |
72 |
/* |
1e50915fe raid: improve MD/... |
73 74 75 76 77 78 |
* Default number of read corrections we'll attempt on an rdev * before ejecting it from the array. We divide the read error * count by 2 for every hour elapsed between read errors. */ #define MD_DEFAULT_MAX_CORRECTED_READ_ERRORS 20 /* |
1da177e4c Linux-2.6.12-rc2 |
79 80 81 |
* Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' * is 1000 KB/sec, so the extra system load does not show up that much. * Increase it if you want to have more _guaranteed_ speed. Note that |
338cec325 [PATCH] merge som... |
82 |
* the RAID driver will use the maximum available bandwidth if the IO |
1da177e4c Linux-2.6.12-rc2 |
83 84 85 86 87 |
* subsystem is idle. There is also an 'absolute maximum' reconstruction * speed limit - in case reconstruction slows down your system despite * idle IO detection. * * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. |
88202a0c8 [PATCH] md: allow... |
88 |
* or /sys/block/mdX/md/sync_speed_{min,max} |
1da177e4c Linux-2.6.12-rc2 |
89 90 91 92 |
*/ static int sysctl_speed_limit_min = 1000; static int sysctl_speed_limit_max = 200000; |
fd01b88c7 md: remove typede... |
93 |
static inline int speed_min(struct mddev *mddev) |
88202a0c8 [PATCH] md: allow... |
94 95 96 97 |
{ return mddev->sync_speed_min ? mddev->sync_speed_min : sysctl_speed_limit_min; } |
fd01b88c7 md: remove typede... |
98 |
static inline int speed_max(struct mddev *mddev) |
88202a0c8 [PATCH] md: allow... |
99 100 101 102 |
{ return mddev->sync_speed_max ? mddev->sync_speed_max : sysctl_speed_limit_max; } |
1da177e4c Linux-2.6.12-rc2 |
103 104 105 106 107 |
static struct ctl_table_header *raid_table_header; static ctl_table raid_table[] = { { |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 |
.procname = "speed_limit_min", .data = &sysctl_speed_limit_min, .maxlen = sizeof(int), |
80ca3a44f [PATCH] md: unify... |
111 |
.mode = S_IRUGO|S_IWUSR, |
6d4561110 sysctl: Drop & in... |
112 |
.proc_handler = proc_dointvec, |
1da177e4c Linux-2.6.12-rc2 |
113 114 |
}, { |
1da177e4c Linux-2.6.12-rc2 |
115 116 117 |
.procname = "speed_limit_max", .data = &sysctl_speed_limit_max, .maxlen = sizeof(int), |
80ca3a44f [PATCH] md: unify... |
118 |
.mode = S_IRUGO|S_IWUSR, |
6d4561110 sysctl: Drop & in... |
119 |
.proc_handler = proc_dointvec, |
1da177e4c Linux-2.6.12-rc2 |
120 |
}, |
894d24911 sysctl drivers: R... |
121 |
{ } |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 |
}; static ctl_table raid_dir_table[] = { { |
1da177e4c Linux-2.6.12-rc2 |
126 127 |
.procname = "raid", .maxlen = 0, |
80ca3a44f [PATCH] md: unify... |
128 |
.mode = S_IRUGO|S_IXUGO, |
1da177e4c Linux-2.6.12-rc2 |
129 130 |
.child = raid_table, }, |
894d24911 sysctl drivers: R... |
131 |
{ } |
1da177e4c Linux-2.6.12-rc2 |
132 133 134 135 |
}; static ctl_table raid_root_table[] = { { |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 |
.procname = "dev", .maxlen = 0, .mode = 0555, .child = raid_dir_table, }, |
894d24911 sysctl drivers: R... |
141 |
{ } |
1da177e4c Linux-2.6.12-rc2 |
142 |
}; |
83d5cde47 const: make block... |
143 |
static const struct block_device_operations md_fops; |
1da177e4c Linux-2.6.12-rc2 |
144 |
|
f91de92ed [PATCH] md: allow... |
145 |
static int start_readonly; |
a167f6632 md: use separate ... |
146 147 148 149 150 151 |
/* bio_clone_mddev * like bio_clone, but with a local bio set */ static void mddev_bio_destructor(struct bio *bio) { |
fd01b88c7 md: remove typede... |
152 |
struct mddev *mddev, **mddevp; |
a167f6632 md: use separate ... |
153 154 155 156 157 158 159 160 |
mddevp = (void*)bio; mddev = mddevp[-1]; bio_free(bio, mddev->bio_set); } struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, |
fd01b88c7 md: remove typede... |
161 |
struct mddev *mddev) |
a167f6632 md: use separate ... |
162 163 |
{ struct bio *b; |
fd01b88c7 md: remove typede... |
164 |
struct mddev **mddevp; |
a167f6632 md: use separate ... |
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
if (!mddev || !mddev->bio_set) return bio_alloc(gfp_mask, nr_iovecs); b = bio_alloc_bioset(gfp_mask, nr_iovecs, mddev->bio_set); if (!b) return NULL; mddevp = (void*)b; mddevp[-1] = mddev; b->bi_destructor = mddev_bio_destructor; return b; } EXPORT_SYMBOL_GPL(bio_alloc_mddev); struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask, |
fd01b88c7 md: remove typede... |
181 |
struct mddev *mddev) |
a167f6632 md: use separate ... |
182 183 |
{ struct bio *b; |
fd01b88c7 md: remove typede... |
184 |
struct mddev **mddevp; |
a167f6632 md: use separate ... |
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
if (!mddev || !mddev->bio_set) return bio_clone(bio, gfp_mask); b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, mddev->bio_set); if (!b) return NULL; mddevp = (void*)b; mddevp[-1] = mddev; b->bi_destructor = mddev_bio_destructor; __bio_clone(b, bio); if (bio_integrity(bio)) { int ret; ret = bio_integrity_clone(b, bio, gfp_mask, mddev->bio_set); if (ret < 0) { bio_put(b); return NULL; } } return b; } EXPORT_SYMBOL_GPL(bio_clone_mddev); |
d2eb35acf md/raid1: avoid r... |
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
void md_trim_bio(struct bio *bio, int offset, int size) { /* 'bio' is a cloned bio which we need to trim to match * the given offset and size. * This requires adjusting bi_sector, bi_size, and bi_io_vec */ int i; struct bio_vec *bvec; int sofar = 0; size <<= 9; if (offset == 0 && size == bio->bi_size) return; bio->bi_sector += offset; bio->bi_size = size; offset <<= 9; clear_bit(BIO_SEG_VALID, &bio->bi_flags); while (bio->bi_idx < bio->bi_vcnt && bio->bi_io_vec[bio->bi_idx].bv_len <= offset) { /* remove this whole bio_vec */ offset -= bio->bi_io_vec[bio->bi_idx].bv_len; bio->bi_idx++; } if (bio->bi_idx < bio->bi_vcnt) { bio->bi_io_vec[bio->bi_idx].bv_offset += offset; bio->bi_io_vec[bio->bi_idx].bv_len -= offset; } /* avoid any complications with bi_idx being non-zero*/ if (bio->bi_idx) { memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_idx, (bio->bi_vcnt - bio->bi_idx) * sizeof(struct bio_vec)); bio->bi_vcnt -= bio->bi_idx; bio->bi_idx = 0; } /* Make sure vcnt and last bv are not too big */ bio_for_each_segment(bvec, bio, i) { if (sofar + bvec->bv_len > size) bvec->bv_len = size - sofar; if (bvec->bv_len == 0) { bio->bi_vcnt = i; break; } sofar += bvec->bv_len; } } EXPORT_SYMBOL_GPL(md_trim_bio); |
1da177e4c Linux-2.6.12-rc2 |
259 |
/* |
d7603b7e3 [PATCH] md: make ... |
260 261 262 263 264 265 266 267 268 |
* We have a system wide 'event count' that is incremented * on any 'interesting' event, and readers of /proc/mdstat * can use 'poll' or 'select' to find out when the event * count increases. * * Events are: * start array, stop array, error, add device, remove device, * start build, activate spare */ |
2989ddbd6 [PATCH] md: make ... |
269 |
static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters); |
d7603b7e3 [PATCH] md: make ... |
270 |
static atomic_t md_event_count; |
fd01b88c7 md: remove typede... |
271 |
void md_new_event(struct mddev *mddev) |
d7603b7e3 [PATCH] md: make ... |
272 273 274 275 |
{ atomic_inc(&md_event_count); wake_up(&md_event_waiters); } |
292695531 [PATCH] md: Final... |
276 |
EXPORT_SYMBOL_GPL(md_new_event); |
d7603b7e3 [PATCH] md: make ... |
277 |
|
c331eb04b [PATCH] md: Fix b... |
278 279 280 |
/* Alternate version that can be called from interrupts * when calling sysfs_notify isn't needed. */ |
fd01b88c7 md: remove typede... |
281 |
static void md_new_event_inintr(struct mddev *mddev) |
c331eb04b [PATCH] md: Fix b... |
282 283 284 285 |
{ atomic_inc(&md_event_count); wake_up(&md_event_waiters); } |
d7603b7e3 [PATCH] md: make ... |
286 |
/* |
1da177e4c Linux-2.6.12-rc2 |
287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
* Enables to iterate over all existing md arrays * all_mddevs_lock protects this list. */ static LIST_HEAD(all_mddevs); static DEFINE_SPINLOCK(all_mddevs_lock); /* * iterates through all used mddevs in the system. * We take care to grab the all_mddevs_lock whenever navigating * the list, and to always hold a refcount when unlocked. * Any code which breaks out of this loop while own * a reference to the current mddev and must mddev_put it. */ |
fd01b88c7 md: remove typede... |
301 |
#define for_each_mddev(_mddev,_tmp) \ |
1da177e4c Linux-2.6.12-rc2 |
302 303 |
\ for (({ spin_lock(&all_mddevs_lock); \ |
fd01b88c7 md: remove typede... |
304 305 306 307 |
_tmp = all_mddevs.next; \ _mddev = NULL;}); \ ({ if (_tmp != &all_mddevs) \ mddev_get(list_entry(_tmp, struct mddev, all_mddevs));\ |
1da177e4c Linux-2.6.12-rc2 |
308 |
spin_unlock(&all_mddevs_lock); \ |
fd01b88c7 md: remove typede... |
309 310 311 |
if (_mddev) mddev_put(_mddev); \ _mddev = list_entry(_tmp, struct mddev, all_mddevs); \ _tmp != &all_mddevs;}); \ |
1da177e4c Linux-2.6.12-rc2 |
312 |
({ spin_lock(&all_mddevs_lock); \ |
fd01b88c7 md: remove typede... |
313 |
_tmp = _tmp->next;}) \ |
1da177e4c Linux-2.6.12-rc2 |
314 |
) |
409c57f38 md: enable suspen... |
315 316 317 318 319 320 321 |
/* Rather than calling directly into the personality make_request function, * IO requests come here first so that we can check if the device is * being suspended pending a reconfiguration. * We hold a refcount over the call to ->make_request. By the time that * call has finished, the bio has been linked into some internal structure * and so is visible to ->quiesce(), so we don't need the refcount any more. */ |
5a7bbad27 block: remove sup... |
322 |
static void md_make_request(struct request_queue *q, struct bio *bio) |
1da177e4c Linux-2.6.12-rc2 |
323 |
{ |
490773268 md: move io accou... |
324 |
const int rw = bio_data_dir(bio); |
fd01b88c7 md: remove typede... |
325 |
struct mddev *mddev = q->queuedata; |
490773268 md: move io accou... |
326 |
int cpu; |
e91ece559 md_make_request: ... |
327 |
unsigned int sectors; |
490773268 md: move io accou... |
328 |
|
0ca69886a md: Ensure no IO ... |
329 330 |
if (mddev == NULL || mddev->pers == NULL || !mddev->ready) { |
409c57f38 md: enable suspen... |
331 |
bio_io_error(bio); |
5a7bbad27 block: remove sup... |
332 |
return; |
409c57f38 md: enable suspen... |
333 |
} |
0ca69886a md: Ensure no IO ... |
334 |
smp_rmb(); /* Ensure implications of 'active' are visible */ |
409c57f38 md: enable suspen... |
335 |
rcu_read_lock(); |
e9c7469bb md: implment REQ_... |
336 |
if (mddev->suspended) { |
409c57f38 md: enable suspen... |
337 338 339 340 |
DEFINE_WAIT(__wait); for (;;) { prepare_to_wait(&mddev->sb_wait, &__wait, TASK_UNINTERRUPTIBLE); |
e9c7469bb md: implment REQ_... |
341 |
if (!mddev->suspended) |
409c57f38 md: enable suspen... |
342 343 344 345 346 347 348 349 350 |
break; rcu_read_unlock(); schedule(); rcu_read_lock(); } finish_wait(&mddev->sb_wait, &__wait); } atomic_inc(&mddev->active_io); rcu_read_unlock(); |
490773268 md: move io accou... |
351 |
|
e91ece559 md_make_request: ... |
352 353 354 355 356 |
/* * save the sectors now since our bio can * go away inside make_request */ sectors = bio_sectors(bio); |
5a7bbad27 block: remove sup... |
357 |
mddev->pers->make_request(mddev, bio); |
490773268 md: move io accou... |
358 359 360 |
cpu = part_stat_lock(); part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); |
e91ece559 md_make_request: ... |
361 |
part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors); |
490773268 md: move io accou... |
362 |
part_stat_unlock(); |
409c57f38 md: enable suspen... |
363 364 |
if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended) wake_up(&mddev->sb_wait); |
409c57f38 md: enable suspen... |
365 |
} |
9e35b99c7 md: don't unregis... |
366 367 368 369 370 371 |
/* mddev_suspend makes sure no new requests are submitted * to the device, and that any requests that have been submitted * are completely handled. * Once ->stop is called and completes, the module will be completely * unused. */ |
fd01b88c7 md: remove typede... |
372 |
void mddev_suspend(struct mddev *mddev) |
409c57f38 md: enable suspen... |
373 374 375 376 377 378 |
{ BUG_ON(mddev->suspended); mddev->suspended = 1; synchronize_rcu(); wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0); mddev->pers->quiesce(mddev, 1); |
409c57f38 md: enable suspen... |
379 |
} |
390ee602a md: export variou... |
380 |
EXPORT_SYMBOL_GPL(mddev_suspend); |
409c57f38 md: enable suspen... |
381 |
|
fd01b88c7 md: remove typede... |
382 |
void mddev_resume(struct mddev *mddev) |
409c57f38 md: enable suspen... |
383 384 385 386 |
{ mddev->suspended = 0; wake_up(&mddev->sb_wait); mddev->pers->quiesce(mddev, 0); |
0fd018af3 MD: move thread w... |
387 388 389 |
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ |
1da177e4c Linux-2.6.12-rc2 |
390 |
} |
390ee602a md: export variou... |
391 |
EXPORT_SYMBOL_GPL(mddev_resume); |
1da177e4c Linux-2.6.12-rc2 |
392 |
|
fd01b88c7 md: remove typede... |
393 |
int mddev_congested(struct mddev *mddev, int bits) |
3fa841d7e md: report device... |
394 395 396 397 |
{ return mddev->suspended; } EXPORT_SYMBOL(mddev_congested); |
a2826aa92 md: support barri... |
398 |
/* |
e9c7469bb md: implment REQ_... |
399 |
* Generic flush handling for md |
a2826aa92 md: support barri... |
400 |
*/ |
e9c7469bb md: implment REQ_... |
401 |
static void md_end_flush(struct bio *bio, int err) |
a2826aa92 md: support barri... |
402 |
{ |
3cb030020 md: removing type... |
403 |
struct md_rdev *rdev = bio->bi_private; |
fd01b88c7 md: remove typede... |
404 |
struct mddev *mddev = rdev->mddev; |
a2826aa92 md: support barri... |
405 406 407 408 |
rdev_dec_pending(rdev, mddev); if (atomic_dec_and_test(&mddev->flush_pending)) { |
e9c7469bb md: implment REQ_... |
409 |
/* The pre-request flush has finished */ |
e804ac780 md: fix and updat... |
410 |
queue_work(md_wq, &mddev->flush_work); |
a2826aa92 md: support barri... |
411 412 413 |
} bio_put(bio); } |
a7a07e696 md: move code in ... |
414 |
static void md_submit_flush_data(struct work_struct *ws); |
a035fc3e2 md: fix possible ... |
415 |
static void submit_flushes(struct work_struct *ws) |
a2826aa92 md: support barri... |
416 |
{ |
fd01b88c7 md: remove typede... |
417 |
struct mddev *mddev = container_of(ws, struct mddev, flush_work); |
3cb030020 md: removing type... |
418 |
struct md_rdev *rdev; |
a2826aa92 md: support barri... |
419 |
|
a7a07e696 md: move code in ... |
420 421 |
INIT_WORK(&mddev->flush_work, md_submit_flush_data); atomic_set(&mddev->flush_pending, 1); |
a2826aa92 md: support barri... |
422 423 424 425 426 427 428 429 430 431 432 433 |
rcu_read_lock(); list_for_each_entry_rcu(rdev, &mddev->disks, same_set) if (rdev->raid_disk >= 0 && !test_bit(Faulty, &rdev->flags)) { /* Take two references, one is dropped * when request finishes, one after * we reclaim rcu_read_lock */ struct bio *bi; atomic_inc(&rdev->nr_pending); atomic_inc(&rdev->nr_pending); rcu_read_unlock(); |
a167f6632 md: use separate ... |
434 |
bi = bio_alloc_mddev(GFP_KERNEL, 0, mddev); |
e9c7469bb md: implment REQ_... |
435 |
bi->bi_end_io = md_end_flush; |
a2826aa92 md: support barri... |
436 437 438 |
bi->bi_private = rdev; bi->bi_bdev = rdev->bdev; atomic_inc(&mddev->flush_pending); |
e9c7469bb md: implment REQ_... |
439 |
submit_bio(WRITE_FLUSH, bi); |
a2826aa92 md: support barri... |
440 441 442 443 |
rcu_read_lock(); rdev_dec_pending(rdev, mddev); } rcu_read_unlock(); |
a7a07e696 md: move code in ... |
444 445 |
if (atomic_dec_and_test(&mddev->flush_pending)) queue_work(md_wq, &mddev->flush_work); |
a2826aa92 md: support barri... |
446 |
} |
e9c7469bb md: implment REQ_... |
447 |
static void md_submit_flush_data(struct work_struct *ws) |
a2826aa92 md: support barri... |
448 |
{ |
fd01b88c7 md: remove typede... |
449 |
struct mddev *mddev = container_of(ws, struct mddev, flush_work); |
e9c7469bb md: implment REQ_... |
450 |
struct bio *bio = mddev->flush_bio; |
a2826aa92 md: support barri... |
451 |
|
e9c7469bb md: implment REQ_... |
452 |
if (bio->bi_size == 0) |
a2826aa92 md: support barri... |
453 454 455 |
/* an empty barrier - all done */ bio_endio(bio, 0); else { |
e9c7469bb md: implment REQ_... |
456 |
bio->bi_rw &= ~REQ_FLUSH; |
5a7bbad27 block: remove sup... |
457 |
mddev->pers->make_request(mddev, bio); |
a2826aa92 md: support barri... |
458 |
} |
2b74e12e5 md: remove handli... |
459 460 461 |
mddev->flush_bio = NULL; wake_up(&mddev->sb_wait); |
a2826aa92 md: support barri... |
462 |
} |
fd01b88c7 md: remove typede... |
463 |
void md_flush_request(struct mddev *mddev, struct bio *bio) |
a2826aa92 md: support barri... |
464 465 466 |
{ spin_lock_irq(&mddev->write_lock); wait_event_lock_irq(mddev->sb_wait, |
e9c7469bb md: implment REQ_... |
467 |
!mddev->flush_bio, |
a2826aa92 md: support barri... |
468 |
mddev->write_lock, /*nothing*/); |
e9c7469bb md: implment REQ_... |
469 |
mddev->flush_bio = bio; |
a2826aa92 md: support barri... |
470 |
spin_unlock_irq(&mddev->write_lock); |
a035fc3e2 md: fix possible ... |
471 472 |
INIT_WORK(&mddev->flush_work, submit_flushes); queue_work(md_wq, &mddev->flush_work); |
a2826aa92 md: support barri... |
473 |
} |
e9c7469bb md: implment REQ_... |
474 |
EXPORT_SYMBOL(md_flush_request); |
409c57f38 md: enable suspen... |
475 |
|
97658cdd3 md: provide gener... |
476 477 478 479 480 481 482 483 484 485 |
/* Support for plugging. * This mirrors the plugging support in request_queue, but does not * require having a whole queue or request structures. * We allocate an md_plug_cb for each md device and each thread it gets * plugged on. This links tot the private plug_handle structure in the * personality data where we keep a count of the number of outstanding * plugs so other code can see if a plug is active. */ struct md_plug_cb { struct blk_plug_cb cb; |
fd01b88c7 md: remove typede... |
486 |
struct mddev *mddev; |
97658cdd3 md: provide gener... |
487 488 489 490 491 492 493 494 495 496 497 498 499 |
}; static void plugger_unplug(struct blk_plug_cb *cb) { struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb); if (atomic_dec_and_test(&mdcb->mddev->plug_cnt)) md_wakeup_thread(mdcb->mddev->thread); kfree(mdcb); } /* Check that an unplug wakeup will come shortly. * If not, wakeup the md thread immediately */ |
fd01b88c7 md: remove typede... |
500 |
int mddev_check_plugged(struct mddev *mddev) |
97658cdd3 md: provide gener... |
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
{ struct blk_plug *plug = current->plug; struct md_plug_cb *mdcb; if (!plug) return 0; list_for_each_entry(mdcb, &plug->cb_list, cb.list) { if (mdcb->cb.callback == plugger_unplug && mdcb->mddev == mddev) { /* Already on the list, move to top */ if (mdcb != list_first_entry(&plug->cb_list, struct md_plug_cb, cb.list)) list_move(&mdcb->cb.list, &plug->cb_list); return 1; } } /* Not currently on the callback list */ mdcb = kmalloc(sizeof(*mdcb), GFP_ATOMIC); if (!mdcb) return 0; mdcb->mddev = mddev; mdcb->cb.callback = plugger_unplug; atomic_inc(&mddev->plug_cnt); list_add(&mdcb->cb.list, &plug->cb_list); return 1; } EXPORT_SYMBOL_GPL(mddev_check_plugged); |
2ac874015 md/raid5: add sim... |
531 |
|
fd01b88c7 md: remove typede... |
532 |
static inline struct mddev *mddev_get(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
533 534 535 536 |
{ atomic_inc(&mddev->active); return mddev; } |
5fd3a17ed md: fix deadlock ... |
537 |
static void mddev_delayed_delete(struct work_struct *ws); |
d3374825c md: make devices ... |
538 |
|
fd01b88c7 md: remove typede... |
539 |
static void mddev_put(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
540 |
{ |
a167f6632 md: use separate ... |
541 |
struct bio_set *bs = NULL; |
1da177e4c Linux-2.6.12-rc2 |
542 543 |
if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) return; |
d3374825c md: make devices ... |
544 |
if (!mddev->raid_disks && list_empty(&mddev->disks) && |
cbd199837 md: Fix unfortuna... |
545 546 547 |
mddev->ctime == 0 && !mddev->hold_active) { /* Array is not configured at all, and not held active, * so destroy it */ |
af8a24347 md: take a refere... |
548 |
list_del_init(&mddev->all_mddevs); |
a167f6632 md: use separate ... |
549 550 |
bs = mddev->bio_set; mddev->bio_set = NULL; |
d3374825c md: make devices ... |
551 |
if (mddev->gendisk) { |
e804ac780 md: fix and updat... |
552 553 554 555 |
/* We did a probe so need to clean up. Call * queue_work inside the spinlock so that * flush_workqueue() after mddev_find will * succeed in waiting for the work to be done. |
d3374825c md: make devices ... |
556 557 |
*/ INIT_WORK(&mddev->del_work, mddev_delayed_delete); |
e804ac780 md: fix and updat... |
558 |
queue_work(md_misc_wq, &mddev->del_work); |
d3374825c md: make devices ... |
559 560 561 562 |
} else kfree(mddev); } spin_unlock(&all_mddevs_lock); |
a167f6632 md: use separate ... |
563 564 |
if (bs) bioset_free(bs); |
1da177e4c Linux-2.6.12-rc2 |
565 |
} |
fd01b88c7 md: remove typede... |
566 |
void mddev_init(struct mddev *mddev) |
fafd7fb05 md: factor out in... |
567 568 569 570 571 572 573 574 575 576 |
{ mutex_init(&mddev->open_mutex); mutex_init(&mddev->reconfig_mutex); mutex_init(&mddev->bitmap_info.mutex); INIT_LIST_HEAD(&mddev->disks); INIT_LIST_HEAD(&mddev->all_mddevs); init_timer(&mddev->safemode_timer); atomic_set(&mddev->active, 1); atomic_set(&mddev->openers, 0); atomic_set(&mddev->active_io, 0); |
97658cdd3 md: provide gener... |
577 |
atomic_set(&mddev->plug_cnt, 0); |
fafd7fb05 md: factor out in... |
578 579 580 581 582 583 584 585 586 |
spin_lock_init(&mddev->write_lock); atomic_set(&mddev->flush_pending, 0); init_waitqueue_head(&mddev->sb_wait); init_waitqueue_head(&mddev->recovery_wait); mddev->reshape_position = MaxSector; mddev->resync_min = 0; mddev->resync_max = MaxSector; mddev->level = LEVEL_NONE; } |
390ee602a md: export variou... |
587 |
EXPORT_SYMBOL_GPL(mddev_init); |
fafd7fb05 md: factor out in... |
588 |
|
fd01b88c7 md: remove typede... |
589 |
static struct mddev * mddev_find(dev_t unit) |
1da177e4c Linux-2.6.12-rc2 |
590 |
{ |
fd01b88c7 md: remove typede... |
591 |
struct mddev *mddev, *new = NULL; |
1da177e4c Linux-2.6.12-rc2 |
592 |
|
8f5f02c46 md: correctly han... |
593 594 |
if (unit && MAJOR(unit) != MD_MAJOR) unit &= ~((1<<MdpMinorShift)-1); |
1da177e4c Linux-2.6.12-rc2 |
595 596 |
retry: spin_lock(&all_mddevs_lock); |
efeb53c0e md: Allow md devi... |
597 598 599 600 601 602 603 604 605 606 607 608 |
if (unit) { list_for_each_entry(mddev, &all_mddevs, all_mddevs) if (mddev->unit == unit) { mddev_get(mddev); spin_unlock(&all_mddevs_lock); kfree(new); return mddev; } if (new) { list_add(&new->all_mddevs, &all_mddevs); |
1da177e4c Linux-2.6.12-rc2 |
609 |
spin_unlock(&all_mddevs_lock); |
efeb53c0e md: Allow md devi... |
610 611 |
new->hold_active = UNTIL_IOCTL; return new; |
1da177e4c Linux-2.6.12-rc2 |
612 |
} |
efeb53c0e md: Allow md devi... |
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 |
} else if (new) { /* find an unused unit number */ static int next_minor = 512; int start = next_minor; int is_free = 0; int dev = 0; while (!is_free) { dev = MKDEV(MD_MAJOR, next_minor); next_minor++; if (next_minor > MINORMASK) next_minor = 0; if (next_minor == start) { /* Oh dear, all in use. */ spin_unlock(&all_mddevs_lock); kfree(new); return NULL; } is_free = 1; list_for_each_entry(mddev, &all_mddevs, all_mddevs) if (mddev->unit == dev) { is_free = 0; break; } } new->unit = dev; new->md_minor = MINOR(dev); new->hold_active = UNTIL_STOP; |
1da177e4c Linux-2.6.12-rc2 |
641 642 643 644 645 |
list_add(&new->all_mddevs, &all_mddevs); spin_unlock(&all_mddevs_lock); return new; } spin_unlock(&all_mddevs_lock); |
9ffae0cf3 [PATCH] md: conve... |
646 |
new = kzalloc(sizeof(*new), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
647 648 |
if (!new) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
649 650 651 652 653 |
new->unit = unit; if (MAJOR(unit) == MD_MAJOR) new->md_minor = MINOR(unit); else new->md_minor = MINOR(unit) >> MdpMinorShift; |
fafd7fb05 md: factor out in... |
654 |
mddev_init(new); |
1da177e4c Linux-2.6.12-rc2 |
655 |
|
1da177e4c Linux-2.6.12-rc2 |
656 657 |
goto retry; } |
fd01b88c7 md: remove typede... |
658 |
static inline int mddev_lock(struct mddev * mddev) |
1da177e4c Linux-2.6.12-rc2 |
659 |
{ |
df5b89b32 [PATCH] md: Conve... |
660 |
return mutex_lock_interruptible(&mddev->reconfig_mutex); |
1da177e4c Linux-2.6.12-rc2 |
661 |
} |
fd01b88c7 md: remove typede... |
662 |
static inline int mddev_is_locked(struct mddev *mddev) |
b522adcde md: 'array_size' ... |
663 664 665 |
{ return mutex_is_locked(&mddev->reconfig_mutex); } |
fd01b88c7 md: remove typede... |
666 |
static inline int mddev_trylock(struct mddev * mddev) |
1da177e4c Linux-2.6.12-rc2 |
667 |
{ |
df5b89b32 [PATCH] md: Conve... |
668 |
return mutex_trylock(&mddev->reconfig_mutex); |
1da177e4c Linux-2.6.12-rc2 |
669 |
} |
b6eb127d2 md: remove unneed... |
670 |
static struct attribute_group md_redundancy_group; |
fd01b88c7 md: remove typede... |
671 |
static void mddev_unlock(struct mddev * mddev) |
1da177e4c Linux-2.6.12-rc2 |
672 |
{ |
a64c876fd md: manage redund... |
673 |
if (mddev->to_remove) { |
b6eb127d2 md: remove unneed... |
674 675 676 677 |
/* These cannot be removed under reconfig_mutex as * an access to the files will try to take reconfig_mutex * while holding the file unremovable, which leads to * a deadlock. |
bb4f1e9d0 md: fix another d... |
678 679 680 681 682 683 684 |
* So hold set sysfs_active while the remove in happeing, * and anything else which might set ->to_remove or my * otherwise change the sysfs namespace will fail with * -EBUSY if sysfs_active is still set. * We set sysfs_active under reconfig_mutex and elsewhere * test it under the same mutex to ensure its correct value * is seen. |
b6eb127d2 md: remove unneed... |
685 |
*/ |
a64c876fd md: manage redund... |
686 687 |
struct attribute_group *to_remove = mddev->to_remove; mddev->to_remove = NULL; |
bb4f1e9d0 md: fix another d... |
688 |
mddev->sysfs_active = 1; |
b6eb127d2 md: remove unneed... |
689 |
mutex_unlock(&mddev->reconfig_mutex); |
00bcb4ac7 md: reduce depend... |
690 691 692 693 694 695 696 697 698 699 |
if (mddev->kobj.sd) { if (to_remove != &md_redundancy_group) sysfs_remove_group(&mddev->kobj, to_remove); if (mddev->pers == NULL || mddev->pers->sync_request == NULL) { sysfs_remove_group(&mddev->kobj, &md_redundancy_group); if (mddev->sysfs_action) sysfs_put(mddev->sysfs_action); mddev->sysfs_action = NULL; } |
a64c876fd md: manage redund... |
700 |
} |
bb4f1e9d0 md: fix another d... |
701 |
mddev->sysfs_active = 0; |
b6eb127d2 md: remove unneed... |
702 703 |
} else mutex_unlock(&mddev->reconfig_mutex); |
1da177e4c Linux-2.6.12-rc2 |
704 |
|
751e67ca2 md.c: trivial com... |
705 706 |
/* As we've dropped the mutex we need a spinlock to * make sure the thread doesn't disappear |
01f96c0a9 md: Avoid waking ... |
707 708 |
*/ spin_lock(&pers_lock); |
005eca5e7 [PATCH] md: make ... |
709 |
md_wakeup_thread(mddev->thread); |
01f96c0a9 md: Avoid waking ... |
710 |
spin_unlock(&pers_lock); |
1da177e4c Linux-2.6.12-rc2 |
711 |
} |
fd01b88c7 md: remove typede... |
712 |
static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr) |
1da177e4c Linux-2.6.12-rc2 |
713 |
{ |
3cb030020 md: removing type... |
714 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
715 |
|
159ec1fc0 md: use list_for_... |
716 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
1da177e4c Linux-2.6.12-rc2 |
717 718 |
if (rdev->desc_nr == nr) return rdev; |
159ec1fc0 md: use list_for_... |
719 |
|
1da177e4c Linux-2.6.12-rc2 |
720 721 |
return NULL; } |
fd01b88c7 md: remove typede... |
722 |
static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev) |
1da177e4c Linux-2.6.12-rc2 |
723 |
{ |
3cb030020 md: removing type... |
724 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
725 |
|
159ec1fc0 md: use list_for_... |
726 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
1da177e4c Linux-2.6.12-rc2 |
727 728 |
if (rdev->bdev->bd_dev == dev) return rdev; |
159ec1fc0 md: use list_for_... |
729 |
|
1da177e4c Linux-2.6.12-rc2 |
730 731 |
return NULL; } |
84fc4b56d md: rename "mdk_p... |
732 |
static struct md_personality *find_pers(int level, char *clevel) |
2604b703b [PATCH] md: remov... |
733 |
{ |
84fc4b56d md: rename "mdk_p... |
734 |
struct md_personality *pers; |
d9d166c2a [PATCH] md: allow... |
735 736 |
list_for_each_entry(pers, &pers_list, list) { if (level != LEVEL_NONE && pers->level == level) |
2604b703b [PATCH] md: remov... |
737 |
return pers; |
d9d166c2a [PATCH] md: allow... |
738 739 740 |
if (strcmp(pers->name, clevel)==0) return pers; } |
2604b703b [PATCH] md: remov... |
741 742 |
return NULL; } |
b73df2d3d md: Make calc_dev... |
743 |
/* return the offset of the super block in 512byte sectors */ |
3cb030020 md: removing type... |
744 |
static inline sector_t calc_dev_sboffset(struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
745 |
{ |
57b2caa39 md-new-param-to-c... |
746 |
sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512; |
b73df2d3d md: Make calc_dev... |
747 |
return MD_NEW_SIZE_SECTORS(num_sectors); |
1da177e4c Linux-2.6.12-rc2 |
748 |
} |
3cb030020 md: removing type... |
749 |
static int alloc_disk_sb(struct md_rdev * rdev) |
1da177e4c Linux-2.6.12-rc2 |
750 751 752 753 754 755 756 757 |
{ if (rdev->sb_page) MD_BUG(); rdev->sb_page = alloc_page(GFP_KERNEL); if (!rdev->sb_page) { printk(KERN_ALERT "md: out of memory. "); |
ebc243372 md: alloc_disk_sb... |
758 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
759 760 761 762 |
} return 0; } |
3cb030020 md: removing type... |
763 |
static void free_disk_sb(struct md_rdev * rdev) |
1da177e4c Linux-2.6.12-rc2 |
764 765 |
{ if (rdev->sb_page) { |
2d1f3b5d1 [PATCH] md: clean... |
766 |
put_page(rdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
767 768 |
rdev->sb_loaded = 0; rdev->sb_page = NULL; |
0f420358e md: Turn rdev->sb... |
769 |
rdev->sb_start = 0; |
dd8ac336c md: Represent rai... |
770 |
rdev->sectors = 0; |
1da177e4c Linux-2.6.12-rc2 |
771 |
} |
2699b6722 md: load/store ba... |
772 773 774 775 |
if (rdev->bb_page) { put_page(rdev->bb_page); rdev->bb_page = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
776 |
} |
6712ecf8f Drop 'size' argum... |
777 |
static void super_written(struct bio *bio, int error) |
7bfa19f27 [PATCH] md: allow... |
778 |
{ |
3cb030020 md: removing type... |
779 |
struct md_rdev *rdev = bio->bi_private; |
fd01b88c7 md: remove typede... |
780 |
struct mddev *mddev = rdev->mddev; |
7bfa19f27 [PATCH] md: allow... |
781 |
|
3a0f5bbb1 [PATCH] md: add e... |
782 783 784 785 786 |
if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk("md: super_written gets error=%d, uptodate=%d ", error, test_bit(BIO_UPTODATE, &bio->bi_flags)); WARN_ON(test_bit(BIO_UPTODATE, &bio->bi_flags)); |
a9701a304 [PATCH] md: suppo... |
787 |
md_error(mddev, rdev); |
3a0f5bbb1 [PATCH] md: add e... |
788 |
} |
7bfa19f27 [PATCH] md: allow... |
789 |
|
a9701a304 [PATCH] md: suppo... |
790 791 |
if (atomic_dec_and_test(&mddev->pending_writes)) wake_up(&mddev->sb_wait); |
f8b58edf3 [PATCH] md: bio l... |
792 |
bio_put(bio); |
7bfa19f27 [PATCH] md: allow... |
793 |
} |
fd01b88c7 md: remove typede... |
794 |
void md_super_write(struct mddev *mddev, struct md_rdev *rdev, |
7bfa19f27 [PATCH] md: allow... |
795 796 797 798 799 800 801 802 |
sector_t sector, int size, struct page *page) { /* write first size bytes of page to sector of rdev * Increment mddev->pending_writes before returning * and decrement it on completion, waking up sb_wait * if zero is reached. * If an error occurred, call md_error */ |
a167f6632 md: use separate ... |
803 |
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev); |
7bfa19f27 [PATCH] md: allow... |
804 |
|
a6ff7e089 md: separate meta... |
805 |
bio->bi_bdev = rdev->meta_bdev ? rdev->meta_bdev : rdev->bdev; |
7bfa19f27 [PATCH] md: allow... |
806 807 808 809 |
bio->bi_sector = sector; bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; |
a9701a304 [PATCH] md: suppo... |
810 |
|
7bfa19f27 [PATCH] md: allow... |
811 |
atomic_inc(&mddev->pending_writes); |
a5bf4df0c md: use REQ_NOIDL... |
812 |
submit_bio(WRITE_FLUSH_FUA, bio); |
a9701a304 [PATCH] md: suppo... |
813 |
} |
fd01b88c7 md: remove typede... |
814 |
void md_super_wait(struct mddev *mddev) |
a9701a304 [PATCH] md: suppo... |
815 |
{ |
e9c7469bb md: implment REQ_... |
816 |
/* wait for all superblock writes that were scheduled to complete */ |
a9701a304 [PATCH] md: suppo... |
817 818 819 820 821 |
DEFINE_WAIT(wq); for(;;) { prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE); if (atomic_read(&mddev->pending_writes)==0) break; |
a9701a304 [PATCH] md: suppo... |
822 823 824 |
schedule(); } finish_wait(&mddev->sb_wait, &wq); |
7bfa19f27 [PATCH] md: allow... |
825 |
} |
6712ecf8f Drop 'size' argum... |
826 |
static void bi_complete(struct bio *bio, int error) |
1da177e4c Linux-2.6.12-rc2 |
827 |
{ |
1da177e4c Linux-2.6.12-rc2 |
828 |
complete((struct completion*)bio->bi_private); |
1da177e4c Linux-2.6.12-rc2 |
829 |
} |
3cb030020 md: removing type... |
830 |
int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, |
ccebd4c41 md-new-param-to_s... |
831 |
struct page *page, int rw, bool metadata_op) |
1da177e4c Linux-2.6.12-rc2 |
832 |
{ |
a167f6632 md: use separate ... |
833 |
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev); |
1da177e4c Linux-2.6.12-rc2 |
834 835 |
struct completion event; int ret; |
721a9602e block: kill off R... |
836 |
rw |= REQ_SYNC; |
1da177e4c Linux-2.6.12-rc2 |
837 |
|
a6ff7e089 md: separate meta... |
838 839 |
bio->bi_bdev = (metadata_op && rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; |
ccebd4c41 md-new-param-to_s... |
840 841 842 843 |
if (metadata_op) bio->bi_sector = sector + rdev->sb_start; else bio->bi_sector = sector + rdev->data_offset; |
1da177e4c Linux-2.6.12-rc2 |
844 845 846 847 848 849 850 851 852 853 854 |
bio_add_page(bio, page, size, 0); init_completion(&event); bio->bi_private = &event; bio->bi_end_io = bi_complete; submit_bio(rw, bio); wait_for_completion(&event); ret = test_bit(BIO_UPTODATE, &bio->bi_flags); bio_put(bio); return ret; } |
a8745db23 [PATCH] md: conve... |
855 |
EXPORT_SYMBOL_GPL(sync_page_io); |
1da177e4c Linux-2.6.12-rc2 |
856 |
|
3cb030020 md: removing type... |
857 |
static int read_disk_sb(struct md_rdev * rdev, int size) |
1da177e4c Linux-2.6.12-rc2 |
858 859 860 861 862 863 864 865 |
{ char b[BDEVNAME_SIZE]; if (!rdev->sb_page) { MD_BUG(); return -EINVAL; } if (rdev->sb_loaded) return 0; |
ccebd4c41 md-new-param-to_s... |
866 |
if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, true)) |
1da177e4c Linux-2.6.12-rc2 |
867 868 869 870 871 872 873 874 875 876 877 878 879 |
goto fail; rdev->sb_loaded = 1; return 0; fail: printk(KERN_WARNING "md: disabled device %s, could not read superblock. ", bdevname(rdev->bdev,b)); return -EINVAL; } static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2) { |
05710466c md: Simplify uuid... |
880 881 882 883 |
return sb1->set_uuid0 == sb2->set_uuid0 && sb1->set_uuid1 == sb2->set_uuid1 && sb1->set_uuid2 == sb2->set_uuid2 && sb1->set_uuid3 == sb2->set_uuid3; |
1da177e4c Linux-2.6.12-rc2 |
884 |
} |
1da177e4c Linux-2.6.12-rc2 |
885 886 887 888 889 890 891 892 893 894 |
static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2) { int ret; mdp_super_t *tmp1, *tmp2; tmp1 = kmalloc(sizeof(*tmp1),GFP_KERNEL); tmp2 = kmalloc(sizeof(*tmp2),GFP_KERNEL); if (!tmp1 || !tmp2) { ret = 0; |
35020f1a0 md: sb_equal(): F... |
895 896 |
printk(KERN_INFO "md.c sb_equal(): failed to allocate memory! "); |
1da177e4c Linux-2.6.12-rc2 |
897 898 899 900 901 902 903 904 905 906 907 |
goto abort; } *tmp1 = *sb1; *tmp2 = *sb2; /* * nr_disks is not constant */ tmp1->nr_disks = 0; tmp2->nr_disks = 0; |
ce0c8e05f md: Simplify sb_e... |
908 |
ret = (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4) == 0); |
1da177e4c Linux-2.6.12-rc2 |
909 |
abort: |
990a8baf5 [PATCH] md: remov... |
910 911 |
kfree(tmp1); kfree(tmp2); |
1da177e4c Linux-2.6.12-rc2 |
912 913 |
return ret; } |
4d167f093 md: stop using cs... |
914 915 916 917 918 919 |
static u32 md_csum_fold(u32 csum) { csum = (csum & 0xffff) + (csum >> 16); return (csum & 0xffff) + (csum >> 16); } |
1da177e4c Linux-2.6.12-rc2 |
920 921 |
static unsigned int calc_sb_csum(mdp_super_t * sb) { |
4d167f093 md: stop using cs... |
922 923 924 |
u64 newcsum = 0; u32 *sb32 = (u32*)sb; int i; |
1da177e4c Linux-2.6.12-rc2 |
925 926 927 928 |
unsigned int disk_csum, csum; disk_csum = sb->sb_csum; sb->sb_csum = 0; |
4d167f093 md: stop using cs... |
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 |
for (i = 0; i < MD_SB_BYTES/4 ; i++) newcsum += sb32[i]; csum = (newcsum & 0xffffffff) + (newcsum>>32); #ifdef CONFIG_ALPHA /* This used to use csum_partial, which was wrong for several * reasons including that different results are returned on * different architectures. It isn't critical that we get exactly * the same return value as before (we always csum_fold before * testing, and that removes any differences). However as we * know that csum_partial always returned a 16bit value on * alphas, do a fold to maximise conformity to previous behaviour. */ sb->sb_csum = md_csum_fold(disk_csum); #else |
1da177e4c Linux-2.6.12-rc2 |
946 |
sb->sb_csum = disk_csum; |
4d167f093 md: stop using cs... |
947 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
948 949 950 951 952 953 954 955 956 957 958 959 |
return csum; } /* * Handle superblock details. * We want to be able to handle multiple superblock formats * so we have a common interface to them all, and an array of * different handlers. * We rely on user-space to write the initial superblock, and support * reading and updating of superblocks. * Interface methods are: |
3cb030020 md: removing type... |
960 |
* int load_super(struct md_rdev *dev, struct md_rdev *refdev, int minor_version) |
1da177e4c Linux-2.6.12-rc2 |
961 962 963 964 965 966 967 968 969 |
* loads and validates a superblock on dev. * if refdev != NULL, compare superblocks on both devices * Return: * 0 - dev has a superblock that is compatible with refdev * 1 - dev has a superblock that is compatible and newer than refdev * so dev should be used as the refdev in future * -EINVAL superblock incompatible or invalid * -othererror e.g. -EIO * |
fd01b88c7 md: remove typede... |
970 |
* int validate_super(struct mddev *mddev, struct md_rdev *dev) |
1da177e4c Linux-2.6.12-rc2 |
971 972 973 974 975 |
* Verify that dev is acceptable into mddev. * The first time, mddev->raid_disks will be 0, and data from * dev should be merged in. Subsequent calls check that dev * is new enough. Return 0 or -EINVAL * |
fd01b88c7 md: remove typede... |
976 |
* void sync_super(struct mddev *mddev, struct md_rdev *dev) |
1da177e4c Linux-2.6.12-rc2 |
977 978 979 980 981 982 |
* Update the superblock for rdev with data in mddev * This does not write to disc. * */ struct super_type { |
0cd17fec9 Support changing ... |
983 984 |
char *name; struct module *owner; |
3cb030020 md: removing type... |
985 |
int (*load_super)(struct md_rdev *rdev, struct md_rdev *refdev, |
0cd17fec9 Support changing ... |
986 |
int minor_version); |
fd01b88c7 md: remove typede... |
987 988 |
int (*validate_super)(struct mddev *mddev, struct md_rdev *rdev); void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev); |
3cb030020 md: removing type... |
989 |
unsigned long long (*rdev_size_change)(struct md_rdev *rdev, |
15f4a5fdf md: Make super_ty... |
990 |
sector_t num_sectors); |
1da177e4c Linux-2.6.12-rc2 |
991 992 993 |
}; /* |
0894cc306 md: Move check fo... |
994 995 996 997 998 999 1000 |
* Check that the given mddev has no bitmap. * * This function is called from the run method of all personalities that do not * support bitmaps. It prints an error message and returns non-zero if mddev * has a bitmap. Otherwise, it returns 0. * */ |
fd01b88c7 md: remove typede... |
1001 |
int md_check_no_bitmap(struct mddev *mddev) |
0894cc306 md: Move check fo... |
1002 |
{ |
c3d9714e8 md: collect bitma... |
1003 |
if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset) |
0894cc306 md: Move check fo... |
1004 1005 1006 1007 1008 1009 1010 1011 1012 |
return 0; printk(KERN_ERR "%s: bitmaps are not supported for %s ", mdname(mddev), mddev->pers->name); return 1; } EXPORT_SYMBOL(md_check_no_bitmap); /* |
1da177e4c Linux-2.6.12-rc2 |
1013 1014 |
* load_super for 0.90.0 */ |
3cb030020 md: removing type... |
1015 |
static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version) |
1da177e4c Linux-2.6.12-rc2 |
1016 1017 1018 1019 |
{ char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; mdp_super_t *sb; int ret; |
1da177e4c Linux-2.6.12-rc2 |
1020 1021 |
/* |
0f420358e md: Turn rdev->sb... |
1022 |
* Calculate the position of the superblock (512byte sectors), |
1da177e4c Linux-2.6.12-rc2 |
1023 1024 1025 1026 |
* it's at the end of the disk. * * It also happens to be a multiple of 4Kb. */ |
57b2caa39 md-new-param-to-c... |
1027 |
rdev->sb_start = calc_dev_sboffset(rdev); |
1da177e4c Linux-2.6.12-rc2 |
1028 |
|
0002b2718 [PATCH] md: limit... |
1029 |
ret = read_disk_sb(rdev, MD_SB_BYTES); |
1da177e4c Linux-2.6.12-rc2 |
1030 1031 1032 1033 1034 |
if (ret) return ret; ret = -EINVAL; bdevname(rdev->bdev, b); |
65a06f067 md: get rid of un... |
1035 |
sb = page_address(rdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
1036 1037 1038 1039 1040 1041 1042 1043 1044 |
if (sb->md_magic != MD_SB_MAGIC) { printk(KERN_ERR "md: invalid raid superblock magic on %s ", b); goto abort; } if (sb->major_version != 0 || |
f67055780 [PATCH] md: Check... |
1045 1046 |
sb->minor_version < 90 || sb->minor_version > 91) { |
1da177e4c Linux-2.6.12-rc2 |
1047 1048 1049 1050 1051 1052 1053 1054 1055 |
printk(KERN_WARNING "Bad version number %d.%d on %s ", sb->major_version, sb->minor_version, b); goto abort; } if (sb->raid_disks <= 0) goto abort; |
4d167f093 md: stop using cs... |
1056 |
if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) { |
1da177e4c Linux-2.6.12-rc2 |
1057 1058 1059 1060 1061 1062 1063 1064 |
printk(KERN_WARNING "md: invalid superblock checksum on %s ", b); goto abort; } rdev->preferred_minor = sb->md_minor; rdev->data_offset = 0; |
0002b2718 [PATCH] md: limit... |
1065 |
rdev->sb_size = MD_SB_BYTES; |
9f2f38307 md: Disable bad b... |
1066 |
rdev->badblocks.shift = -1; |
1da177e4c Linux-2.6.12-rc2 |
1067 1068 1069 1070 1071 |
if (sb->level == LEVEL_MULTIPATH) rdev->desc_nr = -1; else rdev->desc_nr = sb->this_disk.number; |
9a7b2b0f3 md: fix integer a... |
1072 |
if (!refdev) { |
1da177e4c Linux-2.6.12-rc2 |
1073 |
ret = 1; |
9a7b2b0f3 md: fix integer a... |
1074 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
1075 |
__u64 ev1, ev2; |
65a06f067 md: get rid of un... |
1076 |
mdp_super_t *refsb = page_address(refdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 |
if (!uuid_equal(refsb, sb)) { printk(KERN_WARNING "md: %s has different UUID to %s ", b, bdevname(refdev->bdev,b2)); goto abort; } if (!sb_equal(refsb, sb)) { printk(KERN_WARNING "md: %s has same UUID" " but different superblock to %s ", b, bdevname(refdev->bdev, b2)); goto abort; } ev1 = md_event(sb); ev2 = md_event(refsb); if (ev1 > ev2) ret = 1; else ret = 0; } |
8190e754e md: remove chunks... |
1097 |
rdev->sectors = rdev->sb_start; |
27a7b260f md: Fix handling ... |
1098 1099 1100 |
/* Limit to 4TB as metadata cannot record more than that */ if (rdev->sectors >= (2ULL << 32)) rdev->sectors = (2ULL << 32) - 2; |
1da177e4c Linux-2.6.12-rc2 |
1101 |
|
27a7b260f md: Fix handling ... |
1102 |
if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) |
2bf071bf5 [PATCH] md: keep ... |
1103 1104 |
/* "this cannot possibly happen" ... */ ret = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
1105 1106 1107 1108 1109 1110 1111 |
abort: return ret; } /* * validate_super for 0.90.0 */ |
fd01b88c7 md: remove typede... |
1112 |
static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
1113 1114 |
{ mdp_disk_t *desc; |
65a06f067 md: get rid of un... |
1115 |
mdp_super_t *sb = page_address(rdev->sb_page); |
07d84d109 [PATCH] md: Allow... |
1116 |
__u64 ev1 = md_event(sb); |
1da177e4c Linux-2.6.12-rc2 |
1117 |
|
41158c7eb [PATCH] md: optim... |
1118 |
rdev->raid_disk = -1; |
c5d79adba md: allow devices... |
1119 1120 1121 |
clear_bit(Faulty, &rdev->flags); clear_bit(In_sync, &rdev->flags); clear_bit(WriteMostly, &rdev->flags); |
c5d79adba md: allow devices... |
1122 |
|
1da177e4c Linux-2.6.12-rc2 |
1123 1124 1125 1126 |
if (mddev->raid_disks == 0) { mddev->major_version = 0; mddev->minor_version = sb->minor_version; mddev->patch_version = sb->patch_version; |
e691063a6 md: support 'exte... |
1127 |
mddev->external = 0; |
9d8f03636 md: Make mddev->c... |
1128 |
mddev->chunk_sectors = sb->chunk_size >> 9; |
1da177e4c Linux-2.6.12-rc2 |
1129 1130 1131 |
mddev->ctime = sb->ctime; mddev->utime = sb->utime; mddev->level = sb->level; |
d9d166c2a [PATCH] md: allow... |
1132 |
mddev->clevel[0] = 0; |
1da177e4c Linux-2.6.12-rc2 |
1133 1134 |
mddev->layout = sb->layout; mddev->raid_disks = sb->raid_disks; |
27a7b260f md: Fix handling ... |
1135 |
mddev->dev_sectors = ((sector_t)sb->size) * 2; |
07d84d109 [PATCH] md: Allow... |
1136 |
mddev->events = ev1; |
c3d9714e8 md: collect bitma... |
1137 1138 |
mddev->bitmap_info.offset = 0; mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; |
1da177e4c Linux-2.6.12-rc2 |
1139 |
|
f67055780 [PATCH] md: Check... |
1140 1141 1142 1143 1144 |
if (mddev->minor_version >= 91) { mddev->reshape_position = sb->reshape_position; mddev->delta_disks = sb->delta_disks; mddev->new_level = sb->new_level; mddev->new_layout = sb->new_layout; |
664e7c413 md: Convert mddev... |
1145 |
mddev->new_chunk_sectors = sb->new_chunk >> 9; |
f67055780 [PATCH] md: Check... |
1146 1147 1148 1149 1150 |
} else { mddev->reshape_position = MaxSector; mddev->delta_disks = 0; mddev->new_level = mddev->level; mddev->new_layout = mddev->layout; |
664e7c413 md: Convert mddev... |
1151 |
mddev->new_chunk_sectors = mddev->chunk_sectors; |
f67055780 [PATCH] md: Check... |
1152 |
} |
1da177e4c Linux-2.6.12-rc2 |
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 |
if (sb->state & (1<<MD_SB_CLEAN)) mddev->recovery_cp = MaxSector; else { if (sb->events_hi == sb->cp_events_hi && sb->events_lo == sb->cp_events_lo) { mddev->recovery_cp = sb->recovery_cp; } else mddev->recovery_cp = 0; } memcpy(mddev->uuid+0, &sb->set_uuid0, 4); memcpy(mddev->uuid+4, &sb->set_uuid1, 4); memcpy(mddev->uuid+8, &sb->set_uuid2, 4); memcpy(mddev->uuid+12,&sb->set_uuid3, 4); mddev->max_disks = MD_SB_DISKS; |
a654b9d8f [PATCH] md: allow... |
1169 1170 |
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && |
c3d9714e8 md: collect bitma... |
1171 1172 1173 |
mddev->bitmap_info.file == NULL) mddev->bitmap_info.offset = mddev->bitmap_info.default_offset; |
a654b9d8f [PATCH] md: allow... |
1174 |
|
41158c7eb [PATCH] md: optim... |
1175 |
} else if (mddev->pers == NULL) { |
be6800a73 md: don't insist ... |
1176 1177 |
/* Insist on good event counter while assembling, except * for spares (which don't need an event count) */ |
1da177e4c Linux-2.6.12-rc2 |
1178 |
++ev1; |
be6800a73 md: don't insist ... |
1179 1180 1181 1182 |
if (sb->disks[rdev->desc_nr].state & ( (1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE))) if (ev1 < mddev->events) return -EINVAL; |
41158c7eb [PATCH] md: optim... |
1183 1184 1185 1186 |
} else if (mddev->bitmap) { /* if adding to array with a bitmap, then we can accept an * older device ... but not too old. */ |
41158c7eb [PATCH] md: optim... |
1187 1188 |
if (ev1 < mddev->bitmap->events_cleared) return 0; |
07d84d109 [PATCH] md: Allow... |
1189 1190 1191 1192 1193 |
} else { if (ev1 < mddev->events) /* just a hot-add of a new device, leave raid_disk at -1 */ return 0; } |
41158c7eb [PATCH] md: optim... |
1194 |
|
1da177e4c Linux-2.6.12-rc2 |
1195 |
if (mddev->level != LEVEL_MULTIPATH) { |
1da177e4c Linux-2.6.12-rc2 |
1196 1197 1198 |
desc = sb->disks + rdev->desc_nr; if (desc->state & (1<<MD_DISK_FAULTY)) |
b2d444d7a [PATCH] md: conve... |
1199 |
set_bit(Faulty, &rdev->flags); |
7c7546ccf [PATCH] md: allow... |
1200 1201 |
else if (desc->state & (1<<MD_DISK_SYNC) /* && desc->raid_disk < mddev->raid_disks */) { |
b2d444d7a [PATCH] md: conve... |
1202 |
set_bit(In_sync, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
1203 |
rdev->raid_disk = desc->raid_disk; |
0261cd9f1 md: allow v0.91 m... |
1204 1205 1206 1207 1208 1209 1210 1211 |
} else if (desc->state & (1<<MD_DISK_ACTIVE)) { /* active but not in sync implies recovery up to * reshape position. We don't know exactly where * that is, so set to zero for now */ if (mddev->minor_version >= 91) { rdev->recovery_offset = 0; rdev->raid_disk = desc->raid_disk; } |
1da177e4c Linux-2.6.12-rc2 |
1212 |
} |
8ddf9efe6 [PATCH] md: suppo... |
1213 1214 |
if (desc->state & (1<<MD_DISK_WRITEMOSTLY)) set_bit(WriteMostly, &rdev->flags); |
41158c7eb [PATCH] md: optim... |
1215 |
} else /* MULTIPATH are always insync */ |
b2d444d7a [PATCH] md: conve... |
1216 |
set_bit(In_sync, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
1217 1218 1219 1220 1221 1222 |
return 0; } /* * sync_super for 0.90.0 */ |
fd01b88c7 md: remove typede... |
1223 |
static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
1224 1225 |
{ mdp_super_t *sb; |
3cb030020 md: removing type... |
1226 |
struct md_rdev *rdev2; |
1da177e4c Linux-2.6.12-rc2 |
1227 |
int next_spare = mddev->raid_disks; |
19133a429 [PATCH] md: Remov... |
1228 |
|
1da177e4c Linux-2.6.12-rc2 |
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
/* make rdev->sb match mddev data.. * * 1/ zero out disks * 2/ Add info for each disk, keeping track of highest desc_nr (next_spare); * 3/ any empty disks < next_spare become removed * * disks[0] gets initialised to REMOVED because * we cannot be sure from other fields if it has * been initialised or not. */ int i; int active=0, working=0,failed=0,spare=0,nr_disks=0; |
611815651 [PATCH] md: reall... |
1242 |
rdev->sb_size = MD_SB_BYTES; |
65a06f067 md: get rid of un... |
1243 |
sb = page_address(rdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
1244 1245 1246 1247 1248 |
memset(sb, 0, sizeof(*sb)); sb->md_magic = MD_SB_MAGIC; sb->major_version = mddev->major_version; |
1da177e4c Linux-2.6.12-rc2 |
1249 1250 1251 1252 1253 1254 1255 1256 1257 |
sb->patch_version = mddev->patch_version; sb->gvalid_words = 0; /* ignored */ memcpy(&sb->set_uuid0, mddev->uuid+0, 4); memcpy(&sb->set_uuid1, mddev->uuid+4, 4); memcpy(&sb->set_uuid2, mddev->uuid+8, 4); memcpy(&sb->set_uuid3, mddev->uuid+12,4); sb->ctime = mddev->ctime; sb->level = mddev->level; |
58c0fed40 md: Make mddev->s... |
1258 |
sb->size = mddev->dev_sectors / 2; |
1da177e4c Linux-2.6.12-rc2 |
1259 1260 |
sb->raid_disks = mddev->raid_disks; sb->md_minor = mddev->md_minor; |
e691063a6 md: support 'exte... |
1261 |
sb->not_persistent = 0; |
1da177e4c Linux-2.6.12-rc2 |
1262 1263 1264 1265 |
sb->utime = mddev->utime; sb->state = 0; sb->events_hi = (mddev->events>>32); sb->events_lo = (u32)mddev->events; |
f67055780 [PATCH] md: Check... |
1266 1267 1268 1269 1270 1271 1272 1273 |
if (mddev->reshape_position == MaxSector) sb->minor_version = 90; else { sb->minor_version = 91; sb->reshape_position = mddev->reshape_position; sb->new_level = mddev->new_level; sb->delta_disks = mddev->delta_disks; sb->new_layout = mddev->new_layout; |
664e7c413 md: Convert mddev... |
1274 |
sb->new_chunk = mddev->new_chunk_sectors << 9; |
f67055780 [PATCH] md: Check... |
1275 1276 |
} mddev->minor_version = sb->minor_version; |
1da177e4c Linux-2.6.12-rc2 |
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 |
if (mddev->in_sync) { sb->recovery_cp = mddev->recovery_cp; sb->cp_events_hi = (mddev->events>>32); sb->cp_events_lo = (u32)mddev->events; if (mddev->recovery_cp == MaxSector) sb->state = (1<< MD_SB_CLEAN); } else sb->recovery_cp = 0; sb->layout = mddev->layout; |
9d8f03636 md: Make mddev->c... |
1288 |
sb->chunk_size = mddev->chunk_sectors << 9; |
1da177e4c Linux-2.6.12-rc2 |
1289 |
|
c3d9714e8 md: collect bitma... |
1290 |
if (mddev->bitmap && mddev->bitmap_info.file == NULL) |
a654b9d8f [PATCH] md: allow... |
1291 |
sb->state |= (1<<MD_SB_BITMAP_PRESENT); |
1da177e4c Linux-2.6.12-rc2 |
1292 |
sb->disks[0].state = (1<<MD_DISK_REMOVED); |
159ec1fc0 md: use list_for_... |
1293 |
list_for_each_entry(rdev2, &mddev->disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
1294 |
mdp_disk_t *d; |
86e6ffdd2 [PATCH] md: exten... |
1295 |
int desc_nr; |
0261cd9f1 md: allow v0.91 m... |
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 |
int is_active = test_bit(In_sync, &rdev2->flags); if (rdev2->raid_disk >= 0 && sb->minor_version >= 91) /* we have nowhere to store the recovery_offset, * but if it is not below the reshape_position, * we can piggy-back on that. */ is_active = 1; if (rdev2->raid_disk < 0 || test_bit(Faulty, &rdev2->flags)) is_active = 0; if (is_active) |
86e6ffdd2 [PATCH] md: exten... |
1309 |
desc_nr = rdev2->raid_disk; |
1da177e4c Linux-2.6.12-rc2 |
1310 |
else |
86e6ffdd2 [PATCH] md: exten... |
1311 |
desc_nr = next_spare++; |
19133a429 [PATCH] md: Remov... |
1312 |
rdev2->desc_nr = desc_nr; |
1da177e4c Linux-2.6.12-rc2 |
1313 1314 1315 1316 1317 |
d = &sb->disks[rdev2->desc_nr]; nr_disks++; d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); |
0261cd9f1 md: allow v0.91 m... |
1318 |
if (is_active) |
1da177e4c Linux-2.6.12-rc2 |
1319 1320 1321 |
d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ |
1be7892ff [PATCH] md: Fix t... |
1322 |
if (test_bit(Faulty, &rdev2->flags)) |
1da177e4c Linux-2.6.12-rc2 |
1323 |
d->state = (1<<MD_DISK_FAULTY); |
0261cd9f1 md: allow v0.91 m... |
1324 |
else if (is_active) { |
1da177e4c Linux-2.6.12-rc2 |
1325 |
d->state = (1<<MD_DISK_ACTIVE); |
0261cd9f1 md: allow v0.91 m... |
1326 1327 |
if (test_bit(In_sync, &rdev2->flags)) d->state |= (1<<MD_DISK_SYNC); |
1da177e4c Linux-2.6.12-rc2 |
1328 1329 1330 1331 1332 1333 1334 |
active++; working++; } else { d->state = 0; spare++; working++; } |
8ddf9efe6 [PATCH] md: suppo... |
1335 1336 |
if (test_bit(WriteMostly, &rdev2->flags)) d->state |= (1<<MD_DISK_WRITEMOSTLY); |
1da177e4c Linux-2.6.12-rc2 |
1337 |
} |
1da177e4c Linux-2.6.12-rc2 |
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 |
/* now set the "removed" and "faulty" bits on any missing devices */ for (i=0 ; i < mddev->raid_disks ; i++) { mdp_disk_t *d = &sb->disks[i]; if (d->state == 0 && d->number == 0) { d->number = i; d->raid_disk = i; d->state = (1<<MD_DISK_REMOVED); d->state |= (1<<MD_DISK_FAULTY); failed++; } } sb->nr_disks = nr_disks; sb->active_disks = active; sb->working_disks = working; sb->failed_disks = failed; sb->spare_disks = spare; sb->this_disk = sb->disks[rdev->desc_nr]; sb->sb_csum = calc_sb_csum(sb); } /* |
0cd17fec9 Support changing ... |
1360 1361 1362 |
* rdev_size_change for 0.90.0 */ static unsigned long long |
3cb030020 md: removing type... |
1363 |
super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) |
0cd17fec9 Support changing ... |
1364 |
{ |
58c0fed40 md: Make mddev->s... |
1365 |
if (num_sectors && num_sectors < rdev->mddev->dev_sectors) |
0cd17fec9 Support changing ... |
1366 |
return 0; /* component must fit device */ |
c3d9714e8 md: collect bitma... |
1367 |
if (rdev->mddev->bitmap_info.offset) |
0cd17fec9 Support changing ... |
1368 |
return 0; /* can't move bitmap */ |
57b2caa39 md-new-param-to-c... |
1369 |
rdev->sb_start = calc_dev_sboffset(rdev); |
15f4a5fdf md: Make super_ty... |
1370 1371 |
if (!num_sectors || num_sectors > rdev->sb_start) num_sectors = rdev->sb_start; |
27a7b260f md: Fix handling ... |
1372 1373 1374 1375 1376 |
/* Limit to 4TB as metadata cannot record more than that. * 4TB == 2^32 KB, or 2*2^32 sectors. */ if (num_sectors >= (2ULL << 32)) num_sectors = (2ULL << 32) - 2; |
0f420358e md: Turn rdev->sb... |
1377 |
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, |
0cd17fec9 Support changing ... |
1378 1379 |
rdev->sb_page); md_super_wait(rdev->mddev); |
c26a44ed1 md: fix return va... |
1380 |
return num_sectors; |
0cd17fec9 Support changing ... |
1381 1382 1383 1384 |
} /* |
1da177e4c Linux-2.6.12-rc2 |
1385 1386 |
* version 1 superblock */ |
1c05b4bc2 [PATCH] md: endia... |
1387 |
static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb) |
1da177e4c Linux-2.6.12-rc2 |
1388 |
{ |
1c05b4bc2 [PATCH] md: endia... |
1389 1390 |
__le32 disk_csum; u32 csum; |
1da177e4c Linux-2.6.12-rc2 |
1391 1392 |
unsigned long long newcsum; int size = 256 + le32_to_cpu(sb->max_dev)*2; |
1c05b4bc2 [PATCH] md: endia... |
1393 |
__le32 *isuper = (__le32*)sb; |
1da177e4c Linux-2.6.12-rc2 |
1394 1395 1396 1397 1398 1399 1400 1401 1402 |
int i; disk_csum = sb->sb_csum; sb->sb_csum = 0; newcsum = 0; for (i=0; size>=4; size -= 4 ) newcsum += le32_to_cpu(*isuper++); if (size == 2) |
1c05b4bc2 [PATCH] md: endia... |
1403 |
newcsum += le16_to_cpu(*(__le16*) isuper); |
1da177e4c Linux-2.6.12-rc2 |
1404 1405 1406 1407 1408 |
csum = (newcsum & 0xffffffff) + (newcsum >> 32); sb->sb_csum = disk_csum; return cpu_to_le32(csum); } |
2699b6722 md: load/store ba... |
1409 1410 |
static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors, int acknowledged); |
3cb030020 md: removing type... |
1411 |
static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version) |
1da177e4c Linux-2.6.12-rc2 |
1412 1413 1414 |
{ struct mdp_superblock_1 *sb; int ret; |
0f420358e md: Turn rdev->sb... |
1415 |
sector_t sb_start; |
1da177e4c Linux-2.6.12-rc2 |
1416 |
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; |
0002b2718 [PATCH] md: limit... |
1417 |
int bmask; |
1da177e4c Linux-2.6.12-rc2 |
1418 1419 |
/* |
0f420358e md: Turn rdev->sb... |
1420 |
* Calculate the position of the superblock in 512byte sectors. |
1da177e4c Linux-2.6.12-rc2 |
1421 1422 1423 1424 1425 1426 1427 1428 |
* It is always aligned to a 4K boundary and * depeding on minor_version, it can be: * 0: At least 8K, but less than 12K, from end of device * 1: At start of device * 2: 4K from start of device. */ switch(minor_version) { case 0: |
77304d2ab block: read i_siz... |
1429 |
sb_start = i_size_read(rdev->bdev->bd_inode) >> 9; |
0f420358e md: Turn rdev->sb... |
1430 1431 |
sb_start -= 8*2; sb_start &= ~(sector_t)(4*2-1); |
1da177e4c Linux-2.6.12-rc2 |
1432 1433 |
break; case 1: |
0f420358e md: Turn rdev->sb... |
1434 |
sb_start = 0; |
1da177e4c Linux-2.6.12-rc2 |
1435 1436 |
break; case 2: |
0f420358e md: Turn rdev->sb... |
1437 |
sb_start = 8; |
1da177e4c Linux-2.6.12-rc2 |
1438 1439 1440 1441 |
break; default: return -EINVAL; } |
0f420358e md: Turn rdev->sb... |
1442 |
rdev->sb_start = sb_start; |
1da177e4c Linux-2.6.12-rc2 |
1443 |
|
0002b2718 [PATCH] md: limit... |
1444 1445 1446 1447 |
/* superblock is rarely larger than 1K, but it can be larger, * and it is safe to read 4k, so we do that */ ret = read_disk_sb(rdev, 4096); |
1da177e4c Linux-2.6.12-rc2 |
1448 |
if (ret) return ret; |
65a06f067 md: get rid of un... |
1449 |
sb = page_address(rdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
1450 1451 1452 1453 |
if (sb->magic != cpu_to_le32(MD_SB_MAGIC) || sb->major_version != cpu_to_le32(1) || le32_to_cpu(sb->max_dev) > (4096-256)/2 || |
0f420358e md: Turn rdev->sb... |
1454 |
le64_to_cpu(sb->super_offset) != rdev->sb_start || |
71c0805cb [PATCH] md: allow... |
1455 |
(le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0) |
1da177e4c Linux-2.6.12-rc2 |
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 |
return -EINVAL; if (calc_sb_1_csum(sb) != sb->sb_csum) { printk("md: invalid superblock checksum on %s ", bdevname(rdev->bdev,b)); return -EINVAL; } if (le64_to_cpu(sb->data_size) < 10) { printk("md: data_size too small on %s ", bdevname(rdev->bdev,b)); return -EINVAL; } |
e11e93fac md: move test for... |
1470 |
|
1da177e4c Linux-2.6.12-rc2 |
1471 1472 |
rdev->preferred_minor = 0xffff; rdev->data_offset = le64_to_cpu(sb->data_offset); |
4dbcdc751 [PATCH] md: count... |
1473 |
atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); |
1da177e4c Linux-2.6.12-rc2 |
1474 |
|
0002b2718 [PATCH] md: limit... |
1475 |
rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256; |
e1defc4ff block: Do away wi... |
1476 |
bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; |
0002b2718 [PATCH] md: limit... |
1477 |
if (rdev->sb_size & bmask) |
a1801f858 md: guard against... |
1478 1479 1480 |
rdev->sb_size = (rdev->sb_size | bmask) + 1; if (minor_version |
0f420358e md: Turn rdev->sb... |
1481 |
&& rdev->data_offset < sb_start + (rdev->sb_size/512)) |
a1801f858 md: guard against... |
1482 |
return -EINVAL; |
0002b2718 [PATCH] md: limit... |
1483 |
|
31b65a0d3 [PATCH] md: set d... |
1484 1485 1486 1487 |
if (sb->level == cpu_to_le32(LEVEL_MULTIPATH)) rdev->desc_nr = -1; else rdev->desc_nr = le32_to_cpu(sb->dev_number); |
2699b6722 md: load/store ba... |
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 |
if (!rdev->bb_page) { rdev->bb_page = alloc_page(GFP_KERNEL); if (!rdev->bb_page) return -ENOMEM; } if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BAD_BLOCKS) && rdev->badblocks.count == 0) { /* need to load the bad block list. * Currently we limit it to one page. */ s32 offset; sector_t bb_sector; u64 *bbp; int i; int sectors = le16_to_cpu(sb->bblog_size); if (sectors > (PAGE_SIZE / 512)) return -EINVAL; offset = le32_to_cpu(sb->bblog_offset); if (offset == 0) return -EINVAL; bb_sector = (long long)offset; if (!sync_page_io(rdev, bb_sector, sectors << 9, rdev->bb_page, READ, true)) return -EIO; bbp = (u64 *)page_address(rdev->bb_page); rdev->badblocks.shift = sb->bblog_shift; for (i = 0 ; i < (sectors << (9-3)) ; i++, bbp++) { u64 bb = le64_to_cpu(*bbp); int count = bb & (0x3ff); u64 sector = bb >> 10; sector <<= sb->bblog_shift; count <<= sb->bblog_shift; if (bb + 1 == 0) break; if (md_set_badblocks(&rdev->badblocks, sector, count, 1) == 0) return -EINVAL; } } else if (sb->bblog_offset == 0) rdev->badblocks.shift = -1; |
9a7b2b0f3 md: fix integer a... |
1528 |
if (!refdev) { |
8ed75463b [PATCH] md: Make ... |
1529 |
ret = 1; |
9a7b2b0f3 md: fix integer a... |
1530 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
1531 |
__u64 ev1, ev2; |
65a06f067 md: get rid of un... |
1532 |
struct mdp_superblock_1 *refsb = page_address(refdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 |
if (memcmp(sb->set_uuid, refsb->set_uuid, 16) != 0 || sb->level != refsb->level || sb->layout != refsb->layout || sb->chunksize != refsb->chunksize) { printk(KERN_WARNING "md: %s has strangely different" " superblock to %s ", bdevname(rdev->bdev,b), bdevname(refdev->bdev,b2)); return -EINVAL; } ev1 = le64_to_cpu(sb->events); ev2 = le64_to_cpu(refsb->events); if (ev1 > ev2) |
8ed75463b [PATCH] md: Make ... |
1549 1550 1551 |
ret = 1; else ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
1552 |
} |
a1801f858 md: guard against... |
1553 |
if (minor_version) |
77304d2ab block: read i_siz... |
1554 |
rdev->sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - |
dd8ac336c md: Represent rai... |
1555 |
le64_to_cpu(sb->data_offset); |
1da177e4c Linux-2.6.12-rc2 |
1556 |
else |
dd8ac336c md: Represent rai... |
1557 1558 |
rdev->sectors = rdev->sb_start; if (rdev->sectors < le64_to_cpu(sb->data_size)) |
1da177e4c Linux-2.6.12-rc2 |
1559 |
return -EINVAL; |
dd8ac336c md: Represent rai... |
1560 |
rdev->sectors = le64_to_cpu(sb->data_size); |
dd8ac336c md: Represent rai... |
1561 |
if (le64_to_cpu(sb->size) > rdev->sectors) |
2bf071bf5 [PATCH] md: keep ... |
1562 |
return -EINVAL; |
8ed75463b [PATCH] md: Make ... |
1563 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1564 |
} |
fd01b88c7 md: remove typede... |
1565 |
static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
1566 |
{ |
65a06f067 md: get rid of un... |
1567 |
struct mdp_superblock_1 *sb = page_address(rdev->sb_page); |
07d84d109 [PATCH] md: Allow... |
1568 |
__u64 ev1 = le64_to_cpu(sb->events); |
1da177e4c Linux-2.6.12-rc2 |
1569 |
|
41158c7eb [PATCH] md: optim... |
1570 |
rdev->raid_disk = -1; |
c5d79adba md: allow devices... |
1571 1572 1573 |
clear_bit(Faulty, &rdev->flags); clear_bit(In_sync, &rdev->flags); clear_bit(WriteMostly, &rdev->flags); |
c5d79adba md: allow devices... |
1574 |
|
1da177e4c Linux-2.6.12-rc2 |
1575 1576 1577 |
if (mddev->raid_disks == 0) { mddev->major_version = 1; mddev->patch_version = 0; |
e691063a6 md: support 'exte... |
1578 |
mddev->external = 0; |
9d8f03636 md: Make mddev->c... |
1579 |
mddev->chunk_sectors = le32_to_cpu(sb->chunksize); |
1da177e4c Linux-2.6.12-rc2 |
1580 1581 1582 |
mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); mddev->level = le32_to_cpu(sb->level); |
d9d166c2a [PATCH] md: allow... |
1583 |
mddev->clevel[0] = 0; |
1da177e4c Linux-2.6.12-rc2 |
1584 1585 |
mddev->layout = le32_to_cpu(sb->layout); mddev->raid_disks = le32_to_cpu(sb->raid_disks); |
58c0fed40 md: Make mddev->s... |
1586 |
mddev->dev_sectors = le64_to_cpu(sb->size); |
07d84d109 [PATCH] md: Allow... |
1587 |
mddev->events = ev1; |
c3d9714e8 md: collect bitma... |
1588 1589 |
mddev->bitmap_info.offset = 0; mddev->bitmap_info.default_offset = 1024 >> 9; |
1da177e4c Linux-2.6.12-rc2 |
1590 1591 1592 1593 1594 |
mddev->recovery_cp = le64_to_cpu(sb->resync_offset); memcpy(mddev->uuid, sb->set_uuid, 16); mddev->max_disks = (4096-256)/2; |
a654b9d8f [PATCH] md: allow... |
1595 |
|
71c0805cb [PATCH] md: allow... |
1596 |
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && |
c3d9714e8 md: collect bitma... |
1597 1598 1599 |
mddev->bitmap_info.file == NULL ) mddev->bitmap_info.offset = (__s32)le32_to_cpu(sb->bitmap_offset); |
e11e93fac md: move test for... |
1600 |
|
f67055780 [PATCH] md: Check... |
1601 1602 1603 1604 1605 |
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { mddev->reshape_position = le64_to_cpu(sb->reshape_position); mddev->delta_disks = le32_to_cpu(sb->delta_disks); mddev->new_level = le32_to_cpu(sb->new_level); mddev->new_layout = le32_to_cpu(sb->new_layout); |
664e7c413 md: Convert mddev... |
1606 |
mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk); |
f67055780 [PATCH] md: Check... |
1607 1608 1609 1610 1611 |
} else { mddev->reshape_position = MaxSector; mddev->delta_disks = 0; mddev->new_level = mddev->level; mddev->new_layout = mddev->layout; |
664e7c413 md: Convert mddev... |
1612 |
mddev->new_chunk_sectors = mddev->chunk_sectors; |
f67055780 [PATCH] md: Check... |
1613 |
} |
41158c7eb [PATCH] md: optim... |
1614 |
} else if (mddev->pers == NULL) { |
be6800a73 md: don't insist ... |
1615 1616 |
/* Insist of good event counter while assembling, except for * spares (which don't need an event count) */ |
1da177e4c Linux-2.6.12-rc2 |
1617 |
++ev1; |
be6800a73 md: don't insist ... |
1618 1619 1620 1621 1622 |
if (rdev->desc_nr >= 0 && rdev->desc_nr < le32_to_cpu(sb->max_dev) && le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < 0xfffe) if (ev1 < mddev->events) return -EINVAL; |
41158c7eb [PATCH] md: optim... |
1623 1624 1625 1626 |
} else if (mddev->bitmap) { /* If adding to array with a bitmap, then we can accept an * older device, but not too old. */ |
41158c7eb [PATCH] md: optim... |
1627 1628 |
if (ev1 < mddev->bitmap->events_cleared) return 0; |
07d84d109 [PATCH] md: Allow... |
1629 1630 1631 1632 1633 |
} else { if (ev1 < mddev->events) /* just a hot-add of a new device, leave raid_disk at -1 */ return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1634 1635 |
if (mddev->level != LEVEL_MULTIPATH) { int role; |
3673f305f md: avoid array o... |
1636 1637 1638 1639 1640 1641 |
if (rdev->desc_nr < 0 || rdev->desc_nr >= le32_to_cpu(sb->max_dev)) { role = 0xffff; rdev->desc_nr = -1; } else role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); |
1da177e4c Linux-2.6.12-rc2 |
1642 1643 |
switch(role) { case 0xffff: /* spare */ |
1da177e4c Linux-2.6.12-rc2 |
1644 1645 |
break; case 0xfffe: /* faulty */ |
b2d444d7a [PATCH] md: conve... |
1646 |
set_bit(Faulty, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
1647 1648 |
break; default: |
5fd6c1dce [PATCH] md: allow... |
1649 1650 1651 1652 1653 |
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RECOVERY_OFFSET)) rdev->recovery_offset = le64_to_cpu(sb->recovery_offset); else set_bit(In_sync, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
1654 1655 1656 |
rdev->raid_disk = role; break; } |
8ddf9efe6 [PATCH] md: suppo... |
1657 1658 |
if (sb->devflags & WriteMostly1) set_bit(WriteMostly, &rdev->flags); |
41158c7eb [PATCH] md: optim... |
1659 |
} else /* MULTIPATH are always insync */ |
b2d444d7a [PATCH] md: conve... |
1660 |
set_bit(In_sync, &rdev->flags); |
41158c7eb [PATCH] md: optim... |
1661 |
|
1da177e4c Linux-2.6.12-rc2 |
1662 1663 |
return 0; } |
fd01b88c7 md: remove typede... |
1664 |
static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
1665 1666 |
{ struct mdp_superblock_1 *sb; |
3cb030020 md: removing type... |
1667 |
struct md_rdev *rdev2; |
1da177e4c Linux-2.6.12-rc2 |
1668 1669 |
int max_dev, i; /* make rdev->sb match mddev and rdev data. */ |
65a06f067 md: get rid of un... |
1670 |
sb = page_address(rdev->sb_page); |
1da177e4c Linux-2.6.12-rc2 |
1671 1672 1673 |
sb->feature_map = 0; sb->pad0 = 0; |
5fd6c1dce [PATCH] md: allow... |
1674 |
sb->recovery_offset = cpu_to_le64(0); |
1da177e4c Linux-2.6.12-rc2 |
1675 |
memset(sb->pad1, 0, sizeof(sb->pad1)); |
1da177e4c Linux-2.6.12-rc2 |
1676 1677 1678 1679 1680 1681 1682 1683 |
memset(sb->pad3, 0, sizeof(sb->pad3)); sb->utime = cpu_to_le64((__u64)mddev->utime); sb->events = cpu_to_le64(mddev->events); if (mddev->in_sync) sb->resync_offset = cpu_to_le64(mddev->recovery_cp); else sb->resync_offset = cpu_to_le64(0); |
1c05b4bc2 [PATCH] md: endia... |
1684 |
sb->cnt_corrected_read = cpu_to_le32(atomic_read(&rdev->corrected_errors)); |
4dbcdc751 [PATCH] md: count... |
1685 |
|
f0ca340cd [PATCH] md: Make ... |
1686 |
sb->raid_disks = cpu_to_le32(mddev->raid_disks); |
58c0fed40 md: Make mddev->s... |
1687 |
sb->size = cpu_to_le64(mddev->dev_sectors); |
9d8f03636 md: Make mddev->c... |
1688 |
sb->chunksize = cpu_to_le32(mddev->chunk_sectors); |
62e1e389f md: always update... |
1689 1690 |
sb->level = cpu_to_le32(mddev->level); sb->layout = cpu_to_le32(mddev->layout); |
f0ca340cd [PATCH] md: Make ... |
1691 |
|
aeb9b2118 md: ensure change... |
1692 1693 1694 1695 |
if (test_bit(WriteMostly, &rdev->flags)) sb->devflags |= WriteMostly1; else sb->devflags &= ~WriteMostly1; |
c3d9714e8 md: collect bitma... |
1696 1697 |
if (mddev->bitmap && mddev->bitmap_info.file == NULL) { sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_info.offset); |
71c0805cb [PATCH] md: allow... |
1698 |
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); |
a654b9d8f [PATCH] md: allow... |
1699 |
} |
5fd6c1dce [PATCH] md: allow... |
1700 1701 |
if (rdev->raid_disk >= 0 && |
97e4f42d6 md: occasionally ... |
1702 |
!test_bit(In_sync, &rdev->flags)) { |
93be75ffd md: integrate spa... |
1703 1704 1705 1706 |
sb->feature_map |= cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET); sb->recovery_offset = cpu_to_le64(rdev->recovery_offset); |
5fd6c1dce [PATCH] md: allow... |
1707 |
} |
f67055780 [PATCH] md: Check... |
1708 1709 1710 1711 1712 1713 |
if (mddev->reshape_position != MaxSector) { sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE); sb->reshape_position = cpu_to_le64(mddev->reshape_position); sb->new_layout = cpu_to_le32(mddev->new_layout); sb->delta_disks = cpu_to_le32(mddev->delta_disks); sb->new_level = cpu_to_le32(mddev->new_level); |
664e7c413 md: Convert mddev... |
1714 |
sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors); |
f67055780 [PATCH] md: Check... |
1715 |
} |
a654b9d8f [PATCH] md: allow... |
1716 |
|
2699b6722 md: load/store ba... |
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 |
if (rdev->badblocks.count == 0) /* Nothing to do for bad blocks*/ ; else if (sb->bblog_offset == 0) /* Cannot record bad blocks on this device */ md_error(mddev, rdev); else { struct badblocks *bb = &rdev->badblocks; u64 *bbp = (u64 *)page_address(rdev->bb_page); u64 *p = bb->page; sb->feature_map |= cpu_to_le32(MD_FEATURE_BAD_BLOCKS); if (bb->changed) { unsigned seq; retry: seq = read_seqbegin(&bb->lock); memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { u64 internal_bb = *p++; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); *bbp++ = cpu_to_le64(store_bb); } if (read_seqretry(&bb->lock, seq)) goto retry; bb->sector = (rdev->sb_start + (int)le32_to_cpu(sb->bblog_offset)); bb->size = le16_to_cpu(sb->bblog_size); bb->changed = 0; } } |
1da177e4c Linux-2.6.12-rc2 |
1750 |
max_dev = 0; |
159ec1fc0 md: use list_for_... |
1751 |
list_for_each_entry(rdev2, &mddev->disks, same_set) |
1da177e4c Linux-2.6.12-rc2 |
1752 1753 |
if (rdev2->desc_nr+1 > max_dev) max_dev = rdev2->desc_nr+1; |
a778b73ff md: fix bug with ... |
1754 |
|
70471dafe md: Handle growth... |
1755 1756 |
if (max_dev > le32_to_cpu(sb->max_dev)) { int bmask; |
a778b73ff md: fix bug with ... |
1757 |
sb->max_dev = cpu_to_le32(max_dev); |
70471dafe md: Handle growth... |
1758 1759 1760 1761 |
rdev->sb_size = max_dev * 2 + 256; bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; if (rdev->sb_size & bmask) rdev->sb_size = (rdev->sb_size | bmask) + 1; |
ddcf3522c md: fix v1.x meta... |
1762 1763 |
} else max_dev = le32_to_cpu(sb->max_dev); |
1da177e4c Linux-2.6.12-rc2 |
1764 1765 1766 |
for (i=0; i<max_dev;i++) sb->dev_roles[i] = cpu_to_le16(0xfffe); |
159ec1fc0 md: use list_for_... |
1767 |
list_for_each_entry(rdev2, &mddev->disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
1768 |
i = rdev2->desc_nr; |
b2d444d7a [PATCH] md: conve... |
1769 |
if (test_bit(Faulty, &rdev2->flags)) |
1da177e4c Linux-2.6.12-rc2 |
1770 |
sb->dev_roles[i] = cpu_to_le16(0xfffe); |
b2d444d7a [PATCH] md: conve... |
1771 |
else if (test_bit(In_sync, &rdev2->flags)) |
1da177e4c Linux-2.6.12-rc2 |
1772 |
sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); |
93be75ffd md: integrate spa... |
1773 |
else if (rdev2->raid_disk >= 0) |
5fd6c1dce [PATCH] md: allow... |
1774 |
sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); |
1da177e4c Linux-2.6.12-rc2 |
1775 1776 1777 |
else sb->dev_roles[i] = cpu_to_le16(0xffff); } |
1da177e4c Linux-2.6.12-rc2 |
1778 1779 |
sb->sb_csum = calc_sb_1_csum(sb); } |
0cd17fec9 Support changing ... |
1780 |
static unsigned long long |
3cb030020 md: removing type... |
1781 |
super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) |
0cd17fec9 Support changing ... |
1782 1783 |
{ struct mdp_superblock_1 *sb; |
15f4a5fdf md: Make super_ty... |
1784 |
sector_t max_sectors; |
58c0fed40 md: Make mddev->s... |
1785 |
if (num_sectors && num_sectors < rdev->mddev->dev_sectors) |
0cd17fec9 Support changing ... |
1786 |
return 0; /* component must fit device */ |
0f420358e md: Turn rdev->sb... |
1787 |
if (rdev->sb_start < rdev->data_offset) { |
0cd17fec9 Support changing ... |
1788 |
/* minor versions 1 and 2; superblock before data */ |
77304d2ab block: read i_siz... |
1789 |
max_sectors = i_size_read(rdev->bdev->bd_inode) >> 9; |
15f4a5fdf md: Make super_ty... |
1790 1791 1792 |
max_sectors -= rdev->data_offset; if (!num_sectors || num_sectors > max_sectors) num_sectors = max_sectors; |
c3d9714e8 md: collect bitma... |
1793 |
} else if (rdev->mddev->bitmap_info.offset) { |
0cd17fec9 Support changing ... |
1794 1795 1796 1797 |
/* minor version 0 with bitmap we can't move */ return 0; } else { /* minor version 0; superblock after data */ |
0f420358e md: Turn rdev->sb... |
1798 |
sector_t sb_start; |
77304d2ab block: read i_siz... |
1799 |
sb_start = (i_size_read(rdev->bdev->bd_inode) >> 9) - 8*2; |
0f420358e md: Turn rdev->sb... |
1800 |
sb_start &= ~(sector_t)(4*2 - 1); |
dd8ac336c md: Represent rai... |
1801 |
max_sectors = rdev->sectors + sb_start - rdev->sb_start; |
15f4a5fdf md: Make super_ty... |
1802 1803 |
if (!num_sectors || num_sectors > max_sectors) num_sectors = max_sectors; |
0f420358e md: Turn rdev->sb... |
1804 |
rdev->sb_start = sb_start; |
0cd17fec9 Support changing ... |
1805 |
} |
65a06f067 md: get rid of un... |
1806 |
sb = page_address(rdev->sb_page); |
15f4a5fdf md: Make super_ty... |
1807 |
sb->data_size = cpu_to_le64(num_sectors); |
0f420358e md: Turn rdev->sb... |
1808 |
sb->super_offset = rdev->sb_start; |
0cd17fec9 Support changing ... |
1809 |
sb->sb_csum = calc_sb_1_csum(sb); |
0f420358e md: Turn rdev->sb... |
1810 |
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, |
0cd17fec9 Support changing ... |
1811 1812 |
rdev->sb_page); md_super_wait(rdev->mddev); |
c26a44ed1 md: fix return va... |
1813 |
return num_sectors; |
0cd17fec9 Support changing ... |
1814 |
} |
1da177e4c Linux-2.6.12-rc2 |
1815 |
|
75c96f858 [PATCH] make some... |
1816 |
static struct super_type super_types[] = { |
1da177e4c Linux-2.6.12-rc2 |
1817 1818 1819 |
[0] = { .name = "0.90.0", .owner = THIS_MODULE, |
0cd17fec9 Support changing ... |
1820 1821 1822 1823 |
.load_super = super_90_load, .validate_super = super_90_validate, .sync_super = super_90_sync, .rdev_size_change = super_90_rdev_size_change, |
1da177e4c Linux-2.6.12-rc2 |
1824 1825 1826 1827 |
}, [1] = { .name = "md-1", .owner = THIS_MODULE, |
0cd17fec9 Support changing ... |
1828 1829 1830 1831 |
.load_super = super_1_load, .validate_super = super_1_validate, .sync_super = super_1_sync, .rdev_size_change = super_1_rdev_size_change, |
1da177e4c Linux-2.6.12-rc2 |
1832 1833 |
}, }; |
1da177e4c Linux-2.6.12-rc2 |
1834 |
|
fd01b88c7 md: remove typede... |
1835 |
static void sync_super(struct mddev *mddev, struct md_rdev *rdev) |
076f968b3 MD: add sync_supe... |
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 |
{ if (mddev->sync_super) { mddev->sync_super(mddev, rdev); return; } BUG_ON(mddev->major_version >= ARRAY_SIZE(super_types)); super_types[mddev->major_version].sync_super(mddev, rdev); } |
fd01b88c7 md: remove typede... |
1846 |
static int match_mddev_units(struct mddev *mddev1, struct mddev *mddev2) |
1da177e4c Linux-2.6.12-rc2 |
1847 |
{ |
3cb030020 md: removing type... |
1848 |
struct md_rdev *rdev, *rdev2; |
1da177e4c Linux-2.6.12-rc2 |
1849 |
|
4b80991c6 md: Protect acces... |
1850 1851 1852 |
rcu_read_lock(); rdev_for_each_rcu(rdev, mddev1) rdev_for_each_rcu(rdev2, mddev2) |
7dd5e7c3d [PATCH] md: move ... |
1853 |
if (rdev->bdev->bd_contains == |
4b80991c6 md: Protect acces... |
1854 1855 |
rdev2->bdev->bd_contains) { rcu_read_unlock(); |
7dd5e7c3d [PATCH] md: move ... |
1856 |
return 1; |
4b80991c6 md: Protect acces... |
1857 1858 |
} rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1859 1860 1861 1862 |
return 0; } static LIST_HEAD(pending_raid_disks); |
ac5e7113e md: Push down dat... |
1863 1864 1865 1866 1867 1868 1869 |
/* * Try to register data integrity profile for an mddev * * This is called when an array is started and after a disk has been kicked * from the array. It only succeeds if all working and active component devices * are integrity capable with matching profiles. */ |
fd01b88c7 md: remove typede... |
1870 |
int md_integrity_register(struct mddev *mddev) |
ac5e7113e md: Push down dat... |
1871 |
{ |
3cb030020 md: removing type... |
1872 |
struct md_rdev *rdev, *reference = NULL; |
ac5e7113e md: Push down dat... |
1873 1874 1875 |
if (list_empty(&mddev->disks)) return 0; /* nothing to do */ |
629acb6ab MD: no integrity ... |
1876 1877 |
if (!mddev->gendisk || blk_get_integrity(mddev->gendisk)) return 0; /* shouldn't register, or already is */ |
ac5e7113e md: Push down dat... |
1878 1879 1880 1881 1882 1883 |
list_for_each_entry(rdev, &mddev->disks, same_set) { /* skip spares and non-functional disks */ if (test_bit(Faulty, &rdev->flags)) continue; if (rdev->raid_disk < 0) continue; |
ac5e7113e md: Push down dat... |
1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 |
if (!reference) { /* Use the first rdev as the reference */ reference = rdev; continue; } /* does this rdev's profile match the reference profile? */ if (blk_integrity_compare(reference->bdev->bd_disk, rdev->bdev->bd_disk) < 0) return -EINVAL; } |
89078d572 md: Fix integrity... |
1894 1895 |
if (!reference || !bdev_get_integrity(reference->bdev)) return 0; |
ac5e7113e md: Push down dat... |
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 |
/* * All component devices are integrity capable and have matching * profiles, register the common profile for the md device. */ if (blk_integrity_register(mddev->gendisk, bdev_get_integrity(reference->bdev)) != 0) { printk(KERN_ERR "md: failed to register integrity for %s ", mdname(mddev)); return -EINVAL; } |
a91a2785b block: Require su... |
1907 1908 1909 1910 1911 1912 1913 1914 |
printk(KERN_NOTICE "md: data integrity enabled on %s ", mdname(mddev)); if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) { printk(KERN_ERR "md: failed to create integrity pool for %s ", mdname(mddev)); return -EINVAL; } |
ac5e7113e md: Push down dat... |
1915 1916 1917 1918 1919 |
return 0; } EXPORT_SYMBOL(md_integrity_register); /* Disable data integrity if non-capable/non-matching disk is being added */ |
fd01b88c7 md: remove typede... |
1920 |
void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev) |
3f9d99c12 MD data integrity... |
1921 |
{ |
3f9d99c12 MD data integrity... |
1922 |
struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev); |
ac5e7113e md: Push down dat... |
1923 |
struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk); |
3f9d99c12 MD data integrity... |
1924 |
|
ac5e7113e md: Push down dat... |
1925 |
if (!bi_mddev) /* nothing to do */ |
3f9d99c12 MD data integrity... |
1926 |
return; |
ac5e7113e md: Push down dat... |
1927 |
if (rdev->raid_disk < 0) /* skip spares */ |
3f9d99c12 MD data integrity... |
1928 |
return; |
ac5e7113e md: Push down dat... |
1929 1930 1931 1932 1933 1934 |
if (bi_rdev && blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) >= 0) return; printk(KERN_NOTICE "disabling data integrity on %s ", mdname(mddev)); blk_integrity_unregister(mddev->gendisk); |
3f9d99c12 MD data integrity... |
1935 |
} |
ac5e7113e md: Push down dat... |
1936 |
EXPORT_SYMBOL(md_integrity_add_rdev); |
3f9d99c12 MD data integrity... |
1937 |
|
fd01b88c7 md: remove typede... |
1938 |
static int bind_rdev_to_array(struct md_rdev * rdev, struct mddev * mddev) |
1da177e4c Linux-2.6.12-rc2 |
1939 |
{ |
7dd5e7c3d [PATCH] md: move ... |
1940 |
char b[BDEVNAME_SIZE]; |
f637b9f9f [PATCH] md: make ... |
1941 |
struct kobject *ko; |
1edf80d34 [PATCH] md: remov... |
1942 |
char *s; |
5e55e2f5f [PATCH] md: conve... |
1943 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
1944 1945 1946 1947 1948 |
if (rdev->mddev) { MD_BUG(); return -EINVAL; } |
11e2ede02 md: prevent dupli... |
1949 1950 1951 1952 |
/* prevent duplicates */ if (find_rdev(mddev, rdev->bdev->bd_dev)) return -EEXIST; |
dd8ac336c md: Represent rai... |
1953 1954 1955 |
/* make sure rdev->sectors exceeds mddev->dev_sectors */ if (rdev->sectors && (mddev->dev_sectors == 0 || rdev->sectors < mddev->dev_sectors)) { |
a778b73ff md: fix bug with ... |
1956 1957 1958 1959 1960 1961 1962 1963 |
if (mddev->pers) { /* Cannot change size, so fail * If mddev->level <= 0, then we don't care * about aligning sizes (e.g. linear) */ if (mddev->level > 0) return -ENOSPC; } else |
dd8ac336c md: Represent rai... |
1964 |
mddev->dev_sectors = rdev->sectors; |
2bf071bf5 [PATCH] md: keep ... |
1965 |
} |
1da177e4c Linux-2.6.12-rc2 |
1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 |
/* Verify rdev->desc_nr is unique. * If it is -1, assign a free number, else * check number is not in use */ if (rdev->desc_nr < 0) { int choice = 0; if (mddev->pers) choice = mddev->raid_disks; while (find_rdev_nr(mddev, choice)) choice++; rdev->desc_nr = choice; } else { if (find_rdev_nr(mddev, rdev->desc_nr)) return -EBUSY; } |
de01dfadf md: Ensure an md ... |
1981 1982 1983 1984 1985 1986 |
if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) { printk(KERN_WARNING "md: %s: array is limited to %d devices ", mdname(mddev), mddev->max_disks); return -EBUSY; } |
19133a429 [PATCH] md: Remov... |
1987 |
bdevname(rdev->bdev,b); |
649316b25 Kobject: convert ... |
1988 |
while ( (s=strchr(b, '/')) != NULL) |
1edf80d34 [PATCH] md: remov... |
1989 |
*s = '!'; |
649316b25 Kobject: convert ... |
1990 |
|
1da177e4c Linux-2.6.12-rc2 |
1991 |
rdev->mddev = mddev; |
19133a429 [PATCH] md: Remov... |
1992 1993 |
printk(KERN_INFO "md: bind<%s> ", b); |
86e6ffdd2 [PATCH] md: exten... |
1994 |
|
b2d6db587 Kobject: rename k... |
1995 |
if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b))) |
5e55e2f5f [PATCH] md: conve... |
1996 |
goto fail; |
86e6ffdd2 [PATCH] md: exten... |
1997 |
|
0762b8bde block: always set... |
1998 |
ko = &part_to_dev(rdev->bdev->bd_part)->kobj; |
00bcb4ac7 md: reduce depend... |
1999 2000 2001 |
if (sysfs_create_link(&rdev->kobj, ko, "block")) /* failure here is OK */; rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state"); |
3c0ee63a6 md: use sysfs_not... |
2002 |
|
4b80991c6 md: Protect acces... |
2003 |
list_add_rcu(&rdev->same_set, &mddev->disks); |
e09b457bd block: simplify h... |
2004 |
bd_link_disk_holder(rdev->bdev, mddev->gendisk); |
4044ba58d md: don't retry r... |
2005 2006 |
/* May as well allow recovery to be retried once */ |
5389042ff md: change manage... |
2007 |
mddev->recovery_disabled++; |
3f9d99c12 MD data integrity... |
2008 |
|
1da177e4c Linux-2.6.12-rc2 |
2009 |
return 0; |
5e55e2f5f [PATCH] md: conve... |
2010 2011 2012 2013 2014 2015 |
fail: printk(KERN_WARNING "md: failed to register dev-%s for %s ", b, mdname(mddev)); return err; |
1da177e4c Linux-2.6.12-rc2 |
2016 |
} |
177a99b23 md: fix use-after... |
2017 |
static void md_delayed_delete(struct work_struct *ws) |
5792a2856 [PATCH] md: avoid... |
2018 |
{ |
3cb030020 md: removing type... |
2019 |
struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work); |
5792a2856 [PATCH] md: avoid... |
2020 |
kobject_del(&rdev->kobj); |
177a99b23 md: fix use-after... |
2021 |
kobject_put(&rdev->kobj); |
5792a2856 [PATCH] md: avoid... |
2022 |
} |
3cb030020 md: removing type... |
2023 |
static void unbind_rdev_from_array(struct md_rdev * rdev) |
1da177e4c Linux-2.6.12-rc2 |
2024 2025 2026 2027 2028 2029 |
{ char b[BDEVNAME_SIZE]; if (!rdev->mddev) { MD_BUG(); return; } |
49731baa4 block: restore mu... |
2030 |
bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk); |
4b80991c6 md: Protect acces... |
2031 |
list_del_rcu(&rdev->same_set); |
1da177e4c Linux-2.6.12-rc2 |
2032 2033 2034 |
printk(KERN_INFO "md: unbind<%s> ", bdevname(rdev->bdev,b)); rdev->mddev = NULL; |
86e6ffdd2 [PATCH] md: exten... |
2035 |
sysfs_remove_link(&rdev->kobj, "block"); |
3c0ee63a6 md: use sysfs_not... |
2036 2037 |
sysfs_put(rdev->sysfs_state); rdev->sysfs_state = NULL; |
2230dfe4c md: beginnings of... |
2038 2039 2040 |
kfree(rdev->badblocks.page); rdev->badblocks.count = 0; rdev->badblocks.page = NULL; |
5792a2856 [PATCH] md: avoid... |
2041 |
/* We need to delay this, otherwise we can deadlock when |
4b80991c6 md: Protect acces... |
2042 2043 |
* writing to 'remove' to "dev/state". We also need * to delay it due to rcu usage. |
5792a2856 [PATCH] md: avoid... |
2044 |
*/ |
4b80991c6 md: Protect acces... |
2045 |
synchronize_rcu(); |
177a99b23 md: fix use-after... |
2046 2047 |
INIT_WORK(&rdev->del_work, md_delayed_delete); kobject_get(&rdev->kobj); |
e804ac780 md: fix and updat... |
2048 |
queue_work(md_misc_wq, &rdev->del_work); |
1da177e4c Linux-2.6.12-rc2 |
2049 2050 2051 2052 2053 2054 2055 |
} /* * prevent the device from being mounted, repartitioned or * otherwise reused by a RAID array (or any other kernel * subsystem), by bd_claiming the device. */ |
3cb030020 md: removing type... |
2056 |
static int lock_rdev(struct md_rdev *rdev, dev_t dev, int shared) |
1da177e4c Linux-2.6.12-rc2 |
2057 2058 2059 2060 |
{ int err = 0; struct block_device *bdev; char b[BDEVNAME_SIZE]; |
d4d776299 block: clean up b... |
2061 |
bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, |
3cb030020 md: removing type... |
2062 |
shared ? (struct md_rdev *)lock_rdev : rdev); |
1da177e4c Linux-2.6.12-rc2 |
2063 2064 2065 2066 2067 2068 |
if (IS_ERR(bdev)) { printk(KERN_ERR "md: could not open %s. ", __bdevname(dev, b)); return PTR_ERR(bdev); } |
1da177e4c Linux-2.6.12-rc2 |
2069 2070 2071 |
rdev->bdev = bdev; return err; } |
3cb030020 md: removing type... |
2072 |
static void unlock_rdev(struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
2073 2074 2075 2076 2077 |
{ struct block_device *bdev = rdev->bdev; rdev->bdev = NULL; if (!bdev) MD_BUG(); |
e525fd89d block: make blkde... |
2078 |
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); |
1da177e4c Linux-2.6.12-rc2 |
2079 2080 2081 |
} void md_autodetect_dev(dev_t dev); |
3cb030020 md: removing type... |
2082 |
static void export_rdev(struct md_rdev * rdev) |
1da177e4c Linux-2.6.12-rc2 |
2083 2084 2085 2086 2087 2088 2089 2090 |
{ char b[BDEVNAME_SIZE]; printk(KERN_INFO "md: export_rdev(%s) ", bdevname(rdev->bdev,b)); if (rdev->mddev) MD_BUG(); free_disk_sb(rdev); |
1da177e4c Linux-2.6.12-rc2 |
2091 |
#ifndef MODULE |
d0fae18f1 md: clean up irre... |
2092 2093 |
if (test_bit(AutoDetected, &rdev->flags)) md_autodetect_dev(rdev->bdev->bd_dev); |
1da177e4c Linux-2.6.12-rc2 |
2094 2095 |
#endif unlock_rdev(rdev); |
86e6ffdd2 [PATCH] md: exten... |
2096 |
kobject_put(&rdev->kobj); |
1da177e4c Linux-2.6.12-rc2 |
2097 |
} |
3cb030020 md: removing type... |
2098 |
static void kick_rdev_from_array(struct md_rdev * rdev) |
1da177e4c Linux-2.6.12-rc2 |
2099 2100 2101 2102 |
{ unbind_rdev_from_array(rdev); export_rdev(rdev); } |
fd01b88c7 md: remove typede... |
2103 |
static void export_array(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
2104 |
{ |
3cb030020 md: removing type... |
2105 |
struct md_rdev *rdev, *tmp; |
1da177e4c Linux-2.6.12-rc2 |
2106 |
|
d089c6af1 md: change ITERAT... |
2107 |
rdev_for_each(rdev, tmp, mddev) { |
1da177e4c Linux-2.6.12-rc2 |
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 |
if (!rdev->mddev) { MD_BUG(); continue; } kick_rdev_from_array(rdev); } if (!list_empty(&mddev->disks)) MD_BUG(); mddev->raid_disks = 0; mddev->major_version = 0; } static void print_desc(mdp_disk_t *desc) { printk(" DISK<N:%d,(%d,%d),R:%d,S:%d> ", desc->number, desc->major,desc->minor,desc->raid_disk,desc->state); } |
cd2ac9321 md: need another ... |
2126 |
static void print_sb_90(mdp_super_t *sb) |
1da177e4c Linux-2.6.12-rc2 |
2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 |
{ int i; printk(KERN_INFO "md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x ", sb->major_version, sb->minor_version, sb->patch_version, sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3, sb->ctime); printk(KERN_INFO "md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d ", sb->level, sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor, sb->layout, sb->chunk_size); printk(KERN_INFO "md: UT:%08x ST:%d AD:%d WD:%d" " FD:%d SD:%d CSUM:%08x E:%08lx ", sb->utime, sb->state, sb->active_disks, sb->working_disks, sb->failed_disks, sb->spare_disks, sb->sb_csum, (unsigned long)sb->events_lo); printk(KERN_INFO); for (i = 0; i < MD_SB_DISKS; i++) { mdp_disk_t *desc; desc = sb->disks + i; if (desc->number || desc->major || desc->minor || desc->raid_disk || (desc->state && (desc->state != 4))) { printk(" D %2d: ", i); print_desc(desc); } } printk(KERN_INFO "md: THIS: "); print_desc(&sb->this_disk); |
cd2ac9321 md: need another ... |
2160 |
} |
1da177e4c Linux-2.6.12-rc2 |
2161 |
|
cd2ac9321 md: need another ... |
2162 2163 2164 2165 2166 |
static void print_sb_1(struct mdp_superblock_1 *sb) { __u8 *uuid; uuid = sb->set_uuid; |
ad361c988 Remove multiple K... |
2167 |
printk(KERN_INFO |
7b75c2f8c drivers/md/md.c: ... |
2168 2169 |
"md: SB: (V:%u) (F:0x%08x) Array-ID:<%pU> " |
ad361c988 Remove multiple K... |
2170 2171 |
"md: Name: \"%s\" CT:%llu ", |
cd2ac9321 md: need another ... |
2172 2173 |
le32_to_cpu(sb->major_version), le32_to_cpu(sb->feature_map), |
7b75c2f8c drivers/md/md.c: ... |
2174 |
uuid, |
cd2ac9321 md: need another ... |
2175 2176 2177 2178 2179 |
sb->set_name, (unsigned long long)le64_to_cpu(sb->ctime) & MD_SUPERBLOCK_1_TIME_SEC_MASK); uuid = sb->device_uuid; |
ad361c988 Remove multiple K... |
2180 2181 |
printk(KERN_INFO "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" |
cd2ac9321 md: need another ... |
2182 2183 |
" RO:%llu " |
7b75c2f8c drivers/md/md.c: ... |
2184 2185 |
"md: Dev:%08x UUID: %pU " |
ad361c988 Remove multiple K... |
2186 2187 2188 2189 |
"md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x " "md: (MaxDev:%u) ", |
cd2ac9321 md: need another ... |
2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 |
le32_to_cpu(sb->level), (unsigned long long)le64_to_cpu(sb->size), le32_to_cpu(sb->raid_disks), le32_to_cpu(sb->layout), le32_to_cpu(sb->chunksize), (unsigned long long)le64_to_cpu(sb->data_offset), (unsigned long long)le64_to_cpu(sb->data_size), (unsigned long long)le64_to_cpu(sb->super_offset), (unsigned long long)le64_to_cpu(sb->recovery_offset), le32_to_cpu(sb->dev_number), |
7b75c2f8c drivers/md/md.c: ... |
2200 |
uuid, |
cd2ac9321 md: need another ... |
2201 2202 2203 2204 2205 2206 2207 |
sb->devflags, (unsigned long long)le64_to_cpu(sb->utime) & MD_SUPERBLOCK_1_TIME_SEC_MASK, (unsigned long long)le64_to_cpu(sb->events), (unsigned long long)le64_to_cpu(sb->resync_offset), le32_to_cpu(sb->sb_csum), le32_to_cpu(sb->max_dev) ); |
1da177e4c Linux-2.6.12-rc2 |
2208 |
} |
3cb030020 md: removing type... |
2209 |
static void print_rdev(struct md_rdev *rdev, int major_version) |
1da177e4c Linux-2.6.12-rc2 |
2210 2211 |
{ char b[BDEVNAME_SIZE]; |
dd8ac336c md: Represent rai... |
2212 2213 2214 |
printk(KERN_INFO "md: rdev %s, Sect:%08llu F:%d S:%d DN:%u ", bdevname(rdev->bdev, b), (unsigned long long)rdev->sectors, |
b2d444d7a [PATCH] md: conve... |
2215 2216 |
test_bit(Faulty, &rdev->flags), test_bit(In_sync, &rdev->flags), rdev->desc_nr); |
1da177e4c Linux-2.6.12-rc2 |
2217 |
if (rdev->sb_loaded) { |
cd2ac9321 md: need another ... |
2218 2219 2220 2221 |
printk(KERN_INFO "md: rdev superblock (MJ:%d): ", major_version); switch (major_version) { case 0: |
65a06f067 md: get rid of un... |
2222 |
print_sb_90(page_address(rdev->sb_page)); |
cd2ac9321 md: need another ... |
2223 2224 |
break; case 1: |
65a06f067 md: get rid of un... |
2225 |
print_sb_1(page_address(rdev->sb_page)); |
cd2ac9321 md: need another ... |
2226 2227 |
break; } |
1da177e4c Linux-2.6.12-rc2 |
2228 2229 2230 2231 |
} else printk(KERN_INFO "md: no rdev superblock! "); } |
5e56341d0 [PATCH] md: make ... |
2232 |
static void md_print_devices(void) |
1da177e4c Linux-2.6.12-rc2 |
2233 |
{ |
159ec1fc0 md: use list_for_... |
2234 |
struct list_head *tmp; |
3cb030020 md: removing type... |
2235 |
struct md_rdev *rdev; |
fd01b88c7 md: remove typede... |
2236 |
struct mddev *mddev; |
1da177e4c Linux-2.6.12-rc2 |
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 |
char b[BDEVNAME_SIZE]; printk(" "); printk("md: ********************************** "); printk("md: * <COMPLETE RAID STATE PRINTOUT> * "); printk("md: ********************************** "); |
29ac4aa3f md: change INTERA... |
2247 |
for_each_mddev(mddev, tmp) { |
1da177e4c Linux-2.6.12-rc2 |
2248 |
|
32a7627cf [PATCH] md: optim... |
2249 2250 2251 2252 |
if (mddev->bitmap) bitmap_print_sb(mddev->bitmap); else printk("%s: ", mdname(mddev)); |
159ec1fc0 md: use list_for_... |
2253 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
1da177e4c Linux-2.6.12-rc2 |
2254 2255 2256 |
printk("<%s>", bdevname(rdev->bdev,b)); printk(" "); |
159ec1fc0 md: use list_for_... |
2257 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
cd2ac9321 md: need another ... |
2258 |
print_rdev(rdev, mddev->major_version); |
1da177e4c Linux-2.6.12-rc2 |
2259 2260 2261 2262 2263 2264 |
} printk("md: ********************************** "); printk(" "); } |
fd01b88c7 md: remove typede... |
2265 |
static void sync_sbs(struct mddev * mddev, int nospares) |
1da177e4c Linux-2.6.12-rc2 |
2266 |
{ |
425437691 [PATCH] md: Don't... |
2267 2268 2269 2270 2271 2272 |
/* Update each superblock (in-memory image), but * if we are allowed to, skip spares which already * have the right event counter, or have one earlier * (which would mean they aren't being marked as dirty * with the rest of the array) */ |
3cb030020 md: removing type... |
2273 |
struct md_rdev *rdev; |
159ec1fc0 md: use list_for_... |
2274 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
425437691 [PATCH] md: Don't... |
2275 2276 2277 |
if (rdev->sb_events == mddev->events || (nospares && rdev->raid_disk < 0 && |
425437691 [PATCH] md: Don't... |
2278 2279 2280 2281 |
rdev->sb_events+1 == mddev->events)) { /* Don't update this superblock */ rdev->sb_loaded = 2; } else { |
076f968b3 MD: add sync_supe... |
2282 |
sync_super(mddev, rdev); |
425437691 [PATCH] md: Don't... |
2283 2284 |
rdev->sb_loaded = 1; } |
1da177e4c Linux-2.6.12-rc2 |
2285 2286 |
} } |
fd01b88c7 md: remove typede... |
2287 |
static void md_update_sb(struct mddev * mddev, int force_change) |
1da177e4c Linux-2.6.12-rc2 |
2288 |
{ |
3cb030020 md: removing type... |
2289 |
struct md_rdev *rdev; |
06d91a5fe [PATCH] md: impro... |
2290 |
int sync_req; |
425437691 [PATCH] md: Don't... |
2291 |
int nospares = 0; |
2699b6722 md: load/store ba... |
2292 |
int any_badblocks_changed = 0; |
1da177e4c Linux-2.6.12-rc2 |
2293 |
|
1da177e4c Linux-2.6.12-rc2 |
2294 |
repeat: |
3a3a5ddb7 Update recovery_o... |
2295 2296 2297 2298 2299 2300 2301 2302 2303 |
/* First make sure individual recovery_offsets are correct */ list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk >= 0 && mddev->delta_disks >= 0 && !test_bit(In_sync, &rdev->flags) && mddev->curr_resync_completed > rdev->recovery_offset) rdev->recovery_offset = mddev->curr_resync_completed; } |
bd52b7462 md: don't clear M... |
2304 |
if (!mddev->persistent) { |
070dc6dd7 md: resolve confu... |
2305 |
clear_bit(MD_CHANGE_CLEAN, &mddev->flags); |
3a3a5ddb7 Update recovery_o... |
2306 |
clear_bit(MD_CHANGE_DEVS, &mddev->flags); |
de393cdea md: make it easie... |
2307 |
if (!mddev->external) { |
d97a41dc9 md: Fix regressio... |
2308 |
clear_bit(MD_CHANGE_PENDING, &mddev->flags); |
de393cdea md: make it easie... |
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 |
list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->badblocks.changed) { md_ack_all_badblocks(&rdev->badblocks); md_error(mddev, rdev); } clear_bit(Blocked, &rdev->flags); clear_bit(BlockedBadBlocks, &rdev->flags); wake_up(&rdev->blocked_wait); } } |
3a3a5ddb7 Update recovery_o... |
2319 2320 2321 |
wake_up(&mddev->sb_wait); return; } |
a9701a304 [PATCH] md: suppo... |
2322 |
spin_lock_irq(&mddev->write_lock); |
846921959 [PATCH] md: avoid... |
2323 |
|
3a3a5ddb7 Update recovery_o... |
2324 |
mddev->utime = get_seconds(); |
850b2b420 [PATCH] md: repla... |
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 |
if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags)) force_change = 1; if (test_and_clear_bit(MD_CHANGE_CLEAN, &mddev->flags)) /* just a clean<-> dirty transition, possibly leave spares alone, * though if events isn't the right even/odd, we will have to do * spares after all */ nospares = 1; if (force_change) nospares = 0; if (mddev->degraded) |
846921959 [PATCH] md: avoid... |
2336 2337 2338 2339 2340 2341 2342 2343 2344 |
/* If the array is degraded, then skipping spares is both * dangerous and fairly pointless. * Dangerous because a device that was removed from the array * might have a event_count that still looks up-to-date, * so it can be re-added without a resync. * Pointless because if there are any spares to skip, * then a recovery will happen and soon that array won't * be degraded any more and the spare can go back to sleep then. */ |
850b2b420 [PATCH] md: repla... |
2345 |
nospares = 0; |
846921959 [PATCH] md: avoid... |
2346 |
|
06d91a5fe [PATCH] md: impro... |
2347 |
sync_req = mddev->in_sync; |
425437691 [PATCH] md: Don't... |
2348 2349 2350 |
/* If this is just a dirty<->clean transition, and the array is clean * and 'events' is odd, we can roll back to the previous clean state */ |
850b2b420 [PATCH] md: repla... |
2351 |
if (nospares |
425437691 [PATCH] md: Don't... |
2352 |
&& (mddev->in_sync && mddev->recovery_cp == MaxSector) |
a8707c08f md: simplify upda... |
2353 2354 |
&& mddev->can_decrease_events && mddev->events != 1) { |
425437691 [PATCH] md: Don't... |
2355 |
mddev->events--; |
a8707c08f md: simplify upda... |
2356 2357 |
mddev->can_decrease_events = 0; } else { |
425437691 [PATCH] md: Don't... |
2358 2359 |
/* otherwise we have to go forward and ... */ mddev->events ++; |
a8707c08f md: simplify upda... |
2360 |
mddev->can_decrease_events = nospares; |
425437691 [PATCH] md: Don't... |
2361 |
} |
1da177e4c Linux-2.6.12-rc2 |
2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 |
if (!mddev->events) { /* * oops, this 64-bit counter should never wrap. * Either we are in around ~1 trillion A.C., assuming * 1 reboot per second, or we have a bug: */ MD_BUG(); mddev->events --; } |
2699b6722 md: load/store ba... |
2372 |
|
de393cdea md: make it easie... |
2373 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
2699b6722 md: load/store ba... |
2374 2375 |
if (rdev->badblocks.changed) any_badblocks_changed++; |
de393cdea md: make it easie... |
2376 2377 2378 |
if (test_bit(Faulty, &rdev->flags)) set_bit(FaultRecorded, &rdev->flags); } |
2699b6722 md: load/store ba... |
2379 |
|
e691063a6 md: support 'exte... |
2380 |
sync_sbs(mddev, nospares); |
a9701a304 [PATCH] md: suppo... |
2381 |
spin_unlock_irq(&mddev->write_lock); |
1da177e4c Linux-2.6.12-rc2 |
2382 |
|
36a4e1fe0 md: remove PRINTK... |
2383 2384 2385 |
pr_debug("md: updating %s RAID superblock on device (in sync %d) ", mdname(mddev), mddev->in_sync); |
1da177e4c Linux-2.6.12-rc2 |
2386 |
|
4ad136637 md: change bitmap... |
2387 |
bitmap_update_sb(mddev->bitmap); |
159ec1fc0 md: use list_for_... |
2388 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
2389 |
char b[BDEVNAME_SIZE]; |
36a4e1fe0 md: remove PRINTK... |
2390 |
|
425437691 [PATCH] md: Don't... |
2391 2392 |
if (rdev->sb_loaded != 1) continue; /* no noise on spare devices */ |
1da177e4c Linux-2.6.12-rc2 |
2393 |
|
d70ed2e4f MD: Allow restart... |
2394 2395 |
if (!test_bit(Faulty, &rdev->flags) && rdev->saved_raid_disk == -1) { |
7bfa19f27 [PATCH] md: allow... |
2396 |
md_super_write(mddev,rdev, |
0f420358e md: Turn rdev->sb... |
2397 |
rdev->sb_start, rdev->sb_size, |
7bfa19f27 [PATCH] md: allow... |
2398 |
rdev->sb_page); |
36a4e1fe0 md: remove PRINTK... |
2399 2400 2401 2402 |
pr_debug("md: (write) %s's sb offset: %llu ", bdevname(rdev->bdev, b), (unsigned long long)rdev->sb_start); |
425437691 [PATCH] md: Don't... |
2403 |
rdev->sb_events = mddev->events; |
2699b6722 md: load/store ba... |
2404 2405 2406 2407 2408 2409 2410 |
if (rdev->badblocks.size) { md_super_write(mddev, rdev, rdev->badblocks.sector, rdev->badblocks.size << 9, rdev->bb_page); rdev->badblocks.size = 0; } |
7bfa19f27 [PATCH] md: allow... |
2411 |
|
d70ed2e4f MD: Allow restart... |
2412 |
} else if (test_bit(Faulty, &rdev->flags)) |
36a4e1fe0 md: remove PRINTK... |
2413 2414 2415 |
pr_debug("md: %s (skipping faulty) ", bdevname(rdev->bdev, b)); |
d70ed2e4f MD: Allow restart... |
2416 2417 |
else pr_debug("(skipping incremental s/r "); |
7bfa19f27 [PATCH] md: allow... |
2418 |
if (mddev->level == LEVEL_MULTIPATH) |
1da177e4c Linux-2.6.12-rc2 |
2419 2420 2421 |
/* only need to write one superblock... */ break; } |
a9701a304 [PATCH] md: suppo... |
2422 |
md_super_wait(mddev); |
850b2b420 [PATCH] md: repla... |
2423 |
/* if there was a failure, MD_CHANGE_DEVS was set, and we re-write super */ |
7bfa19f27 [PATCH] md: allow... |
2424 |
|
a9701a304 [PATCH] md: suppo... |
2425 |
spin_lock_irq(&mddev->write_lock); |
850b2b420 [PATCH] md: repla... |
2426 2427 |
if (mddev->in_sync != sync_req || test_bit(MD_CHANGE_DEVS, &mddev->flags)) { |
06d91a5fe [PATCH] md: impro... |
2428 |
/* have to write it out again */ |
a9701a304 [PATCH] md: suppo... |
2429 |
spin_unlock_irq(&mddev->write_lock); |
06d91a5fe [PATCH] md: impro... |
2430 2431 |
goto repeat; } |
850b2b420 [PATCH] md: repla... |
2432 |
clear_bit(MD_CHANGE_PENDING, &mddev->flags); |
a9701a304 [PATCH] md: suppo... |
2433 |
spin_unlock_irq(&mddev->write_lock); |
3d310eb7b [PATCH] md: fix d... |
2434 |
wake_up(&mddev->sb_wait); |
acb180b0e md: improve usefu... |
2435 2436 |
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
06d91a5fe [PATCH] md: impro... |
2437 |
|
de393cdea md: make it easie... |
2438 2439 2440 2441 2442 |
list_for_each_entry(rdev, &mddev->disks, same_set) { if (test_and_clear_bit(FaultRecorded, &rdev->flags)) clear_bit(Blocked, &rdev->flags); if (any_badblocks_changed) |
2699b6722 md: load/store ba... |
2443 |
md_ack_all_badblocks(&rdev->badblocks); |
de393cdea md: make it easie... |
2444 2445 2446 |
clear_bit(BlockedBadBlocks, &rdev->flags); wake_up(&rdev->blocked_wait); } |
1da177e4c Linux-2.6.12-rc2 |
2447 |
} |
7f6ce7692 md: Fix a typo in... |
2448 2449 |
/* words written to sysfs files may, or may not, be terminated. |
bce74dac0 [PATCH] md: helpe... |
2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 |
* We want to accept with case. For this we use cmd_match. */ static int cmd_match(const char *cmd, const char *str) { /* See if cmd, written into a sysfs file, matches * str. They must either be the same, or cmd can * have a trailing newline */ while (*cmd && *str && *cmd == *str) { cmd++; str++; } if (*cmd == ' ') cmd++; if (*str || *cmd) return 0; return 1; } |
86e6ffdd2 [PATCH] md: exten... |
2469 2470 |
struct rdev_sysfs_entry { struct attribute attr; |
3cb030020 md: removing type... |
2471 2472 |
ssize_t (*show)(struct md_rdev *, char *); ssize_t (*store)(struct md_rdev *, const char *, size_t); |
86e6ffdd2 [PATCH] md: exten... |
2473 2474 2475 |
}; static ssize_t |
3cb030020 md: removing type... |
2476 |
state_show(struct md_rdev *rdev, char *page) |
86e6ffdd2 [PATCH] md: exten... |
2477 2478 |
{ char *sep = ""; |
20a49ff67 md: change a few ... |
2479 |
size_t len = 0; |
86e6ffdd2 [PATCH] md: exten... |
2480 |
|
de393cdea md: make it easie... |
2481 2482 |
if (test_bit(Faulty, &rdev->flags) || rdev->badblocks.unacked_exist) { |
86e6ffdd2 [PATCH] md: exten... |
2483 2484 2485 |
len+= sprintf(page+len, "%sfaulty",sep); sep = ","; } |
b2d444d7a [PATCH] md: conve... |
2486 |
if (test_bit(In_sync, &rdev->flags)) { |
86e6ffdd2 [PATCH] md: exten... |
2487 2488 2489 |
len += sprintf(page+len, "%sin_sync",sep); sep = ","; } |
f655675b3 [PATCH] md: Allow... |
2490 2491 2492 2493 |
if (test_bit(WriteMostly, &rdev->flags)) { len += sprintf(page+len, "%swrite_mostly",sep); sep = ","; } |
de393cdea md: make it easie... |
2494 |
if (test_bit(Blocked, &rdev->flags) || |
52c64152a md: bad blocks sh... |
2495 2496 |
(rdev->badblocks.unacked_exist && !test_bit(Faulty, &rdev->flags))) { |
6bfe0b499 md: support block... |
2497 2498 2499 |
len += sprintf(page+len, "%sblocked", sep); sep = ","; } |
b2d444d7a [PATCH] md: conve... |
2500 2501 |
if (!test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags)) { |
86e6ffdd2 [PATCH] md: exten... |
2502 2503 2504 |
len += sprintf(page+len, "%sspare", sep); sep = ","; } |
d7a9d443b md: add 'write_er... |
2505 2506 2507 2508 |
if (test_bit(WriteErrorSeen, &rdev->flags)) { len += sprintf(page+len, "%swrite_error", sep); sep = ","; } |
86e6ffdd2 [PATCH] md: exten... |
2509 2510 2511 |
return len+sprintf(page+len, " "); } |
45dc2de1e [PATCH] md: Allow... |
2512 |
static ssize_t |
3cb030020 md: removing type... |
2513 |
state_store(struct md_rdev *rdev, const char *buf, size_t len) |
45dc2de1e [PATCH] md: Allow... |
2514 2515 |
{ /* can write |
de393cdea md: make it easie... |
2516 |
* faulty - simulates an error |
45dc2de1e [PATCH] md: Allow... |
2517 |
* remove - disconnects the device |
f655675b3 [PATCH] md: Allow... |
2518 2519 |
* writemostly - sets write_mostly * -writemostly - clears write_mostly |
de393cdea md: make it easie... |
2520 2521 |
* blocked - sets the Blocked flags * -blocked - clears the Blocked and possibly simulates an error |
6d56e2784 md: allow setting... |
2522 |
* insync - sets Insync providing device isn't active |
d7a9d443b md: add 'write_er... |
2523 2524 |
* write_error - sets WriteErrorSeen * -write_error - clears WriteErrorSeen |
45dc2de1e [PATCH] md: Allow... |
2525 2526 2527 2528 |
*/ int err = -EINVAL; if (cmd_match(buf, "faulty") && rdev->mddev->pers) { md_error(rdev->mddev, rdev); |
5ef56c8fe md: report failur... |
2529 2530 2531 2532 |
if (test_bit(Faulty, &rdev->flags)) err = 0; else err = -EBUSY; |
45dc2de1e [PATCH] md: Allow... |
2533 2534 2535 2536 |
} else if (cmd_match(buf, "remove")) { if (rdev->raid_disk >= 0) err = -EBUSY; else { |
fd01b88c7 md: remove typede... |
2537 |
struct mddev *mddev = rdev->mddev; |
45dc2de1e [PATCH] md: Allow... |
2538 |
kick_rdev_from_array(rdev); |
3f9d7b0d8 [PATCH] md: fix a... |
2539 2540 |
if (mddev->pers) md_update_sb(mddev, 1); |
45dc2de1e [PATCH] md: Allow... |
2541 2542 2543 |
md_new_event(mddev); err = 0; } |
f655675b3 [PATCH] md: Allow... |
2544 2545 2546 2547 2548 2549 |
} else if (cmd_match(buf, "writemostly")) { set_bit(WriteMostly, &rdev->flags); err = 0; } else if (cmd_match(buf, "-writemostly")) { clear_bit(WriteMostly, &rdev->flags); err = 0; |
6bfe0b499 md: support block... |
2550 2551 2552 2553 |
} else if (cmd_match(buf, "blocked")) { set_bit(Blocked, &rdev->flags); err = 0; } else if (cmd_match(buf, "-blocked")) { |
de393cdea md: make it easie... |
2554 |
if (!test_bit(Faulty, &rdev->flags) && |
7da64a0ab md: fix clearing ... |
2555 |
rdev->badblocks.unacked_exist) { |
de393cdea md: make it easie... |
2556 2557 2558 2559 2560 |
/* metadata handler doesn't understand badblocks, * so we need to fail the device */ md_error(rdev->mddev, rdev); } |
6bfe0b499 md: support block... |
2561 |
clear_bit(Blocked, &rdev->flags); |
de393cdea md: make it easie... |
2562 |
clear_bit(BlockedBadBlocks, &rdev->flags); |
6bfe0b499 md: support block... |
2563 2564 2565 2566 2567 |
wake_up(&rdev->blocked_wait); set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); md_wakeup_thread(rdev->mddev->thread); err = 0; |
6d56e2784 md: allow setting... |
2568 2569 2570 |
} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) { set_bit(In_sync, &rdev->flags); err = 0; |
d7a9d443b md: add 'write_er... |
2571 2572 2573 2574 2575 2576 |
} else if (cmd_match(buf, "write_error")) { set_bit(WriteErrorSeen, &rdev->flags); err = 0; } else if (cmd_match(buf, "-write_error")) { clear_bit(WriteErrorSeen, &rdev->flags); err = 0; |
45dc2de1e [PATCH] md: Allow... |
2577 |
} |
00bcb4ac7 md: reduce depend... |
2578 2579 |
if (!err) sysfs_notify_dirent_safe(rdev->sysfs_state); |
45dc2de1e [PATCH] md: Allow... |
2580 2581 |
return err ? err : len; } |
80ca3a44f [PATCH] md: unify... |
2582 2583 |
static struct rdev_sysfs_entry rdev_state = __ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store); |
86e6ffdd2 [PATCH] md: exten... |
2584 2585 |
static ssize_t |
3cb030020 md: removing type... |
2586 |
errors_show(struct md_rdev *rdev, char *page) |
4dbcdc751 [PATCH] md: count... |
2587 2588 2589 2590 2591 2592 |
{ return sprintf(page, "%d ", atomic_read(&rdev->corrected_errors)); } static ssize_t |
3cb030020 md: removing type... |
2593 |
errors_store(struct md_rdev *rdev, const char *buf, size_t len) |
4dbcdc751 [PATCH] md: count... |
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 |
{ char *e; unsigned long n = simple_strtoul(buf, &e, 10); if (*buf && (*e == 0 || *e == ' ')) { atomic_set(&rdev->corrected_errors, n); return len; } return -EINVAL; } static struct rdev_sysfs_entry rdev_errors = |
80ca3a44f [PATCH] md: unify... |
2605 |
__ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store); |
4dbcdc751 [PATCH] md: count... |
2606 |
|
014236d2b [PATCH] md: expos... |
2607 |
static ssize_t |
3cb030020 md: removing type... |
2608 |
slot_show(struct md_rdev *rdev, char *page) |
014236d2b [PATCH] md: expos... |
2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 |
{ if (rdev->raid_disk < 0) return sprintf(page, "none "); else return sprintf(page, "%d ", rdev->raid_disk); } static ssize_t |
3cb030020 md: removing type... |
2619 |
slot_store(struct md_rdev *rdev, const char *buf, size_t len) |
014236d2b [PATCH] md: expos... |
2620 2621 |
{ char *e; |
c303da6d7 md: give userspac... |
2622 |
int err; |
014236d2b [PATCH] md: expos... |
2623 2624 2625 2626 2627 2628 |
int slot = simple_strtoul(buf, &e, 10); if (strncmp(buf, "none", 4)==0) slot = -1; else if (e==buf || (*e && *e!= ' ')) return -EINVAL; |
6c2fce2ef Support adding a ... |
2629 |
if (rdev->mddev->pers && slot == -1) { |
c303da6d7 md: give userspac... |
2630 2631 2632 2633 2634 2635 2636 |
/* Setting 'slot' on an active array requires also * updating the 'rd%d' link, and communicating * with the personality with ->hot_*_disk. * For now we only support removing * failed/spare devices. This normally happens automatically, * but not when the metadata is externally managed. */ |
c303da6d7 md: give userspac... |
2637 2638 2639 |
if (rdev->raid_disk == -1) return -EEXIST; /* personality does all needed checks */ |
01393f3d5 md: check ->hot_r... |
2640 |
if (rdev->mddev->pers->hot_remove_disk == NULL) |
c303da6d7 md: give userspac... |
2641 2642 2643 2644 2645 |
return -EINVAL; err = rdev->mddev->pers-> hot_remove_disk(rdev->mddev, rdev->raid_disk); if (err) return err; |
36fad858a md: introduce lin... |
2646 |
sysfs_unlink_rdev(rdev->mddev, rdev); |
b71031076 md: Correctly han... |
2647 |
rdev->raid_disk = -1; |
c303da6d7 md: give userspac... |
2648 2649 |
set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); md_wakeup_thread(rdev->mddev->thread); |
6c2fce2ef Support adding a ... |
2650 |
} else if (rdev->mddev->pers) { |
3cb030020 md: removing type... |
2651 |
struct md_rdev *rdev2; |
6c2fce2ef Support adding a ... |
2652 |
/* Activating a spare .. or possibly reactivating |
6d56e2784 md: allow setting... |
2653 |
* if we ever get bitmaps working here. |
6c2fce2ef Support adding a ... |
2654 2655 2656 2657 |
*/ if (rdev->raid_disk != -1) return -EBUSY; |
c6751b2bd md: Don't allow s... |
2658 2659 |
if (test_bit(MD_RECOVERY_RUNNING, &rdev->mddev->recovery)) return -EBUSY; |
6c2fce2ef Support adding a ... |
2660 2661 |
if (rdev->mddev->pers->hot_add_disk == NULL) return -EINVAL; |
159ec1fc0 md: use list_for_... |
2662 |
list_for_each_entry(rdev2, &rdev->mddev->disks, same_set) |
6c2fce2ef Support adding a ... |
2663 2664 |
if (rdev2->raid_disk == slot) return -EEXIST; |
ba1b41b6b md: range check s... |
2665 2666 2667 |
if (slot >= rdev->mddev->raid_disks && slot >= rdev->mddev->raid_disks + rdev->mddev->delta_disks) return -ENOSPC; |
6c2fce2ef Support adding a ... |
2668 2669 2670 2671 2672 |
rdev->raid_disk = slot; if (test_bit(In_sync, &rdev->flags)) rdev->saved_raid_disk = slot; else rdev->saved_raid_disk = -1; |
d30519fc5 md: clear In_sync... |
2673 |
clear_bit(In_sync, &rdev->flags); |
6c2fce2ef Support adding a ... |
2674 2675 |
err = rdev->mddev->pers-> hot_add_disk(rdev->mddev, rdev); |
199050ea1 rationalise retur... |
2676 |
if (err) { |
6c2fce2ef Support adding a ... |
2677 |
rdev->raid_disk = -1; |
6c2fce2ef Support adding a ... |
2678 |
return err; |
526647320 Make sure all cha... |
2679 |
} else |
00bcb4ac7 md: reduce depend... |
2680 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
36fad858a md: introduce lin... |
2681 |
if (sysfs_link_rdev(rdev->mddev, rdev)) |
00bcb4ac7 md: reduce depend... |
2682 |
/* failure here is OK */; |
6c2fce2ef Support adding a ... |
2683 |
/* don't wakeup anyone, leave that to userspace. */ |
c303da6d7 md: give userspac... |
2684 |
} else { |
ba1b41b6b md: range check s... |
2685 2686 |
if (slot >= rdev->mddev->raid_disks && slot >= rdev->mddev->raid_disks + rdev->mddev->delta_disks) |
c303da6d7 md: give userspac... |
2687 2688 2689 |
return -ENOSPC; rdev->raid_disk = slot; /* assume it is working */ |
c5d79adba md: allow devices... |
2690 2691 |
clear_bit(Faulty, &rdev->flags); clear_bit(WriteMostly, &rdev->flags); |
c303da6d7 md: give userspac... |
2692 |
set_bit(In_sync, &rdev->flags); |
00bcb4ac7 md: reduce depend... |
2693 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
c303da6d7 md: give userspac... |
2694 |
} |
014236d2b [PATCH] md: expos... |
2695 2696 2697 2698 2699 |
return len; } static struct rdev_sysfs_entry rdev_slot = |
80ca3a44f [PATCH] md: unify... |
2700 |
__ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store); |
014236d2b [PATCH] md: expos... |
2701 |
|
93c8cad03 [PATCH] md: expor... |
2702 |
static ssize_t |
3cb030020 md: removing type... |
2703 |
offset_show(struct md_rdev *rdev, char *page) |
93c8cad03 [PATCH] md: expor... |
2704 |
{ |
6961ece46 [PATCH] md-export... |
2705 2706 |
return sprintf(page, "%llu ", (unsigned long long)rdev->data_offset); |
93c8cad03 [PATCH] md: expor... |
2707 2708 2709 |
} static ssize_t |
3cb030020 md: removing type... |
2710 |
offset_store(struct md_rdev *rdev, const char *buf, size_t len) |
93c8cad03 [PATCH] md: expor... |
2711 2712 2713 2714 2715 2716 |
{ char *e; unsigned long long offset = simple_strtoull(buf, &e, 10); if (e==buf || (*e && *e != ' ')) return -EINVAL; |
8ed0a5216 Enable setting of... |
2717 |
if (rdev->mddev->pers && rdev->raid_disk >= 0) |
93c8cad03 [PATCH] md: expor... |
2718 |
return -EBUSY; |
dd8ac336c md: Represent rai... |
2719 |
if (rdev->sectors && rdev->mddev->external) |
c5d79adba md: allow devices... |
2720 2721 2722 |
/* Must set offset before size, so overlap checks * can be sane */ return -EBUSY; |
93c8cad03 [PATCH] md: expor... |
2723 2724 2725 2726 2727 |
rdev->data_offset = offset; return len; } static struct rdev_sysfs_entry rdev_offset = |
80ca3a44f [PATCH] md: unify... |
2728 |
__ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store); |
93c8cad03 [PATCH] md: expor... |
2729 |
|
83303b613 [PATCH] md: allow... |
2730 |
static ssize_t |
3cb030020 md: removing type... |
2731 |
rdev_size_show(struct md_rdev *rdev, char *page) |
83303b613 [PATCH] md: allow... |
2732 |
{ |
dd8ac336c md: Represent rai... |
2733 2734 |
return sprintf(page, "%llu ", (unsigned long long)rdev->sectors / 2); |
83303b613 [PATCH] md: allow... |
2735 |
} |
c5d79adba md: allow devices... |
2736 2737 2738 2739 2740 2741 2742 2743 2744 |
static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2) { /* check if two start/length pairs overlap */ if (s1+l1 <= s2) return 0; if (s2+l2 <= s1) return 0; return 1; } |
b522adcde md: 'array_size' ... |
2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 |
static int strict_blocks_to_sectors(const char *buf, sector_t *sectors) { unsigned long long blocks; sector_t new; if (strict_strtoull(buf, 10, &blocks) < 0) return -EINVAL; if (blocks & 1ULL << (8 * sizeof(blocks) - 1)) return -EINVAL; /* sector conversion overflow */ new = blocks * 2; if (new != blocks * 2) return -EINVAL; /* unsigned long long to sector_t overflow */ *sectors = new; return 0; } |
83303b613 [PATCH] md: allow... |
2763 |
static ssize_t |
3cb030020 md: removing type... |
2764 |
rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) |
83303b613 [PATCH] md: allow... |
2765 |
{ |
fd01b88c7 md: remove typede... |
2766 |
struct mddev *my_mddev = rdev->mddev; |
dd8ac336c md: Represent rai... |
2767 |
sector_t oldsectors = rdev->sectors; |
b522adcde md: 'array_size' ... |
2768 |
sector_t sectors; |
27c529bb8 md: lock access t... |
2769 |
|
b522adcde md: 'array_size' ... |
2770 |
if (strict_blocks_to_sectors(buf, §ors) < 0) |
d7027458d md: Tidy up rdev_... |
2771 |
return -EINVAL; |
0cd17fec9 Support changing ... |
2772 |
if (my_mddev->pers && rdev->raid_disk >= 0) { |
d7027458d md: Tidy up rdev_... |
2773 |
if (my_mddev->persistent) { |
dd8ac336c md: Represent rai... |
2774 2775 2776 |
sectors = super_types[my_mddev->major_version]. rdev_size_change(rdev, sectors); if (!sectors) |
0cd17fec9 Support changing ... |
2777 |
return -EBUSY; |
dd8ac336c md: Represent rai... |
2778 |
} else if (!sectors) |
77304d2ab block: read i_siz... |
2779 |
sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - |
dd8ac336c md: Represent rai... |
2780 |
rdev->data_offset; |
0cd17fec9 Support changing ... |
2781 |
} |
dd8ac336c md: Represent rai... |
2782 |
if (sectors < my_mddev->dev_sectors) |
7d3c6f871 md: Fix rdev_size... |
2783 |
return -EINVAL; /* component must fit device */ |
0cd17fec9 Support changing ... |
2784 |
|
dd8ac336c md: Represent rai... |
2785 2786 |
rdev->sectors = sectors; if (sectors > oldsectors && my_mddev->external) { |
c5d79adba md: allow devices... |
2787 2788 |
/* need to check that all other rdevs with the same ->bdev * do not overlap. We need to unlock the mddev to avoid |
dd8ac336c md: Represent rai... |
2789 |
* a deadlock. We have already changed rdev->sectors, and if |
c5d79adba md: allow devices... |
2790 2791 |
* we have to change it back, we will have the lock again. */ |
fd01b88c7 md: remove typede... |
2792 |
struct mddev *mddev; |
c5d79adba md: allow devices... |
2793 |
int overlap = 0; |
159ec1fc0 md: use list_for_... |
2794 |
struct list_head *tmp; |
c5d79adba md: allow devices... |
2795 |
|
27c529bb8 md: lock access t... |
2796 |
mddev_unlock(my_mddev); |
29ac4aa3f md: change INTERA... |
2797 |
for_each_mddev(mddev, tmp) { |
3cb030020 md: removing type... |
2798 |
struct md_rdev *rdev2; |
c5d79adba md: allow devices... |
2799 2800 |
mddev_lock(mddev); |
159ec1fc0 md: use list_for_... |
2801 |
list_for_each_entry(rdev2, &mddev->disks, same_set) |
f21e9ff7f md: Remove the Al... |
2802 2803 2804 2805 2806 |
if (rdev->bdev == rdev2->bdev && rdev != rdev2 && overlaps(rdev->data_offset, rdev->sectors, rdev2->data_offset, rdev2->sectors)) { |
c5d79adba md: allow devices... |
2807 2808 2809 2810 2811 2812 2813 2814 2815 |
overlap = 1; break; } mddev_unlock(mddev); if (overlap) { mddev_put(mddev); break; } } |
27c529bb8 md: lock access t... |
2816 |
mddev_lock(my_mddev); |
c5d79adba md: allow devices... |
2817 2818 2819 |
if (overlap) { /* Someone else could have slipped in a size * change here, but doing so is just silly. |
dd8ac336c md: Represent rai... |
2820 |
* We put oldsectors back because we *know* it is |
c5d79adba md: allow devices... |
2821 2822 2823 |
* safe, and trust userspace not to race with * itself */ |
dd8ac336c md: Represent rai... |
2824 |
rdev->sectors = oldsectors; |
c5d79adba md: allow devices... |
2825 2826 2827 |
return -EBUSY; } } |
83303b613 [PATCH] md: allow... |
2828 2829 2830 2831 |
return len; } static struct rdev_sysfs_entry rdev_size = |
80ca3a44f [PATCH] md: unify... |
2832 |
__ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store); |
83303b613 [PATCH] md: allow... |
2833 |
|
06e3c817b md: add 'recovery... |
2834 |
|
3cb030020 md: removing type... |
2835 |
static ssize_t recovery_start_show(struct md_rdev *rdev, char *page) |
06e3c817b md: add 'recovery... |
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 |
{ unsigned long long recovery_start = rdev->recovery_offset; if (test_bit(In_sync, &rdev->flags) || recovery_start == MaxSector) return sprintf(page, "none "); return sprintf(page, "%llu ", recovery_start); } |
3cb030020 md: removing type... |
2847 |
static ssize_t recovery_start_store(struct md_rdev *rdev, const char *buf, size_t len) |
06e3c817b md: add 'recovery... |
2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 |
{ unsigned long long recovery_start; if (cmd_match(buf, "none")) recovery_start = MaxSector; else if (strict_strtoull(buf, 10, &recovery_start)) return -EINVAL; if (rdev->mddev->pers && rdev->raid_disk >= 0) return -EBUSY; rdev->recovery_offset = recovery_start; if (recovery_start == MaxSector) set_bit(In_sync, &rdev->flags); else clear_bit(In_sync, &rdev->flags); return len; } static struct rdev_sysfs_entry rdev_recovery_start = __ATTR(recovery_start, S_IRUGO|S_IWUSR, recovery_start_show, recovery_start_store); |
16c791a5a md/bad-block-log:... |
2870 2871 2872 2873 2874 |
static ssize_t badblocks_show(struct badblocks *bb, char *page, int unack); static ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack); |
3cb030020 md: removing type... |
2875 |
static ssize_t bb_show(struct md_rdev *rdev, char *page) |
16c791a5a md/bad-block-log:... |
2876 2877 2878 |
{ return badblocks_show(&rdev->badblocks, page, 0); } |
3cb030020 md: removing type... |
2879 |
static ssize_t bb_store(struct md_rdev *rdev, const char *page, size_t len) |
16c791a5a md/bad-block-log:... |
2880 |
{ |
de393cdea md: make it easie... |
2881 2882 2883 2884 2885 |
int rv = badblocks_store(&rdev->badblocks, page, len, 0); /* Maybe that ack was all we needed */ if (test_and_clear_bit(BlockedBadBlocks, &rdev->flags)) wake_up(&rdev->blocked_wait); return rv; |
16c791a5a md/bad-block-log:... |
2886 2887 2888 |
} static struct rdev_sysfs_entry rdev_bad_blocks = __ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store); |
3cb030020 md: removing type... |
2889 |
static ssize_t ubb_show(struct md_rdev *rdev, char *page) |
16c791a5a md/bad-block-log:... |
2890 2891 2892 |
{ return badblocks_show(&rdev->badblocks, page, 1); } |
3cb030020 md: removing type... |
2893 |
static ssize_t ubb_store(struct md_rdev *rdev, const char *page, size_t len) |
16c791a5a md/bad-block-log:... |
2894 2895 2896 2897 2898 |
{ return badblocks_store(&rdev->badblocks, page, len, 1); } static struct rdev_sysfs_entry rdev_unack_bad_blocks = __ATTR(unacknowledged_bad_blocks, S_IRUGO|S_IWUSR, ubb_show, ubb_store); |
86e6ffdd2 [PATCH] md: exten... |
2899 2900 |
static struct attribute *rdev_default_attrs[] = { &rdev_state.attr, |
4dbcdc751 [PATCH] md: count... |
2901 |
&rdev_errors.attr, |
014236d2b [PATCH] md: expos... |
2902 |
&rdev_slot.attr, |
93c8cad03 [PATCH] md: expor... |
2903 |
&rdev_offset.attr, |
83303b613 [PATCH] md: allow... |
2904 |
&rdev_size.attr, |
06e3c817b md: add 'recovery... |
2905 |
&rdev_recovery_start.attr, |
16c791a5a md/bad-block-log:... |
2906 2907 |
&rdev_bad_blocks.attr, &rdev_unack_bad_blocks.attr, |
86e6ffdd2 [PATCH] md: exten... |
2908 2909 2910 2911 2912 2913 |
NULL, }; static ssize_t rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page) { struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); |
3cb030020 md: removing type... |
2914 |
struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj); |
fd01b88c7 md: remove typede... |
2915 |
struct mddev *mddev = rdev->mddev; |
27c529bb8 md: lock access t... |
2916 |
ssize_t rv; |
86e6ffdd2 [PATCH] md: exten... |
2917 2918 2919 |
if (!entry->show) return -EIO; |
27c529bb8 md: lock access t... |
2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 |
rv = mddev ? mddev_lock(mddev) : -EBUSY; if (!rv) { if (rdev->mddev == NULL) rv = -EBUSY; else rv = entry->show(rdev, page); mddev_unlock(mddev); } return rv; |
86e6ffdd2 [PATCH] md: exten... |
2930 2931 2932 2933 2934 2935 2936 |
} static ssize_t rdev_attr_store(struct kobject *kobj, struct attribute *attr, const char *page, size_t length) { struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); |
3cb030020 md: removing type... |
2937 |
struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj); |
27c529bb8 md: lock access t... |
2938 |
ssize_t rv; |
fd01b88c7 md: remove typede... |
2939 |
struct mddev *mddev = rdev->mddev; |
86e6ffdd2 [PATCH] md: exten... |
2940 2941 2942 |
if (!entry->store) return -EIO; |
67463acb6 [PATCH] md: requi... |
2943 2944 |
if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
27c529bb8 md: lock access t... |
2945 |
rv = mddev ? mddev_lock(mddev): -EBUSY; |
ca3880594 md: lock address ... |
2946 |
if (!rv) { |
27c529bb8 md: lock access t... |
2947 2948 2949 2950 |
if (rdev->mddev == NULL) rv = -EBUSY; else rv = entry->store(rdev, page, length); |
6a51830e1 md: fix use after... |
2951 |
mddev_unlock(mddev); |
ca3880594 md: lock address ... |
2952 2953 |
} return rv; |
86e6ffdd2 [PATCH] md: exten... |
2954 2955 2956 2957 |
} static void rdev_free(struct kobject *ko) { |
3cb030020 md: removing type... |
2958 |
struct md_rdev *rdev = container_of(ko, struct md_rdev, kobj); |
86e6ffdd2 [PATCH] md: exten... |
2959 2960 |
kfree(rdev); } |
52cf25d0a Driver core: Cons... |
2961 |
static const struct sysfs_ops rdev_sysfs_ops = { |
86e6ffdd2 [PATCH] md: exten... |
2962 2963 2964 2965 2966 2967 2968 2969 |
.show = rdev_attr_show, .store = rdev_attr_store, }; static struct kobj_type rdev_ktype = { .release = rdev_free, .sysfs_ops = &rdev_sysfs_ops, .default_attrs = rdev_default_attrs, }; |
3cb030020 md: removing type... |
2970 |
int md_rdev_init(struct md_rdev *rdev) |
e8bb9a839 md: split out md_... |
2971 2972 2973 2974 2975 2976 2977 2978 2979 |
{ rdev->desc_nr = -1; rdev->saved_raid_disk = -1; rdev->raid_disk = -1; rdev->flags = 0; rdev->data_offset = 0; rdev->sb_events = 0; rdev->last_read_error.tv_sec = 0; rdev->last_read_error.tv_nsec = 0; |
2699b6722 md: load/store ba... |
2980 2981 |
rdev->sb_loaded = 0; rdev->bb_page = NULL; |
e8bb9a839 md: split out md_... |
2982 2983 2984 2985 2986 2987 |
atomic_set(&rdev->nr_pending, 0); atomic_set(&rdev->read_errors, 0); atomic_set(&rdev->corrected_errors, 0); INIT_LIST_HEAD(&rdev->same_set); init_waitqueue_head(&rdev->blocked_wait); |
2230dfe4c md: beginnings of... |
2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 |
/* Add space to store bad block list. * This reserves the space even on arrays where it cannot * be used - I wonder if that matters */ rdev->badblocks.count = 0; rdev->badblocks.shift = 0; rdev->badblocks.page = kmalloc(PAGE_SIZE, GFP_KERNEL); seqlock_init(&rdev->badblocks.lock); if (rdev->badblocks.page == NULL) return -ENOMEM; return 0; |
e8bb9a839 md: split out md_... |
3001 3002 |
} EXPORT_SYMBOL_GPL(md_rdev_init); |
1da177e4c Linux-2.6.12-rc2 |
3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 |
/* * Import a device. If 'super_format' >= 0, then sanity check the superblock * * mark the device faulty if: * * - the device is nonexistent (zero size) * - the device has no valid superblock * * a faulty rdev _never_ has rdev->sb set. */ |
3cb030020 md: removing type... |
3013 |
static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor) |
1da177e4c Linux-2.6.12-rc2 |
3014 3015 3016 |
{ char b[BDEVNAME_SIZE]; int err; |
3cb030020 md: removing type... |
3017 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
3018 |
sector_t size; |
9ffae0cf3 [PATCH] md: conve... |
3019 |
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
3020 3021 3022 3023 3024 |
if (!rdev) { printk(KERN_ERR "md: could not alloc mem for new device! "); return ERR_PTR(-ENOMEM); } |
1da177e4c Linux-2.6.12-rc2 |
3025 |
|
2230dfe4c md: beginnings of... |
3026 3027 3028 3029 3030 |
err = md_rdev_init(rdev); if (err) goto abort_free; err = alloc_disk_sb(rdev); if (err) |
1da177e4c Linux-2.6.12-rc2 |
3031 |
goto abort_free; |
c5d79adba md: allow devices... |
3032 |
err = lock_rdev(rdev, newdev, super_format == -2); |
1da177e4c Linux-2.6.12-rc2 |
3033 3034 |
if (err) goto abort_free; |
f9cb074bf Kobject: rename k... |
3035 |
kobject_init(&rdev->kobj, &rdev_ktype); |
86e6ffdd2 [PATCH] md: exten... |
3036 |
|
77304d2ab block: read i_siz... |
3037 |
size = i_size_read(rdev->bdev->bd_inode) >> BLOCK_SIZE_BITS; |
1da177e4c Linux-2.6.12-rc2 |
3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 |
if (!size) { printk(KERN_WARNING "md: %s has zero or unknown size, marking faulty! ", bdevname(rdev->bdev,b)); err = -EINVAL; goto abort_free; } if (super_format >= 0) { err = super_types[super_format]. load_super(rdev, NULL, super_minor); if (err == -EINVAL) { |
df968c4e8 md: improve messa... |
3051 3052 3053 3054 3055 3056 |
printk(KERN_WARNING "md: %s does not have a valid v%d.%d " "superblock, not importing! ", bdevname(rdev->bdev,b), super_format, super_minor); |
1da177e4c Linux-2.6.12-rc2 |
3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 |
goto abort_free; } if (err < 0) { printk(KERN_WARNING "md: could not read %s's sb, not importing! ", bdevname(rdev->bdev,b)); goto abort_free; } } |
9f2f38307 md: Disable bad b... |
3067 3068 3069 |
if (super_format == -1) /* hot-add for 0.90, or non-persistent: so no badblocks */ rdev->badblocks.shift = -1; |
6bfe0b499 md: support block... |
3070 |
|
1da177e4c Linux-2.6.12-rc2 |
3071 3072 3073 |
return rdev; abort_free: |
2699b6722 md: load/store ba... |
3074 3075 3076 |
if (rdev->bdev) unlock_rdev(rdev); free_disk_sb(rdev); |
2230dfe4c md: beginnings of... |
3077 |
kfree(rdev->badblocks.page); |
1da177e4c Linux-2.6.12-rc2 |
3078 3079 3080 3081 3082 3083 3084 |
kfree(rdev); return ERR_PTR(err); } /* * Check a full RAID array for plausibility */ |
fd01b88c7 md: remove typede... |
3085 |
static void analyze_sbs(struct mddev * mddev) |
1da177e4c Linux-2.6.12-rc2 |
3086 3087 |
{ int i; |
3cb030020 md: removing type... |
3088 |
struct md_rdev *rdev, *freshest, *tmp; |
1da177e4c Linux-2.6.12-rc2 |
3089 3090 3091 |
char b[BDEVNAME_SIZE]; freshest = NULL; |
d089c6af1 md: change ITERAT... |
3092 |
rdev_for_each(rdev, tmp, mddev) |
1da177e4c Linux-2.6.12-rc2 |
3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 |
switch (super_types[mddev->major_version]. load_super(rdev, freshest, mddev->minor_version)) { case 1: freshest = rdev; break; case 0: break; default: printk( KERN_ERR \ "md: fatal superblock inconsistency in %s" " -- removing from array ", bdevname(rdev->bdev,b)); kick_rdev_from_array(rdev); } super_types[mddev->major_version]. validate_super(mddev, freshest); i = 0; |
d089c6af1 md: change ITERAT... |
3114 |
rdev_for_each(rdev, tmp, mddev) { |
233fca36b md: Relax checks ... |
3115 3116 3117 |
if (mddev->max_disks && (rdev->desc_nr >= mddev->max_disks || i > mddev->max_disks)) { |
de01dfadf md: Ensure an md ... |
3118 3119 3120 3121 3122 3123 3124 3125 |
printk(KERN_WARNING "md: %s: %s: only %d devices permitted ", mdname(mddev), bdevname(rdev->bdev, b), mddev->max_disks); kick_rdev_from_array(rdev); continue; } |
1da177e4c Linux-2.6.12-rc2 |
3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 |
if (rdev != freshest) if (super_types[mddev->major_version]. validate_super(mddev, rdev)) { printk(KERN_WARNING "md: kicking non-fresh %s" " from array! ", bdevname(rdev->bdev,b)); kick_rdev_from_array(rdev); continue; } if (mddev->level == LEVEL_MULTIPATH) { rdev->desc_nr = i++; rdev->raid_disk = rdev->desc_nr; |
b2d444d7a [PATCH] md: conve... |
3139 |
set_bit(In_sync, &rdev->flags); |
5e5e3e78e md: Fix handling ... |
3140 |
} else if (rdev->raid_disk >= (mddev->raid_disks - min(0, mddev->delta_disks))) { |
a778b73ff md: fix bug with ... |
3141 3142 |
rdev->raid_disk = -1; clear_bit(In_sync, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
3143 3144 |
} } |
1da177e4c Linux-2.6.12-rc2 |
3145 |
} |
72e02075a md: factor out pa... |
3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 |
/* Read a fixed-point number. * Numbers in sysfs attributes should be in "standard" units where * possible, so time should be in seconds. * However we internally use a a much smaller unit such as * milliseconds or jiffies. * This function takes a decimal number with a possible fractional * component, and produces an integer which is the result of * multiplying that number by 10^'scale'. * all without any floating-point arithmetic. */ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) { unsigned long result = 0; long decimals = -1; while (isdigit(*cp) || (*cp == '.' && decimals < 0)) { if (*cp == '.') decimals = 0; else if (decimals < scale) { unsigned int value; value = *cp - '0'; result = result * 10 + value; if (decimals >= 0) decimals++; } cp++; } if (*cp == ' ') cp++; if (*cp) return -EINVAL; if (decimals < 0) decimals = 0; while (decimals < scale) { result *= 10; decimals ++; } *res = result; return 0; } |
19052c0e8 Make writes to md... |
3186 |
static void md_safemode_timeout(unsigned long data); |
eae1701fb [PATCH] md: initi... |
3187 |
static ssize_t |
fd01b88c7 md: remove typede... |
3188 |
safe_delay_show(struct mddev *mddev, char *page) |
16f17b39f [PATCH] md: incre... |
3189 3190 3191 3192 3193 3194 |
{ int msec = (mddev->safemode_delay*1000)/HZ; return sprintf(page, "%d.%03d ", msec/1000, msec%1000); } static ssize_t |
fd01b88c7 md: remove typede... |
3195 |
safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) |
16f17b39f [PATCH] md: incre... |
3196 |
{ |
16f17b39f [PATCH] md: incre... |
3197 |
unsigned long msec; |
97ce0a7f9 md: fix input tru... |
3198 |
|
72e02075a md: factor out pa... |
3199 |
if (strict_strtoul_scaled(cbuf, &msec, 3) < 0) |
16f17b39f [PATCH] md: incre... |
3200 |
return -EINVAL; |
16f17b39f [PATCH] md: incre... |
3201 3202 3203 |
if (msec == 0) mddev->safemode_delay = 0; else { |
19052c0e8 Make writes to md... |
3204 |
unsigned long old_delay = mddev->safemode_delay; |
16f17b39f [PATCH] md: incre... |
3205 3206 3207 |
mddev->safemode_delay = (msec*HZ)/1000; if (mddev->safemode_delay == 0) mddev->safemode_delay = 1; |
19052c0e8 Make writes to md... |
3208 3209 |
if (mddev->safemode_delay < old_delay) md_safemode_timeout((unsigned long)mddev); |
16f17b39f [PATCH] md: incre... |
3210 3211 3212 3213 |
} return len; } static struct md_sysfs_entry md_safe_delay = |
80ca3a44f [PATCH] md: unify... |
3214 |
__ATTR(safe_mode_delay, S_IRUGO|S_IWUSR,safe_delay_show, safe_delay_store); |
16f17b39f [PATCH] md: incre... |
3215 3216 |
static ssize_t |
fd01b88c7 md: remove typede... |
3217 |
level_show(struct mddev *mddev, char *page) |
eae1701fb [PATCH] md: initi... |
3218 |
{ |
84fc4b56d md: rename "mdk_p... |
3219 |
struct md_personality *p = mddev->pers; |
d9d166c2a [PATCH] md: allow... |
3220 |
if (p) |
eae1701fb [PATCH] md: initi... |
3221 3222 |
return sprintf(page, "%s ", p->name); |
d9d166c2a [PATCH] md: allow... |
3223 3224 3225 3226 3227 3228 3229 3230 |
else if (mddev->clevel[0]) return sprintf(page, "%s ", mddev->clevel); else if (mddev->level != LEVEL_NONE) return sprintf(page, "%d ", mddev->level); else return 0; |
eae1701fb [PATCH] md: initi... |
3231 |
} |
d9d166c2a [PATCH] md: allow... |
3232 |
static ssize_t |
fd01b88c7 md: remove typede... |
3233 |
level_store(struct mddev *mddev, const char *buf, size_t len) |
d9d166c2a [PATCH] md: allow... |
3234 |
{ |
f2859af67 md: allow integer... |
3235 |
char clevel[16]; |
20a49ff67 md: change a few ... |
3236 |
ssize_t rv = len; |
84fc4b56d md: rename "mdk_p... |
3237 |
struct md_personality *pers; |
f2859af67 md: allow integer... |
3238 |
long level; |
245f46c2c md: add ->takeove... |
3239 |
void *priv; |
3cb030020 md: removing type... |
3240 |
struct md_rdev *rdev; |
245f46c2c md: add ->takeove... |
3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 |
if (mddev->pers == NULL) { if (len == 0) return 0; if (len >= sizeof(mddev->clevel)) return -ENOSPC; strncpy(mddev->clevel, buf, len); if (mddev->clevel[len-1] == ' ') len--; mddev->clevel[len] = 0; mddev->level = LEVEL_NONE; return rv; } /* request to change the personality. Need to ensure: * - array is not engaged in resync/recovery/reshape * - old personality can be suspended * - new personality will access other array. */ |
bb4f1e9d0 md: fix another d... |
3261 3262 3263 |
if (mddev->sync_thread || mddev->reshape_position != MaxSector || mddev->sysfs_active) |
d9d166c2a [PATCH] md: allow... |
3264 |
return -EBUSY; |
245f46c2c md: add ->takeove... |
3265 3266 3267 3268 3269 3270 3271 3272 3273 |
if (!mddev->pers->quiesce) { printk(KERN_WARNING "md: %s: %s does not support online personality change ", mdname(mddev), mddev->pers->name); return -EINVAL; } /* Now find the new personality */ |
f2859af67 md: allow integer... |
3274 |
if (len == 0 || len >= sizeof(clevel)) |
245f46c2c md: add ->takeove... |
3275 |
return -EINVAL; |
f2859af67 md: allow integer... |
3276 3277 3278 |
strncpy(clevel, buf, len); if (clevel[len-1] == ' ') |
d9d166c2a [PATCH] md: allow... |
3279 |
len--; |
f2859af67 md: allow integer... |
3280 3281 3282 |
clevel[len] = 0; if (strict_strtol(clevel, 10, &level)) level = LEVEL_NONE; |
245f46c2c md: add ->takeove... |
3283 |
|
f2859af67 md: allow integer... |
3284 3285 |
if (request_module("md-%s", clevel) != 0) request_module("md-level-%s", clevel); |
245f46c2c md: add ->takeove... |
3286 |
spin_lock(&pers_lock); |
f2859af67 md: allow integer... |
3287 |
pers = find_pers(level, clevel); |
245f46c2c md: add ->takeove... |
3288 3289 |
if (!pers || !try_module_get(pers->owner)) { spin_unlock(&pers_lock); |
f2859af67 md: allow integer... |
3290 3291 |
printk(KERN_WARNING "md: personality %s not loaded ", clevel); |
245f46c2c md: add ->takeove... |
3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 |
return -EINVAL; } spin_unlock(&pers_lock); if (pers == mddev->pers) { /* Nothing to do! */ module_put(pers->owner); return rv; } if (!pers->takeover) { module_put(pers->owner); printk(KERN_WARNING "md: %s: %s does not support personality takeover ", |
f2859af67 md: allow integer... |
3305 |
mdname(mddev), clevel); |
245f46c2c md: add ->takeove... |
3306 3307 |
return -EINVAL; } |
e93f68a1f md: fix handling ... |
3308 3309 |
list_for_each_entry(rdev, &mddev->disks, same_set) rdev->new_raid_disk = rdev->raid_disk; |
245f46c2c md: add ->takeove... |
3310 3311 3312 3313 3314 3315 3316 |
/* ->takeover must set new_* and/or delta_disks * if it succeeds, and may set them when it fails. */ priv = pers->takeover(mddev); if (IS_ERR(priv)) { mddev->new_level = mddev->level; mddev->new_layout = mddev->layout; |
664e7c413 md: Convert mddev... |
3317 |
mddev->new_chunk_sectors = mddev->chunk_sectors; |
245f46c2c md: add ->takeove... |
3318 3319 3320 3321 3322 |
mddev->raid_disks -= mddev->delta_disks; mddev->delta_disks = 0; module_put(pers->owner); printk(KERN_WARNING "md: %s: %s would not accept array ", |
f2859af67 md: allow integer... |
3323 |
mdname(mddev), clevel); |
245f46c2c md: add ->takeove... |
3324 3325 3326 3327 3328 3329 |
return PTR_ERR(priv); } /* Looks like we have a winner */ mddev_suspend(mddev); mddev->pers->stop(mddev); |
a64c876fd md: manage redund... |
3330 3331 3332 3333 3334 3335 3336 3337 3338 |
if (mddev->pers->sync_request == NULL && pers->sync_request != NULL) { /* need to add the md_redundancy_group */ if (sysfs_create_group(&mddev->kobj, &md_redundancy_group)) printk(KERN_WARNING "md: cannot register extra attributes for %s ", mdname(mddev)); |
19fdb9eef Merge commit '3ff... |
3339 |
mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, NULL, "sync_action"); |
a64c876fd md: manage redund... |
3340 3341 3342 3343 3344 3345 3346 |
} if (mddev->pers->sync_request != NULL && pers->sync_request == NULL) { /* need to remove the md_redundancy_group */ if (mddev->to_remove == NULL) mddev->to_remove = &md_redundancy_group; } |
54071b380 md:Add support fo... |
3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 |
if (mddev->pers->sync_request == NULL && mddev->external) { /* We are converting from a no-redundancy array * to a redundancy array and metadata is managed * externally so we need to be sure that writes * won't block due to a need to transition * clean->dirty * until external management is started. */ mddev->in_sync = 0; mddev->safemode_delay = 0; mddev->safemode = 0; } |
e93f68a1f md: fix handling ... |
3360 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
e93f68a1f md: fix handling ... |
3361 3362 |
if (rdev->raid_disk < 0) continue; |
bf2cb0dab md: Fix removal o... |
3363 |
if (rdev->new_raid_disk >= mddev->raid_disks) |
e93f68a1f md: fix handling ... |
3364 3365 3366 |
rdev->new_raid_disk = -1; if (rdev->new_raid_disk == rdev->raid_disk) continue; |
36fad858a md: introduce lin... |
3367 |
sysfs_unlink_rdev(mddev, rdev); |
e93f68a1f md: fix handling ... |
3368 3369 3370 3371 3372 3373 3374 3375 |
} list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk < 0) continue; if (rdev->new_raid_disk == rdev->raid_disk) continue; rdev->raid_disk = rdev->new_raid_disk; if (rdev->raid_disk < 0) |
3a981b03f md: when a level ... |
3376 |
clear_bit(In_sync, &rdev->flags); |
e93f68a1f md: fix handling ... |
3377 |
else { |
36fad858a md: introduce lin... |
3378 3379 3380 3381 3382 |
if (sysfs_link_rdev(mddev, rdev)) printk(KERN_WARNING "md: cannot register rd%d" " for %s after level change ", rdev->raid_disk, mdname(mddev)); |
3a981b03f md: when a level ... |
3383 |
} |
e93f68a1f md: fix handling ... |
3384 3385 3386 |
} module_put(mddev->pers->owner); |
245f46c2c md: add ->takeove... |
3387 3388 3389 3390 3391 |
mddev->pers = pers; mddev->private = priv; strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); mddev->level = mddev->new_level; mddev->layout = mddev->new_layout; |
664e7c413 md: Convert mddev... |
3392 |
mddev->chunk_sectors = mddev->new_chunk_sectors; |
245f46c2c md: add ->takeove... |
3393 |
mddev->delta_disks = 0; |
fee68723c md: Cleanup after... |
3394 |
mddev->degraded = 0; |
9af204cf7 md: Add support f... |
3395 3396 3397 3398 3399 3400 3401 |
if (mddev->pers->sync_request == NULL) { /* this is now an array without redundancy, so * it must always be in_sync */ mddev->in_sync = 1; del_timer_sync(&mddev->safemode_timer); } |
245f46c2c md: add ->takeove... |
3402 3403 3404 3405 3406 |
pers->run(mddev); mddev_resume(mddev); set_bit(MD_CHANGE_DEVS, &mddev->flags); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); |
5cac7861b md: notify level ... |
3407 |
sysfs_notify(&mddev->kobj, NULL, "level"); |
bb7f8d221 md: notify mdstat... |
3408 |
md_new_event(mddev); |
d9d166c2a [PATCH] md: allow... |
3409 3410 3411 3412 |
return rv; } static struct md_sysfs_entry md_level = |
80ca3a44f [PATCH] md: unify... |
3413 |
__ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store); |
eae1701fb [PATCH] md: initi... |
3414 |
|
d4dbd0250 [PATCH] md: Allow... |
3415 3416 |
static ssize_t |
fd01b88c7 md: remove typede... |
3417 |
layout_show(struct mddev *mddev, char *page) |
d4dbd0250 [PATCH] md: Allow... |
3418 3419 |
{ /* just a number, not meaningful for all levels */ |
08a02ecd2 md: allow reshape... |
3420 3421 3422 3423 3424 |
if (mddev->reshape_position != MaxSector && mddev->layout != mddev->new_layout) return sprintf(page, "%d (%d) ", mddev->new_layout, mddev->layout); |
d4dbd0250 [PATCH] md: Allow... |
3425 3426 3427 3428 3429 |
return sprintf(page, "%d ", mddev->layout); } static ssize_t |
fd01b88c7 md: remove typede... |
3430 |
layout_store(struct mddev *mddev, const char *buf, size_t len) |
d4dbd0250 [PATCH] md: Allow... |
3431 3432 3433 |
{ char *e; unsigned long n = simple_strtoul(buf, &e, 10); |
d4dbd0250 [PATCH] md: Allow... |
3434 3435 3436 3437 |
if (!*buf || (*e && *e != ' ')) return -EINVAL; |
b35460352 md/raid5: allow l... |
3438 3439 |
if (mddev->pers) { int err; |
50ac168a6 md: merge reconfi... |
3440 |
if (mddev->pers->check_reshape == NULL) |
b35460352 md/raid5: allow l... |
3441 |
return -EBUSY; |
597a711b6 md: remove unnece... |
3442 |
mddev->new_layout = n; |
50ac168a6 md: merge reconfi... |
3443 |
err = mddev->pers->check_reshape(mddev); |
597a711b6 md: remove unnece... |
3444 3445 |
if (err) { mddev->new_layout = mddev->layout; |
b35460352 md/raid5: allow l... |
3446 |
return err; |
597a711b6 md: remove unnece... |
3447 |
} |
b35460352 md/raid5: allow l... |
3448 |
} else { |
08a02ecd2 md: allow reshape... |
3449 |
mddev->new_layout = n; |
b35460352 md/raid5: allow l... |
3450 3451 3452 |
if (mddev->reshape_position == MaxSector) mddev->layout = n; } |
d4dbd0250 [PATCH] md: Allow... |
3453 3454 3455 |
return len; } static struct md_sysfs_entry md_layout = |
80ca3a44f [PATCH] md: unify... |
3456 |
__ATTR(layout, S_IRUGO|S_IWUSR, layout_show, layout_store); |
d4dbd0250 [PATCH] md: Allow... |
3457 |
|
eae1701fb [PATCH] md: initi... |
3458 |
static ssize_t |
fd01b88c7 md: remove typede... |
3459 |
raid_disks_show(struct mddev *mddev, char *page) |
eae1701fb [PATCH] md: initi... |
3460 |
{ |
bb636547b [PATCH] md: docum... |
3461 3462 |
if (mddev->raid_disks == 0) return 0; |
08a02ecd2 md: allow reshape... |
3463 3464 3465 3466 3467 |
if (mddev->reshape_position != MaxSector && mddev->delta_disks != 0) return sprintf(page, "%d (%d) ", mddev->raid_disks, mddev->raid_disks - mddev->delta_disks); |
eae1701fb [PATCH] md: initi... |
3468 3469 3470 |
return sprintf(page, "%d ", mddev->raid_disks); } |
fd01b88c7 md: remove typede... |
3471 |
static int update_raid_disks(struct mddev *mddev, int raid_disks); |
da943b991 [PATCH] md: allow... |
3472 3473 |
static ssize_t |
fd01b88c7 md: remove typede... |
3474 |
raid_disks_store(struct mddev *mddev, const char *buf, size_t len) |
da943b991 [PATCH] md: allow... |
3475 |
{ |
da943b991 [PATCH] md: allow... |
3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 |
char *e; int rv = 0; unsigned long n = simple_strtoul(buf, &e, 10); if (!*buf || (*e && *e != ' ')) return -EINVAL; if (mddev->pers) rv = update_raid_disks(mddev, n); |
08a02ecd2 md: allow reshape... |
3486 3487 3488 3489 3490 |
else if (mddev->reshape_position != MaxSector) { int olddisks = mddev->raid_disks - mddev->delta_disks; mddev->delta_disks = n - olddisks; mddev->raid_disks = n; } else |
da943b991 [PATCH] md: allow... |
3491 3492 3493 3494 |
mddev->raid_disks = n; return rv ? rv : len; } static struct md_sysfs_entry md_raid_disks = |
80ca3a44f [PATCH] md: unify... |
3495 |
__ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store); |
eae1701fb [PATCH] md: initi... |
3496 |
|
24dd469d7 [PATCH] md: allow... |
3497 |
static ssize_t |
fd01b88c7 md: remove typede... |
3498 |
chunk_size_show(struct mddev *mddev, char *page) |
3b34380ae [PATCH] md: allow... |
3499 |
{ |
08a02ecd2 md: allow reshape... |
3500 |
if (mddev->reshape_position != MaxSector && |
664e7c413 md: Convert mddev... |
3501 3502 3503 3504 |
mddev->chunk_sectors != mddev->new_chunk_sectors) return sprintf(page, "%d (%d) ", mddev->new_chunk_sectors << 9, |
9d8f03636 md: Make mddev->c... |
3505 3506 3507 |
mddev->chunk_sectors << 9); return sprintf(page, "%d ", mddev->chunk_sectors << 9); |
3b34380ae [PATCH] md: allow... |
3508 3509 3510 |
} static ssize_t |
fd01b88c7 md: remove typede... |
3511 |
chunk_size_store(struct mddev *mddev, const char *buf, size_t len) |
3b34380ae [PATCH] md: allow... |
3512 |
{ |
3b34380ae [PATCH] md: allow... |
3513 3514 |
char *e; unsigned long n = simple_strtoul(buf, &e, 10); |
3b34380ae [PATCH] md: allow... |
3515 3516 3517 |
if (!*buf || (*e && *e != ' ')) return -EINVAL; |
b35460352 md/raid5: allow l... |
3518 3519 |
if (mddev->pers) { int err; |
50ac168a6 md: merge reconfi... |
3520 |
if (mddev->pers->check_reshape == NULL) |
b35460352 md/raid5: allow l... |
3521 |
return -EBUSY; |
597a711b6 md: remove unnece... |
3522 |
mddev->new_chunk_sectors = n >> 9; |
50ac168a6 md: merge reconfi... |
3523 |
err = mddev->pers->check_reshape(mddev); |
597a711b6 md: remove unnece... |
3524 3525 |
if (err) { mddev->new_chunk_sectors = mddev->chunk_sectors; |
b35460352 md/raid5: allow l... |
3526 |
return err; |
597a711b6 md: remove unnece... |
3527 |
} |
b35460352 md/raid5: allow l... |
3528 |
} else { |
664e7c413 md: Convert mddev... |
3529 |
mddev->new_chunk_sectors = n >> 9; |
b35460352 md/raid5: allow l... |
3530 |
if (mddev->reshape_position == MaxSector) |
9d8f03636 md: Make mddev->c... |
3531 |
mddev->chunk_sectors = n >> 9; |
b35460352 md/raid5: allow l... |
3532 |
} |
3b34380ae [PATCH] md: allow... |
3533 3534 3535 |
return len; } static struct md_sysfs_entry md_chunk_size = |
80ca3a44f [PATCH] md: unify... |
3536 |
__ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store); |
3b34380ae [PATCH] md: allow... |
3537 |
|
a94213b1f [PATCH] md: Allow... |
3538 |
static ssize_t |
fd01b88c7 md: remove typede... |
3539 |
resync_start_show(struct mddev *mddev, char *page) |
a94213b1f [PATCH] md: Allow... |
3540 |
{ |
d1a7c5036 md: don't display... |
3541 3542 3543 |
if (mddev->recovery_cp == MaxSector) return sprintf(page, "none "); |
a94213b1f [PATCH] md: Allow... |
3544 3545 3546 3547 3548 |
return sprintf(page, "%llu ", (unsigned long long)mddev->recovery_cp); } static ssize_t |
fd01b88c7 md: remove typede... |
3549 |
resync_start_store(struct mddev *mddev, const char *buf, size_t len) |
a94213b1f [PATCH] md: Allow... |
3550 |
{ |
a94213b1f [PATCH] md: Allow... |
3551 3552 |
char *e; unsigned long long n = simple_strtoull(buf, &e, 10); |
b098636cf md: allow resync_... |
3553 |
if (mddev->pers && !test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) |
a94213b1f [PATCH] md: Allow... |
3554 |
return -EBUSY; |
06e3c817b md: add 'recovery... |
3555 3556 3557 3558 |
if (cmd_match(buf, "none")) n = MaxSector; else if (!*buf || (*e && *e != ' ')) |
a94213b1f [PATCH] md: Allow... |
3559 3560 3561 3562 3563 3564 |
return -EINVAL; mddev->recovery_cp = n; return len; } static struct md_sysfs_entry md_resync_start = |
80ca3a44f [PATCH] md: unify... |
3565 |
__ATTR(resync_start, S_IRUGO|S_IWUSR, resync_start_show, resync_start_store); |
a94213b1f [PATCH] md: Allow... |
3566 |
|
9e653b634 [PATCH] md: Set/g... |
3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 |
/* * The array state can be: * * clear * No devices, no size, no level * Equivalent to STOP_ARRAY ioctl * inactive * May have some settings, but array is not active * all IO results in error * When written, doesn't tear down array, but just stops it * suspended (not supported yet) * All IO requests will block. The array can be reconfigured. |
910d8cb3f md: Fix typo in a... |
3579 |
* Writing this, if accepted, will block until array is quiescent |
9e653b634 [PATCH] md: Set/g... |
3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 |
* readonly * no resync can happen. no superblocks get written. * write requests fail * read-auto * like readonly, but behaves like 'clean' on a write request. * * clean - no pending writes, but otherwise active. * When written to inactive array, starts without resync * If a write request arrives then * if metadata is known, mark 'dirty' and switch to 'active'. * if not known, block and switch to write-pending * If written to an active array that has pending writes, then fails. * active * fully active: IO and resync can be happening. * When written to inactive array, starts with resync * * write-pending * clean, but writes are blocked waiting for 'active' to be written. * * active-idle * like active, but no writes have been seen for a while (100msec). * */ enum array_state { clear, inactive, suspended, readonly, read_auto, clean, active, write_pending, active_idle, bad_word}; |
053819542 [PATCH] drivers/m... |
3605 |
static char *array_states[] = { |
9e653b634 [PATCH] md: Set/g... |
3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 |
"clear", "inactive", "suspended", "readonly", "read-auto", "clean", "active", "write-pending", "active-idle", NULL }; static int match_word(const char *word, char **list) { int n; for (n=0; list[n]; n++) if (cmd_match(word, list[n])) break; return n; } static ssize_t |
fd01b88c7 md: remove typede... |
3619 |
array_state_show(struct mddev *mddev, char *page) |
9e653b634 [PATCH] md: Set/g... |
3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 |
{ enum array_state st = inactive; if (mddev->pers) switch(mddev->ro) { case 1: st = readonly; break; case 2: st = read_auto; break; case 0: if (mddev->in_sync) st = clean; |
070dc6dd7 md: resolve confu... |
3634 |
else if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) |
e691063a6 md: support 'exte... |
3635 |
st = write_pending; |
9e653b634 [PATCH] md: Set/g... |
3636 3637 3638 3639 3640 3641 3642 3643 |
else if (mddev->safemode) st = active_idle; else st = active; } else { if (list_empty(&mddev->disks) && mddev->raid_disks == 0 && |
58c0fed40 md: Make mddev->s... |
3644 |
mddev->dev_sectors == 0) |
9e653b634 [PATCH] md: Set/g... |
3645 3646 3647 3648 3649 3650 3651 |
st = clear; else st = inactive; } return sprintf(page, "%s ", array_states[st]); } |
fd01b88c7 md: remove typede... |
3652 3653 3654 3655 |
static int do_md_stop(struct mddev * mddev, int ro, int is_open); static int md_set_readonly(struct mddev * mddev, int is_open); static int do_md_run(struct mddev * mddev); static int restart_array(struct mddev *mddev); |
9e653b634 [PATCH] md: Set/g... |
3656 3657 |
static ssize_t |
fd01b88c7 md: remove typede... |
3658 |
array_state_store(struct mddev *mddev, const char *buf, size_t len) |
9e653b634 [PATCH] md: Set/g... |
3659 3660 3661 3662 3663 3664 3665 3666 |
{ int err = -EINVAL; enum array_state st = match_word(buf, array_states); switch(st) { case bad_word: break; case clear: /* stopping an active array */ |
f2ea68cf4 md: only count ac... |
3667 |
if (atomic_read(&mddev->openers) > 0) |
e691063a6 md: support 'exte... |
3668 |
return -EBUSY; |
df5b20cf6 md: Better contro... |
3669 |
err = do_md_stop(mddev, 0, 0); |
9e653b634 [PATCH] md: Set/g... |
3670 3671 3672 3673 |
break; case inactive: /* stopping an active array */ if (mddev->pers) { |
f2ea68cf4 md: only count ac... |
3674 |
if (atomic_read(&mddev->openers) > 0) |
9e653b634 [PATCH] md: Set/g... |
3675 |
return -EBUSY; |
df5b20cf6 md: Better contro... |
3676 |
err = do_md_stop(mddev, 2, 0); |
e691063a6 md: support 'exte... |
3677 3678 |
} else err = 0; /* already inactive */ |
9e653b634 [PATCH] md: Set/g... |
3679 3680 3681 3682 3683 |
break; case suspended: break; /* not supported yet */ case readonly: if (mddev->pers) |
a4bd82d0d md: split md_set_... |
3684 |
err = md_set_readonly(mddev, 0); |
9e653b634 [PATCH] md: Set/g... |
3685 3686 |
else { mddev->ro = 1; |
648b629ed md: fix up switch... |
3687 |
set_disk_ro(mddev->gendisk, 1); |
9e653b634 [PATCH] md: Set/g... |
3688 3689 3690 3691 |
err = do_md_run(mddev); } break; case read_auto: |
9e653b634 [PATCH] md: Set/g... |
3692 |
if (mddev->pers) { |
80268ee92 md: Don't try to ... |
3693 |
if (mddev->ro == 0) |
a4bd82d0d md: split md_set_... |
3694 |
err = md_set_readonly(mddev, 0); |
80268ee92 md: Don't try to ... |
3695 |
else if (mddev->ro == 1) |
648b629ed md: fix up switch... |
3696 3697 3698 3699 3700 |
err = restart_array(mddev); if (err == 0) { mddev->ro = 2; set_disk_ro(mddev->gendisk, 0); } |
9e653b634 [PATCH] md: Set/g... |
3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 |
} else { mddev->ro = 2; err = do_md_run(mddev); } break; case clean: if (mddev->pers) { restart_array(mddev); spin_lock_irq(&mddev->write_lock); if (atomic_read(&mddev->writes_pending) == 0) { |
e691063a6 md: support 'exte... |
3711 3712 |
if (mddev->in_sync == 0) { mddev->in_sync = 1; |
31a59e342 md: fix 'safemode... |
3713 3714 |
if (mddev->safemode == 1) mddev->safemode = 0; |
070dc6dd7 md: resolve confu... |
3715 |
set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
e691063a6 md: support 'exte... |
3716 3717 3718 3719 |
} err = 0; } else err = -EBUSY; |
9e653b634 [PATCH] md: Set/g... |
3720 |
spin_unlock_irq(&mddev->write_lock); |
5bf295975 md: remove abilit... |
3721 3722 |
} else err = -EINVAL; |
9e653b634 [PATCH] md: Set/g... |
3723 3724 3725 3726 |
break; case active: if (mddev->pers) { restart_array(mddev); |
070dc6dd7 md: resolve confu... |
3727 |
clear_bit(MD_CHANGE_PENDING, &mddev->flags); |
9e653b634 [PATCH] md: Set/g... |
3728 3729 3730 3731 |
wake_up(&mddev->sb_wait); err = 0; } else { mddev->ro = 0; |
648b629ed md: fix up switch... |
3732 |
set_disk_ro(mddev->gendisk, 0); |
9e653b634 [PATCH] md: Set/g... |
3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 |
err = do_md_run(mddev); } break; case write_pending: case active_idle: /* these cannot be set */ break; } if (err) return err; |
0fd62b861 Make sure all cha... |
3743 |
else { |
1d23f178d md: refine interp... |
3744 3745 |
if (mddev->hold_active == UNTIL_IOCTL) mddev->hold_active = 0; |
00bcb4ac7 md: reduce depend... |
3746 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
9e653b634 [PATCH] md: Set/g... |
3747 |
return len; |
0fd62b861 Make sure all cha... |
3748 |
} |
9e653b634 [PATCH] md: Set/g... |
3749 |
} |
80ca3a44f [PATCH] md: unify... |
3750 3751 |
static struct md_sysfs_entry md_array_state = __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store); |
9e653b634 [PATCH] md: Set/g... |
3752 |
|
6d7ff7380 [PATCH] md: suppo... |
3753 |
static ssize_t |
fd01b88c7 md: remove typede... |
3754 |
max_corrected_read_errors_show(struct mddev *mddev, char *page) { |
1e50915fe raid: improve MD/... |
3755 3756 3757 3758 3759 3760 |
return sprintf(page, "%d ", atomic_read(&mddev->max_corr_read_errors)); } static ssize_t |
fd01b88c7 md: remove typede... |
3761 |
max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len) |
1e50915fe raid: improve MD/... |
3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 |
{ char *e; unsigned long n = simple_strtoul(buf, &e, 10); if (*buf && (*e == 0 || *e == ' ')) { atomic_set(&mddev->max_corr_read_errors, n); return len; } return -EINVAL; } static struct md_sysfs_entry max_corr_read_errors = __ATTR(max_read_errors, S_IRUGO|S_IWUSR, max_corrected_read_errors_show, max_corrected_read_errors_store); static ssize_t |
fd01b88c7 md: remove typede... |
3779 |
null_show(struct mddev *mddev, char *page) |
6d7ff7380 [PATCH] md: suppo... |
3780 3781 3782 3783 3784 |
{ return -EINVAL; } static ssize_t |
fd01b88c7 md: remove typede... |
3785 |
new_dev_store(struct mddev *mddev, const char *buf, size_t len) |
6d7ff7380 [PATCH] md: suppo... |
3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 |
{ /* buf must be %d:%d ? giving major and minor numbers */ /* The new device is added to the array. * If the array has a persistent superblock, we read the * superblock to initialise info and check validity. * Otherwise, only checking done is that in bind_rdev_to_array, * which mainly checks size. */ char *e; int major = simple_strtoul(buf, &e, 10); int minor; dev_t dev; |
3cb030020 md: removing type... |
3799 |
struct md_rdev *rdev; |
6d7ff7380 [PATCH] md: suppo... |
3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 |
int err; if (!*buf || *e != ':' || !e[1] || e[1] == ' ') return -EINVAL; minor = simple_strtoul(e+1, &e, 10); if (*e && *e != ' ') return -EINVAL; dev = MKDEV(major, minor); if (major != MAJOR(dev) || minor != MINOR(dev)) return -EOVERFLOW; if (mddev->persistent) { rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) { |
3cb030020 md: removing type... |
3819 3820 3821 |
struct md_rdev *rdev0 = list_entry(mddev->disks.next, struct md_rdev, same_set); |
6d7ff7380 [PATCH] md: suppo... |
3822 3823 3824 3825 3826 |
err = super_types[mddev->major_version] .load_super(rdev, rdev0, mddev->minor_version); if (err < 0) goto out; } |
c5d79adba md: allow devices... |
3827 3828 3829 |
} else if (mddev->external) rdev = md_import_device(dev, -2, -1); else |
6d7ff7380 [PATCH] md: suppo... |
3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 |
rdev = md_import_device(dev, -1, -1); if (IS_ERR(rdev)) return PTR_ERR(rdev); err = bind_rdev_to_array(rdev, mddev); out: if (err) export_rdev(rdev); return err ? err : len; } static struct md_sysfs_entry md_new_device = |
80ca3a44f [PATCH] md: unify... |
3842 |
__ATTR(new_dev, S_IWUSR, null_show, new_dev_store); |
3b34380ae [PATCH] md: allow... |
3843 3844 |
static ssize_t |
fd01b88c7 md: remove typede... |
3845 |
bitmap_store(struct mddev *mddev, const char *buf, size_t len) |
9b1d1dac1 [PATCH] md: new s... |
3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 |
{ char *end; unsigned long chunk, end_chunk; if (!mddev->bitmap) goto out; /* buf should be <chunk> <chunk> ... or <chunk>-<chunk> ... (range) */ while (*buf) { chunk = end_chunk = simple_strtoul(buf, &end, 0); if (buf == end) break; if (*end == '-') { /* range */ buf = end + 1; end_chunk = simple_strtoul(buf, &end, 0); if (buf == end) break; } if (*end && !isspace(*end)) break; bitmap_dirty_bits(mddev->bitmap, chunk, end_chunk); |
e7d2860b6 tree-wide: conver... |
3863 |
buf = skip_spaces(end); |
9b1d1dac1 [PATCH] md: new s... |
3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 |
} bitmap_unplug(mddev->bitmap); /* flush the bits to disk */ out: return len; } static struct md_sysfs_entry md_bitmap = __ATTR(bitmap_set_bits, S_IWUSR, null_show, bitmap_store); static ssize_t |
fd01b88c7 md: remove typede... |
3874 |
size_show(struct mddev *mddev, char *page) |
a35b0d695 [PATCH] md: allow... |
3875 |
{ |
58c0fed40 md: Make mddev->s... |
3876 3877 3878 |
return sprintf(page, "%llu ", (unsigned long long)mddev->dev_sectors / 2); |
a35b0d695 [PATCH] md: allow... |
3879 |
} |
fd01b88c7 md: remove typede... |
3880 |
static int update_size(struct mddev *mddev, sector_t num_sectors); |
a35b0d695 [PATCH] md: allow... |
3881 3882 |
static ssize_t |
fd01b88c7 md: remove typede... |
3883 |
size_store(struct mddev *mddev, const char *buf, size_t len) |
a35b0d695 [PATCH] md: allow... |
3884 3885 3886 3887 3888 |
{ /* If array is inactive, we can reduce the component size, but * not increase it (except from 0). * If array is active, we can try an on-line resize */ |
b522adcde md: 'array_size' ... |
3889 3890 |
sector_t sectors; int err = strict_blocks_to_sectors(buf, §ors); |
a35b0d695 [PATCH] md: allow... |
3891 |
|
58c0fed40 md: Make mddev->s... |
3892 3893 |
if (err < 0) return err; |
a35b0d695 [PATCH] md: allow... |
3894 |
if (mddev->pers) { |
58c0fed40 md: Make mddev->s... |
3895 |
err = update_size(mddev, sectors); |
850b2b420 [PATCH] md: repla... |
3896 |
md_update_sb(mddev, 1); |
a35b0d695 [PATCH] md: allow... |
3897 |
} else { |
58c0fed40 md: Make mddev->s... |
3898 3899 3900 |
if (mddev->dev_sectors == 0 || mddev->dev_sectors > sectors) mddev->dev_sectors = sectors; |
a35b0d695 [PATCH] md: allow... |
3901 3902 3903 3904 3905 3906 3907 |
else err = -ENOSPC; } return err ? err : len; } static struct md_sysfs_entry md_size = |
80ca3a44f [PATCH] md: unify... |
3908 |
__ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store); |
a35b0d695 [PATCH] md: allow... |
3909 |
|
8bb93aaca [PATCH] md: expos... |
3910 3911 |
/* Metdata version. |
e691063a6 md: support 'exte... |
3912 3913 3914 |
* This is one of * 'none' for arrays with no metadata (good luck...) * 'external' for arrays with externally managed metadata, |
8bb93aaca [PATCH] md: expos... |
3915 3916 3917 |
* or N.M for internally known formats */ static ssize_t |
fd01b88c7 md: remove typede... |
3918 |
metadata_show(struct mddev *mddev, char *page) |
8bb93aaca [PATCH] md: expos... |
3919 3920 3921 3922 3923 |
{ if (mddev->persistent) return sprintf(page, "%d.%d ", mddev->major_version, mddev->minor_version); |
e691063a6 md: support 'exte... |
3924 3925 3926 |
else if (mddev->external) return sprintf(page, "external:%s ", mddev->metadata_type); |
8bb93aaca [PATCH] md: expos... |
3927 3928 3929 3930 3931 3932 |
else return sprintf(page, "none "); } static ssize_t |
fd01b88c7 md: remove typede... |
3933 |
metadata_store(struct mddev *mddev, const char *buf, size_t len) |
8bb93aaca [PATCH] md: expos... |
3934 3935 3936 |
{ int major, minor; char *e; |
ea43ddd84 md: Allow metadat... |
3937 3938 3939 3940 3941 3942 3943 |
/* Changing the details of 'external' metadata is * always permitted. Otherwise there must be * no devices attached to the array. */ if (mddev->external && strncmp(buf, "external:", 9) == 0) ; else if (!list_empty(&mddev->disks)) |
8bb93aaca [PATCH] md: expos... |
3944 3945 3946 3947 |
return -EBUSY; if (cmd_match(buf, "none")) { mddev->persistent = 0; |
e691063a6 md: support 'exte... |
3948 3949 3950 3951 3952 3953 |
mddev->external = 0; mddev->major_version = 0; mddev->minor_version = 90; return len; } if (strncmp(buf, "external:", 9) == 0) { |
20a49ff67 md: change a few ... |
3954 |
size_t namelen = len-9; |
e691063a6 md: support 'exte... |
3955 3956 3957 3958 3959 3960 3961 3962 3963 |
if (namelen >= sizeof(mddev->metadata_type)) namelen = sizeof(mddev->metadata_type)-1; strncpy(mddev->metadata_type, buf+9, namelen); mddev->metadata_type[namelen] = 0; if (namelen && mddev->metadata_type[namelen-1] == ' ') mddev->metadata_type[--namelen] = 0; mddev->persistent = 0; mddev->external = 1; |
8bb93aaca [PATCH] md: expos... |
3964 3965 3966 3967 3968 3969 3970 3971 3972 |
mddev->major_version = 0; mddev->minor_version = 90; return len; } major = simple_strtoul(buf, &e, 10); if (e==buf || *e != '.') return -EINVAL; buf = e+1; minor = simple_strtoul(buf, &e, 10); |
3f9d7b0d8 [PATCH] md: fix a... |
3973 3974 |
if (e==buf || (*e && *e != ' ') ) |
8bb93aaca [PATCH] md: expos... |
3975 |
return -EINVAL; |
50511da3d drivers/md.c: Use... |
3976 |
if (major >= ARRAY_SIZE(super_types) || super_types[major].name == NULL) |
8bb93aaca [PATCH] md: expos... |
3977 3978 3979 3980 |
return -ENOENT; mddev->major_version = major; mddev->minor_version = minor; mddev->persistent = 1; |
e691063a6 md: support 'exte... |
3981 |
mddev->external = 0; |
8bb93aaca [PATCH] md: expos... |
3982 3983 3984 3985 |
return len; } static struct md_sysfs_entry md_metadata = |
80ca3a44f [PATCH] md: unify... |
3986 |
__ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store); |
8bb93aaca [PATCH] md: expos... |
3987 |
|
a35b0d695 [PATCH] md: allow... |
3988 |
static ssize_t |
fd01b88c7 md: remove typede... |
3989 |
action_show(struct mddev *mddev, char *page) |
24dd469d7 [PATCH] md: allow... |
3990 |
{ |
7eec314d7 [PATCH] md: impro... |
3991 |
char *type = "idle"; |
b6a9ce688 md: export 'froze... |
3992 3993 3994 |
if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) type = "frozen"; else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || |
2b12ab6d3 md: 'sync_action'... |
3995 |
(!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))) { |
ccfcc3c10 [PATCH] md: Core ... |
3996 3997 3998 |
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) type = "reshape"; else if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { |
24dd469d7 [PATCH] md: allow... |
3999 4000 4001 4002 4003 4004 |
if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) type = "resync"; else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) type = "check"; else type = "repair"; |
72a23c211 Make sure all cha... |
4005 |
} else if (test_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) |
24dd469d7 [PATCH] md: allow... |
4006 4007 4008 4009 4010 |
type = "recover"; } return sprintf(page, "%s ", type); } |
fd01b88c7 md: remove typede... |
4011 |
static void reap_sync_thread(struct mddev *mddev); |
7ebc0be7f md: Be more caref... |
4012 |
|
24dd469d7 [PATCH] md: allow... |
4013 |
static ssize_t |
fd01b88c7 md: remove typede... |
4014 |
action_store(struct mddev *mddev, const char *page, size_t len) |
24dd469d7 [PATCH] md: allow... |
4015 |
{ |
7eec314d7 [PATCH] md: impro... |
4016 4017 |
if (!mddev->pers || !mddev->pers->sync_request) return -EINVAL; |
b6a9ce688 md: export 'froze... |
4018 4019 4020 4021 4022 4023 |
if (cmd_match(page, "frozen")) set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); else clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); if (cmd_match(page, "idle") || cmd_match(page, "frozen")) { |
7eec314d7 [PATCH] md: impro... |
4024 4025 |
if (mddev->sync_thread) { set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
7ebc0be7f md: Be more caref... |
4026 |
reap_sync_thread(mddev); |
7eec314d7 [PATCH] md: impro... |
4027 |
} |
03c902e17 [PATCH] md: fix r... |
4028 4029 |
} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) |
24dd469d7 [PATCH] md: allow... |
4030 |
return -EBUSY; |
72a23c211 Make sure all cha... |
4031 4032 4033 4034 |
else if (cmd_match(page, "resync")) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); else if (cmd_match(page, "recover")) { set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
7eec314d7 [PATCH] md: impro... |
4035 |
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
72a23c211 Make sure all cha... |
4036 |
} else if (cmd_match(page, "reshape")) { |
16484bf59 [PATCH] md: Make ... |
4037 4038 4039 4040 4041 4042 |
int err; if (mddev->pers->start_reshape == NULL) return -EINVAL; err = mddev->pers->start_reshape(mddev); if (err) return err; |
a99ac9711 Make sure all cha... |
4043 |
sysfs_notify(&mddev->kobj, NULL, "degraded"); |
16484bf59 [PATCH] md: Make ... |
4044 |
} else { |
bce74dac0 [PATCH] md: helpe... |
4045 |
if (cmd_match(page, "check")) |
7eec314d7 [PATCH] md: impro... |
4046 |
set_bit(MD_RECOVERY_CHECK, &mddev->recovery); |
2adc7d47c [PATCH] md: Fix i... |
4047 |
else if (!cmd_match(page, "repair")) |
7eec314d7 [PATCH] md: impro... |
4048 4049 4050 |
return -EINVAL; set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); set_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
7eec314d7 [PATCH] md: impro... |
4051 |
} |
03c902e17 [PATCH] md: fix r... |
4052 |
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
24dd469d7 [PATCH] md: allow... |
4053 |
md_wakeup_thread(mddev->thread); |
00bcb4ac7 md: reduce depend... |
4054 |
sysfs_notify_dirent_safe(mddev->sysfs_action); |
24dd469d7 [PATCH] md: allow... |
4055 4056 |
return len; } |
9d88883e6 [PATCH] md: teach... |
4057 |
static ssize_t |
fd01b88c7 md: remove typede... |
4058 |
mismatch_cnt_show(struct mddev *mddev, char *page) |
9d88883e6 [PATCH] md: teach... |
4059 4060 4061 4062 4063 |
{ return sprintf(page, "%llu ", (unsigned long long) mddev->resync_mismatches); } |
80ca3a44f [PATCH] md: unify... |
4064 4065 |
static struct md_sysfs_entry md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store); |
24dd469d7 [PATCH] md: allow... |
4066 |
|
96de1e663 [PATCH] md: fix s... |
4067 |
|
80ca3a44f [PATCH] md: unify... |
4068 |
static struct md_sysfs_entry md_mismatches = __ATTR_RO(mismatch_cnt); |
9d88883e6 [PATCH] md: teach... |
4069 |
|
88202a0c8 [PATCH] md: allow... |
4070 |
static ssize_t |
fd01b88c7 md: remove typede... |
4071 |
sync_min_show(struct mddev *mddev, char *page) |
88202a0c8 [PATCH] md: allow... |
4072 4073 4074 4075 4076 4077 4078 |
{ return sprintf(page, "%d (%s) ", speed_min(mddev), mddev->sync_speed_min ? "local": "system"); } static ssize_t |
fd01b88c7 md: remove typede... |
4079 |
sync_min_store(struct mddev *mddev, const char *buf, size_t len) |
88202a0c8 [PATCH] md: allow... |
4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 |
{ int min; char *e; if (strncmp(buf, "system", 6)==0) { mddev->sync_speed_min = 0; return len; } min = simple_strtoul(buf, &e, 10); if (buf == e || (*e && *e != ' ') || min <= 0) return -EINVAL; mddev->sync_speed_min = min; return len; } static struct md_sysfs_entry md_sync_min = __ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store); static ssize_t |
fd01b88c7 md: remove typede... |
4099 |
sync_max_show(struct mddev *mddev, char *page) |
88202a0c8 [PATCH] md: allow... |
4100 4101 4102 4103 4104 4105 4106 |
{ return sprintf(page, "%d (%s) ", speed_max(mddev), mddev->sync_speed_max ? "local": "system"); } static ssize_t |
fd01b88c7 md: remove typede... |
4107 |
sync_max_store(struct mddev *mddev, const char *buf, size_t len) |
88202a0c8 [PATCH] md: allow... |
4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 |
{ int max; char *e; if (strncmp(buf, "system", 6)==0) { mddev->sync_speed_max = 0; return len; } max = simple_strtoul(buf, &e, 10); if (buf == e || (*e && *e != ' ') || max <= 0) return -EINVAL; mddev->sync_speed_max = max; return len; } static struct md_sysfs_entry md_sync_max = __ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store); |
d7f3d291a md: expose the de... |
4125 |
static ssize_t |
fd01b88c7 md: remove typede... |
4126 |
degraded_show(struct mddev *mddev, char *page) |
d7f3d291a md: expose the de... |
4127 4128 4129 4130 4131 |
{ return sprintf(page, "%d ", mddev->degraded); } static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded); |
88202a0c8 [PATCH] md: allow... |
4132 4133 |
static ssize_t |
fd01b88c7 md: remove typede... |
4134 |
sync_force_parallel_show(struct mddev *mddev, char *page) |
90b08710e md: allow paralle... |
4135 4136 4137 4138 4139 4140 |
{ return sprintf(page, "%d ", mddev->parallel_resync); } static ssize_t |
fd01b88c7 md: remove typede... |
4141 |
sync_force_parallel_store(struct mddev *mddev, const char *buf, size_t len) |
90b08710e md: allow paralle... |
4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 |
{ long n; if (strict_strtol(buf, 10, &n)) return -EINVAL; if (n != 0 && n != 1) return -EINVAL; mddev->parallel_resync = n; if (mddev->sync_thread) wake_up(&resync_wait); return len; } /* force parallel resync, even with shared block devices */ static struct md_sysfs_entry md_sync_force_parallel = __ATTR(sync_force_parallel, S_IRUGO|S_IWUSR, sync_force_parallel_show, sync_force_parallel_store); static ssize_t |
fd01b88c7 md: remove typede... |
4165 |
sync_speed_show(struct mddev *mddev, char *page) |
88202a0c8 [PATCH] md: allow... |
4166 4167 |
{ unsigned long resync, dt, db; |
d1a7c5036 md: don't display... |
4168 4169 4170 |
if (mddev->curr_resync == 0) return sprintf(page, "none "); |
9687a60c7 md: sync_speed_sh... |
4171 4172 |
resync = mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active); dt = (jiffies - mddev->resync_mark) / HZ; |
88202a0c8 [PATCH] md: allow... |
4173 |
if (!dt) dt++; |
9687a60c7 md: sync_speed_sh... |
4174 4175 4176 |
db = resync - mddev->resync_mark_cnt; return sprintf(page, "%lu ", db/dt/2); /* K/sec */ |
88202a0c8 [PATCH] md: allow... |
4177 |
} |
80ca3a44f [PATCH] md: unify... |
4178 |
static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed); |
88202a0c8 [PATCH] md: allow... |
4179 4180 |
static ssize_t |
fd01b88c7 md: remove typede... |
4181 |
sync_completed_show(struct mddev *mddev, char *page) |
88202a0c8 [PATCH] md: allow... |
4182 |
{ |
13ae864bc md: fix sync_comp... |
4183 |
unsigned long long max_sectors, resync; |
88202a0c8 [PATCH] md: allow... |
4184 |
|
acb180b0e md: improve usefu... |
4185 4186 4187 |
if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return sprintf(page, "none "); |
88202a0c8 [PATCH] md: allow... |
4188 |
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) |
58c0fed40 md: Make mddev->s... |
4189 |
max_sectors = mddev->resync_max_sectors; |
88202a0c8 [PATCH] md: allow... |
4190 |
else |
58c0fed40 md: Make mddev->s... |
4191 |
max_sectors = mddev->dev_sectors; |
88202a0c8 [PATCH] md: allow... |
4192 |
|
acb180b0e md: improve usefu... |
4193 |
resync = mddev->curr_resync_completed; |
13ae864bc md: fix sync_comp... |
4194 4195 |
return sprintf(page, "%llu / %llu ", resync, max_sectors); |
88202a0c8 [PATCH] md: allow... |
4196 |
} |
80ca3a44f [PATCH] md: unify... |
4197 |
static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); |
88202a0c8 [PATCH] md: allow... |
4198 |
|
e464eafdb [PATCH] md: Suppo... |
4199 |
static ssize_t |
fd01b88c7 md: remove typede... |
4200 |
min_sync_show(struct mddev *mddev, char *page) |
5e96ee65c Allow setting sta... |
4201 4202 4203 4204 4205 4206 |
{ return sprintf(page, "%llu ", (unsigned long long)mddev->resync_min); } static ssize_t |
fd01b88c7 md: remove typede... |
4207 |
min_sync_store(struct mddev *mddev, const char *buf, size_t len) |
5e96ee65c Allow setting sta... |
4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 |
{ unsigned long long min; if (strict_strtoull(buf, 10, &min)) return -EINVAL; if (min > mddev->resync_max) return -EINVAL; if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; /* Must be a multiple of chunk_size */ |
9d8f03636 md: Make mddev->c... |
4218 |
if (mddev->chunk_sectors) { |
2ac06c333 md: prepare for n... |
4219 |
sector_t temp = min; |
9d8f03636 md: Make mddev->c... |
4220 |
if (sector_div(temp, mddev->chunk_sectors)) |
5e96ee65c Allow setting sta... |
4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 |
return -EINVAL; } mddev->resync_min = min; return len; } static struct md_sysfs_entry md_min_sync = __ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store); static ssize_t |
fd01b88c7 md: remove typede... |
4232 |
max_sync_show(struct mddev *mddev, char *page) |
c62072777 md: allow a maxim... |
4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 |
{ if (mddev->resync_max == MaxSector) return sprintf(page, "max "); else return sprintf(page, "%llu ", (unsigned long long)mddev->resync_max); } static ssize_t |
fd01b88c7 md: remove typede... |
4243 |
max_sync_store(struct mddev *mddev, const char *buf, size_t len) |
c62072777 md: allow a maxim... |
4244 4245 4246 4247 |
{ if (strncmp(buf, "max", 3) == 0) mddev->resync_max = MaxSector; else { |
5e96ee65c Allow setting sta... |
4248 4249 4250 4251 |
unsigned long long max; if (strict_strtoull(buf, 10, &max)) return -EINVAL; if (max < mddev->resync_min) |
c62072777 md: allow a maxim... |
4252 4253 |
return -EINVAL; if (max < mddev->resync_max && |
4d484a4a7 md: allow upper l... |
4254 |
mddev->ro == 0 && |
c62072777 md: allow a maxim... |
4255 4256 4257 4258 |
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; /* Must be a multiple of chunk_size */ |
9d8f03636 md: Make mddev->c... |
4259 |
if (mddev->chunk_sectors) { |
2ac06c333 md: prepare for n... |
4260 |
sector_t temp = max; |
9d8f03636 md: Make mddev->c... |
4261 |
if (sector_div(temp, mddev->chunk_sectors)) |
c62072777 md: allow a maxim... |
4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 |
return -EINVAL; } mddev->resync_max = max; } wake_up(&mddev->recovery_wait); return len; } static struct md_sysfs_entry md_max_sync = __ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store); static ssize_t |
fd01b88c7 md: remove typede... |
4274 |
suspend_lo_show(struct mddev *mddev, char *page) |
e464eafdb [PATCH] md: Suppo... |
4275 4276 4277 4278 4279 4280 |
{ return sprintf(page, "%llu ", (unsigned long long)mddev->suspend_lo); } static ssize_t |
fd01b88c7 md: remove typede... |
4281 |
suspend_lo_store(struct mddev *mddev, const char *buf, size_t len) |
e464eafdb [PATCH] md: Suppo... |
4282 4283 4284 |
{ char *e; unsigned long long new = simple_strtoull(buf, &e, 10); |
23ddff379 md: allow suspend... |
4285 |
unsigned long long old = mddev->suspend_lo; |
e464eafdb [PATCH] md: Suppo... |
4286 |
|
b8d966efd md: avoid derefer... |
4287 4288 |
if (mddev->pers == NULL || mddev->pers->quiesce == NULL) |
e464eafdb [PATCH] md: Suppo... |
4289 4290 4291 4292 |
return -EINVAL; if (buf == e || (*e && *e != ' ')) return -EINVAL; |
23ddff379 md: allow suspend... |
4293 4294 4295 4296 |
mddev->suspend_lo = new; if (new >= old) /* Shrinking suspended region */ |
e464eafdb [PATCH] md: Suppo... |
4297 |
mddev->pers->quiesce(mddev, 2); |
23ddff379 md: allow suspend... |
4298 4299 4300 4301 4302 4303 |
else { /* Expanding suspended region - need to wait */ mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 0); } return len; |
e464eafdb [PATCH] md: Suppo... |
4304 4305 4306 4307 4308 4309 |
} static struct md_sysfs_entry md_suspend_lo = __ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store); static ssize_t |
fd01b88c7 md: remove typede... |
4310 |
suspend_hi_show(struct mddev *mddev, char *page) |
e464eafdb [PATCH] md: Suppo... |
4311 4312 4313 4314 4315 4316 |
{ return sprintf(page, "%llu ", (unsigned long long)mddev->suspend_hi); } static ssize_t |
fd01b88c7 md: remove typede... |
4317 |
suspend_hi_store(struct mddev *mddev, const char *buf, size_t len) |
e464eafdb [PATCH] md: Suppo... |
4318 4319 4320 |
{ char *e; unsigned long long new = simple_strtoull(buf, &e, 10); |
23ddff379 md: allow suspend... |
4321 |
unsigned long long old = mddev->suspend_hi; |
e464eafdb [PATCH] md: Suppo... |
4322 |
|
b8d966efd md: avoid derefer... |
4323 4324 |
if (mddev->pers == NULL || mddev->pers->quiesce == NULL) |
e464eafdb [PATCH] md: Suppo... |
4325 4326 4327 4328 |
return -EINVAL; if (buf == e || (*e && *e != ' ')) return -EINVAL; |
23ddff379 md: allow suspend... |
4329 4330 4331 4332 4333 4334 4335 |
mddev->suspend_hi = new; if (new <= old) /* Shrinking suspended region */ mddev->pers->quiesce(mddev, 2); else { /* Expanding suspended region - need to wait */ |
e464eafdb [PATCH] md: Suppo... |
4336 4337 |
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 0); |
23ddff379 md: allow suspend... |
4338 4339 |
} return len; |
e464eafdb [PATCH] md: Suppo... |
4340 4341 4342 |
} static struct md_sysfs_entry md_suspend_hi = __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); |
08a02ecd2 md: allow reshape... |
4343 |
static ssize_t |
fd01b88c7 md: remove typede... |
4344 |
reshape_position_show(struct mddev *mddev, char *page) |
08a02ecd2 md: allow reshape... |
4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 |
{ if (mddev->reshape_position != MaxSector) return sprintf(page, "%llu ", (unsigned long long)mddev->reshape_position); strcpy(page, "none "); return 5; } static ssize_t |
fd01b88c7 md: remove typede... |
4356 |
reshape_position_store(struct mddev *mddev, const char *buf, size_t len) |
08a02ecd2 md: allow reshape... |
4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 |
{ char *e; unsigned long long new = simple_strtoull(buf, &e, 10); if (mddev->pers) return -EBUSY; if (buf == e || (*e && *e != ' ')) return -EINVAL; mddev->reshape_position = new; mddev->delta_disks = 0; mddev->new_level = mddev->level; mddev->new_layout = mddev->layout; |
664e7c413 md: Convert mddev... |
4369 |
mddev->new_chunk_sectors = mddev->chunk_sectors; |
08a02ecd2 md: allow reshape... |
4370 4371 4372 4373 4374 4375 |
return len; } static struct md_sysfs_entry md_reshape_position = __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show, reshape_position_store); |
b522adcde md: 'array_size' ... |
4376 |
static ssize_t |
fd01b88c7 md: remove typede... |
4377 |
array_size_show(struct mddev *mddev, char *page) |
b522adcde md: 'array_size' ... |
4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 |
{ if (mddev->external_size) return sprintf(page, "%llu ", (unsigned long long)mddev->array_sectors/2); else return sprintf(page, "default "); } static ssize_t |
fd01b88c7 md: remove typede... |
4389 |
array_size_store(struct mddev *mddev, const char *buf, size_t len) |
b522adcde md: 'array_size' ... |
4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 |
{ sector_t sectors; if (strncmp(buf, "default", 7) == 0) { if (mddev->pers) sectors = mddev->pers->size(mddev, 0, 0); else sectors = mddev->array_sectors; mddev->external_size = 0; } else { if (strict_blocks_to_sectors(buf, §ors) < 0) return -EINVAL; if (mddev->pers && mddev->pers->size(mddev, 0, 0) < sectors) |
2b69c8392 md: improve errno... |
4404 |
return -E2BIG; |
b522adcde md: 'array_size' ... |
4405 4406 4407 4408 4409 |
mddev->external_size = 1; } mddev->array_sectors = sectors; |
cbe6ef1d2 md: don't set_cap... |
4410 4411 |
if (mddev->pers) { set_capacity(mddev->gendisk, mddev->array_sectors); |
449aad3e2 md: Use revalidat... |
4412 |
revalidate_disk(mddev->gendisk); |
cbe6ef1d2 md: don't set_cap... |
4413 |
} |
b522adcde md: 'array_size' ... |
4414 4415 4416 4417 4418 4419 |
return len; } static struct md_sysfs_entry md_array_size = __ATTR(array_size, S_IRUGO|S_IWUSR, array_size_show, array_size_store); |
e464eafdb [PATCH] md: Suppo... |
4420 |
|
eae1701fb [PATCH] md: initi... |
4421 4422 |
static struct attribute *md_default_attrs[] = { &md_level.attr, |
d4dbd0250 [PATCH] md: Allow... |
4423 |
&md_layout.attr, |
eae1701fb [PATCH] md: initi... |
4424 |
&md_raid_disks.attr, |
3b34380ae [PATCH] md: allow... |
4425 |
&md_chunk_size.attr, |
a35b0d695 [PATCH] md: allow... |
4426 |
&md_size.attr, |
a94213b1f [PATCH] md: Allow... |
4427 |
&md_resync_start.attr, |
8bb93aaca [PATCH] md: expos... |
4428 |
&md_metadata.attr, |
6d7ff7380 [PATCH] md: suppo... |
4429 |
&md_new_device.attr, |
16f17b39f [PATCH] md: incre... |
4430 |
&md_safe_delay.attr, |
9e653b634 [PATCH] md: Set/g... |
4431 |
&md_array_state.attr, |
08a02ecd2 md: allow reshape... |
4432 |
&md_reshape_position.attr, |
b522adcde md: 'array_size' ... |
4433 |
&md_array_size.attr, |
1e50915fe raid: improve MD/... |
4434 |
&max_corr_read_errors.attr, |
411036fa1 [PATCH] md: split... |
4435 4436 4437 4438 |
NULL, }; static struct attribute *md_redundancy_attrs[] = { |
24dd469d7 [PATCH] md: allow... |
4439 |
&md_scan_mode.attr, |
9d88883e6 [PATCH] md: teach... |
4440 |
&md_mismatches.attr, |
88202a0c8 [PATCH] md: allow... |
4441 4442 4443 |
&md_sync_min.attr, &md_sync_max.attr, &md_sync_speed.attr, |
90b08710e md: allow paralle... |
4444 |
&md_sync_force_parallel.attr, |
88202a0c8 [PATCH] md: allow... |
4445 |
&md_sync_completed.attr, |
5e96ee65c Allow setting sta... |
4446 |
&md_min_sync.attr, |
c62072777 md: allow a maxim... |
4447 |
&md_max_sync.attr, |
e464eafdb [PATCH] md: Suppo... |
4448 4449 |
&md_suspend_lo.attr, &md_suspend_hi.attr, |
9b1d1dac1 [PATCH] md: new s... |
4450 |
&md_bitmap.attr, |
d7f3d291a md: expose the de... |
4451 |
&md_degraded.attr, |
eae1701fb [PATCH] md: initi... |
4452 4453 |
NULL, }; |
411036fa1 [PATCH] md: split... |
4454 4455 4456 4457 |
static struct attribute_group md_redundancy_group = { .name = NULL, .attrs = md_redundancy_attrs, }; |
eae1701fb [PATCH] md: initi... |
4458 4459 4460 4461 4462 |
static ssize_t md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) { struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); |
fd01b88c7 md: remove typede... |
4463 |
struct mddev *mddev = container_of(kobj, struct mddev, kobj); |
96de1e663 [PATCH] md: fix s... |
4464 |
ssize_t rv; |
eae1701fb [PATCH] md: initi... |
4465 4466 4467 |
if (!entry->show) return -EIO; |
af8a24347 md: take a refere... |
4468 4469 4470 4471 4472 4473 4474 |
spin_lock(&all_mddevs_lock); if (list_empty(&mddev->all_mddevs)) { spin_unlock(&all_mddevs_lock); return -EBUSY; } mddev_get(mddev); spin_unlock(&all_mddevs_lock); |
5dc5cf7dd [PATCH] md: locki... |
4475 4476 4477 4478 4479 |
rv = mddev_lock(mddev); if (!rv) { rv = entry->show(mddev, page); mddev_unlock(mddev); } |
af8a24347 md: take a refere... |
4480 |
mddev_put(mddev); |
96de1e663 [PATCH] md: fix s... |
4481 |
return rv; |
eae1701fb [PATCH] md: initi... |
4482 4483 4484 4485 4486 4487 4488 |
} static ssize_t md_attr_store(struct kobject *kobj, struct attribute *attr, const char *page, size_t length) { struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); |
fd01b88c7 md: remove typede... |
4489 |
struct mddev *mddev = container_of(kobj, struct mddev, kobj); |
96de1e663 [PATCH] md: fix s... |
4490 |
ssize_t rv; |
eae1701fb [PATCH] md: initi... |
4491 4492 4493 |
if (!entry->store) return -EIO; |
67463acb6 [PATCH] md: requi... |
4494 4495 |
if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
af8a24347 md: take a refere... |
4496 4497 4498 4499 4500 4501 4502 |
spin_lock(&all_mddevs_lock); if (list_empty(&mddev->all_mddevs)) { spin_unlock(&all_mddevs_lock); return -EBUSY; } mddev_get(mddev); spin_unlock(&all_mddevs_lock); |
5dc5cf7dd [PATCH] md: locki... |
4503 4504 4505 4506 4507 |
rv = mddev_lock(mddev); if (!rv) { rv = entry->store(mddev, page, length); mddev_unlock(mddev); } |
af8a24347 md: take a refere... |
4508 |
mddev_put(mddev); |
96de1e663 [PATCH] md: fix s... |
4509 |
return rv; |
eae1701fb [PATCH] md: initi... |
4510 4511 4512 4513 |
} static void md_free(struct kobject *ko) { |
fd01b88c7 md: remove typede... |
4514 |
struct mddev *mddev = container_of(ko, struct mddev, kobj); |
a21d15042 md: centralise al... |
4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 |
if (mddev->sysfs_state) sysfs_put(mddev->sysfs_state); if (mddev->gendisk) { del_gendisk(mddev->gendisk); put_disk(mddev->gendisk); } if (mddev->queue) blk_cleanup_queue(mddev->queue); |
eae1701fb [PATCH] md: initi... |
4525 4526 |
kfree(mddev); } |
52cf25d0a Driver core: Cons... |
4527 |
static const struct sysfs_ops md_sysfs_ops = { |
eae1701fb [PATCH] md: initi... |
4528 4529 4530 4531 4532 4533 4534 4535 |
.show = md_attr_show, .store = md_attr_store, }; static struct kobj_type md_ktype = { .release = md_free, .sysfs_ops = &md_sysfs_ops, .default_attrs = md_default_attrs, }; |
1da177e4c Linux-2.6.12-rc2 |
4536 |
int mdp_major = 0; |
5fd3a17ed md: fix deadlock ... |
4537 4538 |
static void mddev_delayed_delete(struct work_struct *ws) { |
fd01b88c7 md: remove typede... |
4539 |
struct mddev *mddev = container_of(ws, struct mddev, del_work); |
5fd3a17ed md: fix deadlock ... |
4540 |
|
43a705076 md: support updat... |
4541 |
sysfs_remove_group(&mddev->kobj, &md_bitmap_group); |
5fd3a17ed md: fix deadlock ... |
4542 4543 4544 |
kobject_del(&mddev->kobj); kobject_put(&mddev->kobj); } |
efeb53c0e md: Allow md devi... |
4545 |
static int md_alloc(dev_t dev, char *name) |
1da177e4c Linux-2.6.12-rc2 |
4546 |
{ |
48c9c27b8 [PATCH] sem2mutex... |
4547 |
static DEFINE_MUTEX(disks_mutex); |
fd01b88c7 md: remove typede... |
4548 |
struct mddev *mddev = mddev_find(dev); |
1da177e4c Linux-2.6.12-rc2 |
4549 |
struct gendisk *disk; |
efeb53c0e md: Allow md devi... |
4550 4551 4552 |
int partitioned; int shift; int unit; |
3830c62fe Kobject: change d... |
4553 |
int error; |
1da177e4c Linux-2.6.12-rc2 |
4554 4555 |
if (!mddev) |
efeb53c0e md: Allow md devi... |
4556 4557 4558 4559 4560 |
return -ENODEV; partitioned = (MAJOR(mddev->unit) != MD_MAJOR); shift = partitioned ? MdpMinorShift : 0; unit = MINOR(mddev->unit) >> shift; |
1da177e4c Linux-2.6.12-rc2 |
4561 |
|
e804ac780 md: fix and updat... |
4562 4563 |
/* wait for any previous instance of this device to be * completely removed (mddev_delayed_delete). |
d3374825c md: make devices ... |
4564 |
*/ |
e804ac780 md: fix and updat... |
4565 |
flush_workqueue(md_misc_wq); |
d3374825c md: make devices ... |
4566 |
|
48c9c27b8 [PATCH] sem2mutex... |
4567 |
mutex_lock(&disks_mutex); |
0909dc448 md: tidy up error... |
4568 4569 4570 |
error = -EEXIST; if (mddev->gendisk) goto abort; |
efeb53c0e md: Allow md devi... |
4571 4572 4573 4574 |
if (name) { /* Need to ensure that 'name' is not a duplicate. */ |
fd01b88c7 md: remove typede... |
4575 |
struct mddev *mddev2; |
efeb53c0e md: Allow md devi... |
4576 4577 4578 4579 4580 4581 |
spin_lock(&all_mddevs_lock); list_for_each_entry(mddev2, &all_mddevs, all_mddevs) if (mddev2->gendisk && strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); |
0909dc448 md: tidy up error... |
4582 |
goto abort; |
efeb53c0e md: Allow md devi... |
4583 4584 |
} spin_unlock(&all_mddevs_lock); |
1da177e4c Linux-2.6.12-rc2 |
4585 |
} |
8b7653982 md: move allocati... |
4586 |
|
0909dc448 md: tidy up error... |
4587 |
error = -ENOMEM; |
8b7653982 md: move allocati... |
4588 |
mddev->queue = blk_alloc_queue(GFP_KERNEL); |
0909dc448 md: tidy up error... |
4589 4590 |
if (!mddev->queue) goto abort; |
409c57f38 md: enable suspen... |
4591 |
mddev->queue->queuedata = mddev; |
409c57f38 md: enable suspen... |
4592 |
blk_queue_make_request(mddev->queue, md_make_request); |
8b7653982 md: move allocati... |
4593 |
|
1da177e4c Linux-2.6.12-rc2 |
4594 4595 |
disk = alloc_disk(1 << shift); if (!disk) { |
8b7653982 md: move allocati... |
4596 4597 |
blk_cleanup_queue(mddev->queue); mddev->queue = NULL; |
0909dc448 md: tidy up error... |
4598 |
goto abort; |
1da177e4c Linux-2.6.12-rc2 |
4599 |
} |
efeb53c0e md: Allow md devi... |
4600 |
disk->major = MAJOR(mddev->unit); |
1da177e4c Linux-2.6.12-rc2 |
4601 |
disk->first_minor = unit << shift; |
efeb53c0e md: Allow md devi... |
4602 4603 4604 |
if (name) strcpy(disk->disk_name, name); else if (partitioned) |
1da177e4c Linux-2.6.12-rc2 |
4605 |
sprintf(disk->disk_name, "md_d%d", unit); |
ce7b0f46b [PATCH] devfs: Re... |
4606 |
else |
1da177e4c Linux-2.6.12-rc2 |
4607 |
sprintf(disk->disk_name, "md%d", unit); |
1da177e4c Linux-2.6.12-rc2 |
4608 4609 4610 |
disk->fops = &md_fops; disk->private_data = mddev; disk->queue = mddev->queue; |
b0140891a md: Fix race when... |
4611 |
blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA); |
92850bbd7 md: allow extende... |
4612 |
/* Allow extended partitions. This makes the |
d3374825c md: make devices ... |
4613 |
* 'mdp' device redundant, but we can't really |
92850bbd7 md: allow extende... |
4614 4615 4616 |
* remove it now. */ disk->flags |= GENHD_FL_EXT_DEVT; |
1da177e4c Linux-2.6.12-rc2 |
4617 |
mddev->gendisk = disk; |
b0140891a md: Fix race when... |
4618 4619 4620 4621 4622 |
/* As soon as we call add_disk(), another thread could get * through to md_open, so make sure it doesn't get too far */ mutex_lock(&mddev->open_mutex); add_disk(disk); |
ed9e19823 block: implement ... |
4623 4624 |
error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk_to_dev(disk)->kobj, "%s", "md"); |
0909dc448 md: tidy up error... |
4625 4626 4627 4628 |
if (error) { /* This isn't possible, but as kobject_init_and_add is marked * __must_check, we must do something with the result */ |
5e55e2f5f [PATCH] md: conve... |
4629 4630 4631 |
printk(KERN_WARNING "md: cannot register %s/md - name in use ", disk->disk_name); |
0909dc448 md: tidy up error... |
4632 4633 |
error = 0; } |
00bcb4ac7 md: reduce depend... |
4634 4635 |
if (mddev->kobj.sd && sysfs_create_group(&mddev->kobj, &md_bitmap_group)) |
43a705076 md: support updat... |
4636 4637 |
printk(KERN_DEBUG "pointless warning "); |
b0140891a md: Fix race when... |
4638 |
mutex_unlock(&mddev->open_mutex); |
0909dc448 md: tidy up error... |
4639 4640 |
abort: mutex_unlock(&disks_mutex); |
00bcb4ac7 md: reduce depend... |
4641 |
if (!error && mddev->kobj.sd) { |
3830c62fe Kobject: change d... |
4642 |
kobject_uevent(&mddev->kobj, KOBJ_ADD); |
00bcb4ac7 md: reduce depend... |
4643 |
mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); |
b62b75905 md: use sysfs_not... |
4644 |
} |
d3374825c md: make devices ... |
4645 |
mddev_put(mddev); |
0909dc448 md: tidy up error... |
4646 |
return error; |
efeb53c0e md: Allow md devi... |
4647 4648 4649 4650 4651 |
} static struct kobject *md_probe(dev_t dev, int *part, void *data) { md_alloc(dev, NULL); |
1da177e4c Linux-2.6.12-rc2 |
4652 4653 |
return NULL; } |
efeb53c0e md: Allow md devi... |
4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 |
static int add_named_array(const char *val, struct kernel_param *kp) { /* val must be "md_*" where * is not all digits. * We allocate an array with a large free minor number, and * set the name to val. val must not already be an active name. */ int len = strlen(val); char buf[DISK_NAME_LEN]; while (len && val[len-1] == ' ') len--; if (len >= DISK_NAME_LEN) return -E2BIG; strlcpy(buf, val, len+1); if (strncmp(buf, "md_", 3) != 0) return -EINVAL; return md_alloc(0, buf); } |
1da177e4c Linux-2.6.12-rc2 |
4673 4674 |
static void md_safemode_timeout(unsigned long data) { |
fd01b88c7 md: remove typede... |
4675 |
struct mddev *mddev = (struct mddev *) data; |
1da177e4c Linux-2.6.12-rc2 |
4676 |
|
0fd62b861 Make sure all cha... |
4677 4678 4679 |
if (!atomic_read(&mddev->writes_pending)) { mddev->safemode = 1; if (mddev->external) |
00bcb4ac7 md: reduce depend... |
4680 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
0fd62b861 Make sure all cha... |
4681 |
} |
1da177e4c Linux-2.6.12-rc2 |
4682 4683 |
md_wakeup_thread(mddev->thread); } |
6ff8d8ec0 [PATCH] md: allow... |
4684 |
static int start_dirty_degraded; |
1da177e4c Linux-2.6.12-rc2 |
4685 |
|
fd01b88c7 md: remove typede... |
4686 |
int md_run(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
4687 |
{ |
2604b703b [PATCH] md: remov... |
4688 |
int err; |
3cb030020 md: removing type... |
4689 |
struct md_rdev *rdev; |
84fc4b56d md: rename "mdk_p... |
4690 |
struct md_personality *pers; |
1da177e4c Linux-2.6.12-rc2 |
4691 |
|
a757e64cf [PATCH] md: remov... |
4692 4693 |
if (list_empty(&mddev->disks)) /* cannot run an array with no devices.. */ |
1da177e4c Linux-2.6.12-rc2 |
4694 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
4695 4696 4697 |
if (mddev->pers) return -EBUSY; |
bb4f1e9d0 md: fix another d... |
4698 4699 4700 |
/* Cannot run until previous stop completes properly */ if (mddev->sysfs_active) return -EBUSY; |
b6eb127d2 md: remove unneed... |
4701 |
|
1da177e4c Linux-2.6.12-rc2 |
4702 4703 4704 |
/* * Analyze all RAID superblock(s) */ |
1ec4a9398 md: set and test ... |
4705 4706 4707 |
if (!mddev->raid_disks) { if (!mddev->persistent) return -EINVAL; |
a757e64cf [PATCH] md: remov... |
4708 |
analyze_sbs(mddev); |
1ec4a9398 md: set and test ... |
4709 |
} |
1da177e4c Linux-2.6.12-rc2 |
4710 |
|
d9d166c2a [PATCH] md: allow... |
4711 4712 4713 4714 |
if (mddev->level != LEVEL_NONE) request_module("md-level-%d", mddev->level); else if (mddev->clevel[0]) request_module("md-%s", mddev->clevel); |
1da177e4c Linux-2.6.12-rc2 |
4715 4716 4717 4718 4719 |
/* * Drop all container device buffers, from now on * the only valid external interface is through the md * device. |
1da177e4c Linux-2.6.12-rc2 |
4720 |
*/ |
159ec1fc0 md: use list_for_... |
4721 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
b2d444d7a [PATCH] md: conve... |
4722 |
if (test_bit(Faulty, &rdev->flags)) |
1da177e4c Linux-2.6.12-rc2 |
4723 4724 |
continue; sync_blockdev(rdev->bdev); |
f98393a64 mm: remove destro... |
4725 |
invalidate_bdev(rdev->bdev); |
f0d76d70b md: check that in... |
4726 4727 4728 |
/* perform some consistency tests on the device. * We don't want the data to overlap the metadata, |
58c0fed40 md: Make mddev->s... |
4729 |
* Internal Bitmap issues have been handled elsewhere. |
f0d76d70b md: check that in... |
4730 |
*/ |
a6ff7e089 md: separate meta... |
4731 4732 4733 |
if (rdev->meta_bdev) { /* Nothing to check */; } else if (rdev->data_offset < rdev->sb_start) { |
58c0fed40 md: Make mddev->s... |
4734 4735 |
if (mddev->dev_sectors && rdev->data_offset + mddev->dev_sectors |
0f420358e md: Turn rdev->sb... |
4736 |
> rdev->sb_start) { |
f0d76d70b md: check that in... |
4737 4738 4739 4740 4741 4742 |
printk("md: %s: data overlaps metadata ", mdname(mddev)); return -EINVAL; } } else { |
0f420358e md: Turn rdev->sb... |
4743 |
if (rdev->sb_start + rdev->sb_size/512 |
f0d76d70b md: check that in... |
4744 4745 4746 4747 4748 4749 4750 |
> rdev->data_offset) { printk("md: %s: metadata overlaps data ", mdname(mddev)); return -EINVAL; } } |
00bcb4ac7 md: reduce depend... |
4751 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
1da177e4c Linux-2.6.12-rc2 |
4752 |
} |
a167f6632 md: use separate ... |
4753 |
if (mddev->bio_set == NULL) |
a519b26db md: remove suspic... |
4754 |
mddev->bio_set = bioset_create(BIO_POOL_SIZE, |
fd01b88c7 md: remove typede... |
4755 |
sizeof(struct mddev *)); |
a167f6632 md: use separate ... |
4756 |
|
1da177e4c Linux-2.6.12-rc2 |
4757 |
spin_lock(&pers_lock); |
d9d166c2a [PATCH] md: allow... |
4758 |
pers = find_pers(mddev->level, mddev->clevel); |
2604b703b [PATCH] md: remov... |
4759 |
if (!pers || !try_module_get(pers->owner)) { |
1da177e4c Linux-2.6.12-rc2 |
4760 |
spin_unlock(&pers_lock); |
d9d166c2a [PATCH] md: allow... |
4761 4762 4763 4764 4765 4766 4767 4768 |
if (mddev->level != LEVEL_NONE) printk(KERN_WARNING "md: personality for level %d is not loaded! ", mddev->level); else printk(KERN_WARNING "md: personality for level %s is not loaded! ", mddev->clevel); |
1da177e4c Linux-2.6.12-rc2 |
4769 4770 |
return -EINVAL; } |
2604b703b [PATCH] md: remov... |
4771 |
mddev->pers = pers; |
1da177e4c Linux-2.6.12-rc2 |
4772 |
spin_unlock(&pers_lock); |
34817e8c3 md: make sure new... |
4773 4774 4775 4776 |
if (mddev->level != pers->level) { mddev->level = pers->level; mddev->new_level = pers->level; } |
d9d166c2a [PATCH] md: allow... |
4777 |
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); |
1da177e4c Linux-2.6.12-rc2 |
4778 |
|
f67055780 [PATCH] md: Check... |
4779 |
if (mddev->reshape_position != MaxSector && |
63c70c4f3 [PATCH] md: Split... |
4780 |
pers->start_reshape == NULL) { |
f67055780 [PATCH] md: Check... |
4781 4782 4783 4784 4785 |
/* This personality cannot handle reshaping... */ mddev->pers = NULL; module_put(pers->owner); return -EINVAL; } |
7dd5e7c3d [PATCH] md: move ... |
4786 4787 4788 4789 4790 |
if (pers->sync_request) { /* Warn if this is a potentially silly * configuration. */ char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; |
3cb030020 md: removing type... |
4791 |
struct md_rdev *rdev2; |
7dd5e7c3d [PATCH] md: move ... |
4792 |
int warned = 0; |
159ec1fc0 md: use list_for_... |
4793 4794 4795 |
list_for_each_entry(rdev, &mddev->disks, same_set) list_for_each_entry(rdev2, &mddev->disks, same_set) { |
7dd5e7c3d [PATCH] md: move ... |
4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 |
if (rdev < rdev2 && rdev->bdev->bd_contains == rdev2->bdev->bd_contains) { printk(KERN_WARNING "%s: WARNING: %s appears to be" " on the same physical disk as" " %s. ", mdname(mddev), bdevname(rdev->bdev,b), bdevname(rdev2->bdev,b2)); warned = 1; } } |
159ec1fc0 md: use list_for_... |
4810 |
|
7dd5e7c3d [PATCH] md: move ... |
4811 4812 4813 4814 4815 4816 |
if (warned) printk(KERN_WARNING "True protection against single-disk" " failure might be compromised. "); } |
657390d25 [PATCH] md: clear... |
4817 |
mddev->recovery = 0; |
58c0fed40 md: Make mddev->s... |
4818 4819 |
/* may be over-ridden by personality */ mddev->resync_max_sectors = mddev->dev_sectors; |
6ff8d8ec0 [PATCH] md: allow... |
4820 |
mddev->ok_start_degraded = start_dirty_degraded; |
1da177e4c Linux-2.6.12-rc2 |
4821 |
|
0f9552b5d md: fix small irr... |
4822 |
if (start_readonly && mddev->ro == 0) |
f91de92ed [PATCH] md: allow... |
4823 |
mddev->ro = 2; /* read-only, but switch on first write */ |
b15c2e57f [PATCH] md: move ... |
4824 |
err = mddev->pers->run(mddev); |
13e53df35 md: do_md_run(): ... |
4825 4826 4827 |
if (err) printk(KERN_ERR "md: pers->run() failed ... "); |
b522adcde md: 'array_size' ... |
4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 |
else if (mddev->pers->size(mddev, 0, 0) < mddev->array_sectors) { WARN_ONCE(!mddev->external_size, "%s: default size too small," " but 'external_size' not in effect? ", __func__); printk(KERN_ERR "md: invalid array_size %llu > default size %llu ", (unsigned long long)mddev->array_sectors / 2, (unsigned long long)mddev->pers->size(mddev, 0, 0) / 2); err = -EINVAL; mddev->pers->stop(mddev); } if (err == 0 && mddev->pers->sync_request) { |
b15c2e57f [PATCH] md: move ... |
4841 4842 4843 4844 4845 4846 4847 4848 |
err = bitmap_create(mddev); if (err) { printk(KERN_ERR "%s: failed to create bitmap (%d) ", mdname(mddev), err); mddev->pers->stop(mddev); } } |
1da177e4c Linux-2.6.12-rc2 |
4849 |
if (err) { |
1da177e4c Linux-2.6.12-rc2 |
4850 4851 |
module_put(mddev->pers->owner); mddev->pers = NULL; |
32a7627cf [PATCH] md: optim... |
4852 4853 |
bitmap_destroy(mddev); return err; |
1da177e4c Linux-2.6.12-rc2 |
4854 |
} |
5e55e2f5f [PATCH] md: conve... |
4855 |
if (mddev->pers->sync_request) { |
00bcb4ac7 md: reduce depend... |
4856 4857 |
if (mddev->kobj.sd && sysfs_create_group(&mddev->kobj, &md_redundancy_group)) |
5e55e2f5f [PATCH] md: conve... |
4858 4859 4860 4861 |
printk(KERN_WARNING "md: cannot register extra attributes for %s ", mdname(mddev)); |
00bcb4ac7 md: reduce depend... |
4862 |
mddev->sysfs_action = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_action"); |
5e55e2f5f [PATCH] md: conve... |
4863 |
} else if (mddev->ro == 2) /* auto-readonly not meaningful */ |
fd9d49cac [PATCH] md: ignor... |
4864 |
mddev->ro = 0; |
1da177e4c Linux-2.6.12-rc2 |
4865 |
atomic_set(&mddev->writes_pending,0); |
1e50915fe raid: improve MD/... |
4866 4867 |
atomic_set(&mddev->max_corr_read_errors, MD_DEFAULT_MAX_CORRECTED_READ_ERRORS); |
1da177e4c Linux-2.6.12-rc2 |
4868 4869 4870 |
mddev->safemode = 0; mddev->safemode_timer.function = md_safemode_timeout; mddev->safemode_timer.data = (unsigned long) mddev; |
16f17b39f [PATCH] md: incre... |
4871 |
mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ |
1da177e4c Linux-2.6.12-rc2 |
4872 |
mddev->in_sync = 1; |
0ca69886a md: Ensure no IO ... |
4873 4874 |
smp_wmb(); mddev->ready = 1; |
159ec1fc0 md: use list_for_... |
4875 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
36fad858a md: introduce lin... |
4876 4877 |
if (rdev->raid_disk >= 0) if (sysfs_link_rdev(mddev, rdev)) |
00bcb4ac7 md: reduce depend... |
4878 |
/* failure here is OK */; |
1da177e4c Linux-2.6.12-rc2 |
4879 4880 4881 |
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
850b2b420 [PATCH] md: repla... |
4882 4883 |
if (mddev->flags) md_update_sb(mddev, 0); |
1da177e4c Linux-2.6.12-rc2 |
4884 |
|
d7603b7e3 [PATCH] md: make ... |
4885 |
md_new_event(mddev); |
00bcb4ac7 md: reduce depend... |
4886 4887 |
sysfs_notify_dirent_safe(mddev->sysfs_state); sysfs_notify_dirent_safe(mddev->sysfs_action); |
a99ac9711 Make sure all cha... |
4888 |
sysfs_notify(&mddev->kobj, NULL, "degraded"); |
1da177e4c Linux-2.6.12-rc2 |
4889 4890 |
return 0; } |
390ee602a md: export variou... |
4891 |
EXPORT_SYMBOL_GPL(md_run); |
1da177e4c Linux-2.6.12-rc2 |
4892 |
|
fd01b88c7 md: remove typede... |
4893 |
static int do_md_run(struct mddev *mddev) |
fe60b0142 md: factor do_md_... |
4894 4895 4896 4897 4898 4899 |
{ int err; err = md_run(mddev); if (err) goto out; |
69e51b449 md/bitmap: separ... |
4900 4901 4902 4903 4904 |
err = bitmap_load(mddev); if (err) { bitmap_destroy(mddev); goto out; } |
0fd018af3 MD: move thread w... |
4905 4906 4907 |
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ |
fe60b0142 md: factor do_md_... |
4908 4909 |
set_capacity(mddev->gendisk, mddev->array_sectors); revalidate_disk(mddev->gendisk); |
f0b4f7e2f md: Fix - again -... |
4910 |
mddev->changed = 1; |
fe60b0142 md: factor do_md_... |
4911 4912 4913 4914 |
kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); out: return err; } |
fd01b88c7 md: remove typede... |
4915 |
static int restart_array(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
4916 4917 |
{ struct gendisk *disk = mddev->gendisk; |
1da177e4c Linux-2.6.12-rc2 |
4918 |
|
80fab1d77 md: Simplify rest... |
4919 |
/* Complain if it has no devices */ |
1da177e4c Linux-2.6.12-rc2 |
4920 |
if (list_empty(&mddev->disks)) |
80fab1d77 md: Simplify rest... |
4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 |
return -ENXIO; if (!mddev->pers) return -EINVAL; if (!mddev->ro) return -EBUSY; mddev->safemode = 0; mddev->ro = 0; set_disk_ro(disk, 0); printk(KERN_INFO "md: %s switched to read-write mode. ", mdname(mddev)); /* Kick recovery or resync if necessary */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->sync_thread); |
00bcb4ac7 md: reduce depend... |
4936 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
80fab1d77 md: Simplify rest... |
4937 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
4938 |
} |
acc55e220 [PATCH] md/bitmap... |
4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 |
/* similar to deny_write_access, but accounts for our holding a reference * to the file ourselves */ static int deny_bitmap_write_access(struct file * file) { struct inode *inode = file->f_mapping->host; spin_lock(&inode->i_lock); if (atomic_read(&inode->i_writecount) > 1) { spin_unlock(&inode->i_lock); return -ETXTBSY; } atomic_set(&inode->i_writecount, -1); spin_unlock(&inode->i_lock); return 0; } |
43a705076 md: support updat... |
4955 |
void restore_bitmap_write_access(struct file *file) |
acc55e220 [PATCH] md/bitmap... |
4956 4957 4958 4959 4960 4961 4962 |
{ struct inode *inode = file->f_mapping->host; spin_lock(&inode->i_lock); atomic_set(&inode->i_writecount, 1); spin_unlock(&inode->i_lock); } |
fd01b88c7 md: remove typede... |
4963 |
static void md_clean(struct mddev *mddev) |
6177b472a md: start to refa... |
4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 |
{ mddev->array_sectors = 0; mddev->external_size = 0; mddev->dev_sectors = 0; mddev->raid_disks = 0; mddev->recovery_cp = 0; mddev->resync_min = 0; mddev->resync_max = MaxSector; mddev->reshape_position = MaxSector; mddev->external = 0; mddev->persistent = 0; mddev->level = LEVEL_NONE; mddev->clevel[0] = 0; mddev->flags = 0; mddev->ro = 0; mddev->metadata_type[0] = 0; mddev->chunk_sectors = 0; mddev->ctime = mddev->utime = 0; mddev->layout = 0; mddev->max_disks = 0; mddev->events = 0; |
a8707c08f md: simplify upda... |
4985 |
mddev->can_decrease_events = 0; |
6177b472a md: start to refa... |
4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 |
mddev->delta_disks = 0; mddev->new_level = LEVEL_NONE; mddev->new_layout = 0; mddev->new_chunk_sectors = 0; mddev->curr_resync = 0; mddev->resync_mismatches = 0; mddev->suspend_lo = mddev->suspend_hi = 0; mddev->sync_speed_min = mddev->sync_speed_max = 0; mddev->recovery = 0; mddev->in_sync = 0; |
f0b4f7e2f md: Fix - again -... |
4996 |
mddev->changed = 0; |
6177b472a md: start to refa... |
4997 |
mddev->degraded = 0; |
6177b472a md: start to refa... |
4998 4999 5000 5001 5002 5003 5004 |
mddev->safemode = 0; mddev->bitmap_info.offset = 0; mddev->bitmap_info.default_offset = 0; mddev->bitmap_info.chunksize = 0; mddev->bitmap_info.daemon_sleep = 0; mddev->bitmap_info.max_write_behind = 0; } |
fd01b88c7 md: remove typede... |
5005 |
static void __md_stop_writes(struct mddev *mddev) |
a047e1254 md: factor md_sto... |
5006 5007 5008 5009 |
{ if (mddev->sync_thread) { set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
7ebc0be7f md: Be more caref... |
5010 |
reap_sync_thread(mddev); |
a047e1254 md: factor md_sto... |
5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 |
} del_timer_sync(&mddev->safemode_timer); bitmap_flush(mddev); md_super_wait(mddev); if (!mddev->in_sync || mddev->flags) { /* mark array as shutdown cleanly */ mddev->in_sync = 1; md_update_sb(mddev, 1); } } |
defad61a5 md: md_stop_write... |
5024 |
|
fd01b88c7 md: remove typede... |
5025 |
void md_stop_writes(struct mddev *mddev) |
defad61a5 md: md_stop_write... |
5026 5027 5028 5029 5030 |
{ mddev_lock(mddev); __md_stop_writes(mddev); mddev_unlock(mddev); } |
390ee602a md: export variou... |
5031 |
EXPORT_SYMBOL_GPL(md_stop_writes); |
a047e1254 md: factor md_sto... |
5032 |
|
fd01b88c7 md: remove typede... |
5033 |
void md_stop(struct mddev *mddev) |
6177b472a md: start to refa... |
5034 |
{ |
0ca69886a md: Ensure no IO ... |
5035 |
mddev->ready = 0; |
6177b472a md: start to refa... |
5036 5037 5038 5039 5040 |
mddev->pers->stop(mddev); if (mddev->pers->sync_request && mddev->to_remove == NULL) mddev->to_remove = &md_redundancy_group; module_put(mddev->pers->owner); mddev->pers = NULL; |
cca9cf90c md: call md_stop_... |
5041 |
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
6177b472a md: start to refa... |
5042 |
} |
390ee602a md: export variou... |
5043 |
EXPORT_SYMBOL_GPL(md_stop); |
6177b472a md: start to refa... |
5044 |
|
fd01b88c7 md: remove typede... |
5045 |
static int md_set_readonly(struct mddev *mddev, int is_open) |
a4bd82d0d md: split md_set_... |
5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 |
{ int err = 0; mutex_lock(&mddev->open_mutex); if (atomic_read(&mddev->openers) > is_open) { printk("md: %s still in use. ",mdname(mddev)); err = -EBUSY; goto out; } if (mddev->pers) { |
defad61a5 md: md_stop_write... |
5056 |
__md_stop_writes(mddev); |
a4bd82d0d md: split md_set_... |
5057 5058 5059 5060 5061 5062 5063 |
err = -ENXIO; if (mddev->ro==1) goto out; mddev->ro = 1; set_disk_ro(mddev->gendisk, 1); clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
00bcb4ac7 md: reduce depend... |
5064 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
a4bd82d0d md: split md_set_... |
5065 5066 5067 5068 5069 5070 |
err = 0; } out: mutex_unlock(&mddev->open_mutex); return err; } |
9e653b634 [PATCH] md: Set/g... |
5071 5072 |
/* mode: * 0 - completely stop and dis-assemble array |
9e653b634 [PATCH] md: Set/g... |
5073 5074 |
* 2 - stop but do not disassemble array */ |
fd01b88c7 md: remove typede... |
5075 |
static int do_md_stop(struct mddev * mddev, int mode, int is_open) |
1da177e4c Linux-2.6.12-rc2 |
5076 |
{ |
1da177e4c Linux-2.6.12-rc2 |
5077 |
struct gendisk *disk = mddev->gendisk; |
3cb030020 md: removing type... |
5078 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5079 |
|
c8c00a691 Remove deadlock p... |
5080 |
mutex_lock(&mddev->open_mutex); |
bb4f1e9d0 md: fix another d... |
5081 5082 |
if (atomic_read(&mddev->openers) > is_open || mddev->sysfs_active) { |
df5b20cf6 md: Better contro... |
5083 5084 |
printk("md: %s still in use. ",mdname(mddev)); |
6e17b0276 md: clean up do_m... |
5085 5086 5087 |
mutex_unlock(&mddev->open_mutex); return -EBUSY; } |
1da177e4c Linux-2.6.12-rc2 |
5088 |
|
6e17b0276 md: clean up do_m... |
5089 |
if (mddev->pers) { |
a4bd82d0d md: split md_set_... |
5090 5091 |
if (mddev->ro) set_disk_ro(disk, 0); |
409c57f38 md: enable suspen... |
5092 |
|
defad61a5 md: md_stop_write... |
5093 |
__md_stop_writes(mddev); |
a4bd82d0d md: split md_set_... |
5094 5095 |
md_stop(mddev); mddev->queue->merge_bvec_fn = NULL; |
a4bd82d0d md: split md_set_... |
5096 |
mddev->queue->backing_dev_info.congested_fn = NULL; |
6177b472a md: start to refa... |
5097 |
|
a4bd82d0d md: split md_set_... |
5098 |
/* tell userspace to handle 'inactive' */ |
00bcb4ac7 md: reduce depend... |
5099 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
0d4ca600f [PATCH] md: tidy ... |
5100 |
|
a4bd82d0d md: split md_set_... |
5101 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
36fad858a md: introduce lin... |
5102 5103 |
if (rdev->raid_disk >= 0) sysfs_unlink_rdev(mddev, rdev); |
c4647292f md: remove rd%d l... |
5104 |
|
a4bd82d0d md: split md_set_... |
5105 |
set_capacity(disk, 0); |
6e17b0276 md: clean up do_m... |
5106 |
mutex_unlock(&mddev->open_mutex); |
f0b4f7e2f md: Fix - again -... |
5107 |
mddev->changed = 1; |
a4bd82d0d md: split md_set_... |
5108 |
revalidate_disk(disk); |
0d4ca600f [PATCH] md: tidy ... |
5109 |
|
a4bd82d0d md: split md_set_... |
5110 5111 |
if (mddev->ro) mddev->ro = 0; |
6e17b0276 md: clean up do_m... |
5112 5113 |
} else mutex_unlock(&mddev->open_mutex); |
1da177e4c Linux-2.6.12-rc2 |
5114 5115 5116 |
/* * Free resources if final stop */ |
9e653b634 [PATCH] md: Set/g... |
5117 |
if (mode == 0) { |
1da177e4c Linux-2.6.12-rc2 |
5118 5119 |
printk(KERN_INFO "md: %s stopped. ", mdname(mddev)); |
978f946bb [PATCH] md: Don't... |
5120 |
bitmap_destroy(mddev); |
c3d9714e8 md: collect bitma... |
5121 5122 5123 5124 |
if (mddev->bitmap_info.file) { restore_bitmap_write_access(mddev->bitmap_info.file); fput(mddev->bitmap_info.file); mddev->bitmap_info.file = NULL; |
978f946bb [PATCH] md: Don't... |
5125 |
} |
c3d9714e8 md: collect bitma... |
5126 |
mddev->bitmap_info.offset = 0; |
978f946bb [PATCH] md: Don't... |
5127 |
|
1da177e4c Linux-2.6.12-rc2 |
5128 |
export_array(mddev); |
6177b472a md: start to refa... |
5129 |
md_clean(mddev); |
934d9c23b md: destroy parti... |
5130 |
kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); |
efeb53c0e md: Allow md devi... |
5131 5132 |
if (mddev->hold_active == UNTIL_STOP) mddev->hold_active = 0; |
a4bd82d0d md: split md_set_... |
5133 |
} |
3f9d99c12 MD data integrity... |
5134 |
blk_integrity_unregister(disk); |
d7603b7e3 [PATCH] md: make ... |
5135 |
md_new_event(mddev); |
00bcb4ac7 md: reduce depend... |
5136 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
6e17b0276 md: clean up do_m... |
5137 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
5138 |
} |
fdee8ae44 [PATCH] MD: condi... |
5139 |
#ifndef MODULE |
fd01b88c7 md: remove typede... |
5140 |
static void autorun_array(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
5141 |
{ |
3cb030020 md: removing type... |
5142 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5143 |
int err; |
a757e64cf [PATCH] md: remov... |
5144 |
if (list_empty(&mddev->disks)) |
1da177e4c Linux-2.6.12-rc2 |
5145 |
return; |
1da177e4c Linux-2.6.12-rc2 |
5146 5147 |
printk(KERN_INFO "md: running: "); |
159ec1fc0 md: use list_for_... |
5148 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
5149 5150 5151 5152 5153 |
char b[BDEVNAME_SIZE]; printk("<%s>", bdevname(rdev->bdev,b)); } printk(" "); |
d710e1381 md: remove space ... |
5154 |
err = do_md_run(mddev); |
1da177e4c Linux-2.6.12-rc2 |
5155 5156 5157 |
if (err) { printk(KERN_WARNING "md: do_md_run() returned %d ", err); |
d710e1381 md: remove space ... |
5158 |
do_md_stop(mddev, 0, 0); |
1da177e4c Linux-2.6.12-rc2 |
5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 |
} } /* * lets try to run arrays based on all disks that have arrived * until now. (those are in pending_raid_disks) * * the method: pick the first pending disk, collect all disks with * the same UUID, remove all from the pending list and put them into * the 'same_array' list. Then order this list based on superblock * update time (freshest comes first), kick out 'old' disks and * compare superblocks. If everything's fine then run it. * * If "unit" is allocated, then bump its reference count */ static void autorun_devices(int part) { |
3cb030020 md: removing type... |
5176 |
struct md_rdev *rdev0, *rdev, *tmp; |
fd01b88c7 md: remove typede... |
5177 |
struct mddev *mddev; |
1da177e4c Linux-2.6.12-rc2 |
5178 5179 5180 5181 5182 |
char b[BDEVNAME_SIZE]; printk(KERN_INFO "md: autorun ... "); while (!list_empty(&pending_raid_disks)) { |
e8703fe1f [PATCH] md: remov... |
5183 |
int unit; |
1da177e4c Linux-2.6.12-rc2 |
5184 |
dev_t dev; |
ad01c9e37 [PATCH] md: Allow... |
5185 |
LIST_HEAD(candidates); |
1da177e4c Linux-2.6.12-rc2 |
5186 |
rdev0 = list_entry(pending_raid_disks.next, |
3cb030020 md: removing type... |
5187 |
struct md_rdev, same_set); |
1da177e4c Linux-2.6.12-rc2 |
5188 5189 5190 5191 5192 |
printk(KERN_INFO "md: considering %s ... ", bdevname(rdev0->bdev,b)); INIT_LIST_HEAD(&candidates); |
159ec1fc0 md: use list_for_... |
5193 |
rdev_for_each_list(rdev, tmp, &pending_raid_disks) |
1da177e4c Linux-2.6.12-rc2 |
5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 |
if (super_90_load(rdev, rdev0, 0) >= 0) { printk(KERN_INFO "md: adding %s ... ", bdevname(rdev->bdev,b)); list_move(&rdev->same_set, &candidates); } /* * now we have a set of devices, with all of them having * mostly sane superblocks. It's time to allocate the * mddev. */ |
e8703fe1f [PATCH] md: remov... |
5205 5206 5207 5208 5209 5210 5211 5212 5213 |
if (part) { dev = MKDEV(mdp_major, rdev0->preferred_minor << MdpMinorShift); unit = MINOR(dev) >> MdpMinorShift; } else { dev = MKDEV(MD_MAJOR, rdev0->preferred_minor); unit = MINOR(dev); } if (rdev0->preferred_minor != unit) { |
1da177e4c Linux-2.6.12-rc2 |
5214 5215 5216 5217 5218 |
printk(KERN_INFO "md: unit number in %s is bad: %d ", bdevname(rdev0->bdev, b), rdev0->preferred_minor); break; } |
1da177e4c Linux-2.6.12-rc2 |
5219 5220 5221 |
md_probe(dev, NULL, NULL); mddev = mddev_find(dev); |
9bbbca3a0 Fix error paths i... |
5222 5223 5224 5225 |
if (!mddev || !mddev->gendisk) { if (mddev) mddev_put(mddev); printk(KERN_ERR |
1da177e4c Linux-2.6.12-rc2 |
5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 |
"md: cannot allocate memory for md drive. "); break; } if (mddev_lock(mddev)) printk(KERN_WARNING "md: %s locked, cannot run ", mdname(mddev)); else if (mddev->raid_disks || mddev->major_version || !list_empty(&mddev->disks)) { printk(KERN_WARNING "md: %s already running, cannot run %s ", mdname(mddev), bdevname(rdev0->bdev,b)); mddev_unlock(mddev); } else { printk(KERN_INFO "md: created %s ", mdname(mddev)); |
1ec4a9398 md: set and test ... |
5244 |
mddev->persistent = 1; |
159ec1fc0 md: use list_for_... |
5245 |
rdev_for_each_list(rdev, tmp, &candidates) { |
1da177e4c Linux-2.6.12-rc2 |
5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 |
list_del_init(&rdev->same_set); if (bind_rdev_to_array(rdev, mddev)) export_rdev(rdev); } autorun_array(mddev); mddev_unlock(mddev); } /* on success, candidates will be empty, on error * it won't... */ |
159ec1fc0 md: use list_for_... |
5256 |
rdev_for_each_list(rdev, tmp, &candidates) { |
4b80991c6 md: Protect acces... |
5257 |
list_del_init(&rdev->same_set); |
1da177e4c Linux-2.6.12-rc2 |
5258 |
export_rdev(rdev); |
4b80991c6 md: Protect acces... |
5259 |
} |
1da177e4c Linux-2.6.12-rc2 |
5260 5261 5262 5263 5264 |
mddev_put(mddev); } printk(KERN_INFO "md: ... autorun DONE. "); } |
fdee8ae44 [PATCH] MD: condi... |
5265 |
#endif /* !MODULE */ |
1da177e4c Linux-2.6.12-rc2 |
5266 |
|
1da177e4c Linux-2.6.12-rc2 |
5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 |
static int get_version(void __user * arg) { mdu_version_t ver; ver.major = MD_MAJOR_VERSION; ver.minor = MD_MINOR_VERSION; ver.patchlevel = MD_PATCHLEVEL_VERSION; if (copy_to_user(arg, &ver, sizeof(ver))) return -EFAULT; return 0; } |
fd01b88c7 md: remove typede... |
5280 |
static int get_array_info(struct mddev * mddev, void __user * arg) |
1da177e4c Linux-2.6.12-rc2 |
5281 5282 |
{ mdu_array_info_t info; |
a9f326ebf md: remove sparse... |
5283 |
int nr,working,insync,failed,spare; |
3cb030020 md: removing type... |
5284 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5285 |
|
a9f326ebf md: remove sparse... |
5286 |
nr=working=insync=failed=spare=0; |
159ec1fc0 md: use list_for_... |
5287 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
5288 |
nr++; |
b2d444d7a [PATCH] md: conve... |
5289 |
if (test_bit(Faulty, &rdev->flags)) |
1da177e4c Linux-2.6.12-rc2 |
5290 5291 5292 |
failed++; else { working++; |
b2d444d7a [PATCH] md: conve... |
5293 |
if (test_bit(In_sync, &rdev->flags)) |
a9f326ebf md: remove sparse... |
5294 |
insync++; |
1da177e4c Linux-2.6.12-rc2 |
5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 |
else spare++; } } info.major_version = mddev->major_version; info.minor_version = mddev->minor_version; info.patch_version = MD_PATCHLEVEL_VERSION; info.ctime = mddev->ctime; info.level = mddev->level; |
58c0fed40 md: Make mddev->s... |
5305 5306 |
info.size = mddev->dev_sectors / 2; if (info.size != mddev->dev_sectors / 2) /* overflow */ |
284ae7cab [PATCH] md: Handl... |
5307 |
info.size = -1; |
1da177e4c Linux-2.6.12-rc2 |
5308 5309 5310 5311 5312 5313 5314 5315 5316 |
info.nr_disks = nr; info.raid_disks = mddev->raid_disks; info.md_minor = mddev->md_minor; info.not_persistent= !mddev->persistent; info.utime = mddev->utime; info.state = 0; if (mddev->in_sync) info.state = (1<<MD_SB_CLEAN); |
c3d9714e8 md: collect bitma... |
5317 |
if (mddev->bitmap && mddev->bitmap_info.offset) |
36fa30636 [PATCH] md: all h... |
5318 |
info.state = (1<<MD_SB_BITMAP_PRESENT); |
a9f326ebf md: remove sparse... |
5319 |
info.active_disks = insync; |
1da177e4c Linux-2.6.12-rc2 |
5320 5321 5322 5323 5324 |
info.working_disks = working; info.failed_disks = failed; info.spare_disks = spare; info.layout = mddev->layout; |
9d8f03636 md: Make mddev->c... |
5325 |
info.chunk_size = mddev->chunk_sectors << 9; |
1da177e4c Linux-2.6.12-rc2 |
5326 5327 5328 5329 5330 5331 |
if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } |
fd01b88c7 md: remove typede... |
5332 |
static int get_bitmap_file(struct mddev * mddev, void __user * arg) |
32a7627cf [PATCH] md: optim... |
5333 5334 5335 5336 |
{ mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */ char *ptr, *buf = NULL; int err = -ENOMEM; |
b5470dc5f md: resolve exter... |
5337 5338 5339 5340 |
if (md_allow_write(mddev)) file = kmalloc(sizeof(*file), GFP_NOIO); else file = kmalloc(sizeof(*file), GFP_KERNEL); |
2a2275d63 [PATCH] md: fix p... |
5341 |
|
32a7627cf [PATCH] md: optim... |
5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 |
if (!file) goto out; /* bitmap disabled, zero the first byte and copy out */ if (!mddev->bitmap || !mddev->bitmap->file) { file->pathname[0] = '\0'; goto copy_out; } buf = kmalloc(sizeof(file->pathname), GFP_KERNEL); if (!buf) goto out; |
6bcfd6018 md: kill file_pat... |
5354 5355 |
ptr = d_path(&mddev->bitmap->file->f_path, buf, sizeof(file->pathname)); if (IS_ERR(ptr)) |
32a7627cf [PATCH] md: optim... |
5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 |
goto out; strcpy(file->pathname, ptr); copy_out: err = 0; if (copy_to_user(arg, file, sizeof(*file))) err = -EFAULT; out: kfree(buf); kfree(file); return err; } |
fd01b88c7 md: remove typede... |
5369 |
static int get_disk_info(struct mddev * mddev, void __user * arg) |
1da177e4c Linux-2.6.12-rc2 |
5370 5371 |
{ mdu_disk_info_t info; |
3cb030020 md: removing type... |
5372 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5373 5374 5375 |
if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; |
26ef379f5 md: get_disk_info... |
5376 |
rdev = find_rdev_nr(mddev, info.number); |
1da177e4c Linux-2.6.12-rc2 |
5377 5378 5379 5380 5381 |
if (rdev) { info.major = MAJOR(rdev->bdev->bd_dev); info.minor = MINOR(rdev->bdev->bd_dev); info.raid_disk = rdev->raid_disk; info.state = 0; |
b2d444d7a [PATCH] md: conve... |
5382 |
if (test_bit(Faulty, &rdev->flags)) |
1da177e4c Linux-2.6.12-rc2 |
5383 |
info.state |= (1<<MD_DISK_FAULTY); |
b2d444d7a [PATCH] md: conve... |
5384 |
else if (test_bit(In_sync, &rdev->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
5385 5386 5387 |
info.state |= (1<<MD_DISK_ACTIVE); info.state |= (1<<MD_DISK_SYNC); } |
8ddf9efe6 [PATCH] md: suppo... |
5388 5389 |
if (test_bit(WriteMostly, &rdev->flags)) info.state |= (1<<MD_DISK_WRITEMOSTLY); |
1da177e4c Linux-2.6.12-rc2 |
5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 |
} else { info.major = info.minor = 0; info.raid_disk = -1; info.state = (1<<MD_DISK_REMOVED); } if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } |
fd01b88c7 md: remove typede... |
5401 |
static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) |
1da177e4c Linux-2.6.12-rc2 |
5402 5403 |
{ char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; |
3cb030020 md: removing type... |
5404 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 |
dev_t dev = MKDEV(info->major,info->minor); if (info->major != MAJOR(dev) || info->minor != MINOR(dev)) return -EOVERFLOW; if (!mddev->raid_disks) { int err; /* expecting a device which has a superblock */ rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: md_import_device returned %ld ", PTR_ERR(rdev)); return PTR_ERR(rdev); } if (!list_empty(&mddev->disks)) { |
3cb030020 md: removing type... |
5422 5423 5424 |
struct md_rdev *rdev0 = list_entry(mddev->disks.next, struct md_rdev, same_set); |
a9f326ebf md: remove sparse... |
5425 |
err = super_types[mddev->major_version] |
1da177e4c Linux-2.6.12-rc2 |
5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 |
.load_super(rdev, rdev0, mddev->minor_version); if (err < 0) { printk(KERN_WARNING "md: %s has different UUID to %s ", bdevname(rdev->bdev,b), bdevname(rdev0->bdev,b2)); export_rdev(rdev); return -EINVAL; } } err = bind_rdev_to_array(rdev, mddev); if (err) export_rdev(rdev); return err; } /* * add_new_disk can be used once the array is assembled * to add "hot spares". They must already have a superblock * written */ if (mddev->pers) { int err; if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING "%s: personality does not support diskops! ", mdname(mddev)); return -EINVAL; } |
7b1e35f6d [PATCH] md: allow... |
5457 5458 5459 5460 5461 |
if (mddev->persistent) rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); else rdev = md_import_device(dev, -1, -1); |
1da177e4c Linux-2.6.12-rc2 |
5462 5463 5464 5465 5466 5467 5468 |
if (IS_ERR(rdev)) { printk(KERN_WARNING "md: md_import_device returned %ld ", PTR_ERR(rdev)); return PTR_ERR(rdev); } |
1a855a060 md: fix bug with ... |
5469 |
/* set saved_raid_disk if appropriate */ |
41158c7eb [PATCH] md: optim... |
5470 5471 |
if (!mddev->persistent) { if (info->state & (1<<MD_DISK_SYNC) && |
bf572541a md: fix regressio... |
5472 |
info->raid_disk < mddev->raid_disks) { |
41158c7eb [PATCH] md: optim... |
5473 |
rdev->raid_disk = info->raid_disk; |
bf572541a md: fix regressio... |
5474 5475 |
set_bit(In_sync, &rdev->flags); } else |
41158c7eb [PATCH] md: optim... |
5476 5477 5478 5479 |
rdev->raid_disk = -1; } else super_types[mddev->major_version]. validate_super(mddev, rdev); |
bedd86b77 md: reject a re-a... |
5480 5481 5482 5483 5484 5485 5486 5487 5488 |
if ((info->state & (1<<MD_DISK_SYNC)) && (!test_bit(In_sync, &rdev->flags) || rdev->raid_disk != info->raid_disk)) { /* This was a hot-add request, but events doesn't * match, so reject it. */ export_rdev(rdev); return -EINVAL; } |
1a855a060 md: fix bug with ... |
5489 5490 5491 5492 |
if (test_bit(In_sync, &rdev->flags)) rdev->saved_raid_disk = rdev->raid_disk; else rdev->saved_raid_disk = -1; |
41158c7eb [PATCH] md: optim... |
5493 |
|
b2d444d7a [PATCH] md: conve... |
5494 |
clear_bit(In_sync, &rdev->flags); /* just to be sure */ |
8ddf9efe6 [PATCH] md: suppo... |
5495 5496 |
if (info->state & (1<<MD_DISK_WRITEMOSTLY)) set_bit(WriteMostly, &rdev->flags); |
575a80fa4 md: be more consi... |
5497 5498 |
else clear_bit(WriteMostly, &rdev->flags); |
8ddf9efe6 [PATCH] md: suppo... |
5499 |
|
1da177e4c Linux-2.6.12-rc2 |
5500 5501 |
rdev->raid_disk = -1; err = bind_rdev_to_array(rdev, mddev); |
7c7546ccf [PATCH] md: allow... |
5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 |
if (!err && !mddev->pers->hot_remove_disk) { /* If there is hot_add_disk but no hot_remove_disk * then added disks for geometry changes, * and should be added immediately. */ super_types[mddev->major_version]. validate_super(mddev, rdev); err = mddev->pers->hot_add_disk(mddev, rdev); if (err) unbind_rdev_from_array(rdev); } |
1da177e4c Linux-2.6.12-rc2 |
5513 5514 |
if (err) export_rdev(rdev); |
526647320 Make sure all cha... |
5515 |
else |
00bcb4ac7 md: reduce depend... |
5516 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
c361777fb [PATCH] md: make ... |
5517 |
|
175712843 [PATCH] md: assor... |
5518 |
md_update_sb(mddev, 1); |
72a23c211 Make sure all cha... |
5519 5520 |
if (mddev->degraded) set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
c361777fb [PATCH] md: make ... |
5521 |
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
9864c0053 md: Using poll /... |
5522 5523 |
if (!err) md_new_event(mddev); |
005eca5e7 [PATCH] md: make ... |
5524 |
md_wakeup_thread(mddev->thread); |
1da177e4c Linux-2.6.12-rc2 |
5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 |
return err; } /* otherwise, add_new_disk is only allowed * for major_version==0 superblocks */ if (mddev->major_version != 0) { printk(KERN_WARNING "%s: ADD_NEW_DISK not supported ", mdname(mddev)); return -EINVAL; } if (!(info->state & (1<<MD_DISK_FAULTY))) { int err; |
d710e1381 md: remove space ... |
5540 |
rdev = md_import_device(dev, -1, 0); |
1da177e4c Linux-2.6.12-rc2 |
5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 |
if (IS_ERR(rdev)) { printk(KERN_WARNING "md: error, md_import_device() returned %ld ", PTR_ERR(rdev)); return PTR_ERR(rdev); } rdev->desc_nr = info->number; if (info->raid_disk < mddev->raid_disks) rdev->raid_disk = info->raid_disk; else rdev->raid_disk = -1; |
1da177e4c Linux-2.6.12-rc2 |
5553 |
if (rdev->raid_disk < mddev->raid_disks) |
b2d444d7a [PATCH] md: conve... |
5554 5555 |
if (info->state & (1<<MD_DISK_SYNC)) set_bit(In_sync, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
5556 |
|
8ddf9efe6 [PATCH] md: suppo... |
5557 5558 |
if (info->state & (1<<MD_DISK_WRITEMOSTLY)) set_bit(WriteMostly, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
5559 5560 5561 |
if (!mddev->persistent) { printk(KERN_INFO "md: nonpersistent superblock ... "); |
77304d2ab block: read i_siz... |
5562 5563 |
rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512; } else |
57b2caa39 md-new-param-to-c... |
5564 |
rdev->sb_start = calc_dev_sboffset(rdev); |
8190e754e md: remove chunks... |
5565 |
rdev->sectors = rdev->sb_start; |
1da177e4c Linux-2.6.12-rc2 |
5566 |
|
2bf071bf5 [PATCH] md: keep ... |
5567 5568 5569 5570 5571 |
err = bind_rdev_to_array(rdev, mddev); if (err) { export_rdev(rdev); return err; } |
1da177e4c Linux-2.6.12-rc2 |
5572 5573 5574 5575 |
} return 0; } |
fd01b88c7 md: remove typede... |
5576 |
static int hot_remove_disk(struct mddev * mddev, dev_t dev) |
1da177e4c Linux-2.6.12-rc2 |
5577 5578 |
{ char b[BDEVNAME_SIZE]; |
3cb030020 md: removing type... |
5579 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5580 |
|
1da177e4c Linux-2.6.12-rc2 |
5581 5582 5583 5584 5585 5586 5587 5588 |
rdev = find_rdev(mddev, dev); if (!rdev) return -ENXIO; if (rdev->raid_disk >= 0) goto busy; kick_rdev_from_array(rdev); |
850b2b420 [PATCH] md: repla... |
5589 |
md_update_sb(mddev, 1); |
d7603b7e3 [PATCH] md: make ... |
5590 |
md_new_event(mddev); |
1da177e4c Linux-2.6.12-rc2 |
5591 5592 5593 |
return 0; busy: |
fdefa4d87 RAID: remove trai... |
5594 5595 |
printk(KERN_WARNING "md: cannot remove active disk %s from %s ... ", |
1da177e4c Linux-2.6.12-rc2 |
5596 5597 5598 |
bdevname(rdev->bdev,b), mdname(mddev)); return -EBUSY; } |
fd01b88c7 md: remove typede... |
5599 |
static int hot_add_disk(struct mddev * mddev, dev_t dev) |
1da177e4c Linux-2.6.12-rc2 |
5600 5601 5602 |
{ char b[BDEVNAME_SIZE]; int err; |
3cb030020 md: removing type... |
5603 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 |
if (!mddev->pers) return -ENODEV; if (mddev->major_version != 0) { printk(KERN_WARNING "%s: HOT_ADD may only be used with" " version-0 superblocks. ", mdname(mddev)); return -EINVAL; } if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING "%s: personality does not support diskops! ", mdname(mddev)); return -EINVAL; } |
d710e1381 md: remove space ... |
5622 |
rdev = md_import_device(dev, -1, 0); |
1da177e4c Linux-2.6.12-rc2 |
5623 5624 5625 5626 5627 5628 5629 5630 5631 |
if (IS_ERR(rdev)) { printk(KERN_WARNING "md: error, md_import_device() returned %ld ", PTR_ERR(rdev)); return -EINVAL; } if (mddev->persistent) |
57b2caa39 md-new-param-to-c... |
5632 |
rdev->sb_start = calc_dev_sboffset(rdev); |
1da177e4c Linux-2.6.12-rc2 |
5633 |
else |
77304d2ab block: read i_siz... |
5634 |
rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512; |
1da177e4c Linux-2.6.12-rc2 |
5635 |
|
8190e754e md: remove chunks... |
5636 |
rdev->sectors = rdev->sb_start; |
1da177e4c Linux-2.6.12-rc2 |
5637 |
|
b2d444d7a [PATCH] md: conve... |
5638 |
if (test_bit(Faulty, &rdev->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
5639 5640 5641 5642 5643 5644 5645 |
printk(KERN_WARNING "md: can not hot-add faulty %s disk to %s! ", bdevname(rdev->bdev,b), mdname(mddev)); err = -EINVAL; goto abort_export; } |
b2d444d7a [PATCH] md: conve... |
5646 |
clear_bit(In_sync, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
5647 |
rdev->desc_nr = -1; |
5842730de [PATCH] md: fix b... |
5648 |
rdev->saved_raid_disk = -1; |
2bf071bf5 [PATCH] md: keep ... |
5649 5650 5651 |
err = bind_rdev_to_array(rdev, mddev); if (err) goto abort_export; |
1da177e4c Linux-2.6.12-rc2 |
5652 5653 5654 5655 5656 |
/* * The rest should better be atomic, we can have disk failures * noticed in interrupt contexts ... */ |
1da177e4c Linux-2.6.12-rc2 |
5657 |
rdev->raid_disk = -1; |
850b2b420 [PATCH] md: repla... |
5658 |
md_update_sb(mddev, 1); |
1da177e4c Linux-2.6.12-rc2 |
5659 5660 5661 5662 5663 5664 5665 |
/* * Kick recovery, maybe this spare has to be added to the * array immediately. */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); |
d7603b7e3 [PATCH] md: make ... |
5666 |
md_new_event(mddev); |
1da177e4c Linux-2.6.12-rc2 |
5667 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
5668 5669 5670 5671 |
abort_export: export_rdev(rdev); return err; } |
fd01b88c7 md: remove typede... |
5672 |
static int set_bitmap_file(struct mddev *mddev, int fd) |
32a7627cf [PATCH] md: optim... |
5673 5674 |
{ int err; |
36fa30636 [PATCH] md: all h... |
5675 5676 5677 5678 5679 5680 5681 |
if (mddev->pers) { if (!mddev->pers->quiesce) return -EBUSY; if (mddev->recovery || mddev->sync_thread) return -EBUSY; /* we should be able to change the bitmap.. */ } |
32a7627cf [PATCH] md: optim... |
5682 |
|
32a7627cf [PATCH] md: optim... |
5683 |
|
36fa30636 [PATCH] md: all h... |
5684 5685 5686 |
if (fd >= 0) { if (mddev->bitmap) return -EEXIST; /* cannot add when bitmap is present */ |
c3d9714e8 md: collect bitma... |
5687 |
mddev->bitmap_info.file = fget(fd); |
32a7627cf [PATCH] md: optim... |
5688 |
|
c3d9714e8 md: collect bitma... |
5689 |
if (mddev->bitmap_info.file == NULL) { |
36fa30636 [PATCH] md: all h... |
5690 5691 5692 5693 5694 |
printk(KERN_ERR "%s: error: failed to get bitmap file ", mdname(mddev)); return -EBADF; } |
c3d9714e8 md: collect bitma... |
5695 |
err = deny_bitmap_write_access(mddev->bitmap_info.file); |
36fa30636 [PATCH] md: all h... |
5696 5697 5698 5699 |
if (err) { printk(KERN_ERR "%s: error: bitmap file is already in use ", mdname(mddev)); |
c3d9714e8 md: collect bitma... |
5700 5701 |
fput(mddev->bitmap_info.file); mddev->bitmap_info.file = NULL; |
36fa30636 [PATCH] md: all h... |
5702 5703 |
return err; } |
c3d9714e8 md: collect bitma... |
5704 |
mddev->bitmap_info.offset = 0; /* file overrides offset */ |
36fa30636 [PATCH] md: all h... |
5705 5706 5707 5708 5709 |
} else if (mddev->bitmap == NULL) return -ENOENT; /* cannot remove what isn't there */ err = 0; if (mddev->pers) { mddev->pers->quiesce(mddev, 1); |
69e51b449 md/bitmap: separ... |
5710 |
if (fd >= 0) { |
36fa30636 [PATCH] md: all h... |
5711 |
err = bitmap_create(mddev); |
69e51b449 md/bitmap: separ... |
5712 5713 5714 |
if (!err) err = bitmap_load(mddev); } |
d7375ab32 [PATCH] md/bitmap... |
5715 |
if (fd < 0 || err) { |
36fa30636 [PATCH] md: all h... |
5716 |
bitmap_destroy(mddev); |
d7375ab32 [PATCH] md/bitmap... |
5717 5718 |
fd = -1; /* make sure to put the file */ } |
36fa30636 [PATCH] md: all h... |
5719 |
mddev->pers->quiesce(mddev, 0); |
d7375ab32 [PATCH] md/bitmap... |
5720 5721 |
} if (fd < 0) { |
c3d9714e8 md: collect bitma... |
5722 5723 5724 |
if (mddev->bitmap_info.file) { restore_bitmap_write_access(mddev->bitmap_info.file); fput(mddev->bitmap_info.file); |
acc55e220 [PATCH] md/bitmap... |
5725 |
} |
c3d9714e8 md: collect bitma... |
5726 |
mddev->bitmap_info.file = NULL; |
36fa30636 [PATCH] md: all h... |
5727 |
} |
32a7627cf [PATCH] md: optim... |
5728 5729 |
return err; } |
1da177e4c Linux-2.6.12-rc2 |
5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 |
/* * set_array_info is used two different ways * The original usage is when creating a new array. * In this usage, raid_disks is > 0 and it together with * level, size, not_persistent,layout,chunksize determine the * shape of the array. * This will always create an array with a type-0.90.0 superblock. * The newer usage is when assembling an array. * In this case raid_disks will be 0, and the major_version field is * use to determine which style super-blocks are to be found on the devices. * The minor and patch _version numbers are also kept incase the * super_block handler wishes to interpret them. */ |
fd01b88c7 md: remove typede... |
5743 |
static int set_array_info(struct mddev * mddev, mdu_array_info_t *info) |
1da177e4c Linux-2.6.12-rc2 |
5744 5745 5746 5747 5748 |
{ if (info->raid_disks == 0) { /* just setting version number for superblock loading */ if (info->major_version < 0 || |
50511da3d drivers/md.c: Use... |
5749 |
info->major_version >= ARRAY_SIZE(super_types) || |
1da177e4c Linux-2.6.12-rc2 |
5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 |
super_types[info->major_version].name == NULL) { /* maybe try to auto-load a module? */ printk(KERN_INFO "md: superblock version %d not known ", info->major_version); return -EINVAL; } mddev->major_version = info->major_version; mddev->minor_version = info->minor_version; mddev->patch_version = info->patch_version; |
3f9d7b0d8 [PATCH] md: fix a... |
5761 |
mddev->persistent = !info->not_persistent; |
cbd199837 md: Fix unfortuna... |
5762 5763 5764 5765 |
/* ensure mddev_put doesn't delete this now that there * is some minimal configuration. */ mddev->ctime = get_seconds(); |
1da177e4c Linux-2.6.12-rc2 |
5766 5767 5768 5769 5770 5771 5772 5773 |
return 0; } mddev->major_version = MD_MAJOR_VERSION; mddev->minor_version = MD_MINOR_VERSION; mddev->patch_version = MD_PATCHLEVEL_VERSION; mddev->ctime = get_seconds(); mddev->level = info->level; |
17115e038 [PATCH] md: Clear... |
5774 |
mddev->clevel[0] = 0; |
58c0fed40 md: Make mddev->s... |
5775 |
mddev->dev_sectors = 2 * (sector_t)info->size; |
1da177e4c Linux-2.6.12-rc2 |
5776 5777 5778 5779 5780 5781 5782 5783 5784 |
mddev->raid_disks = info->raid_disks; /* don't set md_minor, it is determined by which /dev/md* was * openned */ if (info->state & (1<<MD_SB_CLEAN)) mddev->recovery_cp = MaxSector; else mddev->recovery_cp = 0; mddev->persistent = ! info->not_persistent; |
e691063a6 md: support 'exte... |
5785 |
mddev->external = 0; |
1da177e4c Linux-2.6.12-rc2 |
5786 5787 |
mddev->layout = info->layout; |
9d8f03636 md: Make mddev->c... |
5788 |
mddev->chunk_sectors = info->chunk_size >> 9; |
1da177e4c Linux-2.6.12-rc2 |
5789 5790 |
mddev->max_disks = MD_SB_DISKS; |
e691063a6 md: support 'exte... |
5791 5792 |
if (mddev->persistent) mddev->flags = 0; |
850b2b420 [PATCH] md: repla... |
5793 |
set_bit(MD_CHANGE_DEVS, &mddev->flags); |
1da177e4c Linux-2.6.12-rc2 |
5794 |
|
c3d9714e8 md: collect bitma... |
5795 5796 |
mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; mddev->bitmap_info.offset = 0; |
b2a2703c2 [PATCH] md: set d... |
5797 |
|
f67055780 [PATCH] md: Check... |
5798 |
mddev->reshape_position = MaxSector; |
1da177e4c Linux-2.6.12-rc2 |
5799 5800 5801 5802 |
/* * Generate a 128 bit UUID */ get_random_bytes(mddev->uuid, 16); |
f67055780 [PATCH] md: Check... |
5803 |
mddev->new_level = mddev->level; |
664e7c413 md: Convert mddev... |
5804 |
mddev->new_chunk_sectors = mddev->chunk_sectors; |
f67055780 [PATCH] md: Check... |
5805 5806 |
mddev->new_layout = mddev->layout; mddev->delta_disks = 0; |
1da177e4c Linux-2.6.12-rc2 |
5807 5808 |
return 0; } |
fd01b88c7 md: remove typede... |
5809 |
void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors) |
1f403624b md: centralize ->... |
5810 |
{ |
b522adcde md: 'array_size' ... |
5811 5812 5813 5814 5815 |
WARN(!mddev_is_locked(mddev), "%s: unlocked mddev! ", __func__); if (mddev->external_size) return; |
1f403624b md: centralize ->... |
5816 5817 5818 |
mddev->array_sectors = array_sectors; } EXPORT_SYMBOL(md_set_array_sectors); |
fd01b88c7 md: remove typede... |
5819 |
static int update_size(struct mddev *mddev, sector_t num_sectors) |
a35b0d695 [PATCH] md: allow... |
5820 |
{ |
3cb030020 md: removing type... |
5821 |
struct md_rdev *rdev; |
a35b0d695 [PATCH] md: allow... |
5822 |
int rv; |
d71f9f88d md: Make update_s... |
5823 |
int fit = (num_sectors == 0); |
a35b0d695 [PATCH] md: allow... |
5824 5825 5826 |
if (mddev->pers->resize == NULL) return -EINVAL; |
d71f9f88d md: Make update_s... |
5827 5828 5829 5830 5831 |
/* The "num_sectors" is the number of sectors of each device that * is used. This can only make sense for arrays with redundancy. * linear and raid0 always use whatever space is available. We can only * consider changing this number if no resync or reconstruction is * happening, and if the new size is acceptable. It must fit before the |
0f420358e md: Turn rdev->sb... |
5832 |
* sb_start or, if that is <data_offset, it must fit before the size |
d71f9f88d md: Make update_s... |
5833 5834 |
* of each device. If num_sectors is zero, we find the largest size * that fits. |
a35b0d695 [PATCH] md: allow... |
5835 5836 5837 |
*/ if (mddev->sync_thread) return -EBUSY; |
dba034eef Fail safely when ... |
5838 5839 5840 5841 5842 |
if (mddev->bitmap) /* Sorry, cannot grow a bitmap yet, just remove it, * grow, and re-add. */ return -EBUSY; |
159ec1fc0 md: use list_for_... |
5843 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
dd8ac336c md: Represent rai... |
5844 |
sector_t avail = rdev->sectors; |
01ab5662f [PATCH] md: simpl... |
5845 |
|
d71f9f88d md: Make update_s... |
5846 5847 5848 |
if (fit && (num_sectors == 0 || num_sectors > avail)) num_sectors = avail; if (avail < num_sectors) |
a35b0d695 [PATCH] md: allow... |
5849 5850 |
return -ENOSPC; } |
d71f9f88d md: Make update_s... |
5851 |
rv = mddev->pers->resize(mddev, num_sectors); |
449aad3e2 md: Use revalidat... |
5852 5853 |
if (!rv) revalidate_disk(mddev->gendisk); |
a35b0d695 [PATCH] md: allow... |
5854 5855 |
return rv; } |
fd01b88c7 md: remove typede... |
5856 |
static int update_raid_disks(struct mddev *mddev, int raid_disks) |
da943b991 [PATCH] md: allow... |
5857 5858 5859 |
{ int rv; /* change the number of raid disks */ |
63c70c4f3 [PATCH] md: Split... |
5860 |
if (mddev->pers->check_reshape == NULL) |
da943b991 [PATCH] md: allow... |
5861 5862 |
return -EINVAL; if (raid_disks <= 0 || |
233fca36b md: Relax checks ... |
5863 |
(mddev->max_disks && raid_disks >= mddev->max_disks)) |
da943b991 [PATCH] md: allow... |
5864 |
return -EINVAL; |
63c70c4f3 [PATCH] md: Split... |
5865 |
if (mddev->sync_thread || mddev->reshape_position != MaxSector) |
da943b991 [PATCH] md: allow... |
5866 |
return -EBUSY; |
63c70c4f3 [PATCH] md: Split... |
5867 5868 5869 |
mddev->delta_disks = raid_disks - mddev->raid_disks; rv = mddev->pers->check_reshape(mddev); |
de171cb9a md: revert change... |
5870 5871 |
if (rv < 0) mddev->delta_disks = 0; |
da943b991 [PATCH] md: allow... |
5872 5873 |
return rv; } |
1da177e4c Linux-2.6.12-rc2 |
5874 5875 5876 5877 5878 5879 5880 5881 |
/* * update_array_info is used to change the configuration of an * on-line array. * The version, ctime,level,size,raid_disks,not_persistent, layout,chunk_size * fields in the info are checked against the array. * Any differences that cannot be handled will cause an error. * Normally, only one change can be managed at a time. */ |
fd01b88c7 md: remove typede... |
5882 |
static int update_array_info(struct mddev *mddev, mdu_array_info_t *info) |
1da177e4c Linux-2.6.12-rc2 |
5883 5884 5885 |
{ int rv = 0; int cnt = 0; |
36fa30636 [PATCH] md: all h... |
5886 5887 5888 |
int state = 0; /* calculate expected state,ignoring low bits */ |
c3d9714e8 md: collect bitma... |
5889 |
if (mddev->bitmap && mddev->bitmap_info.offset) |
36fa30636 [PATCH] md: all h... |
5890 |
state |= (1 << MD_SB_BITMAP_PRESENT); |
1da177e4c Linux-2.6.12-rc2 |
5891 5892 5893 5894 5895 5896 5897 5898 |
if (mddev->major_version != info->major_version || mddev->minor_version != info->minor_version || /* mddev->patch_version != info->patch_version || */ mddev->ctime != info->ctime || mddev->level != info->level || /* mddev->layout != info->layout || */ !mddev->persistent != info->not_persistent|| |
9d8f03636 md: Make mddev->c... |
5899 |
mddev->chunk_sectors != info->chunk_size >> 9 || |
36fa30636 [PATCH] md: all h... |
5900 5901 5902 |
/* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */ ((state^info->state) & 0xfffffe00) ) |
1da177e4c Linux-2.6.12-rc2 |
5903 5904 |
return -EINVAL; /* Check there is only one change */ |
58c0fed40 md: Make mddev->s... |
5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 |
if (info->size >= 0 && mddev->dev_sectors / 2 != info->size) cnt++; if (mddev->raid_disks != info->raid_disks) cnt++; if (mddev->layout != info->layout) cnt++; if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++; if (cnt == 0) return 0; if (cnt > 1) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
5917 5918 5919 5920 5921 5922 |
if (mddev->layout != info->layout) { /* Change layout * we don't need to do anything at the md level, the * personality will take care of it all. */ |
50ac168a6 md: merge reconfi... |
5923 |
if (mddev->pers->check_reshape == NULL) |
1da177e4c Linux-2.6.12-rc2 |
5924 |
return -EINVAL; |
597a711b6 md: remove unnece... |
5925 5926 |
else { mddev->new_layout = info->layout; |
50ac168a6 md: merge reconfi... |
5927 |
rv = mddev->pers->check_reshape(mddev); |
597a711b6 md: remove unnece... |
5928 5929 5930 5931 |
if (rv) mddev->new_layout = mddev->layout; return rv; } |
1da177e4c Linux-2.6.12-rc2 |
5932 |
} |
58c0fed40 md: Make mddev->s... |
5933 |
if (info->size >= 0 && mddev->dev_sectors / 2 != info->size) |
d71f9f88d md: Make update_s... |
5934 |
rv = update_size(mddev, (sector_t)info->size * 2); |
a35b0d695 [PATCH] md: allow... |
5935 |
|
da943b991 [PATCH] md: allow... |
5936 5937 |
if (mddev->raid_disks != info->raid_disks) rv = update_raid_disks(mddev, info->raid_disks); |
36fa30636 [PATCH] md: all h... |
5938 5939 5940 5941 5942 5943 5944 5945 5946 |
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) { if (mddev->pers->quiesce == NULL) return -EINVAL; if (mddev->recovery || mddev->sync_thread) return -EBUSY; if (info->state & (1<<MD_SB_BITMAP_PRESENT)) { /* add the bitmap */ if (mddev->bitmap) return -EEXIST; |
c3d9714e8 md: collect bitma... |
5947 |
if (mddev->bitmap_info.default_offset == 0) |
36fa30636 [PATCH] md: all h... |
5948 |
return -EINVAL; |
c3d9714e8 md: collect bitma... |
5949 5950 |
mddev->bitmap_info.offset = mddev->bitmap_info.default_offset; |
36fa30636 [PATCH] md: all h... |
5951 5952 |
mddev->pers->quiesce(mddev, 1); rv = bitmap_create(mddev); |
69e51b449 md/bitmap: separ... |
5953 5954 |
if (!rv) rv = bitmap_load(mddev); |
36fa30636 [PATCH] md: all h... |
5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 |
if (rv) bitmap_destroy(mddev); mddev->pers->quiesce(mddev, 0); } else { /* remove the bitmap */ if (!mddev->bitmap) return -ENOENT; if (mddev->bitmap->file) return -EINVAL; mddev->pers->quiesce(mddev, 1); bitmap_destroy(mddev); mddev->pers->quiesce(mddev, 0); |
c3d9714e8 md: collect bitma... |
5967 |
mddev->bitmap_info.offset = 0; |
36fa30636 [PATCH] md: all h... |
5968 5969 |
} } |
850b2b420 [PATCH] md: repla... |
5970 |
md_update_sb(mddev, 1); |
1da177e4c Linux-2.6.12-rc2 |
5971 5972 |
return rv; } |
fd01b88c7 md: remove typede... |
5973 |
static int set_disk_faulty(struct mddev *mddev, dev_t dev) |
1da177e4c Linux-2.6.12-rc2 |
5974 |
{ |
3cb030020 md: removing type... |
5975 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
5976 5977 5978 5979 5980 5981 5982 5983 5984 |
if (mddev->pers == NULL) return -ENODEV; rdev = find_rdev(mddev, dev); if (!rdev) return -ENODEV; md_error(mddev, rdev); |
5ef56c8fe md: report failur... |
5985 5986 |
if (!test_bit(Faulty, &rdev->flags)) return -EBUSY; |
1da177e4c Linux-2.6.12-rc2 |
5987 5988 |
return 0; } |
2f9618ce6 md: md_getgeo(): ... |
5989 5990 5991 5992 5993 5994 |
/* * We have a problem here : there is no easy way to give a CHS * virtual geometry. We currently pretend that we have a 2 heads * 4 sectors (with a BIG number of cylinders...). This drives * dosfs just mad... ;-) */ |
a885c8c43 [PATCH] Add block... |
5995 5996 |
static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo) { |
fd01b88c7 md: remove typede... |
5997 |
struct mddev *mddev = bdev->bd_disk->private_data; |
a885c8c43 [PATCH] Add block... |
5998 5999 6000 |
geo->heads = 2; geo->sectors = 4; |
49ce6cea8 md: don't referen... |
6001 |
geo->cylinders = mddev->array_sectors / 8; |
a885c8c43 [PATCH] Add block... |
6002 6003 |
return 0; } |
a39907fa2 [PATCH] switch md |
6004 |
static int md_ioctl(struct block_device *bdev, fmode_t mode, |
1da177e4c Linux-2.6.12-rc2 |
6005 6006 6007 6008 |
unsigned int cmd, unsigned long arg) { int err = 0; void __user *argp = (void __user *)arg; |
fd01b88c7 md: remove typede... |
6009 |
struct mddev *mddev = NULL; |
e22183504 md: set mddev rea... |
6010 |
int ro; |
1da177e4c Linux-2.6.12-rc2 |
6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 |
if (!capable(CAP_SYS_ADMIN)) return -EACCES; /* * Commands dealing with the RAID driver but not any * particular array: */ switch (cmd) { case RAID_VERSION: err = get_version(argp); goto done; case PRINT_RAID_DEBUG: err = 0; md_print_devices(); goto done; #ifndef MODULE case RAID_AUTORUN: err = 0; autostart_arrays(arg); goto done; #endif default:; } /* * Commands creating/starting a new array: */ |
a39907fa2 [PATCH] switch md |
6042 |
mddev = bdev->bd_disk->private_data; |
1da177e4c Linux-2.6.12-rc2 |
6043 6044 6045 6046 6047 |
if (!mddev) { BUG(); goto abort; } |
1da177e4c Linux-2.6.12-rc2 |
6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 |
err = mddev_lock(mddev); if (err) { printk(KERN_INFO "md: ioctl lock interrupted, reason %d, cmd %d ", err, cmd); goto abort; } switch (cmd) { case SET_ARRAY_INFO: { mdu_array_info_t info; if (!arg) memset(&info, 0, sizeof(info)); else if (copy_from_user(&info, argp, sizeof(info))) { err = -EFAULT; goto abort_unlock; } if (mddev->pers) { err = update_array_info(mddev, &info); if (err) { printk(KERN_WARNING "md: couldn't update" " array info. %d ", err); goto abort_unlock; } goto done_unlock; } if (!list_empty(&mddev->disks)) { printk(KERN_WARNING "md: array %s already has disks! ", mdname(mddev)); err = -EBUSY; goto abort_unlock; } if (mddev->raid_disks) { printk(KERN_WARNING "md: array %s already initialised! ", mdname(mddev)); err = -EBUSY; goto abort_unlock; } err = set_array_info(mddev, &info); if (err) { printk(KERN_WARNING "md: couldn't set" " array info. %d ", err); goto abort_unlock; } } goto done_unlock; default:; } /* * Commands querying/configuring an existing array: */ |
32a7627cf [PATCH] md: optim... |
6110 |
/* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY, |
3f9d7b0d8 [PATCH] md: fix a... |
6111 |
* RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */ |
a17184a91 md: allow an md a... |
6112 6113 6114 6115 |
if ((!mddev->raid_disks && !mddev->external) && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE && cmd != GET_BITMAP_FILE) { |
1da177e4c Linux-2.6.12-rc2 |
6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 |
err = -ENODEV; goto abort_unlock; } /* * Commands even a read-only array can execute: */ switch (cmd) { case GET_ARRAY_INFO: err = get_array_info(mddev, argp); goto done_unlock; |
32a7627cf [PATCH] md: optim... |
6128 |
case GET_BITMAP_FILE: |
87162a28a [PATCH] trivial _... |
6129 |
err = get_bitmap_file(mddev, argp); |
32a7627cf [PATCH] md: optim... |
6130 |
goto done_unlock; |
1da177e4c Linux-2.6.12-rc2 |
6131 6132 6133 6134 6135 6136 6137 6138 6139 |
case GET_DISK_INFO: err = get_disk_info(mddev, argp); goto done_unlock; case RESTART_ARRAY_RW: err = restart_array(mddev); goto done_unlock; case STOP_ARRAY: |
d710e1381 md: remove space ... |
6140 |
err = do_md_stop(mddev, 0, 1); |
1da177e4c Linux-2.6.12-rc2 |
6141 6142 6143 |
goto done_unlock; case STOP_ARRAY_RO: |
a4bd82d0d md: split md_set_... |
6144 |
err = md_set_readonly(mddev, 1); |
1da177e4c Linux-2.6.12-rc2 |
6145 |
goto done_unlock; |
e22183504 md: set mddev rea... |
6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 |
case BLKROSET: if (get_user(ro, (int __user *)(arg))) { err = -EFAULT; goto done_unlock; } err = -EINVAL; /* if the bdev is going readonly the value of mddev->ro * does not matter, no writes are coming */ if (ro) goto done_unlock; /* are we are already prepared for writes? */ if (mddev->ro != 1) goto done_unlock; /* transitioning to readauto need only happen for * arrays that call md_write_start */ if (mddev->pers) { err = restart_array(mddev); if (err == 0) { mddev->ro = 2; set_disk_ro(mddev->gendisk, 0); } } goto done_unlock; |
1da177e4c Linux-2.6.12-rc2 |
6174 6175 6176 6177 |
} /* * The remaining ioctls are changing the state of the |
f91de92ed [PATCH] md: allow... |
6178 6179 6180 6181 |
* superblock, so we do not allow them on read-only arrays. * However non-MD ioctls (e.g. get-size) will still come through * here and hit the 'default' below, so only disallow * 'md' ioctls, and switch to rw mode if started auto-readonly. |
1da177e4c Linux-2.6.12-rc2 |
6182 |
*/ |
bb57fc64b md: md_ioctl(): F... |
6183 |
if (_IOC_TYPE(cmd) == MD_MAJOR && mddev->ro && mddev->pers) { |
f91de92ed [PATCH] md: allow... |
6184 6185 |
if (mddev->ro == 2) { mddev->ro = 0; |
00bcb4ac7 md: reduce depend... |
6186 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
0fd62b861 Make sure all cha... |
6187 6188 |
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); |
f91de92ed [PATCH] md: allow... |
6189 6190 6191 6192 |
} else { err = -EROFS; goto abort_unlock; } |
1da177e4c Linux-2.6.12-rc2 |
6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 |
} switch (cmd) { case ADD_NEW_DISK: { mdu_disk_info_t info; if (copy_from_user(&info, argp, sizeof(info))) err = -EFAULT; else err = add_new_disk(mddev, &info); goto done_unlock; } case HOT_REMOVE_DISK: err = hot_remove_disk(mddev, new_decode_dev(arg)); goto done_unlock; case HOT_ADD_DISK: err = hot_add_disk(mddev, new_decode_dev(arg)); goto done_unlock; case SET_DISK_FAULTY: err = set_disk_faulty(mddev, new_decode_dev(arg)); goto done_unlock; case RUN_ARRAY: |
d710e1381 md: remove space ... |
6220 |
err = do_md_run(mddev); |
1da177e4c Linux-2.6.12-rc2 |
6221 |
goto done_unlock; |
32a7627cf [PATCH] md: optim... |
6222 6223 6224 |
case SET_BITMAP_FILE: err = set_bitmap_file(mddev, (int)arg); goto done_unlock; |
1da177e4c Linux-2.6.12-rc2 |
6225 |
default: |
1da177e4c Linux-2.6.12-rc2 |
6226 6227 6228 6229 6230 6231 |
err = -EINVAL; goto abort_unlock; } done_unlock: abort_unlock: |
d3374825c md: make devices ... |
6232 6233 6234 |
if (mddev->hold_active == UNTIL_IOCTL && err != -EINVAL) mddev->hold_active = 0; |
1da177e4c Linux-2.6.12-rc2 |
6235 6236 6237 6238 6239 6240 6241 6242 6243 |
mddev_unlock(mddev); return err; done: if (err) MD_BUG(); abort: return err; } |
aa98aa319 md: move compat_i... |
6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 |
#ifdef CONFIG_COMPAT static int md_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { switch (cmd) { case HOT_REMOVE_DISK: case HOT_ADD_DISK: case SET_DISK_FAULTY: case SET_BITMAP_FILE: /* These take in integer arg, do not convert */ break; default: arg = (unsigned long)compat_ptr(arg); break; } return md_ioctl(bdev, mode, cmd, arg); } #endif /* CONFIG_COMPAT */ |
1da177e4c Linux-2.6.12-rc2 |
6263 |
|
a39907fa2 [PATCH] switch md |
6264 |
static int md_open(struct block_device *bdev, fmode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
6265 6266 6267 6268 6269 |
{ /* * Succeed if we can lock the mddev, which confirms that * it isn't being stopped right now. */ |
fd01b88c7 md: remove typede... |
6270 |
struct mddev *mddev = mddev_find(bdev->bd_dev); |
1da177e4c Linux-2.6.12-rc2 |
6271 |
int err; |
d3374825c md: make devices ... |
6272 6273 6274 6275 6276 6277 |
if (mddev->gendisk != bdev->bd_disk) { /* we are racing with mddev_put which is discarding this * bd_disk. */ mddev_put(mddev); /* Wait until bdev->bd_disk is definitely gone */ |
e804ac780 md: fix and updat... |
6278 |
flush_workqueue(md_misc_wq); |
d3374825c md: make devices ... |
6279 6280 6281 6282 |
/* Then retry the open from the top */ return -ERESTARTSYS; } BUG_ON(mddev != bdev->bd_disk->private_data); |
c8c00a691 Remove deadlock p... |
6283 |
if ((err = mutex_lock_interruptible(&mddev->open_mutex))) |
1da177e4c Linux-2.6.12-rc2 |
6284 6285 6286 |
goto out; err = 0; |
f2ea68cf4 md: only count ac... |
6287 |
atomic_inc(&mddev->openers); |
c8c00a691 Remove deadlock p... |
6288 |
mutex_unlock(&mddev->open_mutex); |
1da177e4c Linux-2.6.12-rc2 |
6289 |
|
f0b4f7e2f md: Fix - again -... |
6290 |
check_disk_change(bdev); |
1da177e4c Linux-2.6.12-rc2 |
6291 6292 6293 |
out: return err; } |
a39907fa2 [PATCH] switch md |
6294 |
static int md_release(struct gendisk *disk, fmode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
6295 |
{ |
fd01b88c7 md: remove typede... |
6296 |
struct mddev *mddev = disk->private_data; |
1da177e4c Linux-2.6.12-rc2 |
6297 |
|
52e5f9d1c BUG_ON cleanup fo... |
6298 |
BUG_ON(!mddev); |
f2ea68cf4 md: only count ac... |
6299 |
atomic_dec(&mddev->openers); |
1da177e4c Linux-2.6.12-rc2 |
6300 6301 6302 6303 |
mddev_put(mddev); return 0; } |
f0b4f7e2f md: Fix - again -... |
6304 6305 6306 |
static int md_media_changed(struct gendisk *disk) { |
fd01b88c7 md: remove typede... |
6307 |
struct mddev *mddev = disk->private_data; |
f0b4f7e2f md: Fix - again -... |
6308 6309 6310 6311 6312 6313 |
return mddev->changed; } static int md_revalidate(struct gendisk *disk) { |
fd01b88c7 md: remove typede... |
6314 |
struct mddev *mddev = disk->private_data; |
f0b4f7e2f md: Fix - again -... |
6315 6316 6317 6318 |
mddev->changed = 0; return 0; } |
83d5cde47 const: make block... |
6319 |
static const struct block_device_operations md_fops = |
1da177e4c Linux-2.6.12-rc2 |
6320 6321 |
{ .owner = THIS_MODULE, |
a39907fa2 [PATCH] switch md |
6322 6323 |
.open = md_open, .release = md_release, |
b492b852c md: don't use loc... |
6324 |
.ioctl = md_ioctl, |
aa98aa319 md: move compat_i... |
6325 6326 6327 |
#ifdef CONFIG_COMPAT .compat_ioctl = md_compat_ioctl, #endif |
a885c8c43 [PATCH] Add block... |
6328 |
.getgeo = md_getgeo, |
f0b4f7e2f md: Fix - again -... |
6329 6330 |
.media_changed = md_media_changed, .revalidate_disk= md_revalidate, |
1da177e4c Linux-2.6.12-rc2 |
6331 |
}; |
75c96f858 [PATCH] make some... |
6332 |
static int md_thread(void * arg) |
1da177e4c Linux-2.6.12-rc2 |
6333 |
{ |
2b8bf3451 md: remove typede... |
6334 |
struct md_thread *thread = arg; |
1da177e4c Linux-2.6.12-rc2 |
6335 |
|
1da177e4c Linux-2.6.12-rc2 |
6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 |
/* * md_thread is a 'system-thread', it's priority should be very * high. We avoid resource deadlocks individually in each * raid personality. (RAID5 does preallocation) We also use RR and * the very same RT priority as kswapd, thus we will never get * into a priority inversion deadlock. * * we definitely have to have equal or higher priority than * bdflush, otherwise bdflush will deadlock if there are too * many dirty RAID5 blocks. */ |
1da177e4c Linux-2.6.12-rc2 |
6347 |
|
6985c43f3 [PATCH] Three one... |
6348 |
allow_signal(SIGKILL); |
a6fb0934f [PATCH] md: use k... |
6349 |
while (!kthread_should_stop()) { |
1da177e4c Linux-2.6.12-rc2 |
6350 |
|
93588e228 [PATCH] md: make ... |
6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 |
/* We need to wait INTERRUPTIBLE so that * we don't add to the load-average. * That means we need to be sure no signals are * pending */ if (signal_pending(current)) flush_signals(current); wait_event_interruptible_timeout (thread->wqueue, test_bit(THREAD_WAKEUP, &thread->flags) || kthread_should_stop(), thread->timeout); |
1da177e4c Linux-2.6.12-rc2 |
6364 |
|
6c9879101 md: fix regressio... |
6365 6366 |
clear_bit(THREAD_WAKEUP, &thread->flags); if (!kthread_should_stop()) |
589a594be md: protect again... |
6367 |
thread->run(thread->mddev); |
1da177e4c Linux-2.6.12-rc2 |
6368 |
} |
a6fb0934f [PATCH] md: use k... |
6369 |
|
1da177e4c Linux-2.6.12-rc2 |
6370 6371 |
return 0; } |
2b8bf3451 md: remove typede... |
6372 |
void md_wakeup_thread(struct md_thread *thread) |
1da177e4c Linux-2.6.12-rc2 |
6373 6374 |
{ if (thread) { |
36a4e1fe0 md: remove PRINTK... |
6375 6376 |
pr_debug("md: waking up MD thread %s. ", thread->tsk->comm); |
1da177e4c Linux-2.6.12-rc2 |
6377 6378 6379 6380 |
set_bit(THREAD_WAKEUP, &thread->flags); wake_up(&thread->wqueue); } } |
2b8bf3451 md: remove typede... |
6381 |
struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev *mddev, |
1da177e4c Linux-2.6.12-rc2 |
6382 6383 |
const char *name) { |
2b8bf3451 md: remove typede... |
6384 |
struct md_thread *thread; |
1da177e4c Linux-2.6.12-rc2 |
6385 |
|
2b8bf3451 md: remove typede... |
6386 |
thread = kzalloc(sizeof(struct md_thread), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
6387 6388 |
if (!thread) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
6389 |
init_waitqueue_head(&thread->wqueue); |
1da177e4c Linux-2.6.12-rc2 |
6390 6391 |
thread->run = run; thread->mddev = mddev; |
32a7627cf [PATCH] md: optim... |
6392 |
thread->timeout = MAX_SCHEDULE_TIMEOUT; |
0da3c6194 md: Improve name ... |
6393 6394 6395 6396 |
thread->tsk = kthread_run(md_thread, thread, "%s_%s", mdname(thread->mddev), name ?: mddev->pers->name); |
a6fb0934f [PATCH] md: use k... |
6397 |
if (IS_ERR(thread->tsk)) { |
1da177e4c Linux-2.6.12-rc2 |
6398 6399 6400 |
kfree(thread); return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
6401 6402 |
return thread; } |
2b8bf3451 md: remove typede... |
6403 |
void md_unregister_thread(struct md_thread **threadp) |
1da177e4c Linux-2.6.12-rc2 |
6404 |
{ |
2b8bf3451 md: remove typede... |
6405 |
struct md_thread *thread = *threadp; |
e0cf8f045 md: md_unregister... |
6406 6407 |
if (!thread) return; |
36a4e1fe0 md: remove PRINTK... |
6408 6409 |
pr_debug("interrupting MD-thread pid %d ", task_pid_nr(thread->tsk)); |
01f96c0a9 md: Avoid waking ... |
6410 6411 6412 6413 6414 6415 |
/* Locking ensures that mddev_unlock does not wake_up a * non-existent thread */ spin_lock(&pers_lock); *threadp = NULL; spin_unlock(&pers_lock); |
a6fb0934f [PATCH] md: use k... |
6416 6417 |
kthread_stop(thread->tsk); |
1da177e4c Linux-2.6.12-rc2 |
6418 6419 |
kfree(thread); } |
fd01b88c7 md: remove typede... |
6420 |
void md_error(struct mddev *mddev, struct md_rdev *rdev) |
1da177e4c Linux-2.6.12-rc2 |
6421 6422 6423 6424 6425 |
{ if (!mddev) { MD_BUG(); return; } |
b2d444d7a [PATCH] md: conve... |
6426 |
if (!rdev || test_bit(Faulty, &rdev->flags)) |
1da177e4c Linux-2.6.12-rc2 |
6427 |
return; |
6bfe0b499 md: support block... |
6428 |
|
de393cdea md: make it easie... |
6429 |
if (!mddev->pers || !mddev->pers->error_handler) |
1da177e4c Linux-2.6.12-rc2 |
6430 6431 |
return; mddev->pers->error_handler(mddev,rdev); |
72a23c211 Make sure all cha... |
6432 6433 |
if (mddev->degraded) set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
00bcb4ac7 md: reduce depend... |
6434 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
1da177e4c Linux-2.6.12-rc2 |
6435 6436 6437 |
set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); |
768a418db md: add support f... |
6438 |
if (mddev->event_work.func) |
e804ac780 md: fix and updat... |
6439 |
queue_work(md_misc_wq, &mddev->event_work); |
c331eb04b [PATCH] md: Fix b... |
6440 |
md_new_event_inintr(mddev); |
1da177e4c Linux-2.6.12-rc2 |
6441 6442 6443 6444 6445 6446 6447 |
} /* seq_file implementation /proc/mdstat */ static void status_unused(struct seq_file *seq) { int i = 0; |
3cb030020 md: removing type... |
6448 |
struct md_rdev *rdev; |
1da177e4c Linux-2.6.12-rc2 |
6449 6450 |
seq_printf(seq, "unused devices: "); |
159ec1fc0 md: use list_for_... |
6451 |
list_for_each_entry(rdev, &pending_raid_disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 |
char b[BDEVNAME_SIZE]; i++; seq_printf(seq, "%s ", bdevname(rdev->bdev,b)); } if (!i) seq_printf(seq, "<none>"); seq_printf(seq, " "); } |
fd01b88c7 md: remove typede... |
6463 |
static void status_resync(struct seq_file *seq, struct mddev * mddev) |
1da177e4c Linux-2.6.12-rc2 |
6464 |
{ |
dd71cf6b2 md: tidy up statu... |
6465 6466 6467 |
sector_t max_sectors, resync, res; unsigned long dt, db; sector_t rt; |
4588b42e9 [PATCH] md: Updat... |
6468 6469 |
int scale; unsigned int per_milli; |
1da177e4c Linux-2.6.12-rc2 |
6470 |
|
dd71cf6b2 md: tidy up statu... |
6471 |
resync = mddev->curr_resync - atomic_read(&mddev->recovery_active); |
1da177e4c Linux-2.6.12-rc2 |
6472 6473 |
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) |
dd71cf6b2 md: tidy up statu... |
6474 |
max_sectors = mddev->resync_max_sectors; |
1da177e4c Linux-2.6.12-rc2 |
6475 |
else |
dd71cf6b2 md: tidy up statu... |
6476 |
max_sectors = mddev->dev_sectors; |
1da177e4c Linux-2.6.12-rc2 |
6477 6478 6479 6480 |
/* * Should not happen. */ |
dd71cf6b2 md: tidy up statu... |
6481 |
if (!max_sectors) { |
1da177e4c Linux-2.6.12-rc2 |
6482 6483 6484 |
MD_BUG(); return; } |
4588b42e9 [PATCH] md: Updat... |
6485 |
/* Pick 'scale' such that (resync>>scale)*1000 will fit |
dd71cf6b2 md: tidy up statu... |
6486 |
* in a sector_t, and (max_sectors>>scale) will fit in a |
4588b42e9 [PATCH] md: Updat... |
6487 6488 6489 6490 6491 |
* u32, as those are the requirements for sector_div. * Thus 'scale' must be at least 10 */ scale = 10; if (sizeof(sector_t) > sizeof(unsigned long)) { |
dd71cf6b2 md: tidy up statu... |
6492 |
while ( max_sectors/2 > (1ULL<<(scale+32))) |
4588b42e9 [PATCH] md: Updat... |
6493 6494 6495 |
scale++; } res = (resync>>scale)*1000; |
dd71cf6b2 md: tidy up statu... |
6496 |
sector_div(res, (u32)((max_sectors>>scale)+1)); |
4588b42e9 [PATCH] md: Updat... |
6497 6498 |
per_milli = res; |
1da177e4c Linux-2.6.12-rc2 |
6499 |
{ |
4588b42e9 [PATCH] md: Updat... |
6500 |
int i, x = per_milli/50, y = 20-x; |
1da177e4c Linux-2.6.12-rc2 |
6501 6502 6503 6504 6505 6506 6507 6508 |
seq_printf(seq, "["); for (i = 0; i < x; i++) seq_printf(seq, "="); seq_printf(seq, ">"); for (i = 0; i < y; i++) seq_printf(seq, "."); seq_printf(seq, "] "); } |
4588b42e9 [PATCH] md: Updat... |
6509 |
seq_printf(seq, " %s =%3u.%u%% (%llu/%llu)", |
ccfcc3c10 [PATCH] md: Core ... |
6510 6511 |
(test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)? "reshape" : |
61df9d91e [PATCH] md: make ... |
6512 6513 6514 6515 6516 |
(test_bit(MD_RECOVERY_CHECK, &mddev->recovery)? "check" : (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? "resync" : "recovery"))), per_milli/10, per_milli % 10, |
dd71cf6b2 md: tidy up statu... |
6517 6518 |
(unsigned long long) resync/2, (unsigned long long) max_sectors/2); |
1da177e4c Linux-2.6.12-rc2 |
6519 6520 |
/* |
1da177e4c Linux-2.6.12-rc2 |
6521 6522 6523 |
* dt: time from mark until now * db: blocks written from mark until now * rt: remaining time |
dd71cf6b2 md: tidy up statu... |
6524 6525 6526 6527 |
* * rt is a sector_t, so could be 32bit or 64bit. * So we divide before multiply in case it is 32bit and close * to the limit. |
25985edce Fix common misspe... |
6528 |
* We scale the divisor (db) by 32 to avoid losing precision |
dd71cf6b2 md: tidy up statu... |
6529 6530 6531 6532 |
* near the end of resync when the number of remaining sectors * is close to 'db'. * We then divide rt by 32 after multiplying by db to compensate. * The '+1' avoids division by zero if db is very small. |
1da177e4c Linux-2.6.12-rc2 |
6533 6534 6535 |
*/ dt = ((jiffies - mddev->resync_mark) / HZ); if (!dt) dt++; |
ff4e8d9a9 [PATCH] md: fix r... |
6536 6537 |
db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active)) - mddev->resync_mark_cnt; |
1da177e4c Linux-2.6.12-rc2 |
6538 |
|
dd71cf6b2 md: tidy up statu... |
6539 6540 6541 6542 6543 6544 6545 |
rt = max_sectors - resync; /* number of remaining sectors */ sector_div(rt, db/32+1); rt *= dt; rt >>= 5; seq_printf(seq, " finish=%lu.%lumin", (unsigned long)rt / 60, ((unsigned long)rt % 60)/6); |
1da177e4c Linux-2.6.12-rc2 |
6546 |
|
ff4e8d9a9 [PATCH] md: fix r... |
6547 |
seq_printf(seq, " speed=%ldK/sec", db/2/dt); |
1da177e4c Linux-2.6.12-rc2 |
6548 6549 6550 6551 6552 6553 |
} static void *md_seq_start(struct seq_file *seq, loff_t *pos) { struct list_head *tmp; loff_t l = *pos; |
fd01b88c7 md: remove typede... |
6554 |
struct mddev *mddev; |
1da177e4c Linux-2.6.12-rc2 |
6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 |
if (l >= 0x10000) return NULL; if (!l--) /* header */ return (void*)1; spin_lock(&all_mddevs_lock); list_for_each(tmp,&all_mddevs) if (!l--) { |
fd01b88c7 md: remove typede... |
6565 |
mddev = list_entry(tmp, struct mddev, all_mddevs); |
1da177e4c Linux-2.6.12-rc2 |
6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 |
mddev_get(mddev); spin_unlock(&all_mddevs_lock); return mddev; } spin_unlock(&all_mddevs_lock); if (!l--) return (void*)2;/* tail */ return NULL; } static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct list_head *tmp; |
fd01b88c7 md: remove typede... |
6579 |
struct mddev *next_mddev, *mddev = v; |
1da177e4c Linux-2.6.12-rc2 |
6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 |
++*pos; if (v == (void*)2) return NULL; spin_lock(&all_mddevs_lock); if (v == (void*)1) tmp = all_mddevs.next; else tmp = mddev->all_mddevs.next; if (tmp != &all_mddevs) |
fd01b88c7 md: remove typede... |
6591 |
next_mddev = mddev_get(list_entry(tmp,struct mddev,all_mddevs)); |
1da177e4c Linux-2.6.12-rc2 |
6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 |
else { next_mddev = (void*)2; *pos = 0x10000; } spin_unlock(&all_mddevs_lock); if (v != (void*)1) mddev_put(mddev); return next_mddev; } static void md_seq_stop(struct seq_file *seq, void *v) { |
fd01b88c7 md: remove typede... |
6606 |
struct mddev *mddev = v; |
1da177e4c Linux-2.6.12-rc2 |
6607 6608 6609 6610 6611 6612 6613 |
if (mddev && v != (void*)1 && v != (void*)2) mddev_put(mddev); } static int md_seq_show(struct seq_file *seq, void *v) { |
fd01b88c7 md: remove typede... |
6614 |
struct mddev *mddev = v; |
dd8ac336c md: Represent rai... |
6615 |
sector_t sectors; |
3cb030020 md: removing type... |
6616 |
struct md_rdev *rdev; |
32a7627cf [PATCH] md: optim... |
6617 |
struct bitmap *bitmap; |
1da177e4c Linux-2.6.12-rc2 |
6618 6619 |
if (v == (void*)1) { |
84fc4b56d md: rename "mdk_p... |
6620 |
struct md_personality *pers; |
1da177e4c Linux-2.6.12-rc2 |
6621 6622 |
seq_printf(seq, "Personalities : "); spin_lock(&pers_lock); |
2604b703b [PATCH] md: remov... |
6623 6624 |
list_for_each_entry(pers, &pers_list, list) seq_printf(seq, "[%s] ", pers->name); |
1da177e4c Linux-2.6.12-rc2 |
6625 6626 6627 6628 |
spin_unlock(&pers_lock); seq_printf(seq, " "); |
f15146380 fs: seq_file - ad... |
6629 |
seq->poll_event = atomic_read(&md_event_count); |
1da177e4c Linux-2.6.12-rc2 |
6630 6631 6632 6633 6634 6635 |
return 0; } if (v == (void*)2) { status_unused(seq); return 0; } |
5dc5cf7dd [PATCH] md: locki... |
6636 |
if (mddev_lock(mddev) < 0) |
1da177e4c Linux-2.6.12-rc2 |
6637 |
return -EINTR; |
5dc5cf7dd [PATCH] md: locki... |
6638 |
|
1da177e4c Linux-2.6.12-rc2 |
6639 6640 6641 6642 |
if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) { seq_printf(seq, "%s : %sactive", mdname(mddev), mddev->pers ? "" : "in"); if (mddev->pers) { |
f91de92ed [PATCH] md: allow... |
6643 |
if (mddev->ro==1) |
1da177e4c Linux-2.6.12-rc2 |
6644 |
seq_printf(seq, " (read-only)"); |
f91de92ed [PATCH] md: allow... |
6645 |
if (mddev->ro==2) |
52720ae77 md: fix formattin... |
6646 |
seq_printf(seq, " (auto-read-only)"); |
1da177e4c Linux-2.6.12-rc2 |
6647 6648 |
seq_printf(seq, " %s", mddev->pers->name); } |
dd8ac336c md: Represent rai... |
6649 |
sectors = 0; |
159ec1fc0 md: use list_for_... |
6650 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
1da177e4c Linux-2.6.12-rc2 |
6651 6652 6653 |
char b[BDEVNAME_SIZE]; seq_printf(seq, " %s[%d]", bdevname(rdev->bdev,b), rdev->desc_nr); |
8ddf9efe6 [PATCH] md: suppo... |
6654 6655 |
if (test_bit(WriteMostly, &rdev->flags)) seq_printf(seq, "(W)"); |
b2d444d7a [PATCH] md: conve... |
6656 |
if (test_bit(Faulty, &rdev->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
6657 6658 |
seq_printf(seq, "(F)"); continue; |
b325a32e5 [PATCH] md: repor... |
6659 6660 |
} else if (rdev->raid_disk < 0) seq_printf(seq, "(S)"); /* spare */ |
dd8ac336c md: Represent rai... |
6661 |
sectors += rdev->sectors; |
1da177e4c Linux-2.6.12-rc2 |
6662 6663 6664 6665 6666 6667 |
} if (!list_empty(&mddev->disks)) { if (mddev->pers) seq_printf(seq, " %llu blocks", |
f233ea5c9 md: Make mddev->a... |
6668 6669 |
(unsigned long long) mddev->array_sectors / 2); |
1da177e4c Linux-2.6.12-rc2 |
6670 6671 6672 |
else seq_printf(seq, " %llu blocks", |
dd8ac336c md: Represent rai... |
6673 |
(unsigned long long)sectors / 2); |
1da177e4c Linux-2.6.12-rc2 |
6674 |
} |
1cd6bf19b [PATCH] md: add i... |
6675 6676 6677 6678 6679 6680 6681 |
if (mddev->persistent) { if (mddev->major_version != 0 || mddev->minor_version != 90) { seq_printf(seq," super %d.%d", mddev->major_version, mddev->minor_version); } |
e691063a6 md: support 'exte... |
6682 6683 6684 6685 |
} else if (mddev->external) seq_printf(seq, " super external:%s", mddev->metadata_type); else |
1cd6bf19b [PATCH] md: add i... |
6686 |
seq_printf(seq, " super non-persistent"); |
1da177e4c Linux-2.6.12-rc2 |
6687 6688 |
if (mddev->pers) { |
d710e1381 md: remove space ... |
6689 |
mddev->pers->status(seq, mddev); |
1da177e4c Linux-2.6.12-rc2 |
6690 6691 |
seq_printf(seq, " "); |
8e1b39d62 [PATCH] md: only ... |
6692 6693 |
if (mddev->pers->sync_request) { if (mddev->curr_resync > 2) { |
d710e1381 md: remove space ... |
6694 |
status_resync(seq, mddev); |
8e1b39d62 [PATCH] md: only ... |
6695 6696 6697 6698 6699 6700 6701 6702 6703 |
seq_printf(seq, " "); } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) seq_printf(seq, "\tresync=DELAYED "); else if (mddev->recovery_cp < MaxSector) seq_printf(seq, "\tresync=PENDING "); } |
32a7627cf [PATCH] md: optim... |
6704 6705 6706 6707 6708 |
} else seq_printf(seq, " "); if ((bitmap = mddev->bitmap)) { |
32a7627cf [PATCH] md: optim... |
6709 6710 |
unsigned long chunk_kb; unsigned long flags; |
32a7627cf [PATCH] md: optim... |
6711 |
spin_lock_irqsave(&bitmap->lock, flags); |
42a04b507 md: move offset, ... |
6712 |
chunk_kb = mddev->bitmap_info.chunksize >> 10; |
32a7627cf [PATCH] md: optim... |
6713 6714 6715 6716 6717 6718 |
seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], " "%lu%s chunk", bitmap->pages - bitmap->missing_pages, bitmap->pages, (bitmap->pages - bitmap->missing_pages) << (PAGE_SHIFT - 10), |
42a04b507 md: move offset, ... |
6719 |
chunk_kb ? chunk_kb : mddev->bitmap_info.chunksize, |
32a7627cf [PATCH] md: optim... |
6720 |
chunk_kb ? "KB" : "B"); |
78d742d87 [PATCH] md: a cou... |
6721 6722 |
if (bitmap->file) { seq_printf(seq, ", file: "); |
c32c2f63a d_path: Make seq_... |
6723 6724 |
seq_path(seq, &bitmap->file->f_path, " \t "); |
32a7627cf [PATCH] md: optim... |
6725 |
} |
78d742d87 [PATCH] md: a cou... |
6726 |
|
32a7627cf [PATCH] md: optim... |
6727 6728 6729 |
seq_printf(seq, " "); spin_unlock_irqrestore(&bitmap->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
6730 6731 6732 6733 6734 6735 6736 6737 6738 |
} seq_printf(seq, " "); } mddev_unlock(mddev); return 0; } |
110518bcc md: constify VFTs |
6739 |
static const struct seq_operations md_seq_ops = { |
1da177e4c Linux-2.6.12-rc2 |
6740 6741 6742 6743 6744 6745 6746 6747 |
.start = md_seq_start, .next = md_seq_next, .stop = md_seq_stop, .show = md_seq_show, }; static int md_seq_open(struct inode *inode, struct file *file) { |
f15146380 fs: seq_file - ad... |
6748 |
struct seq_file *seq; |
1da177e4c Linux-2.6.12-rc2 |
6749 6750 6751 |
int error; error = seq_open(file, &md_seq_ops); |
d7603b7e3 [PATCH] md: make ... |
6752 |
if (error) |
f15146380 fs: seq_file - ad... |
6753 6754 6755 6756 |
return error; seq = file->private_data; seq->poll_event = atomic_read(&md_event_count); |
1da177e4c Linux-2.6.12-rc2 |
6757 6758 |
return error; } |
d7603b7e3 [PATCH] md: make ... |
6759 6760 |
static unsigned int mdstat_poll(struct file *filp, poll_table *wait) { |
f15146380 fs: seq_file - ad... |
6761 |
struct seq_file *seq = filp->private_data; |
d7603b7e3 [PATCH] md: make ... |
6762 6763 6764 6765 6766 6767 |
int mask; poll_wait(filp, &md_event_waiters, wait); /* always allow read */ mask = POLLIN | POLLRDNORM; |
f15146380 fs: seq_file - ad... |
6768 |
if (seq->poll_event != atomic_read(&md_event_count)) |
d7603b7e3 [PATCH] md: make ... |
6769 6770 6771 |
mask |= POLLERR | POLLPRI; return mask; } |
fa027c2a0 [PATCH] mark stru... |
6772 |
static const struct file_operations md_seq_fops = { |
e24650c2e [PATCH] md: fix /... |
6773 |
.owner = THIS_MODULE, |
1da177e4c Linux-2.6.12-rc2 |
6774 6775 6776 |
.open = md_seq_open, .read = seq_read, .llseek = seq_lseek, |
c3f94b40e md: cleanup: use ... |
6777 |
.release = seq_release_private, |
d7603b7e3 [PATCH] md: make ... |
6778 |
.poll = mdstat_poll, |
1da177e4c Linux-2.6.12-rc2 |
6779 |
}; |
84fc4b56d md: rename "mdk_p... |
6780 |
int register_md_personality(struct md_personality *p) |
1da177e4c Linux-2.6.12-rc2 |
6781 |
{ |
1da177e4c Linux-2.6.12-rc2 |
6782 |
spin_lock(&pers_lock); |
2604b703b [PATCH] md: remov... |
6783 6784 6785 |
list_add_tail(&p->list, &pers_list); printk(KERN_INFO "md: %s personality registered for level %d ", p->name, p->level); |
1da177e4c Linux-2.6.12-rc2 |
6786 6787 6788 |
spin_unlock(&pers_lock); return 0; } |
84fc4b56d md: rename "mdk_p... |
6789 |
int unregister_md_personality(struct md_personality *p) |
1da177e4c Linux-2.6.12-rc2 |
6790 |
{ |
2604b703b [PATCH] md: remov... |
6791 6792 |
printk(KERN_INFO "md: %s personality unregistered ", p->name); |
1da177e4c Linux-2.6.12-rc2 |
6793 |
spin_lock(&pers_lock); |
2604b703b [PATCH] md: remov... |
6794 |
list_del_init(&p->list); |
1da177e4c Linux-2.6.12-rc2 |
6795 6796 6797 |
spin_unlock(&pers_lock); return 0; } |
fd01b88c7 md: remove typede... |
6798 |
static int is_mddev_idle(struct mddev *mddev, int init) |
1da177e4c Linux-2.6.12-rc2 |
6799 |
{ |
3cb030020 md: removing type... |
6800 |
struct md_rdev * rdev; |
1da177e4c Linux-2.6.12-rc2 |
6801 |
int idle; |
eea1bf384 md: Fix is_mddev_... |
6802 |
int curr_events; |
1da177e4c Linux-2.6.12-rc2 |
6803 6804 |
idle = 1; |
4b80991c6 md: Protect acces... |
6805 6806 |
rcu_read_lock(); rdev_for_each_rcu(rdev, mddev) { |
1da177e4c Linux-2.6.12-rc2 |
6807 |
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; |
eea1bf384 md: Fix is_mddev_... |
6808 6809 6810 |
curr_events = (int)part_stat_read(&disk->part0, sectors[0]) + (int)part_stat_read(&disk->part0, sectors[1]) - atomic_read(&disk->sync_io); |
713f6ab18 md: improve the i... |
6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 |
/* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and * disk_stats is counted when it completes. * So resync activity will cause curr_events to be smaller than * when there was no such activity. * non-sync IO will cause disk_stat to increase without * increasing sync_io so curr_events will (eventually) * be larger than it was before. Once it becomes * substantially larger, the test below will cause * the array to appear non-idle, and resync will slow * down. * If there is a lot of outstanding resync activity when * we set last_event to curr_events, then all that activity * completing might cause the array to appear non-idle * and resync will be slowed down even though there might * not have been non-resync activity. This will only * happen once though. 'last_events' will soon reflect * the state where there is little or no outstanding * resync requests, and further resync activity will * always make curr_events less than last_events. |
c0e485216 [PATCH] md: fix i... |
6831 |
* |
1da177e4c Linux-2.6.12-rc2 |
6832 |
*/ |
eea1bf384 md: Fix is_mddev_... |
6833 |
if (init || curr_events - rdev->last_events > 64) { |
1da177e4c Linux-2.6.12-rc2 |
6834 6835 6836 6837 |
rdev->last_events = curr_events; idle = 0; } } |
4b80991c6 md: Protect acces... |
6838 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
6839 6840 |
return idle; } |
fd01b88c7 md: remove typede... |
6841 |
void md_done_sync(struct mddev *mddev, int blocks, int ok) |
1da177e4c Linux-2.6.12-rc2 |
6842 6843 6844 6845 6846 |
{ /* another "blocks" (512byte) blocks have been synced */ atomic_sub(blocks, &mddev->recovery_active); wake_up(&mddev->recovery_wait); if (!ok) { |
dfc706450 md: restart recov... |
6847 |
set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
1da177e4c Linux-2.6.12-rc2 |
6848 6849 6850 6851 |
md_wakeup_thread(mddev->thread); // stop recovery, signal do_sync .... } } |
06d91a5fe [PATCH] md: impro... |
6852 6853 |
/* md_write_start(mddev, bi) * If we need to update some array metadata (e.g. 'active' flag |
3d310eb7b [PATCH] md: fix d... |
6854 6855 |
* in superblock) before writing, schedule a superblock update * and wait for it to complete. |
06d91a5fe [PATCH] md: impro... |
6856 |
*/ |
fd01b88c7 md: remove typede... |
6857 |
void md_write_start(struct mddev *mddev, struct bio *bi) |
1da177e4c Linux-2.6.12-rc2 |
6858 |
{ |
0fd62b861 Make sure all cha... |
6859 |
int did_change = 0; |
06d91a5fe [PATCH] md: impro... |
6860 |
if (bio_data_dir(bi) != WRITE) |
3d310eb7b [PATCH] md: fix d... |
6861 |
return; |
06d91a5fe [PATCH] md: impro... |
6862 |
|
f91de92ed [PATCH] md: allow... |
6863 6864 6865 6866 6867 6868 |
BUG_ON(mddev->ro == 1); if (mddev->ro == 2) { /* need to switch to read/write */ mddev->ro = 0; set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); |
251561982 md: make sure a r... |
6869 |
md_wakeup_thread(mddev->sync_thread); |
0fd62b861 Make sure all cha... |
6870 |
did_change = 1; |
f91de92ed [PATCH] md: allow... |
6871 |
} |
06d91a5fe [PATCH] md: impro... |
6872 |
atomic_inc(&mddev->writes_pending); |
31a59e342 md: fix 'safemode... |
6873 6874 |
if (mddev->safemode == 1) mddev->safemode = 0; |
06d91a5fe [PATCH] md: impro... |
6875 |
if (mddev->in_sync) { |
a9701a304 [PATCH] md: suppo... |
6876 |
spin_lock_irq(&mddev->write_lock); |
3d310eb7b [PATCH] md: fix d... |
6877 6878 |
if (mddev->in_sync) { mddev->in_sync = 0; |
850b2b420 [PATCH] md: repla... |
6879 |
set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
070dc6dd7 md: resolve confu... |
6880 |
set_bit(MD_CHANGE_PENDING, &mddev->flags); |
3d310eb7b [PATCH] md: fix d... |
6881 |
md_wakeup_thread(mddev->thread); |
0fd62b861 Make sure all cha... |
6882 |
did_change = 1; |
3d310eb7b [PATCH] md: fix d... |
6883 |
} |
a9701a304 [PATCH] md: suppo... |
6884 |
spin_unlock_irq(&mddev->write_lock); |
06d91a5fe [PATCH] md: impro... |
6885 |
} |
0fd62b861 Make sure all cha... |
6886 |
if (did_change) |
00bcb4ac7 md: reduce depend... |
6887 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
09a44cc15 md: notify usersp... |
6888 |
wait_event(mddev->sb_wait, |
09a44cc15 md: notify usersp... |
6889 |
!test_bit(MD_CHANGE_PENDING, &mddev->flags)); |
1da177e4c Linux-2.6.12-rc2 |
6890 |
} |
fd01b88c7 md: remove typede... |
6891 |
void md_write_end(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
6892 6893 6894 6895 |
{ if (atomic_dec_and_test(&mddev->writes_pending)) { if (mddev->safemode == 2) md_wakeup_thread(mddev->thread); |
16f17b39f [PATCH] md: incre... |
6896 |
else if (mddev->safemode_delay) |
1da177e4c Linux-2.6.12-rc2 |
6897 6898 6899 |
mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); } } |
2a2275d63 [PATCH] md: fix p... |
6900 6901 6902 6903 6904 |
/* md_allow_write(mddev) * Calling this ensures that the array is marked 'active' so that writes * may proceed without blocking. It is important to call this before * attempting a GFP_KERNEL allocation while holding the mddev lock. * Must be called with mddev_lock held. |
b5470dc5f md: resolve exter... |
6905 6906 6907 |
* * In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock * is dropped, so return -EAGAIN after notifying userspace. |
2a2275d63 [PATCH] md: fix p... |
6908 |
*/ |
fd01b88c7 md: remove typede... |
6909 |
int md_allow_write(struct mddev *mddev) |
2a2275d63 [PATCH] md: fix p... |
6910 6911 |
{ if (!mddev->pers) |
b5470dc5f md: resolve exter... |
6912 |
return 0; |
2a2275d63 [PATCH] md: fix p... |
6913 |
if (mddev->ro) |
b5470dc5f md: resolve exter... |
6914 |
return 0; |
1a0fd4977 Don't try to make... |
6915 |
if (!mddev->pers->sync_request) |
b5470dc5f md: resolve exter... |
6916 |
return 0; |
2a2275d63 [PATCH] md: fix p... |
6917 6918 6919 6920 6921 |
spin_lock_irq(&mddev->write_lock); if (mddev->in_sync) { mddev->in_sync = 0; set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
070dc6dd7 md: resolve confu... |
6922 |
set_bit(MD_CHANGE_PENDING, &mddev->flags); |
2a2275d63 [PATCH] md: fix p... |
6923 6924 6925 6926 6927 |
if (mddev->safemode_delay && mddev->safemode == 0) mddev->safemode = 1; spin_unlock_irq(&mddev->write_lock); md_update_sb(mddev, 0); |
00bcb4ac7 md: reduce depend... |
6928 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
2a2275d63 [PATCH] md: fix p... |
6929 6930 |
} else spin_unlock_irq(&mddev->write_lock); |
b5470dc5f md: resolve exter... |
6931 |
|
070dc6dd7 md: resolve confu... |
6932 |
if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) |
b5470dc5f md: resolve exter... |
6933 6934 6935 |
return -EAGAIN; else return 0; |
2a2275d63 [PATCH] md: fix p... |
6936 6937 |
} EXPORT_SYMBOL_GPL(md_allow_write); |
1da177e4c Linux-2.6.12-rc2 |
6938 6939 |
#define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) |
fd01b88c7 md: remove typede... |
6940 |
void md_do_sync(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
6941 |
{ |
fd01b88c7 md: remove typede... |
6942 |
struct mddev *mddev2; |
1da177e4c Linux-2.6.12-rc2 |
6943 6944 |
unsigned int currspeed = 0, window; |
57afd89f9 [PATCH] md: impro... |
6945 |
sector_t max_sectors,j, io_sectors; |
1da177e4c Linux-2.6.12-rc2 |
6946 6947 6948 6949 6950 |
unsigned long mark[SYNC_MARKS]; sector_t mark_cnt[SYNC_MARKS]; int last_mark,m; struct list_head *tmp; sector_t last_check; |
57afd89f9 [PATCH] md: impro... |
6951 |
int skipped = 0; |
3cb030020 md: removing type... |
6952 |
struct md_rdev *rdev; |
61df9d91e [PATCH] md: make ... |
6953 |
char *desc; |
1da177e4c Linux-2.6.12-rc2 |
6954 6955 6956 6957 |
/* just incase thread restarts... */ if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) return; |
5fd6c1dce [PATCH] md: allow... |
6958 6959 |
if (mddev->ro) /* never try to sync a read-only array */ return; |
1da177e4c Linux-2.6.12-rc2 |
6960 |
|
61df9d91e [PATCH] md: make ... |
6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 |
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) desc = "data-check"; else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) desc = "requested-resync"; else desc = "resync"; } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) desc = "reshape"; else desc = "recovery"; |
1da177e4c Linux-2.6.12-rc2 |
6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 |
/* we overload curr_resync somewhat here. * 0 == not engaged in resync at all * 2 == checking that there is no conflict with another sync * 1 == like 2, but have yielded to allow conflicting resync to * commense * other == active in resync - this many blocks * * Before starting a resync we must have set curr_resync to * 2, and then checked that every "conflicting" array has curr_resync * less than ours. When we find one that is the same or higher * we wait on resync_wait. To avoid deadlock, we reduce curr_resync * to 1 if we choose to yield (based arbitrarily on address of mddev structure). * This will mean we have to start checking from the beginning again. * */ do { mddev->curr_resync = 2; try_again: |
404e4b43f md: allow a resyn... |
6992 |
if (kthread_should_stop()) |
6985c43f3 [PATCH] Three one... |
6993 |
set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
404e4b43f md: allow a resyn... |
6994 6995 |
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) |
1da177e4c Linux-2.6.12-rc2 |
6996 |
goto skip; |
29ac4aa3f md: change INTERA... |
6997 |
for_each_mddev(mddev2, tmp) { |
1da177e4c Linux-2.6.12-rc2 |
6998 6999 |
if (mddev2 == mddev) continue; |
90b08710e md: allow paralle... |
7000 7001 7002 |
if (!mddev->parallel_resync && mddev2->curr_resync && match_mddev_units(mddev, mddev2)) { |
1da177e4c Linux-2.6.12-rc2 |
7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 |
DEFINE_WAIT(wq); if (mddev < mddev2 && mddev->curr_resync == 2) { /* arbitrarily yield */ mddev->curr_resync = 1; wake_up(&resync_wait); } if (mddev > mddev2 && mddev->curr_resync == 1) /* no need to wait here, we can wait the next * time 'round when curr_resync == 2 */ continue; |
9744197c3 md: Don't wait UN... |
7014 7015 7016 7017 7018 |
/* We need to wait 'interruptible' so as not to * contribute to the load average, and not to * be caught by 'softlockup' */ prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); |
787453c23 [PATCH] md: compl... |
7019 |
if (!kthread_should_stop() && |
8712e5535 [PATCH] md: make ... |
7020 |
mddev2->curr_resync >= mddev->curr_resync) { |
61df9d91e [PATCH] md: make ... |
7021 7022 |
printk(KERN_INFO "md: delaying %s of %s" " until %s has finished (they" |
1da177e4c Linux-2.6.12-rc2 |
7023 7024 |
" share one or more physical units) ", |
61df9d91e [PATCH] md: make ... |
7025 |
desc, mdname(mddev), mdname(mddev2)); |
1da177e4c Linux-2.6.12-rc2 |
7026 |
mddev_put(mddev2); |
9744197c3 md: Don't wait UN... |
7027 7028 |
if (signal_pending(current)) flush_signals(current); |
1da177e4c Linux-2.6.12-rc2 |
7029 7030 7031 7032 7033 7034 7035 7036 |
schedule(); finish_wait(&resync_wait, &wq); goto try_again; } finish_wait(&resync_wait, &wq); } } } while (mddev->curr_resync < 2); |
5fd6c1dce [PATCH] md: allow... |
7037 |
j = 0; |
9d88883e6 [PATCH] md: teach... |
7038 |
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { |
1da177e4c Linux-2.6.12-rc2 |
7039 |
/* resync follows the size requested by the personality, |
57afd89f9 [PATCH] md: impro... |
7040 |
* which defaults to physical size, but can be virtual size |
1da177e4c Linux-2.6.12-rc2 |
7041 7042 |
*/ max_sectors = mddev->resync_max_sectors; |
9d88883e6 [PATCH] md: teach... |
7043 |
mddev->resync_mismatches = 0; |
5fd6c1dce [PATCH] md: allow... |
7044 |
/* we don't use the checkpoint if there's a bitmap */ |
5e96ee65c Allow setting sta... |
7045 7046 7047 |
if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) j = mddev->resync_min; else if (!mddev->bitmap) |
5fd6c1dce [PATCH] md: allow... |
7048 |
j = mddev->recovery_cp; |
5e96ee65c Allow setting sta... |
7049 |
|
ccfcc3c10 [PATCH] md: Core ... |
7050 |
} else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
58c0fed40 md: Make mddev->s... |
7051 |
max_sectors = mddev->dev_sectors; |
5fd6c1dce [PATCH] md: allow... |
7052 |
else { |
1da177e4c Linux-2.6.12-rc2 |
7053 |
/* recovery follows the physical size of devices */ |
58c0fed40 md: Make mddev->s... |
7054 |
max_sectors = mddev->dev_sectors; |
5fd6c1dce [PATCH] md: allow... |
7055 |
j = MaxSector; |
4e59ca7da md: rcu_read_lock... |
7056 7057 |
rcu_read_lock(); list_for_each_entry_rcu(rdev, &mddev->disks, same_set) |
5fd6c1dce [PATCH] md: allow... |
7058 7059 7060 7061 7062 |
if (rdev->raid_disk >= 0 && !test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) && rdev->recovery_offset < j) j = rdev->recovery_offset; |
4e59ca7da md: rcu_read_lock... |
7063 |
rcu_read_unlock(); |
5fd6c1dce [PATCH] md: allow... |
7064 |
} |
1da177e4c Linux-2.6.12-rc2 |
7065 |
|
61df9d91e [PATCH] md: make ... |
7066 7067 7068 7069 7070 |
printk(KERN_INFO "md: %s of RAID array %s ", desc, mdname(mddev)); printk(KERN_INFO "md: minimum _guaranteed_ speed:" " %d KB/sec/disk. ", speed_min(mddev)); |
338cec325 [PATCH] merge som... |
7071 |
printk(KERN_INFO "md: using maximum available idle IO bandwidth " |
61df9d91e [PATCH] md: make ... |
7072 7073 7074 |
"(but not more than %d KB/sec) for %s. ", speed_max(mddev), desc); |
1da177e4c Linux-2.6.12-rc2 |
7075 |
|
eea1bf384 md: Fix is_mddev_... |
7076 |
is_mddev_idle(mddev, 1); /* this initializes IO event counters */ |
5fd6c1dce [PATCH] md: allow... |
7077 |
|
57afd89f9 [PATCH] md: impro... |
7078 |
io_sectors = 0; |
1da177e4c Linux-2.6.12-rc2 |
7079 7080 |
for (m = 0; m < SYNC_MARKS; m++) { mark[m] = jiffies; |
57afd89f9 [PATCH] md: impro... |
7081 |
mark_cnt[m] = io_sectors; |
1da177e4c Linux-2.6.12-rc2 |
7082 7083 7084 7085 7086 7087 7088 7089 7090 |
} last_mark = 0; mddev->resync_mark = mark[last_mark]; mddev->resync_mark_cnt = mark_cnt[last_mark]; /* * Tune reconstruction: */ window = 32*(PAGE_SIZE/512); |
ac42450c7 MD: possible typo |
7091 7092 7093 |
printk(KERN_INFO "md: using %dk window, over a total of %lluk. ", window/2, (unsigned long long)max_sectors/2); |
1da177e4c Linux-2.6.12-rc2 |
7094 7095 |
atomic_set(&mddev->recovery_active, 0); |
1da177e4c Linux-2.6.12-rc2 |
7096 7097 7098 7099 |
last_check = 0; if (j>2) { printk(KERN_INFO |
61df9d91e [PATCH] md: make ... |
7100 7101 7102 |
"md: resuming %s of %s from checkpoint. ", desc, mdname(mddev)); |
1da177e4c Linux-2.6.12-rc2 |
7103 7104 |
mddev->curr_resync = j; } |
75d3da43c md: Don't let imp... |
7105 |
mddev->curr_resync_completed = j; |
1da177e4c Linux-2.6.12-rc2 |
7106 7107 |
while (j < max_sectors) { |
57afd89f9 [PATCH] md: impro... |
7108 |
sector_t sectors; |
1da177e4c Linux-2.6.12-rc2 |
7109 |
|
57afd89f9 [PATCH] md: impro... |
7110 |
skipped = 0; |
97e4f42d6 md: occasionally ... |
7111 |
|
7a91ee1f6 md: don't update ... |
7112 7113 7114 7115 7116 7117 7118 |
if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && ((mddev->curr_resync > mddev->curr_resync_completed && (mddev->curr_resync - mddev->curr_resync_completed) > (max_sectors >> 4)) || (j - mddev->curr_resync_completed)*2 >= mddev->resync_max - mddev->curr_resync_completed )) { |
97e4f42d6 md: occasionally ... |
7119 |
/* time to update curr_resync_completed */ |
97e4f42d6 md: occasionally ... |
7120 7121 |
wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active) == 0); |
75d3da43c md: Don't let imp... |
7122 |
mddev->curr_resync_completed = j; |
070dc6dd7 md: resolve confu... |
7123 |
set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
acb180b0e md: improve usefu... |
7124 |
sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
97e4f42d6 md: occasionally ... |
7125 |
} |
acb180b0e md: improve usefu... |
7126 |
|
e62e58a5f md: use interrupt... |
7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 |
while (j >= mddev->resync_max && !kthread_should_stop()) { /* As this condition is controlled by user-space, * we can block indefinitely, so use '_interruptible' * to avoid triggering warnings. */ flush_signals(current); /* just in case */ wait_event_interruptible(mddev->recovery_wait, mddev->resync_max > j || kthread_should_stop()); } |
acb180b0e md: improve usefu... |
7137 7138 7139 |
if (kthread_should_stop()) goto interrupted; |
57afd89f9 [PATCH] md: impro... |
7140 |
sectors = mddev->pers->sync_request(mddev, j, &skipped, |
c62072777 md: allow a maxim... |
7141 |
currspeed < speed_min(mddev)); |
57afd89f9 [PATCH] md: impro... |
7142 |
if (sectors == 0) { |
dfc706450 md: restart recov... |
7143 |
set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
1da177e4c Linux-2.6.12-rc2 |
7144 7145 |
goto out; } |
57afd89f9 [PATCH] md: impro... |
7146 7147 7148 7149 7150 |
if (!skipped) { /* actual IO requested */ io_sectors += sectors; atomic_add(sectors, &mddev->recovery_active); } |
e875ecea2 md/raid10 record ... |
7151 7152 |
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) break; |
1da177e4c Linux-2.6.12-rc2 |
7153 7154 |
j += sectors; if (j>1) mddev->curr_resync = j; |
ff4e8d9a9 [PATCH] md: fix r... |
7155 |
mddev->curr_mark_cnt = io_sectors; |
d7603b7e3 [PATCH] md: make ... |
7156 |
if (last_check == 0) |
e875ecea2 md/raid10 record ... |
7157 |
/* this is the earliest that rebuild will be |
d7603b7e3 [PATCH] md: make ... |
7158 7159 7160 |
* visible in /proc/mdstat */ md_new_event(mddev); |
57afd89f9 [PATCH] md: impro... |
7161 7162 |
if (last_check + window > io_sectors || j == max_sectors) |
1da177e4c Linux-2.6.12-rc2 |
7163 |
continue; |
57afd89f9 [PATCH] md: impro... |
7164 |
last_check = io_sectors; |
1da177e4c Linux-2.6.12-rc2 |
7165 7166 7167 7168 7169 7170 7171 7172 |
repeat: if (time_after_eq(jiffies, mark[last_mark] + SYNC_MARK_STEP )) { /* step marks */ int next = (last_mark+1) % SYNC_MARKS; mddev->resync_mark = mark[next]; mddev->resync_mark_cnt = mark_cnt[next]; mark[next] = jiffies; |
57afd89f9 [PATCH] md: impro... |
7173 |
mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active); |
1da177e4c Linux-2.6.12-rc2 |
7174 7175 |
last_mark = next; } |
c62072777 md: allow a maxim... |
7176 7177 |
if (kthread_should_stop()) goto interrupted; |
1da177e4c Linux-2.6.12-rc2 |
7178 7179 7180 7181 7182 7183 7184 7185 7186 |
/* * this loop exits only if either when we are slower than * the 'hard' speed limit, or the system was IO-idle for * a jiffy. * the system might be non-idle CPU-wise, but we only care * about not overloading the IO subsystem. (things like an * e2fsck being done on the RAID array should execute fast) */ |
1da177e4c Linux-2.6.12-rc2 |
7187 |
cond_resched(); |
57afd89f9 [PATCH] md: impro... |
7188 7189 |
currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 /((jiffies-mddev->resync_mark)/HZ +1) +1; |
1da177e4c Linux-2.6.12-rc2 |
7190 |
|
88202a0c8 [PATCH] md: allow... |
7191 7192 |
if (currspeed > speed_min(mddev)) { if ((currspeed > speed_max(mddev)) || |
eea1bf384 md: Fix is_mddev_... |
7193 |
!is_mddev_idle(mddev, 0)) { |
c0e485216 [PATCH] md: fix i... |
7194 |
msleep(500); |
1da177e4c Linux-2.6.12-rc2 |
7195 7196 7197 7198 |
goto repeat; } } } |
61df9d91e [PATCH] md: make ... |
7199 7200 |
printk(KERN_INFO "md: %s: %s done. ",mdname(mddev), desc); |
1da177e4c Linux-2.6.12-rc2 |
7201 7202 7203 7204 |
/* * this also signals 'finished resyncing' to md_stop */ out: |
1da177e4c Linux-2.6.12-rc2 |
7205 7206 7207 |
wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); /* tell personality that we are finished */ |
57afd89f9 [PATCH] md: impro... |
7208 |
mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); |
1da177e4c Linux-2.6.12-rc2 |
7209 |
|
dfc706450 md: restart recov... |
7210 |
if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && |
5fd6c1dce [PATCH] md: allow... |
7211 7212 7213 7214 7215 |
mddev->curr_resync > 2) { if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { if (mddev->curr_resync >= mddev->recovery_cp) { printk(KERN_INFO |
61df9d91e [PATCH] md: make ... |
7216 7217 7218 |
"md: checkpointing %s of %s. ", desc, mdname(mddev)); |
5fd6c1dce [PATCH] md: allow... |
7219 7220 7221 7222 7223 7224 7225 |
mddev->recovery_cp = mddev->curr_resync; } } else mddev->recovery_cp = MaxSector; } else { if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) mddev->curr_resync = MaxSector; |
4e59ca7da md: rcu_read_lock... |
7226 7227 |
rcu_read_lock(); list_for_each_entry_rcu(rdev, &mddev->disks, same_set) |
5fd6c1dce [PATCH] md: allow... |
7228 |
if (rdev->raid_disk >= 0 && |
70fffd0bf md: Don't update ... |
7229 |
mddev->delta_disks >= 0 && |
5fd6c1dce [PATCH] md: allow... |
7230 7231 7232 7233 |
!test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) && rdev->recovery_offset < mddev->curr_resync) rdev->recovery_offset = mddev->curr_resync; |
4e59ca7da md: rcu_read_lock... |
7234 |
rcu_read_unlock(); |
5fd6c1dce [PATCH] md: allow... |
7235 |
} |
1da177e4c Linux-2.6.12-rc2 |
7236 |
} |
175712843 [PATCH] md: assor... |
7237 |
set_bit(MD_CHANGE_DEVS, &mddev->flags); |
1da177e4c Linux-2.6.12-rc2 |
7238 |
|
1da177e4c Linux-2.6.12-rc2 |
7239 |
skip: |
c07b70ad3 md: adjust resync... |
7240 7241 7242 7243 7244 7245 7246 |
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { /* We completed so min/max setting can be forgotten if used. */ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) mddev->resync_min = 0; mddev->resync_max = MaxSector; } else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) mddev->resync_min = mddev->curr_resync_completed; |
1da177e4c Linux-2.6.12-rc2 |
7247 7248 7249 7250 |
mddev->curr_resync = 0; wake_up(&resync_wait); set_bit(MD_RECOVERY_DONE, &mddev->recovery); md_wakeup_thread(mddev->thread); |
c62072777 md: allow a maxim... |
7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 |
return; interrupted: /* * got a signal, exit. */ printk(KERN_INFO "md: md_do_sync() got signal ... exiting "); set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto out; |
1da177e4c Linux-2.6.12-rc2 |
7262 |
} |
292695531 [PATCH] md: Final... |
7263 |
EXPORT_SYMBOL_GPL(md_do_sync); |
1da177e4c Linux-2.6.12-rc2 |
7264 |
|
fd01b88c7 md: remove typede... |
7265 |
static int remove_and_add_spares(struct mddev *mddev) |
b4c4c7b80 [PATCH] md: resta... |
7266 |
{ |
3cb030020 md: removing type... |
7267 |
struct md_rdev *rdev; |
b4c4c7b80 [PATCH] md: resta... |
7268 |
int spares = 0; |
97e4f42d6 md: occasionally ... |
7269 |
mddev->curr_resync_completed = 0; |
159ec1fc0 md: use list_for_... |
7270 |
list_for_each_entry(rdev, &mddev->disks, same_set) |
b4c4c7b80 [PATCH] md: resta... |
7271 |
if (rdev->raid_disk >= 0 && |
6bfe0b499 md: support block... |
7272 |
!test_bit(Blocked, &rdev->flags) && |
b4c4c7b80 [PATCH] md: resta... |
7273 7274 7275 7276 7277 |
(test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && atomic_read(&rdev->nr_pending)==0) { if (mddev->pers->hot_remove_disk( mddev, rdev->raid_disk)==0) { |
36fad858a md: introduce lin... |
7278 |
sysfs_unlink_rdev(mddev, rdev); |
b4c4c7b80 [PATCH] md: resta... |
7279 7280 7281 |
rdev->raid_disk = -1; } } |
5389042ff md: change manage... |
7282 |
if (mddev->degraded) { |
159ec1fc0 md: use list_for_... |
7283 |
list_for_each_entry(rdev, &mddev->disks, same_set) { |
dfc706450 md: restart recov... |
7284 |
if (rdev->raid_disk >= 0 && |
e54271352 md: do not count ... |
7285 |
!test_bit(In_sync, &rdev->flags) && |
de393cdea md: make it easie... |
7286 |
!test_bit(Faulty, &rdev->flags)) |
dfc706450 md: restart recov... |
7287 |
spares++; |
b4c4c7b80 [PATCH] md: resta... |
7288 7289 7290 |
if (rdev->raid_disk < 0 && !test_bit(Faulty, &rdev->flags)) { rdev->recovery_offset = 0; |
199050ea1 rationalise retur... |
7291 7292 |
if (mddev->pers-> hot_add_disk(mddev, rdev) == 0) { |
36fad858a md: introduce lin... |
7293 |
if (sysfs_link_rdev(mddev, rdev)) |
00bcb4ac7 md: reduce depend... |
7294 |
/* failure here is OK */; |
b4c4c7b80 [PATCH] md: resta... |
7295 7296 |
spares++; md_new_event(mddev); |
93be75ffd md: integrate spa... |
7297 |
set_bit(MD_CHANGE_DEVS, &mddev->flags); |
b4c4c7b80 [PATCH] md: resta... |
7298 7299 7300 |
} else break; } |
dfc706450 md: restart recov... |
7301 |
} |
b4c4c7b80 [PATCH] md: resta... |
7302 7303 7304 |
} return spares; } |
7ebc0be7f md: Be more caref... |
7305 |
|
fd01b88c7 md: remove typede... |
7306 |
static void reap_sync_thread(struct mddev *mddev) |
7ebc0be7f md: Be more caref... |
7307 |
{ |
3cb030020 md: removing type... |
7308 |
struct md_rdev *rdev; |
7ebc0be7f md: Be more caref... |
7309 7310 |
/* resync has finished, collect result */ |
01f96c0a9 md: Avoid waking ... |
7311 |
md_unregister_thread(&mddev->sync_thread); |
7ebc0be7f md: Be more caref... |
7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 |
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { /* success...*/ /* activate any spares */ if (mddev->pers->spare_active(mddev)) sysfs_notify(&mddev->kobj, NULL, "degraded"); } if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && mddev->pers->finish_reshape) mddev->pers->finish_reshape(mddev); |
7ebc0be7f md: Be more caref... |
7323 |
|
d70ed2e4f MD: Allow restart... |
7324 7325 7326 7327 7328 |
/* If array is no-longer degraded, then any saved_raid_disk * information must be scrapped. Also if any device is now * In_sync we must scrape the saved_raid_disk for that device * do the superblock for an incrementally recovered device * written out. |
7ebc0be7f md: Be more caref... |
7329 |
*/ |
d70ed2e4f MD: Allow restart... |
7330 7331 7332 |
list_for_each_entry(rdev, &mddev->disks, same_set) if (!mddev->degraded || test_bit(In_sync, &rdev->flags)) |
7ebc0be7f md: Be more caref... |
7333 |
rdev->saved_raid_disk = -1; |
d70ed2e4f MD: Allow restart... |
7334 |
md_update_sb(mddev, 1); |
7ebc0be7f md: Be more caref... |
7335 7336 7337 7338 7339 7340 7341 7342 7343 |
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); /* flag recovery needed just to double check */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); sysfs_notify_dirent_safe(mddev->sysfs_action); md_new_event(mddev); |
768e587e1 MD: generate an e... |
7344 7345 |
if (mddev->event_work.func) queue_work(md_misc_wq, &mddev->event_work); |
7ebc0be7f md: Be more caref... |
7346 |
} |
1da177e4c Linux-2.6.12-rc2 |
7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 |
/* * This routine is regularly called by all per-raid-array threads to * deal with generic issues like resync and super-block update. * Raid personalities that don't have a thread (linear/raid0) do not * need this as they never do any recovery or update the superblock. * * It does not do any resync itself, but rather "forks" off other threads * to do that as needed. * When it is determined that resync is needed, we set MD_RECOVERY_RUNNING in * "->recovery" and create a thread at ->sync_thread. |
dfc706450 md: restart recov... |
7357 |
* When the thread finishes it sets MD_RECOVERY_DONE |
1da177e4c Linux-2.6.12-rc2 |
7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 |
* and wakeups up this thread which will reap the thread and finish up. * This thread also removes any faulty devices (with nr_pending == 0). * * The overall approach is: * 1/ if the superblock needs updating, update it. * 2/ If a recovery thread is running, don't do anything else. * 3/ If recovery has finished, clean up, possibly marking spares active. * 4/ If there are any faulty devices, remove them. * 5/ If array is degraded, try to add spares devices * 6/ If array has spares or is not in-sync, start a resync thread. */ |
fd01b88c7 md: remove typede... |
7369 |
void md_check_recovery(struct mddev *mddev) |
1da177e4c Linux-2.6.12-rc2 |
7370 |
{ |
68866e425 MD: no sync IO wh... |
7371 7372 |
if (mddev->suspended) return; |
5f40402d9 [PATCH] md: call ... |
7373 |
if (mddev->bitmap) |
aa5cbd103 md/bitmap: protec... |
7374 |
bitmap_daemon_work(mddev); |
1da177e4c Linux-2.6.12-rc2 |
7375 |
|
fca4d848f [PATCH] md: merge... |
7376 |
if (signal_pending(current)) { |
31a59e342 md: fix 'safemode... |
7377 |
if (mddev->pers->sync_request && !mddev->external) { |
fca4d848f [PATCH] md: merge... |
7378 7379 7380 7381 7382 7383 7384 |
printk(KERN_INFO "md: %s in immediate safe mode ", mdname(mddev)); mddev->safemode = 2; } flush_signals(current); } |
c89a8eee6 Allow faulty devi... |
7385 7386 |
if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) return; |
1da177e4c Linux-2.6.12-rc2 |
7387 |
if ( ! ( |
126925c09 md: call md_updat... |
7388 |
(mddev->flags & ~ (1<<MD_CHANGE_PENDING)) || |
1da177e4c Linux-2.6.12-rc2 |
7389 |
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || |
fca4d848f [PATCH] md: merge... |
7390 |
test_bit(MD_RECOVERY_DONE, &mddev->recovery) || |
31a59e342 md: fix 'safemode... |
7391 |
(mddev->external == 0 && mddev->safemode == 1) || |
fca4d848f [PATCH] md: merge... |
7392 7393 |
(mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending) && !mddev->in_sync && mddev->recovery_cp == MaxSector) |
1da177e4c Linux-2.6.12-rc2 |
7394 7395 |
)) return; |
fca4d848f [PATCH] md: merge... |
7396 |
|
df5b89b32 [PATCH] md: Conve... |
7397 |
if (mddev_trylock(mddev)) { |
b4c4c7b80 [PATCH] md: resta... |
7398 |
int spares = 0; |
fca4d848f [PATCH] md: merge... |
7399 |
|
c89a8eee6 Allow faulty devi... |
7400 7401 7402 7403 |
if (mddev->ro) { /* Only thing we do on a ro array is remove * failed devices. */ |
3cb030020 md: removing type... |
7404 |
struct md_rdev *rdev; |
a8c42c7f4 md: Don't use rem... |
7405 7406 7407 7408 7409 7410 7411 |
list_for_each_entry(rdev, &mddev->disks, same_set) if (rdev->raid_disk >= 0 && !test_bit(Blocked, &rdev->flags) && test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)==0) { if (mddev->pers->hot_remove_disk( mddev, rdev->raid_disk)==0) { |
36fad858a md: introduce lin... |
7412 |
sysfs_unlink_rdev(mddev, rdev); |
a8c42c7f4 md: Don't use rem... |
7413 7414 7415 |
rdev->raid_disk = -1; } } |
c89a8eee6 Allow faulty devi... |
7416 7417 7418 |
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); goto unlock; } |
31a59e342 md: fix 'safemode... |
7419 |
if (!mddev->external) { |
0fd62b861 Make sure all cha... |
7420 |
int did_change = 0; |
31a59e342 md: fix 'safemode... |
7421 7422 7423 7424 7425 7426 |
spin_lock_irq(&mddev->write_lock); if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; |
0fd62b861 Make sure all cha... |
7427 |
did_change = 1; |
070dc6dd7 md: resolve confu... |
7428 |
set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
31a59e342 md: fix 'safemode... |
7429 7430 7431 7432 |
} if (mddev->safemode == 1) mddev->safemode = 0; spin_unlock_irq(&mddev->write_lock); |
0fd62b861 Make sure all cha... |
7433 |
if (did_change) |
00bcb4ac7 md: reduce depend... |
7434 |
sysfs_notify_dirent_safe(mddev->sysfs_state); |
fca4d848f [PATCH] md: merge... |
7435 |
} |
fca4d848f [PATCH] md: merge... |
7436 |
|
850b2b420 [PATCH] md: repla... |
7437 7438 |
if (mddev->flags) md_update_sb(mddev, 0); |
06d91a5fe [PATCH] md: impro... |
7439 |
|
1da177e4c Linux-2.6.12-rc2 |
7440 7441 7442 7443 7444 7445 7446 |
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) { /* resync/recovery still happening */ clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); goto unlock; } if (mddev->sync_thread) { |
7ebc0be7f md: Be more caref... |
7447 |
reap_sync_thread(mddev); |
1da177e4c Linux-2.6.12-rc2 |
7448 7449 |
goto unlock; } |
72a23c211 Make sure all cha... |
7450 7451 7452 7453 7454 |
/* Set RUNNING before clearing NEEDED to avoid * any transients in the value of "sync_action". */ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
24dd469d7 [PATCH] md: allow... |
7455 7456 7457 |
/* Clear some bits that don't mean anything, but * might be left set */ |
24dd469d7 [PATCH] md: allow... |
7458 7459 |
clear_bit(MD_RECOVERY_INTR, &mddev->recovery); clear_bit(MD_RECOVERY_DONE, &mddev->recovery); |
1da177e4c Linux-2.6.12-rc2 |
7460 |
|
5fd6c1dce [PATCH] md: allow... |
7461 7462 |
if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) goto unlock; |
1da177e4c Linux-2.6.12-rc2 |
7463 7464 7465 7466 7467 7468 |
/* no recovery is running. * remove any failed drives, then * add spares if possible. * Spare are also removed and re-added, to allow * the personality to fail the re-add. */ |
1da177e4c Linux-2.6.12-rc2 |
7469 |
|
b4c4c7b80 [PATCH] md: resta... |
7470 |
if (mddev->reshape_position != MaxSector) { |
50ac168a6 md: merge reconfi... |
7471 7472 |
if (mddev->pers->check_reshape == NULL || mddev->pers->check_reshape(mddev) != 0) |
b4c4c7b80 [PATCH] md: resta... |
7473 7474 7475 |
/* Cannot proceed */ goto unlock; set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); |
72a23c211 Make sure all cha... |
7476 |
clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
b4c4c7b80 [PATCH] md: resta... |
7477 |
} else if ((spares = remove_and_add_spares(mddev))) { |
24dd469d7 [PATCH] md: allow... |
7478 7479 |
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); |
56ac36d72 md: cancel check/... |
7480 |
clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); |
72a23c211 Make sure all cha... |
7481 |
set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
24dd469d7 [PATCH] md: allow... |
7482 7483 |
} else if (mddev->recovery_cp < MaxSector) { set_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
72a23c211 Make sure all cha... |
7484 |
clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
24dd469d7 [PATCH] md: allow... |
7485 7486 |
} else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) /* nothing to be done ... */ |
1da177e4c Linux-2.6.12-rc2 |
7487 |
goto unlock; |
24dd469d7 [PATCH] md: allow... |
7488 |
|
1da177e4c Linux-2.6.12-rc2 |
7489 |
if (mddev->pers->sync_request) { |
a654b9d8f [PATCH] md: allow... |
7490 7491 7492 7493 7494 7495 7496 |
if (spares && mddev->bitmap && ! mddev->bitmap->file) { /* We are adding a device or devices to an array * which has the bitmap stored on all devices. * So make sure all bitmap pages get written */ bitmap_write_all(mddev->bitmap); } |
1da177e4c Linux-2.6.12-rc2 |
7497 7498 |
mddev->sync_thread = md_register_thread(md_do_sync, mddev, |
0da3c6194 md: Improve name ... |
7499 |
"resync"); |
1da177e4c Linux-2.6.12-rc2 |
7500 7501 7502 7503 7504 7505 |
if (!mddev->sync_thread) { printk(KERN_ERR "%s: could not start resync" " thread... ", mdname(mddev)); /* leave the spares where they are, it shouldn't hurt */ |
7ebc0be7f md: Be more caref... |
7506 7507 7508 7509 7510 |
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); |
d7603b7e3 [PATCH] md: make ... |
7511 |
} else |
1da177e4c Linux-2.6.12-rc2 |
7512 |
md_wakeup_thread(mddev->sync_thread); |
00bcb4ac7 md: reduce depend... |
7513 |
sysfs_notify_dirent_safe(mddev->sysfs_action); |
d7603b7e3 [PATCH] md: make ... |
7514 |
md_new_event(mddev); |
1da177e4c Linux-2.6.12-rc2 |
7515 7516 |
} unlock: |
72a23c211 Make sure all cha... |
7517 7518 7519 7520 |
if (!mddev->sync_thread) { clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); if (test_and_clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) |
0c3573f19 md: use sysfs_not... |
7521 |
if (mddev->sysfs_action) |
00bcb4ac7 md: reduce depend... |
7522 |
sysfs_notify_dirent_safe(mddev->sysfs_action); |
72a23c211 Make sure all cha... |
7523 |
} |
1da177e4c Linux-2.6.12-rc2 |
7524 7525 7526 |
mddev_unlock(mddev); } } |
fd01b88c7 md: remove typede... |
7527 |
void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev) |
6bfe0b499 md: support block... |
7528 |
{ |
00bcb4ac7 md: reduce depend... |
7529 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
6bfe0b499 md: support block... |
7530 |
wait_event_timeout(rdev->blocked_wait, |
de393cdea md: make it easie... |
7531 7532 |
!test_bit(Blocked, &rdev->flags) && !test_bit(BlockedBadBlocks, &rdev->flags), |
6bfe0b499 md: support block... |
7533 7534 7535 7536 |
msecs_to_jiffies(5000)); rdev_dec_pending(rdev, mddev); } EXPORT_SYMBOL(md_wait_for_blocked_rdev); |
2230dfe4c md: beginnings of... |
7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 |
/* Bad block management. * We can record which blocks on each device are 'bad' and so just * fail those blocks, or that stripe, rather than the whole device. * Entries in the bad-block table are 64bits wide. This comprises: * Length of bad-range, in sectors: 0-511 for lengths 1-512 * Start of bad-range, sector offset, 54 bits (allows 8 exbibytes) * A 'shift' can be set so that larger blocks are tracked and * consequently larger devices can be covered. * 'Acknowledged' flag - 1 bit. - the most significant bit. * * Locking of the bad-block table uses a seqlock so md_is_badblock * might need to retry if it is very unlucky. * We will sometimes want to check for bad blocks in a bi_end_io function, * so we use the write_seqlock_irq variant. * * When looking for a bad block we specify a range and want to * know if any block in the range is bad. So we binary-search * to the last range that starts at-or-before the given endpoint, * (or "before the sector after the target range") * then see if it ends after the given start. * We return * 0 if there are no known bad blocks in the range * 1 if there are known bad block which are all acknowledged * -1 if there are bad blocks which have not yet been acknowledged in metadata. * plus the start/length of the first bad section we overlap. */ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors) { int hi; int lo = 0; u64 *p = bb->page; int rv = 0; sector_t target = s + sectors; unsigned seq; if (bb->shift > 0) { /* round the start down, and the end up */ s >>= bb->shift; target += (1<<bb->shift) - 1; target >>= bb->shift; sectors = target - s; } /* 'target' is now the first block after the bad range */ retry: seq = read_seqbegin(&bb->lock); hi = bb->count; /* Binary search between lo and hi for 'target' * i.e. for the last range that starts before 'target' */ /* INVARIANT: ranges before 'lo' and at-or-after 'hi' * are known not to be the last range before target. * VARIANT: hi-lo is the number of possible * ranges, and decreases until it reaches 1 */ while (hi - lo > 1) { int mid = (lo + hi) / 2; sector_t a = BB_OFFSET(p[mid]); if (a < target) /* This could still be the one, earlier ranges * could not. */ lo = mid; else /* This and later ranges are definitely out. */ hi = mid; } /* 'lo' might be the last that started before target, but 'hi' isn't */ if (hi > lo) { /* need to check all range that end after 's' to see if * any are unacknowledged. */ while (lo >= 0 && BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) { if (BB_OFFSET(p[lo]) < target) { /* starts before the end, and finishes after * the start, so they must overlap */ if (rv != -1 && BB_ACK(p[lo])) rv = 1; else rv = -1; *first_bad = BB_OFFSET(p[lo]); *bad_sectors = BB_LEN(p[lo]); } lo--; } } if (read_seqretry(&bb->lock, seq)) goto retry; return rv; } EXPORT_SYMBOL_GPL(md_is_badblock); /* * Add a range of bad blocks to the table. * This might extend the table, or might contract it * if two adjacent ranges can be merged. * We binary-search to find the 'insertion' point, then * decide how best to handle it. */ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors, int acknowledged) { u64 *p; int lo, hi; int rv = 1; if (bb->shift < 0) /* badblocks are disabled */ return 0; if (bb->shift) { /* round the start down, and the end up */ sector_t next = s + sectors; s >>= bb->shift; next += (1<<bb->shift) - 1; next >>= bb->shift; sectors = next - s; } write_seqlock_irq(&bb->lock); p = bb->page; lo = 0; hi = bb->count; /* Find the last range that starts at-or-before 's' */ while (hi - lo > 1) { int mid = (lo + hi) / 2; sector_t a = BB_OFFSET(p[mid]); if (a <= s) lo = mid; else hi = mid; } if (hi > lo && BB_OFFSET(p[lo]) > s) hi = lo; if (hi > lo) { /* we found a range that might merge with the start * of our new range */ sector_t a = BB_OFFSET(p[lo]); sector_t e = a + BB_LEN(p[lo]); int ack = BB_ACK(p[lo]); if (e >= s) { /* Yes, we can merge with a previous range */ if (s == a && s + sectors >= e) /* new range covers old */ ack = acknowledged; else ack = ack && acknowledged; if (e < s + sectors) e = s + sectors; if (e - a <= BB_MAX_LEN) { p[lo] = BB_MAKE(a, e-a, ack); s = e; } else { /* does not all fit in one range, * make p[lo] maximal */ if (BB_LEN(p[lo]) != BB_MAX_LEN) p[lo] = BB_MAKE(a, BB_MAX_LEN, ack); s = a + BB_MAX_LEN; } sectors = e - s; } } if (sectors && hi < bb->count) { /* 'hi' points to the first range that starts after 's'. * Maybe we can merge with the start of that range */ sector_t a = BB_OFFSET(p[hi]); sector_t e = a + BB_LEN(p[hi]); int ack = BB_ACK(p[hi]); if (a <= s + sectors) { /* merging is possible */ if (e <= s + sectors) { /* full overlap */ e = s + sectors; ack = acknowledged; } else ack = ack && acknowledged; a = s; if (e - a <= BB_MAX_LEN) { p[hi] = BB_MAKE(a, e-a, ack); s = e; } else { p[hi] = BB_MAKE(a, BB_MAX_LEN, ack); s = a + BB_MAX_LEN; } sectors = e - s; lo = hi; hi++; } } if (sectors == 0 && hi < bb->count) { /* we might be able to combine lo and hi */ /* Note: 's' is at the end of 'lo' */ sector_t a = BB_OFFSET(p[hi]); int lolen = BB_LEN(p[lo]); int hilen = BB_LEN(p[hi]); int newlen = lolen + hilen - (s - a); if (s >= a && newlen < BB_MAX_LEN) { /* yes, we can combine them */ int ack = BB_ACK(p[lo]) && BB_ACK(p[hi]); p[lo] = BB_MAKE(BB_OFFSET(p[lo]), newlen, ack); memmove(p + hi, p + hi + 1, (bb->count - hi - 1) * 8); bb->count--; } } while (sectors) { /* didn't merge (it all). * Need to add a range just before 'hi' */ if (bb->count >= MD_MAX_BADBLOCKS) { /* No room for more */ rv = 0; break; } else { int this_sectors = sectors; memmove(p + hi + 1, p + hi, (bb->count - hi) * 8); bb->count++; if (this_sectors > BB_MAX_LEN) this_sectors = BB_MAX_LEN; p[hi] = BB_MAKE(s, this_sectors, acknowledged); sectors -= this_sectors; s += this_sectors; } } bb->changed = 1; |
de393cdea md: make it easie... |
7777 7778 |
if (!acknowledged) bb->unacked_exist = 1; |
2230dfe4c md: beginnings of... |
7779 7780 7781 7782 |
write_sequnlock_irq(&bb->lock); return rv; } |
3cb030020 md: removing type... |
7783 |
int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors, |
2230dfe4c md: beginnings of... |
7784 7785 7786 7787 7788 7789 |
int acknowledged) { int rv = md_set_badblocks(&rdev->badblocks, s + rdev->data_offset, sectors, acknowledged); if (rv) { /* Make sure they get written out promptly */ |
8bd2f0a05 md: ensure new ba... |
7790 |
sysfs_notify_dirent_safe(rdev->sysfs_state); |
2230dfe4c md: beginnings of... |
7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 |
set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags); md_wakeup_thread(rdev->mddev->thread); } return rv; } EXPORT_SYMBOL_GPL(rdev_set_badblocks); /* * Remove a range of bad blocks from the table. * This may involve extending the table if we spilt a region, * but it must not fail. So if the table becomes full, we just * drop the remove request. */ static int md_clear_badblocks(struct badblocks *bb, sector_t s, int sectors) { u64 *p; int lo, hi; sector_t target = s + sectors; int rv = 0; if (bb->shift > 0) { /* When clearing we round the start up and the end down. * This should not matter as the shift should align with * the block size and no rounding should ever be needed. * However it is better the think a block is bad when it * isn't than to think a block is not bad when it is. */ s += (1<<bb->shift) - 1; s >>= bb->shift; target >>= bb->shift; sectors = target - s; } write_seqlock_irq(&bb->lock); p = bb->page; lo = 0; hi = bb->count; /* Find the last range that starts before 'target' */ while (hi - lo > 1) { int mid = (lo + hi) / 2; sector_t a = BB_OFFSET(p[mid]); if (a < target) lo = mid; else hi = mid; } if (hi > lo) { /* p[lo] is the last range that could overlap the * current range. Earlier ranges could also overlap, * but only this one can overlap the end of the range. */ if (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) { /* Partial overlap, leave the tail of this range */ int ack = BB_ACK(p[lo]); sector_t a = BB_OFFSET(p[lo]); sector_t end = a + BB_LEN(p[lo]); if (a < s) { /* we need to split this range */ if (bb->count >= MD_MAX_BADBLOCKS) { rv = 0; goto out; } memmove(p+lo+1, p+lo, (bb->count - lo) * 8); bb->count++; p[lo] = BB_MAKE(a, s-a, ack); lo++; } p[lo] = BB_MAKE(target, end - target, ack); /* there is no longer an overlap */ hi = lo; lo--; } while (lo >= 0 && BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) { /* This range does overlap */ if (BB_OFFSET(p[lo]) < s) { /* Keep the early parts of this range. */ int ack = BB_ACK(p[lo]); sector_t start = BB_OFFSET(p[lo]); p[lo] = BB_MAKE(start, s - start, ack); /* now low doesn't overlap, so.. */ break; } lo--; } /* 'lo' is strictly before, 'hi' is strictly after, * anything between needs to be discarded */ if (hi - lo > 1) { memmove(p+lo+1, p+hi, (bb->count - hi) * 8); bb->count -= (hi - lo - 1); } } bb->changed = 1; out: write_sequnlock_irq(&bb->lock); return rv; } |
3cb030020 md: removing type... |
7892 |
int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors) |
2230dfe4c md: beginnings of... |
7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 |
{ return md_clear_badblocks(&rdev->badblocks, s + rdev->data_offset, sectors); } EXPORT_SYMBOL_GPL(rdev_clear_badblocks); /* * Acknowledge all bad blocks in a list. * This only succeeds if ->changed is clear. It is used by * in-kernel metadata updates */ void md_ack_all_badblocks(struct badblocks *bb) { if (bb->page == NULL || bb->changed) /* no point even trying */ return; write_seqlock_irq(&bb->lock); if (bb->changed == 0) { u64 *p = bb->page; int i; for (i = 0; i < bb->count ; i++) { if (!BB_ACK(p[i])) { sector_t start = BB_OFFSET(p[i]); int len = BB_LEN(p[i]); p[i] = BB_MAKE(start, len, 1); } } |
de393cdea md: make it easie... |
7922 |
bb->unacked_exist = 0; |
2230dfe4c md: beginnings of... |
7923 7924 7925 7926 |
} write_sequnlock_irq(&bb->lock); } EXPORT_SYMBOL_GPL(md_ack_all_badblocks); |
16c791a5a md/bad-block-log:... |
7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 |
/* sysfs access to bad-blocks list. * We present two files. * 'bad-blocks' lists sector numbers and lengths of ranges that * are recorded as bad. The list is truncated to fit within * the one-page limit of sysfs. * Writing "sector length" to this file adds an acknowledged * bad block list. * 'unacknowledged-bad-blocks' lists bad blocks that have not yet * been acknowledged. Writing to this file adds bad blocks * without acknowledging them. This is largely for testing. */ static ssize_t badblocks_show(struct badblocks *bb, char *page, int unack) { size_t len; int i; u64 *p = bb->page; unsigned seq; if (bb->shift < 0) return 0; retry: seq = read_seqbegin(&bb->lock); len = 0; i = 0; while (len < PAGE_SIZE && i < bb->count) { sector_t s = BB_OFFSET(p[i]); unsigned int length = BB_LEN(p[i]); int ack = BB_ACK(p[i]); i++; if (unack && ack) continue; len += snprintf(page+len, PAGE_SIZE-len, "%llu %u ", (unsigned long long)s << bb->shift, length << bb->shift); } |
de393cdea md: make it easie... |
7970 7971 |
if (unack && len == 0) bb->unacked_exist = 0; |
16c791a5a md/bad-block-log:... |
7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 |
if (read_seqretry(&bb->lock, seq)) goto retry; return len; } #define DO_DEBUG 1 static ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack) { unsigned long long sector; int length; char newline; #ifdef DO_DEBUG /* Allow clearing via sysfs *only* for testing/debugging. * Normally only a successful write may clear a badblock */ int clear = 0; if (page[0] == '-') { clear = 1; page++; } #endif /* DO_DEBUG */ switch (sscanf(page, "%llu %d%c", §or, &length, &newline)) { case 3: if (newline != ' ') return -EINVAL; case 2: if (length <= 0) return -EINVAL; break; default: return -EINVAL; } #ifdef DO_DEBUG if (clear) { md_clear_badblocks(bb, sector, length); return len; } #endif /* DO_DEBUG */ if (md_set_badblocks(bb, sector, length, !unack)) return len; else return -ENOSPC; } |
75c96f858 [PATCH] make some... |
8022 8023 |
static int md_notify_reboot(struct notifier_block *this, unsigned long code, void *x) |
1da177e4c Linux-2.6.12-rc2 |
8024 8025 |
{ struct list_head *tmp; |
fd01b88c7 md: remove typede... |
8026 |
struct mddev *mddev; |
2dba6a911 md: don't delay r... |
8027 |
int need_delay = 0; |
1da177e4c Linux-2.6.12-rc2 |
8028 8029 8030 8031 8032 |
if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) { printk(KERN_INFO "md: stopping all md devices. "); |
2dba6a911 md: don't delay r... |
8033 |
for_each_mddev(mddev, tmp) { |
c71d48877 [PATCH] Unlock md... |
8034 |
if (mddev_trylock(mddev)) { |
2b25000bf Restore force swi... |
8035 8036 8037 8038 |
/* Force a switch to readonly even array * appears to still be in use. Hence * the '100'. */ |
a4bd82d0d md: split md_set_... |
8039 |
md_set_readonly(mddev, 100); |
c71d48877 [PATCH] Unlock md... |
8040 8041 |
mddev_unlock(mddev); } |
2dba6a911 md: don't delay r... |
8042 8043 |
need_delay = 1; } |
1da177e4c Linux-2.6.12-rc2 |
8044 8045 8046 8047 8048 8049 |
/* * certain more exotic SCSI devices are known to be * volatile wrt too early system reboots. While the * right place to handle this issue is the given * driver, we do want to have a safe RAID driver ... */ |
2dba6a911 md: don't delay r... |
8050 8051 |
if (need_delay) mdelay(1000*1); |
1da177e4c Linux-2.6.12-rc2 |
8052 8053 8054 |
} return NOTIFY_DONE; } |
75c96f858 [PATCH] make some... |
8055 |
static struct notifier_block md_notifier = { |
1da177e4c Linux-2.6.12-rc2 |
8056 8057 8058 8059 8060 8061 8062 |
.notifier_call = md_notify_reboot, .next = NULL, .priority = INT_MAX, /* before any real devices */ }; static void md_geninit(void) { |
36a4e1fe0 md: remove PRINTK... |
8063 8064 |
pr_debug("md: sizeof(mdp_super_t) = %d ", (int)sizeof(mdp_super_t)); |
1da177e4c Linux-2.6.12-rc2 |
8065 |
|
c7705f344 drivers: use non-... |
8066 |
proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops); |
1da177e4c Linux-2.6.12-rc2 |
8067 |
} |
75c96f858 [PATCH] make some... |
8068 |
static int __init md_init(void) |
1da177e4c Linux-2.6.12-rc2 |
8069 |
{ |
e804ac780 md: fix and updat... |
8070 |
int ret = -ENOMEM; |
ada609ee2 workqueue: use WQ... |
8071 |
md_wq = alloc_workqueue("md", WQ_MEM_RECLAIM, 0); |
e804ac780 md: fix and updat... |
8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 |
if (!md_wq) goto err_wq; md_misc_wq = alloc_workqueue("md_misc", 0, 0); if (!md_misc_wq) goto err_misc_wq; if ((ret = register_blkdev(MD_MAJOR, "md")) < 0) goto err_md; if ((ret = register_blkdev(0, "mdp")) < 0) goto err_mdp; mdp_major = ret; |
3dbd8c2e3 md: stop defining... |
8085 |
blk_register_region(MKDEV(MD_MAJOR, 0), 1UL<<MINORBITS, THIS_MODULE, |
e8703fe1f [PATCH] md: remov... |
8086 8087 |
md_probe, NULL, NULL); blk_register_region(MKDEV(mdp_major, 0), 1UL<<MINORBITS, THIS_MODULE, |
1da177e4c Linux-2.6.12-rc2 |
8088 |
md_probe, NULL, NULL); |
1da177e4c Linux-2.6.12-rc2 |
8089 |
register_reboot_notifier(&md_notifier); |
0b4d41471 [PATCH] sysctl: r... |
8090 |
raid_table_header = register_sysctl_table(raid_root_table); |
1da177e4c Linux-2.6.12-rc2 |
8091 8092 |
md_geninit(); |
d710e1381 md: remove space ... |
8093 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
8094 |
|
e804ac780 md: fix and updat... |
8095 8096 8097 8098 8099 8100 8101 8102 8103 |
err_mdp: unregister_blkdev(MD_MAJOR, "md"); err_md: destroy_workqueue(md_misc_wq); err_misc_wq: destroy_workqueue(md_wq); err_wq: return ret; } |
1da177e4c Linux-2.6.12-rc2 |
8104 8105 8106 8107 8108 8109 8110 |
#ifndef MODULE /* * Searches all registered partitions for autorun RAID arrays * at boot time. */ |
4d936ec1f md: software Raid... |
8111 8112 8113 8114 8115 8116 |
static LIST_HEAD(all_detected_devices); struct detected_devices_node { struct list_head list; dev_t dev; }; |
1da177e4c Linux-2.6.12-rc2 |
8117 8118 8119 |
void md_autodetect_dev(dev_t dev) { |
4d936ec1f md: software Raid... |
8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 |
struct detected_devices_node *node_detected_dev; node_detected_dev = kzalloc(sizeof(*node_detected_dev), GFP_KERNEL); if (node_detected_dev) { node_detected_dev->dev = dev; list_add_tail(&node_detected_dev->list, &all_detected_devices); } else { printk(KERN_CRIT "md: md_autodetect_dev: kzalloc failed" ", skipping dev(%d,%d) ", MAJOR(dev), MINOR(dev)); } |
1da177e4c Linux-2.6.12-rc2 |
8131 8132 8133 8134 8135 |
} static void autostart_arrays(int part) { |
3cb030020 md: removing type... |
8136 |
struct md_rdev *rdev; |
4d936ec1f md: software Raid... |
8137 8138 8139 |
struct detected_devices_node *node_detected_dev; dev_t dev; int i_scanned, i_passed; |
1da177e4c Linux-2.6.12-rc2 |
8140 |
|
4d936ec1f md: software Raid... |
8141 8142 |
i_scanned = 0; i_passed = 0; |
1da177e4c Linux-2.6.12-rc2 |
8143 |
|
4d936ec1f md: software Raid... |
8144 8145 |
printk(KERN_INFO "md: Autodetecting RAID arrays. "); |
1da177e4c Linux-2.6.12-rc2 |
8146 |
|
4d936ec1f md: software Raid... |
8147 8148 8149 8150 8151 8152 8153 |
while (!list_empty(&all_detected_devices) && i_scanned < INT_MAX) { i_scanned++; node_detected_dev = list_entry(all_detected_devices.next, struct detected_devices_node, list); list_del(&node_detected_dev->list); dev = node_detected_dev->dev; kfree(node_detected_dev); |
df968c4e8 md: improve messa... |
8154 |
rdev = md_import_device(dev,0, 90); |
1da177e4c Linux-2.6.12-rc2 |
8155 8156 |
if (IS_ERR(rdev)) continue; |
b2d444d7a [PATCH] md: conve... |
8157 |
if (test_bit(Faulty, &rdev->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
8158 8159 8160 |
MD_BUG(); continue; } |
d0fae18f1 md: clean up irre... |
8161 |
set_bit(AutoDetected, &rdev->flags); |
1da177e4c Linux-2.6.12-rc2 |
8162 |
list_add(&rdev->same_set, &pending_raid_disks); |
4d936ec1f md: software Raid... |
8163 |
i_passed++; |
1da177e4c Linux-2.6.12-rc2 |
8164 |
} |
4d936ec1f md: software Raid... |
8165 8166 8167 8168 |
printk(KERN_INFO "md: Scanned %d and added %d devices. ", i_scanned, i_passed); |
1da177e4c Linux-2.6.12-rc2 |
8169 8170 8171 |
autorun_devices(part); } |
fdee8ae44 [PATCH] MD: condi... |
8172 |
#endif /* !MODULE */ |
1da177e4c Linux-2.6.12-rc2 |
8173 8174 8175 |
static __exit void md_exit(void) { |
fd01b88c7 md: remove typede... |
8176 |
struct mddev *mddev; |
1da177e4c Linux-2.6.12-rc2 |
8177 |
struct list_head *tmp; |
8ab5e4c15 [PATCH] devfs: Re... |
8178 |
|
3dbd8c2e3 md: stop defining... |
8179 |
blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS); |
e8703fe1f [PATCH] md: remov... |
8180 |
blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS); |
1da177e4c Linux-2.6.12-rc2 |
8181 |
|
3dbd8c2e3 md: stop defining... |
8182 |
unregister_blkdev(MD_MAJOR,"md"); |
1da177e4c Linux-2.6.12-rc2 |
8183 8184 8185 8186 |
unregister_blkdev(mdp_major, "mdp"); unregister_reboot_notifier(&md_notifier); unregister_sysctl_table(raid_table_header); remove_proc_entry("mdstat", NULL); |
29ac4aa3f md: change INTERA... |
8187 |
for_each_mddev(mddev, tmp) { |
1da177e4c Linux-2.6.12-rc2 |
8188 |
export_array(mddev); |
d3374825c md: make devices ... |
8189 |
mddev->hold_active = 0; |
1da177e4c Linux-2.6.12-rc2 |
8190 |
} |
e804ac780 md: fix and updat... |
8191 8192 |
destroy_workqueue(md_misc_wq); destroy_workqueue(md_wq); |
1da177e4c Linux-2.6.12-rc2 |
8193 |
} |
685784aaf xor: make 'xor_bl... |
8194 |
subsys_initcall(md_init); |
1da177e4c Linux-2.6.12-rc2 |
8195 |
module_exit(md_exit) |
f91de92ed [PATCH] md: allow... |
8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 |
static int get_ro(char *buffer, struct kernel_param *kp) { return sprintf(buffer, "%d", start_readonly); } static int set_ro(const char *val, struct kernel_param *kp) { char *e; int num = simple_strtoul(val, &e, 10); if (*val && (*e == '\0' || *e == ' ')) { start_readonly = num; |
4dbcdc751 [PATCH] md: count... |
8207 |
return 0; |
f91de92ed [PATCH] md: allow... |
8208 8209 8210 |
} return -EINVAL; } |
80ca3a44f [PATCH] md: unify... |
8211 8212 |
module_param_call(start_ro, set_ro, get_ro, NULL, S_IRUSR|S_IWUSR); module_param(start_dirty_degraded, int, S_IRUGO|S_IWUSR); |
6ff8d8ec0 [PATCH] md: allow... |
8213 |
|
efeb53c0e md: Allow md devi... |
8214 |
module_param_call(new_array, add_named_array, NULL, NULL, S_IWUSR); |
f91de92ed [PATCH] md: allow... |
8215 |
|
1da177e4c Linux-2.6.12-rc2 |
8216 8217 8218 8219 8220 8221 |
EXPORT_SYMBOL(register_md_personality); EXPORT_SYMBOL(unregister_md_personality); EXPORT_SYMBOL(md_error); EXPORT_SYMBOL(md_done_sync); EXPORT_SYMBOL(md_write_start); EXPORT_SYMBOL(md_write_end); |
1da177e4c Linux-2.6.12-rc2 |
8222 8223 8224 |
EXPORT_SYMBOL(md_register_thread); EXPORT_SYMBOL(md_unregister_thread); EXPORT_SYMBOL(md_wakeup_thread); |
1da177e4c Linux-2.6.12-rc2 |
8225 8226 |
EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); |
0efb9e619 md: add MODULE_DE... |
8227 |
MODULE_DESCRIPTION("MD RAID framework"); |
aa1595e9f [PATCH] md: make ... |
8228 |
MODULE_ALIAS("md"); |
72008652d [PATCH] md: creat... |
8229 |
MODULE_ALIAS_BLOCKDEV_MAJOR(MD_MAJOR); |