diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-ioctl.c | 14 | ||||
-rw-r--r-- | drivers/md/dm-log.c | 48 | ||||
-rw-r--r-- | drivers/md/dm-snap.c | 29 | ||||
-rw-r--r-- | drivers/md/dm-snap.h | 4 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 2 | ||||
-rw-r--r-- | drivers/md/dm.c | 39 | ||||
-rw-r--r-- | drivers/md/md.c | 48 | ||||
-rw-r--r-- | drivers/md/raid0.c | 2 | ||||
-rw-r--r-- | drivers/md/raid10.c | 2 | ||||
-rw-r--r-- | drivers/md/raid5.c | 3 | ||||
-rw-r--r-- | drivers/md/raid6main.c | 152 |
11 files changed, 220 insertions, 123 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 1235135b384b..442e2be6052e 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -1359,16 +1359,11 @@ static int ctl_ioctl(struct inode *inode, struct file *file, | |||
1359 | * Copy the parameters into kernel space. | 1359 | * Copy the parameters into kernel space. |
1360 | */ | 1360 | */ |
1361 | r = copy_params(user, ¶m); | 1361 | r = copy_params(user, ¶m); |
1362 | if (r) { | ||
1363 | current->flags &= ~PF_MEMALLOC; | ||
1364 | return r; | ||
1365 | } | ||
1366 | 1362 | ||
1367 | /* | 1363 | current->flags &= ~PF_MEMALLOC; |
1368 | * FIXME: eventually we will remove the PF_MEMALLOC flag | 1364 | |
1369 | * here. However the tools still do nasty things like | 1365 | if (r) |
1370 | * 'load' while a device is suspended. | 1366 | return r; |
1371 | */ | ||
1372 | 1367 | ||
1373 | r = validate_params(cmd, param); | 1368 | r = validate_params(cmd, param); |
1374 | if (r) | 1369 | if (r) |
@@ -1386,7 +1381,6 @@ static int ctl_ioctl(struct inode *inode, struct file *file, | |||
1386 | 1381 | ||
1387 | out: | 1382 | out: |
1388 | free_params(param); | 1383 | free_params(param); |
1389 | current->flags &= ~PF_MEMALLOC; | ||
1390 | return r; | 1384 | return r; |
1391 | } | 1385 | } |
1392 | 1386 | ||
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index efe4adf78530..d73779a42417 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -112,7 +112,7 @@ void dm_destroy_dirty_log(struct dirty_log *log) | |||
112 | /* | 112 | /* |
113 | * The on-disk version of the metadata. | 113 | * The on-disk version of the metadata. |
114 | */ | 114 | */ |
115 | #define MIRROR_DISK_VERSION 1 | 115 | #define MIRROR_DISK_VERSION 2 |
116 | #define LOG_OFFSET 2 | 116 | #define LOG_OFFSET 2 |
117 | 117 | ||
118 | struct log_header { | 118 | struct log_header { |
@@ -157,7 +157,6 @@ struct log_c { | |||
157 | struct log_header *disk_header; | 157 | struct log_header *disk_header; |
158 | 158 | ||
159 | struct io_region bits_location; | 159 | struct io_region bits_location; |
160 | uint32_t *disk_bits; | ||
161 | }; | 160 | }; |
162 | 161 | ||
163 | /* | 162 | /* |
@@ -166,20 +165,20 @@ struct log_c { | |||
166 | */ | 165 | */ |
167 | static inline int log_test_bit(uint32_t *bs, unsigned bit) | 166 | static inline int log_test_bit(uint32_t *bs, unsigned bit) |
168 | { | 167 | { |
169 | return test_bit(bit, (unsigned long *) bs) ? 1 : 0; | 168 | return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0; |
170 | } | 169 | } |
171 | 170 | ||
172 | static inline void log_set_bit(struct log_c *l, | 171 | static inline void log_set_bit(struct log_c *l, |
173 | uint32_t *bs, unsigned bit) | 172 | uint32_t *bs, unsigned bit) |
174 | { | 173 | { |
175 | set_bit(bit, (unsigned long *) bs); | 174 | ext2_set_bit(bit, (unsigned long *) bs); |
176 | l->touched = 1; | 175 | l->touched = 1; |
177 | } | 176 | } |
178 | 177 | ||
179 | static inline void log_clear_bit(struct log_c *l, | 178 | static inline void log_clear_bit(struct log_c *l, |
180 | uint32_t *bs, unsigned bit) | 179 | uint32_t *bs, unsigned bit) |
181 | { | 180 | { |
182 | clear_bit(bit, (unsigned long *) bs); | 181 | ext2_clear_bit(bit, (unsigned long *) bs); |
183 | l->touched = 1; | 182 | l->touched = 1; |
184 | } | 183 | } |
185 | 184 | ||
@@ -219,6 +218,11 @@ static int read_header(struct log_c *log) | |||
219 | log->header.nr_regions = 0; | 218 | log->header.nr_regions = 0; |
220 | } | 219 | } |
221 | 220 | ||
221 | #ifdef __LITTLE_ENDIAN | ||
222 | if (log->header.version == 1) | ||
223 | log->header.version = 2; | ||
224 | #endif | ||
225 | |||
222 | if (log->header.version != MIRROR_DISK_VERSION) { | 226 | if (log->header.version != MIRROR_DISK_VERSION) { |
223 | DMWARN("incompatible disk log version"); | 227 | DMWARN("incompatible disk log version"); |
224 | return -EINVAL; | 228 | return -EINVAL; |
@@ -239,45 +243,24 @@ static inline int write_header(struct log_c *log) | |||
239 | /*---------------------------------------------------------------- | 243 | /*---------------------------------------------------------------- |
240 | * Bits IO | 244 | * Bits IO |
241 | *--------------------------------------------------------------*/ | 245 | *--------------------------------------------------------------*/ |
242 | static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count) | ||
243 | { | ||
244 | unsigned i; | ||
245 | |||
246 | for (i = 0; i < count; i++) | ||
247 | core[i] = le32_to_cpu(disk[i]); | ||
248 | } | ||
249 | |||
250 | static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count) | ||
251 | { | ||
252 | unsigned i; | ||
253 | |||
254 | /* copy across the clean/dirty bitset */ | ||
255 | for (i = 0; i < count; i++) | ||
256 | disk[i] = cpu_to_le32(core[i]); | ||
257 | } | ||
258 | |||
259 | static int read_bits(struct log_c *log) | 246 | static int read_bits(struct log_c *log) |
260 | { | 247 | { |
261 | int r; | 248 | int r; |
262 | unsigned long ebits; | 249 | unsigned long ebits; |
263 | 250 | ||
264 | r = dm_io_sync_vm(1, &log->bits_location, READ, | 251 | r = dm_io_sync_vm(1, &log->bits_location, READ, |
265 | log->disk_bits, &ebits); | 252 | log->clean_bits, &ebits); |
266 | if (r) | 253 | if (r) |
267 | return r; | 254 | return r; |
268 | 255 | ||
269 | bits_to_core(log->clean_bits, log->disk_bits, | ||
270 | log->bitset_uint32_count); | ||
271 | return 0; | 256 | return 0; |
272 | } | 257 | } |
273 | 258 | ||
274 | static int write_bits(struct log_c *log) | 259 | static int write_bits(struct log_c *log) |
275 | { | 260 | { |
276 | unsigned long ebits; | 261 | unsigned long ebits; |
277 | bits_to_disk(log->clean_bits, log->disk_bits, | ||
278 | log->bitset_uint32_count); | ||
279 | return dm_io_sync_vm(1, &log->bits_location, WRITE, | 262 | return dm_io_sync_vm(1, &log->bits_location, WRITE, |
280 | log->disk_bits, &ebits); | 263 | log->clean_bits, &ebits); |
281 | } | 264 | } |
282 | 265 | ||
283 | /*---------------------------------------------------------------- | 266 | /*---------------------------------------------------------------- |
@@ -433,11 +416,6 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti, | |||
433 | size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), | 416 | size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), |
434 | 1 << SECTOR_SHIFT); | 417 | 1 << SECTOR_SHIFT); |
435 | lc->bits_location.count = size >> SECTOR_SHIFT; | 418 | lc->bits_location.count = size >> SECTOR_SHIFT; |
436 | lc->disk_bits = vmalloc(size); | ||
437 | if (!lc->disk_bits) { | ||
438 | vfree(lc->disk_header); | ||
439 | goto bad; | ||
440 | } | ||
441 | return 0; | 419 | return 0; |
442 | 420 | ||
443 | bad: | 421 | bad: |
@@ -451,7 +429,6 @@ static void disk_dtr(struct dirty_log *log) | |||
451 | struct log_c *lc = (struct log_c *) log->context; | 429 | struct log_c *lc = (struct log_c *) log->context; |
452 | dm_put_device(lc->ti, lc->log_dev); | 430 | dm_put_device(lc->ti, lc->log_dev); |
453 | vfree(lc->disk_header); | 431 | vfree(lc->disk_header); |
454 | vfree(lc->disk_bits); | ||
455 | core_dtr(log); | 432 | core_dtr(log); |
456 | } | 433 | } |
457 | 434 | ||
@@ -568,7 +545,8 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) | |||
568 | return 0; | 545 | return 0; |
569 | 546 | ||
570 | do { | 547 | do { |
571 | *region = find_next_zero_bit((unsigned long *) lc->sync_bits, | 548 | *region = ext2_find_next_zero_bit( |
549 | (unsigned long *) lc->sync_bits, | ||
572 | lc->region_count, | 550 | lc->region_count, |
573 | lc->sync_search); | 551 | lc->sync_search); |
574 | lc->sync_search = *region + 1; | 552 | lc->sync_search = *region + 1; |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 87727d84dbba..f3759dd7828e 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -373,16 +373,11 @@ static inline ulong round_up(ulong n, ulong size) | |||
373 | 373 | ||
374 | static void read_snapshot_metadata(struct dm_snapshot *s) | 374 | static void read_snapshot_metadata(struct dm_snapshot *s) |
375 | { | 375 | { |
376 | if (s->have_metadata) | ||
377 | return; | ||
378 | |||
379 | if (s->store.read_metadata(&s->store)) { | 376 | if (s->store.read_metadata(&s->store)) { |
380 | down_write(&s->lock); | 377 | down_write(&s->lock); |
381 | s->valid = 0; | 378 | s->valid = 0; |
382 | up_write(&s->lock); | 379 | up_write(&s->lock); |
383 | } | 380 | } |
384 | |||
385 | s->have_metadata = 1; | ||
386 | } | 381 | } |
387 | 382 | ||
388 | /* | 383 | /* |
@@ -471,7 +466,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
471 | s->chunk_shift = ffs(chunk_size) - 1; | 466 | s->chunk_shift = ffs(chunk_size) - 1; |
472 | 467 | ||
473 | s->valid = 1; | 468 | s->valid = 1; |
474 | s->have_metadata = 0; | 469 | s->active = 0; |
475 | s->last_percent = 0; | 470 | s->last_percent = 0; |
476 | init_rwsem(&s->lock); | 471 | init_rwsem(&s->lock); |
477 | s->table = ti->table; | 472 | s->table = ti->table; |
@@ -506,7 +501,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
506 | goto bad5; | 501 | goto bad5; |
507 | } | 502 | } |
508 | 503 | ||
504 | /* Metadata must only be loaded into one table at once */ | ||
505 | read_snapshot_metadata(s); | ||
506 | |||
509 | /* Add snapshot to the list of snapshots for this origin */ | 507 | /* Add snapshot to the list of snapshots for this origin */ |
508 | /* Exceptions aren't triggered till snapshot_resume() is called */ | ||
510 | if (register_snapshot(s)) { | 509 | if (register_snapshot(s)) { |
511 | r = -EINVAL; | 510 | r = -EINVAL; |
512 | ti->error = "Cannot register snapshot origin"; | 511 | ti->error = "Cannot register snapshot origin"; |
@@ -793,6 +792,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
793 | if (!s->valid) | 792 | if (!s->valid) |
794 | return -EIO; | 793 | return -EIO; |
795 | 794 | ||
795 | if (unlikely(bio_barrier(bio))) | ||
796 | return -EOPNOTSUPP; | ||
797 | |||
796 | /* | 798 | /* |
797 | * Write to snapshot - higher level takes care of RW/RO | 799 | * Write to snapshot - higher level takes care of RW/RO |
798 | * flags so we should only get this if we are | 800 | * flags so we should only get this if we are |
@@ -862,7 +864,9 @@ static void snapshot_resume(struct dm_target *ti) | |||
862 | { | 864 | { |
863 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; | 865 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; |
864 | 866 | ||
865 | read_snapshot_metadata(s); | 867 | down_write(&s->lock); |
868 | s->active = 1; | ||
869 | up_write(&s->lock); | ||
866 | } | 870 | } |
867 | 871 | ||
868 | static int snapshot_status(struct dm_target *ti, status_type_t type, | 872 | static int snapshot_status(struct dm_target *ti, status_type_t type, |
@@ -932,8 +936,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
932 | /* Do all the snapshots on this origin */ | 936 | /* Do all the snapshots on this origin */ |
933 | list_for_each_entry (snap, snapshots, list) { | 937 | list_for_each_entry (snap, snapshots, list) { |
934 | 938 | ||
935 | /* Only deal with valid snapshots */ | 939 | /* Only deal with valid and active snapshots */ |
936 | if (!snap->valid) | 940 | if (!snap->valid || !snap->active) |
937 | continue; | 941 | continue; |
938 | 942 | ||
939 | /* Nothing to do if writing beyond end of snapshot */ | 943 | /* Nothing to do if writing beyond end of snapshot */ |
@@ -1057,6 +1061,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio, | |||
1057 | struct dm_dev *dev = (struct dm_dev *) ti->private; | 1061 | struct dm_dev *dev = (struct dm_dev *) ti->private; |
1058 | bio->bi_bdev = dev->bdev; | 1062 | bio->bi_bdev = dev->bdev; |
1059 | 1063 | ||
1064 | if (unlikely(bio_barrier(bio))) | ||
1065 | return -EOPNOTSUPP; | ||
1066 | |||
1060 | /* Only tell snapshots if this is a write */ | 1067 | /* Only tell snapshots if this is a write */ |
1061 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; | 1068 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; |
1062 | } | 1069 | } |
@@ -1104,7 +1111,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, | |||
1104 | 1111 | ||
1105 | static struct target_type origin_target = { | 1112 | static struct target_type origin_target = { |
1106 | .name = "snapshot-origin", | 1113 | .name = "snapshot-origin", |
1107 | .version = {1, 0, 1}, | 1114 | .version = {1, 1, 0}, |
1108 | .module = THIS_MODULE, | 1115 | .module = THIS_MODULE, |
1109 | .ctr = origin_ctr, | 1116 | .ctr = origin_ctr, |
1110 | .dtr = origin_dtr, | 1117 | .dtr = origin_dtr, |
@@ -1115,7 +1122,7 @@ static struct target_type origin_target = { | |||
1115 | 1122 | ||
1116 | static struct target_type snapshot_target = { | 1123 | static struct target_type snapshot_target = { |
1117 | .name = "snapshot", | 1124 | .name = "snapshot", |
1118 | .version = {1, 0, 1}, | 1125 | .version = {1, 1, 0}, |
1119 | .module = THIS_MODULE, | 1126 | .module = THIS_MODULE, |
1120 | .ctr = snapshot_ctr, | 1127 | .ctr = snapshot_ctr, |
1121 | .dtr = snapshot_dtr, | 1128 | .dtr = snapshot_dtr, |
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index 375aa24d4d7d..fdec1e2dc871 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h | |||
@@ -99,7 +99,9 @@ struct dm_snapshot { | |||
99 | 99 | ||
100 | /* You can't use a snapshot if this is 0 (e.g. if full) */ | 100 | /* You can't use a snapshot if this is 0 (e.g. if full) */ |
101 | int valid; | 101 | int valid; |
102 | int have_metadata; | 102 | |
103 | /* Origin writes don't trigger exceptions until this is set */ | ||
104 | int active; | ||
103 | 105 | ||
104 | /* Used for display of table */ | 106 | /* Used for display of table */ |
105 | char type; | 107 | char type; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index a6f2dc66c3db..9b1e2f5ca630 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -508,7 +508,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, | |||
508 | if (q->merge_bvec_fn) | 508 | if (q->merge_bvec_fn) |
509 | rs->max_sectors = | 509 | rs->max_sectors = |
510 | min_not_zero(rs->max_sectors, | 510 | min_not_zero(rs->max_sectors, |
511 | (unsigned short)(PAGE_SIZE >> 9)); | 511 | (unsigned int) (PAGE_SIZE >> 9)); |
512 | 512 | ||
513 | rs->max_phys_segments = | 513 | rs->max_phys_segments = |
514 | min_not_zero(rs->max_phys_segments, | 514 | min_not_zero(rs->max_phys_segments, |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8c16359f8b01..e9adeb9d172f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -31,6 +31,7 @@ struct dm_io { | |||
31 | int error; | 31 | int error; |
32 | struct bio *bio; | 32 | struct bio *bio; |
33 | atomic_t io_count; | 33 | atomic_t io_count; |
34 | unsigned long start_time; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | /* | 37 | /* |
@@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) | |||
244 | mempool_free(tio, md->tio_pool); | 245 | mempool_free(tio, md->tio_pool); |
245 | } | 246 | } |
246 | 247 | ||
248 | static void start_io_acct(struct dm_io *io) | ||
249 | { | ||
250 | struct mapped_device *md = io->md; | ||
251 | |||
252 | io->start_time = jiffies; | ||
253 | |||
254 | preempt_disable(); | ||
255 | disk_round_stats(dm_disk(md)); | ||
256 | preempt_enable(); | ||
257 | dm_disk(md)->in_flight = atomic_inc_return(&md->pending); | ||
258 | } | ||
259 | |||
260 | static int end_io_acct(struct dm_io *io) | ||
261 | { | ||
262 | struct mapped_device *md = io->md; | ||
263 | struct bio *bio = io->bio; | ||
264 | unsigned long duration = jiffies - io->start_time; | ||
265 | int pending; | ||
266 | int rw = bio_data_dir(bio); | ||
267 | |||
268 | preempt_disable(); | ||
269 | disk_round_stats(dm_disk(md)); | ||
270 | preempt_enable(); | ||
271 | dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); | ||
272 | |||
273 | disk_stat_add(dm_disk(md), ticks[rw], duration); | ||
274 | |||
275 | return !pending; | ||
276 | } | ||
277 | |||
247 | /* | 278 | /* |
248 | * Add the bio to the list of deferred io. | 279 | * Add the bio to the list of deferred io. |
249 | */ | 280 | */ |
@@ -299,7 +330,7 @@ static void dec_pending(struct dm_io *io, int error) | |||
299 | io->error = error; | 330 | io->error = error; |
300 | 331 | ||
301 | if (atomic_dec_and_test(&io->io_count)) { | 332 | if (atomic_dec_and_test(&io->io_count)) { |
302 | if (atomic_dec_and_test(&io->md->pending)) | 333 | if (end_io_acct(io)) |
303 | /* nudge anyone waiting on suspend queue */ | 334 | /* nudge anyone waiting on suspend queue */ |
304 | wake_up(&io->md->wait); | 335 | wake_up(&io->md->wait); |
305 | 336 | ||
@@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) | |||
554 | ci.sector_count = bio_sectors(bio); | 585 | ci.sector_count = bio_sectors(bio); |
555 | ci.idx = bio->bi_idx; | 586 | ci.idx = bio->bi_idx; |
556 | 587 | ||
557 | atomic_inc(&md->pending); | 588 | start_io_acct(ci.io); |
558 | while (ci.sector_count) | 589 | while (ci.sector_count) |
559 | __clone_and_map(&ci); | 590 | __clone_and_map(&ci); |
560 | 591 | ||
@@ -573,10 +604,14 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) | |||
573 | static int dm_request(request_queue_t *q, struct bio *bio) | 604 | static int dm_request(request_queue_t *q, struct bio *bio) |
574 | { | 605 | { |
575 | int r; | 606 | int r; |
607 | int rw = bio_data_dir(bio); | ||
576 | struct mapped_device *md = q->queuedata; | 608 | struct mapped_device *md = q->queuedata; |
577 | 609 | ||
578 | down_read(&md->io_lock); | 610 | down_read(&md->io_lock); |
579 | 611 | ||
612 | disk_stat_inc(dm_disk(md), ios[rw]); | ||
613 | disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); | ||
614 | |||
580 | /* | 615 | /* |
581 | * If we're suspended we have to queue | 616 | * If we're suspended we have to queue |
582 | * this io for later. | 617 | * this io for later. |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 7145cd150f7b..d05e3125d298 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1024,7 +1024,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1024 | rdev-> sb_size = (rdev->sb_size | bmask)+1; | 1024 | rdev-> sb_size = (rdev->sb_size | bmask)+1; |
1025 | 1025 | ||
1026 | if (refdev == 0) | 1026 | if (refdev == 0) |
1027 | return 1; | 1027 | ret = 1; |
1028 | else { | 1028 | else { |
1029 | __u64 ev1, ev2; | 1029 | __u64 ev1, ev2; |
1030 | struct mdp_superblock_1 *refsb = | 1030 | struct mdp_superblock_1 *refsb = |
@@ -1044,7 +1044,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1044 | ev2 = le64_to_cpu(refsb->events); | 1044 | ev2 = le64_to_cpu(refsb->events); |
1045 | 1045 | ||
1046 | if (ev1 > ev2) | 1046 | if (ev1 > ev2) |
1047 | return 1; | 1047 | ret = 1; |
1048 | else | ||
1049 | ret = 0; | ||
1048 | } | 1050 | } |
1049 | if (minor_version) | 1051 | if (minor_version) |
1050 | rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; | 1052 | rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; |
@@ -1058,7 +1060,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1058 | 1060 | ||
1059 | if (le32_to_cpu(sb->size) > rdev->size*2) | 1061 | if (le32_to_cpu(sb->size) > rdev->size*2) |
1060 | return -EINVAL; | 1062 | return -EINVAL; |
1061 | return 0; | 1063 | return ret; |
1062 | } | 1064 | } |
1063 | 1065 | ||
1064 | static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | 1066 | static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) |
@@ -1081,7 +1083,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1081 | mddev->size = le64_to_cpu(sb->size)/2; | 1083 | mddev->size = le64_to_cpu(sb->size)/2; |
1082 | mddev->events = le64_to_cpu(sb->events); | 1084 | mddev->events = le64_to_cpu(sb->events); |
1083 | mddev->bitmap_offset = 0; | 1085 | mddev->bitmap_offset = 0; |
1084 | mddev->default_bitmap_offset = 1024; | 1086 | mddev->default_bitmap_offset = 1024 >> 9; |
1085 | 1087 | ||
1086 | mddev->recovery_cp = le64_to_cpu(sb->resync_offset); | 1088 | mddev->recovery_cp = le64_to_cpu(sb->resync_offset); |
1087 | memcpy(mddev->uuid, sb->set_uuid, 16); | 1089 | memcpy(mddev->uuid, sb->set_uuid, 16); |
@@ -1161,6 +1163,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1161 | 1163 | ||
1162 | sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); | 1164 | sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); |
1163 | 1165 | ||
1166 | sb->raid_disks = cpu_to_le32(mddev->raid_disks); | ||
1167 | sb->size = cpu_to_le64(mddev->size<<1); | ||
1168 | |||
1164 | if (mddev->bitmap && mddev->bitmap_file == NULL) { | 1169 | if (mddev->bitmap && mddev->bitmap_file == NULL) { |
1165 | sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); | 1170 | sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); |
1166 | sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); | 1171 | sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); |
@@ -2686,14 +2691,6 @@ static int do_md_stop(mddev_t * mddev, int ro) | |||
2686 | set_disk_ro(disk, 1); | 2691 | set_disk_ro(disk, 1); |
2687 | } | 2692 | } |
2688 | 2693 | ||
2689 | bitmap_destroy(mddev); | ||
2690 | if (mddev->bitmap_file) { | ||
2691 | atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); | ||
2692 | fput(mddev->bitmap_file); | ||
2693 | mddev->bitmap_file = NULL; | ||
2694 | } | ||
2695 | mddev->bitmap_offset = 0; | ||
2696 | |||
2697 | /* | 2694 | /* |
2698 | * Free resources if final stop | 2695 | * Free resources if final stop |
2699 | */ | 2696 | */ |
@@ -2703,6 +2700,14 @@ static int do_md_stop(mddev_t * mddev, int ro) | |||
2703 | struct gendisk *disk; | 2700 | struct gendisk *disk; |
2704 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); | 2701 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); |
2705 | 2702 | ||
2703 | bitmap_destroy(mddev); | ||
2704 | if (mddev->bitmap_file) { | ||
2705 | atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); | ||
2706 | fput(mddev->bitmap_file); | ||
2707 | mddev->bitmap_file = NULL; | ||
2708 | } | ||
2709 | mddev->bitmap_offset = 0; | ||
2710 | |||
2706 | ITERATE_RDEV(mddev,rdev,tmp) | 2711 | ITERATE_RDEV(mddev,rdev,tmp) |
2707 | if (rdev->raid_disk >= 0) { | 2712 | if (rdev->raid_disk >= 0) { |
2708 | char nm[20]; | 2713 | char nm[20]; |
@@ -2939,6 +2944,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg) | |||
2939 | info.ctime = mddev->ctime; | 2944 | info.ctime = mddev->ctime; |
2940 | info.level = mddev->level; | 2945 | info.level = mddev->level; |
2941 | info.size = mddev->size; | 2946 | info.size = mddev->size; |
2947 | if (info.size != mddev->size) /* overflow */ | ||
2948 | info.size = -1; | ||
2942 | info.nr_disks = nr; | 2949 | info.nr_disks = nr; |
2943 | info.raid_disks = mddev->raid_disks; | 2950 | info.raid_disks = mddev->raid_disks; |
2944 | info.md_minor = mddev->md_minor; | 2951 | info.md_minor = mddev->md_minor; |
@@ -3465,7 +3472,7 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
3465 | bdev = bdget_disk(mddev->gendisk, 0); | 3472 | bdev = bdget_disk(mddev->gendisk, 0); |
3466 | if (bdev) { | 3473 | if (bdev) { |
3467 | mutex_lock(&bdev->bd_inode->i_mutex); | 3474 | mutex_lock(&bdev->bd_inode->i_mutex); |
3468 | i_size_write(bdev->bd_inode, mddev->array_size << 10); | 3475 | i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10); |
3469 | mutex_unlock(&bdev->bd_inode->i_mutex); | 3476 | mutex_unlock(&bdev->bd_inode->i_mutex); |
3470 | bdput(bdev); | 3477 | bdput(bdev); |
3471 | } | 3478 | } |
@@ -3485,17 +3492,6 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) | |||
3485 | if (mddev->sync_thread) | 3492 | if (mddev->sync_thread) |
3486 | return -EBUSY; | 3493 | return -EBUSY; |
3487 | rv = mddev->pers->reshape(mddev, raid_disks); | 3494 | rv = mddev->pers->reshape(mddev, raid_disks); |
3488 | if (!rv) { | ||
3489 | struct block_device *bdev; | ||
3490 | |||
3491 | bdev = bdget_disk(mddev->gendisk, 0); | ||
3492 | if (bdev) { | ||
3493 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
3494 | i_size_write(bdev->bd_inode, mddev->array_size << 10); | ||
3495 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
3496 | bdput(bdev); | ||
3497 | } | ||
3498 | } | ||
3499 | return rv; | 3495 | return rv; |
3500 | } | 3496 | } |
3501 | 3497 | ||
@@ -3531,7 +3527,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) | |||
3531 | ) | 3527 | ) |
3532 | return -EINVAL; | 3528 | return -EINVAL; |
3533 | /* Check there is only one change */ | 3529 | /* Check there is only one change */ |
3534 | if (mddev->size != info->size) cnt++; | 3530 | if (info->size >= 0 && mddev->size != info->size) cnt++; |
3535 | if (mddev->raid_disks != info->raid_disks) cnt++; | 3531 | if (mddev->raid_disks != info->raid_disks) cnt++; |
3536 | if (mddev->layout != info->layout) cnt++; | 3532 | if (mddev->layout != info->layout) cnt++; |
3537 | if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++; | 3533 | if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++; |
@@ -3548,7 +3544,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) | |||
3548 | else | 3544 | else |
3549 | return mddev->pers->reconfig(mddev, info->layout, -1); | 3545 | return mddev->pers->reconfig(mddev, info->layout, -1); |
3550 | } | 3546 | } |
3551 | if (mddev->size != info->size) | 3547 | if (info->size >= 0 && mddev->size != info->size) |
3552 | rv = update_size(mddev, info->size); | 3548 | rv = update_size(mddev, info->size); |
3553 | 3549 | ||
3554 | if (mddev->raid_disks != info->raid_disks) | 3550 | if (mddev->raid_disks != info->raid_disks) |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index d03f99cf4b7d..678f4dbbea1d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -372,7 +372,7 @@ out_free_conf: | |||
372 | kfree(conf); | 372 | kfree(conf); |
373 | mddev->private = NULL; | 373 | mddev->private = NULL; |
374 | out: | 374 | out: |
375 | return 1; | 375 | return -ENOMEM; |
376 | } | 376 | } |
377 | 377 | ||
378 | static int raid0_stop (mddev_t *mddev) | 378 | static int raid0_stop (mddev_t *mddev) |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9130d051b474..ab90a6d12020 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -565,6 +565,8 @@ rb_out: | |||
565 | 565 | ||
566 | if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL) | 566 | if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL) |
567 | atomic_inc(&conf->mirrors[disk].rdev->nr_pending); | 567 | atomic_inc(&conf->mirrors[disk].rdev->nr_pending); |
568 | else | ||
569 | disk = -1; | ||
568 | rcu_read_unlock(); | 570 | rcu_read_unlock(); |
569 | 571 | ||
570 | return disk; | 572 | return disk; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 25976bfb6f9c..2dba305daf3c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -350,7 +350,8 @@ static void shrink_stripes(raid5_conf_t *conf) | |||
350 | while (drop_one_stripe(conf)) | 350 | while (drop_one_stripe(conf)) |
351 | ; | 351 | ; |
352 | 352 | ||
353 | kmem_cache_destroy(conf->slab_cache); | 353 | if (conf->slab_cache) |
354 | kmem_cache_destroy(conf->slab_cache); | ||
354 | conf->slab_cache = NULL; | 355 | conf->slab_cache = NULL; |
355 | } | 356 | } |
356 | 357 | ||
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index f618a53b98be..cd477ebf2ee4 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
@@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) | |||
115 | list_add_tail(&sh->lru, &conf->inactive_list); | 115 | list_add_tail(&sh->lru, &conf->inactive_list); |
116 | atomic_dec(&conf->active_stripes); | 116 | atomic_dec(&conf->active_stripes); |
117 | if (!conf->inactive_blocked || | 117 | if (!conf->inactive_blocked || |
118 | atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4)) | 118 | atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4)) |
119 | wake_up(&conf->wait_for_stripe); | 119 | wake_up(&conf->wait_for_stripe); |
120 | } | 120 | } |
121 | } | 121 | } |
@@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector | |||
273 | conf->inactive_blocked = 1; | 273 | conf->inactive_blocked = 1; |
274 | wait_event_lock_irq(conf->wait_for_stripe, | 274 | wait_event_lock_irq(conf->wait_for_stripe, |
275 | !list_empty(&conf->inactive_list) && | 275 | !list_empty(&conf->inactive_list) && |
276 | (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4) | 276 | (atomic_read(&conf->active_stripes) |
277 | < (conf->max_nr_stripes *3/4) | ||
277 | || !conf->inactive_blocked), | 278 | || !conf->inactive_blocked), |
278 | conf->device_lock, | 279 | conf->device_lock, |
279 | unplug_slaves(conf->mddev); | 280 | unplug_slaves(conf->mddev); |
@@ -302,9 +303,31 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector | |||
302 | return sh; | 303 | return sh; |
303 | } | 304 | } |
304 | 305 | ||
305 | static int grow_stripes(raid6_conf_t *conf, int num) | 306 | static int grow_one_stripe(raid6_conf_t *conf) |
306 | { | 307 | { |
307 | struct stripe_head *sh; | 308 | struct stripe_head *sh; |
309 | sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); | ||
310 | if (!sh) | ||
311 | return 0; | ||
312 | memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); | ||
313 | sh->raid_conf = conf; | ||
314 | spin_lock_init(&sh->lock); | ||
315 | |||
316 | if (grow_buffers(sh, conf->raid_disks)) { | ||
317 | shrink_buffers(sh, conf->raid_disks); | ||
318 | kmem_cache_free(conf->slab_cache, sh); | ||
319 | return 0; | ||
320 | } | ||
321 | /* we just created an active stripe so... */ | ||
322 | atomic_set(&sh->count, 1); | ||
323 | atomic_inc(&conf->active_stripes); | ||
324 | INIT_LIST_HEAD(&sh->lru); | ||
325 | release_stripe(sh); | ||
326 | return 1; | ||
327 | } | ||
328 | |||
329 | static int grow_stripes(raid6_conf_t *conf, int num) | ||
330 | { | ||
308 | kmem_cache_t *sc; | 331 | kmem_cache_t *sc; |
309 | int devs = conf->raid_disks; | 332 | int devs = conf->raid_disks; |
310 | 333 | ||
@@ -316,45 +339,35 @@ static int grow_stripes(raid6_conf_t *conf, int num) | |||
316 | if (!sc) | 339 | if (!sc) |
317 | return 1; | 340 | return 1; |
318 | conf->slab_cache = sc; | 341 | conf->slab_cache = sc; |
319 | while (num--) { | 342 | while (num--) |
320 | sh = kmem_cache_alloc(sc, GFP_KERNEL); | 343 | if (!grow_one_stripe(conf)) |
321 | if (!sh) | ||
322 | return 1; | ||
323 | memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); | ||
324 | sh->raid_conf = conf; | ||
325 | spin_lock_init(&sh->lock); | ||
326 | |||
327 | if (grow_buffers(sh, conf->raid_disks)) { | ||
328 | shrink_buffers(sh, conf->raid_disks); | ||
329 | kmem_cache_free(sc, sh); | ||
330 | return 1; | 344 | return 1; |
331 | } | ||
332 | /* we just created an active stripe so... */ | ||
333 | atomic_set(&sh->count, 1); | ||
334 | atomic_inc(&conf->active_stripes); | ||
335 | INIT_LIST_HEAD(&sh->lru); | ||
336 | release_stripe(sh); | ||
337 | } | ||
338 | return 0; | 345 | return 0; |
339 | } | 346 | } |
340 | 347 | ||
341 | static void shrink_stripes(raid6_conf_t *conf) | 348 | static int drop_one_stripe(raid6_conf_t *conf) |
342 | { | 349 | { |
343 | struct stripe_head *sh; | 350 | struct stripe_head *sh; |
351 | spin_lock_irq(&conf->device_lock); | ||
352 | sh = get_free_stripe(conf); | ||
353 | spin_unlock_irq(&conf->device_lock); | ||
354 | if (!sh) | ||
355 | return 0; | ||
356 | if (atomic_read(&sh->count)) | ||
357 | BUG(); | ||
358 | shrink_buffers(sh, conf->raid_disks); | ||
359 | kmem_cache_free(conf->slab_cache, sh); | ||
360 | atomic_dec(&conf->active_stripes); | ||
361 | return 1; | ||
362 | } | ||
344 | 363 | ||
345 | while (1) { | 364 | static void shrink_stripes(raid6_conf_t *conf) |
346 | spin_lock_irq(&conf->device_lock); | 365 | { |
347 | sh = get_free_stripe(conf); | 366 | while (drop_one_stripe(conf)) |
348 | spin_unlock_irq(&conf->device_lock); | 367 | ; |
349 | if (!sh) | 368 | |
350 | break; | 369 | if (conf->slab_cache) |
351 | if (atomic_read(&sh->count)) | 370 | kmem_cache_destroy(conf->slab_cache); |
352 | BUG(); | ||
353 | shrink_buffers(sh, conf->raid_disks); | ||
354 | kmem_cache_free(conf->slab_cache, sh); | ||
355 | atomic_dec(&conf->active_stripes); | ||
356 | } | ||
357 | kmem_cache_destroy(conf->slab_cache); | ||
358 | conf->slab_cache = NULL; | 371 | conf->slab_cache = NULL; |
359 | } | 372 | } |
360 | 373 | ||
@@ -1912,6 +1925,74 @@ static void raid6d (mddev_t *mddev) | |||
1912 | PRINTK("--- raid6d inactive\n"); | 1925 | PRINTK("--- raid6d inactive\n"); |
1913 | } | 1926 | } |
1914 | 1927 | ||
1928 | static ssize_t | ||
1929 | raid6_show_stripe_cache_size(mddev_t *mddev, char *page) | ||
1930 | { | ||
1931 | raid6_conf_t *conf = mddev_to_conf(mddev); | ||
1932 | if (conf) | ||
1933 | return sprintf(page, "%d\n", conf->max_nr_stripes); | ||
1934 | else | ||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1938 | static ssize_t | ||
1939 | raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) | ||
1940 | { | ||
1941 | raid6_conf_t *conf = mddev_to_conf(mddev); | ||
1942 | char *end; | ||
1943 | int new; | ||
1944 | if (len >= PAGE_SIZE) | ||
1945 | return -EINVAL; | ||
1946 | if (!conf) | ||
1947 | return -ENODEV; | ||
1948 | |||
1949 | new = simple_strtoul(page, &end, 10); | ||
1950 | if (!*page || (*end && *end != '\n') ) | ||
1951 | return -EINVAL; | ||
1952 | if (new <= 16 || new > 32768) | ||
1953 | return -EINVAL; | ||
1954 | while (new < conf->max_nr_stripes) { | ||
1955 | if (drop_one_stripe(conf)) | ||
1956 | conf->max_nr_stripes--; | ||
1957 | else | ||
1958 | break; | ||
1959 | } | ||
1960 | while (new > conf->max_nr_stripes) { | ||
1961 | if (grow_one_stripe(conf)) | ||
1962 | conf->max_nr_stripes++; | ||
1963 | else break; | ||
1964 | } | ||
1965 | return len; | ||
1966 | } | ||
1967 | |||
1968 | static struct md_sysfs_entry | ||
1969 | raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR, | ||
1970 | raid6_show_stripe_cache_size, | ||
1971 | raid6_store_stripe_cache_size); | ||
1972 | |||
1973 | static ssize_t | ||
1974 | stripe_cache_active_show(mddev_t *mddev, char *page) | ||
1975 | { | ||
1976 | raid6_conf_t *conf = mddev_to_conf(mddev); | ||
1977 | if (conf) | ||
1978 | return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); | ||
1979 | else | ||
1980 | return 0; | ||
1981 | } | ||
1982 | |||
1983 | static struct md_sysfs_entry | ||
1984 | raid6_stripecache_active = __ATTR_RO(stripe_cache_active); | ||
1985 | |||
1986 | static struct attribute *raid6_attrs[] = { | ||
1987 | &raid6_stripecache_size.attr, | ||
1988 | &raid6_stripecache_active.attr, | ||
1989 | NULL, | ||
1990 | }; | ||
1991 | static struct attribute_group raid6_attrs_group = { | ||
1992 | .name = NULL, | ||
1993 | .attrs = raid6_attrs, | ||
1994 | }; | ||
1995 | |||
1915 | static int run(mddev_t *mddev) | 1996 | static int run(mddev_t *mddev) |
1916 | { | 1997 | { |
1917 | raid6_conf_t *conf; | 1998 | raid6_conf_t *conf; |
@@ -2095,6 +2176,7 @@ static int stop (mddev_t *mddev) | |||
2095 | shrink_stripes(conf); | 2176 | shrink_stripes(conf); |
2096 | kfree(conf->stripe_hashtbl); | 2177 | kfree(conf->stripe_hashtbl); |
2097 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 2178 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
2179 | sysfs_remove_group(&mddev->kobj, &raid6_attrs_group); | ||
2098 | kfree(conf); | 2180 | kfree(conf); |
2099 | mddev->private = NULL; | 2181 | mddev->private = NULL; |
2100 | return 0; | 2182 | return 0; |