diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
commit | 1f16f116b01c110db20ab808562c8b8bc3ee3d6e (patch) | |
tree | 44db563f64cf5f8d62af8f99a61e2b248c44ea3a /drivers/md | |
parent | 03724ac3d48f8f0e3caf1d30fa134f8fd96c94e2 (diff) | |
parent | f9eccf24615672896dc13251410c3f2f33a14f95 (diff) |
Merge branches 'clockevents/4.4-fixes' and 'clockevents/4.5-fixes' of http://git.linaro.org/people/daniel.lezcano/linux into timers/urgent
Pull in fixes from Daniel Lezcano:
- Fix the vt8500 timer leading to a system lock up when dealing with too
small delta (Roman Volkov)
- Select the CLKSRC_MMIO when the fsl_ftm_timer is enabled with COMPILE_TEST
(Daniel Lezcano)
- Prevent to compile timers using the 'iomem' API when the architecture has
not HAS_IOMEM set (Richard Weinberger)
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-crypt.c | 22 | ||||
-rw-r--r-- | drivers/md/dm-mpath.c | 30 | ||||
-rw-r--r-- | drivers/md/dm-thin-metadata.c | 34 | ||||
-rw-r--r-- | drivers/md/dm-thin.c | 6 | ||||
-rw-r--r-- | drivers/md/dm.c | 7 | ||||
-rw-r--r-- | drivers/md/md.c | 33 | ||||
-rw-r--r-- | drivers/md/md.h | 8 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-btree.c | 101 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-btree.h | 14 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-space-map-metadata.c | 32 | ||||
-rw-r--r-- | drivers/md/raid10.c | 4 |
11 files changed, 228 insertions, 63 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 917d47e290ae..3147c8d09ea8 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -112,7 +112,8 @@ struct iv_tcw_private { | |||
112 | * and encrypts / decrypts at the same time. | 112 | * and encrypts / decrypts at the same time. |
113 | */ | 113 | */ |
114 | enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID, | 114 | enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID, |
115 | DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD }; | 115 | DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD, |
116 | DM_CRYPT_EXIT_THREAD}; | ||
116 | 117 | ||
117 | /* | 118 | /* |
118 | * The fields in here must be read only after initialization. | 119 | * The fields in here must be read only after initialization. |
@@ -1203,20 +1204,18 @@ continue_locked: | |||
1203 | if (!RB_EMPTY_ROOT(&cc->write_tree)) | 1204 | if (!RB_EMPTY_ROOT(&cc->write_tree)) |
1204 | goto pop_from_list; | 1205 | goto pop_from_list; |
1205 | 1206 | ||
1207 | if (unlikely(test_bit(DM_CRYPT_EXIT_THREAD, &cc->flags))) { | ||
1208 | spin_unlock_irq(&cc->write_thread_wait.lock); | ||
1209 | break; | ||
1210 | } | ||
1211 | |||
1206 | __set_current_state(TASK_INTERRUPTIBLE); | 1212 | __set_current_state(TASK_INTERRUPTIBLE); |
1207 | __add_wait_queue(&cc->write_thread_wait, &wait); | 1213 | __add_wait_queue(&cc->write_thread_wait, &wait); |
1208 | 1214 | ||
1209 | spin_unlock_irq(&cc->write_thread_wait.lock); | 1215 | spin_unlock_irq(&cc->write_thread_wait.lock); |
1210 | 1216 | ||
1211 | if (unlikely(kthread_should_stop())) { | ||
1212 | set_task_state(current, TASK_RUNNING); | ||
1213 | remove_wait_queue(&cc->write_thread_wait, &wait); | ||
1214 | break; | ||
1215 | } | ||
1216 | |||
1217 | schedule(); | 1217 | schedule(); |
1218 | 1218 | ||
1219 | set_task_state(current, TASK_RUNNING); | ||
1220 | spin_lock_irq(&cc->write_thread_wait.lock); | 1219 | spin_lock_irq(&cc->write_thread_wait.lock); |
1221 | __remove_wait_queue(&cc->write_thread_wait, &wait); | 1220 | __remove_wait_queue(&cc->write_thread_wait, &wait); |
1222 | goto continue_locked; | 1221 | goto continue_locked; |
@@ -1531,8 +1530,13 @@ static void crypt_dtr(struct dm_target *ti) | |||
1531 | if (!cc) | 1530 | if (!cc) |
1532 | return; | 1531 | return; |
1533 | 1532 | ||
1534 | if (cc->write_thread) | 1533 | if (cc->write_thread) { |
1534 | spin_lock_irq(&cc->write_thread_wait.lock); | ||
1535 | set_bit(DM_CRYPT_EXIT_THREAD, &cc->flags); | ||
1536 | wake_up_locked(&cc->write_thread_wait); | ||
1537 | spin_unlock_irq(&cc->write_thread_wait.lock); | ||
1535 | kthread_stop(cc->write_thread); | 1538 | kthread_stop(cc->write_thread); |
1539 | } | ||
1536 | 1540 | ||
1537 | if (cc->io_queue) | 1541 | if (cc->io_queue) |
1538 | destroy_workqueue(cc->io_queue); | 1542 | destroy_workqueue(cc->io_queue); |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index aaa6caa46a9f..cfa29f574c2a 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -1537,32 +1537,34 @@ static int multipath_prepare_ioctl(struct dm_target *ti, | |||
1537 | struct block_device **bdev, fmode_t *mode) | 1537 | struct block_device **bdev, fmode_t *mode) |
1538 | { | 1538 | { |
1539 | struct multipath *m = ti->private; | 1539 | struct multipath *m = ti->private; |
1540 | struct pgpath *pgpath; | ||
1541 | unsigned long flags; | 1540 | unsigned long flags; |
1542 | int r; | 1541 | int r; |
1543 | 1542 | ||
1544 | r = 0; | ||
1545 | |||
1546 | spin_lock_irqsave(&m->lock, flags); | 1543 | spin_lock_irqsave(&m->lock, flags); |
1547 | 1544 | ||
1548 | if (!m->current_pgpath) | 1545 | if (!m->current_pgpath) |
1549 | __choose_pgpath(m, 0); | 1546 | __choose_pgpath(m, 0); |
1550 | 1547 | ||
1551 | pgpath = m->current_pgpath; | 1548 | if (m->current_pgpath) { |
1552 | 1549 | if (!m->queue_io) { | |
1553 | if (pgpath) { | 1550 | *bdev = m->current_pgpath->path.dev->bdev; |
1554 | *bdev = pgpath->path.dev->bdev; | 1551 | *mode = m->current_pgpath->path.dev->mode; |
1555 | *mode = pgpath->path.dev->mode; | 1552 | r = 0; |
1553 | } else { | ||
1554 | /* pg_init has not started or completed */ | ||
1555 | r = -ENOTCONN; | ||
1556 | } | ||
1557 | } else { | ||
1558 | /* No path is available */ | ||
1559 | if (m->queue_if_no_path) | ||
1560 | r = -ENOTCONN; | ||
1561 | else | ||
1562 | r = -EIO; | ||
1556 | } | 1563 | } |
1557 | 1564 | ||
1558 | if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) | ||
1559 | r = -ENOTCONN; | ||
1560 | else if (!*bdev) | ||
1561 | r = -EIO; | ||
1562 | |||
1563 | spin_unlock_irqrestore(&m->lock, flags); | 1565 | spin_unlock_irqrestore(&m->lock, flags); |
1564 | 1566 | ||
1565 | if (r == -ENOTCONN && !fatal_signal_pending(current)) { | 1567 | if (r == -ENOTCONN) { |
1566 | spin_lock_irqsave(&m->lock, flags); | 1568 | spin_lock_irqsave(&m->lock, flags); |
1567 | if (!m->current_pg) { | 1569 | if (!m->current_pg) { |
1568 | /* Path status changed, redo selection */ | 1570 | /* Path status changed, redo selection */ |
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 1fa45695b68a..c219a053c7f6 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
@@ -1207,6 +1207,12 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) | |||
1207 | dm_block_t held_root; | 1207 | dm_block_t held_root; |
1208 | 1208 | ||
1209 | /* | 1209 | /* |
1210 | * We commit to ensure the btree roots which we increment in a | ||
1211 | * moment are up to date. | ||
1212 | */ | ||
1213 | __commit_transaction(pmd); | ||
1214 | |||
1215 | /* | ||
1210 | * Copy the superblock. | 1216 | * Copy the superblock. |
1211 | */ | 1217 | */ |
1212 | dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); | 1218 | dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); |
@@ -1538,7 +1544,7 @@ static int __remove(struct dm_thin_device *td, dm_block_t block) | |||
1538 | static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end) | 1544 | static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end) |
1539 | { | 1545 | { |
1540 | int r; | 1546 | int r; |
1541 | unsigned count; | 1547 | unsigned count, total_count = 0; |
1542 | struct dm_pool_metadata *pmd = td->pmd; | 1548 | struct dm_pool_metadata *pmd = td->pmd; |
1543 | dm_block_t keys[1] = { td->id }; | 1549 | dm_block_t keys[1] = { td->id }; |
1544 | __le64 value; | 1550 | __le64 value; |
@@ -1561,11 +1567,29 @@ static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_ | |||
1561 | if (r) | 1567 | if (r) |
1562 | return r; | 1568 | return r; |
1563 | 1569 | ||
1564 | r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count); | 1570 | /* |
1565 | if (r) | 1571 | * Remove leaves stops at the first unmapped entry, so we have to |
1566 | return r; | 1572 | * loop round finding mapped ranges. |
1573 | */ | ||
1574 | while (begin < end) { | ||
1575 | r = dm_btree_lookup_next(&pmd->bl_info, mapping_root, &begin, &begin, &value); | ||
1576 | if (r == -ENODATA) | ||
1577 | break; | ||
1578 | |||
1579 | if (r) | ||
1580 | return r; | ||
1581 | |||
1582 | if (begin >= end) | ||
1583 | break; | ||
1584 | |||
1585 | r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count); | ||
1586 | if (r) | ||
1587 | return r; | ||
1588 | |||
1589 | total_count += count; | ||
1590 | } | ||
1567 | 1591 | ||
1568 | td->mapped_blocks -= count; | 1592 | td->mapped_blocks -= total_count; |
1569 | td->changed = 1; | 1593 | td->changed = 1; |
1570 | 1594 | ||
1571 | /* | 1595 | /* |
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 3897b90bd462..63903a5a5d9e 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -2432,6 +2432,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
2432 | case PM_WRITE: | 2432 | case PM_WRITE: |
2433 | if (old_mode != new_mode) | 2433 | if (old_mode != new_mode) |
2434 | notify_of_pool_mode_change(pool, "write"); | 2434 | notify_of_pool_mode_change(pool, "write"); |
2435 | pool->pf.error_if_no_space = pt->requested_pf.error_if_no_space; | ||
2435 | dm_pool_metadata_read_write(pool->pmd); | 2436 | dm_pool_metadata_read_write(pool->pmd); |
2436 | pool->process_bio = process_bio; | 2437 | pool->process_bio = process_bio; |
2437 | pool->process_discard = process_discard_bio; | 2438 | pool->process_discard = process_discard_bio; |
@@ -4249,10 +4250,9 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
4249 | { | 4250 | { |
4250 | struct thin_c *tc = ti->private; | 4251 | struct thin_c *tc = ti->private; |
4251 | struct pool *pool = tc->pool; | 4252 | struct pool *pool = tc->pool; |
4252 | struct queue_limits *pool_limits = dm_get_queue_limits(pool->pool_md); | ||
4253 | 4253 | ||
4254 | if (!pool_limits->discard_granularity) | 4254 | if (!pool->pf.discard_enabled) |
4255 | return; /* pool's discard support is disabled */ | 4255 | return; |
4256 | 4256 | ||
4257 | limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; | 4257 | limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; |
4258 | limits->max_discard_sectors = 2048 * 1024 * 16; /* 16G */ | 4258 | limits->max_discard_sectors = 2048 * 1024 * 16; /* 16G */ |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6e15f3565892..5df40480228b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -591,7 +591,7 @@ retry: | |||
591 | 591 | ||
592 | out: | 592 | out: |
593 | dm_put_live_table(md, *srcu_idx); | 593 | dm_put_live_table(md, *srcu_idx); |
594 | if (r == -ENOTCONN) { | 594 | if (r == -ENOTCONN && !fatal_signal_pending(current)) { |
595 | msleep(10); | 595 | msleep(10); |
596 | goto retry; | 596 | goto retry; |
597 | } | 597 | } |
@@ -603,9 +603,10 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, | |||
603 | { | 603 | { |
604 | struct mapped_device *md = bdev->bd_disk->private_data; | 604 | struct mapped_device *md = bdev->bd_disk->private_data; |
605 | struct dm_target *tgt; | 605 | struct dm_target *tgt; |
606 | struct block_device *tgt_bdev = NULL; | ||
606 | int srcu_idx, r; | 607 | int srcu_idx, r; |
607 | 608 | ||
608 | r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx); | 609 | r = dm_get_live_table_for_ioctl(md, &tgt, &tgt_bdev, &mode, &srcu_idx); |
609 | if (r < 0) | 610 | if (r < 0) |
610 | return r; | 611 | return r; |
611 | 612 | ||
@@ -620,7 +621,7 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, | |||
620 | goto out; | 621 | goto out; |
621 | } | 622 | } |
622 | 623 | ||
623 | r = __blkdev_driver_ioctl(bdev, mode, cmd, arg); | 624 | r = __blkdev_driver_ioctl(tgt_bdev, mode, cmd, arg); |
624 | out: | 625 | out: |
625 | dm_put_live_table(md, srcu_idx); | 626 | dm_put_live_table(md, srcu_idx); |
626 | return r; | 627 | return r; |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 807095f4c793..61aacab424cf 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -314,8 +314,8 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio) | |||
314 | */ | 314 | */ |
315 | void mddev_suspend(struct mddev *mddev) | 315 | void mddev_suspend(struct mddev *mddev) |
316 | { | 316 | { |
317 | BUG_ON(mddev->suspended); | 317 | if (mddev->suspended++) |
318 | mddev->suspended = 1; | 318 | return; |
319 | synchronize_rcu(); | 319 | synchronize_rcu(); |
320 | wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0); | 320 | wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0); |
321 | mddev->pers->quiesce(mddev, 1); | 321 | mddev->pers->quiesce(mddev, 1); |
@@ -326,7 +326,8 @@ EXPORT_SYMBOL_GPL(mddev_suspend); | |||
326 | 326 | ||
327 | void mddev_resume(struct mddev *mddev) | 327 | void mddev_resume(struct mddev *mddev) |
328 | { | 328 | { |
329 | mddev->suspended = 0; | 329 | if (--mddev->suspended) |
330 | return; | ||
330 | wake_up(&mddev->sb_wait); | 331 | wake_up(&mddev->sb_wait); |
331 | mddev->pers->quiesce(mddev, 0); | 332 | mddev->pers->quiesce(mddev, 0); |
332 | 333 | ||
@@ -1652,7 +1653,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1652 | rdev->journal_tail = le64_to_cpu(sb->journal_tail); | 1653 | rdev->journal_tail = le64_to_cpu(sb->journal_tail); |
1653 | if (mddev->recovery_cp == MaxSector) | 1654 | if (mddev->recovery_cp == MaxSector) |
1654 | set_bit(MD_JOURNAL_CLEAN, &mddev->flags); | 1655 | set_bit(MD_JOURNAL_CLEAN, &mddev->flags); |
1655 | rdev->raid_disk = mddev->raid_disks; | 1656 | rdev->raid_disk = 0; |
1656 | break; | 1657 | break; |
1657 | default: | 1658 | default: |
1658 | rdev->saved_raid_disk = role; | 1659 | rdev->saved_raid_disk = role; |
@@ -2773,6 +2774,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2773 | /* Activating a spare .. or possibly reactivating | 2774 | /* Activating a spare .. or possibly reactivating |
2774 | * if we ever get bitmaps working here. | 2775 | * if we ever get bitmaps working here. |
2775 | */ | 2776 | */ |
2777 | int err; | ||
2776 | 2778 | ||
2777 | if (rdev->raid_disk != -1) | 2779 | if (rdev->raid_disk != -1) |
2778 | return -EBUSY; | 2780 | return -EBUSY; |
@@ -2794,9 +2796,15 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2794 | rdev->saved_raid_disk = -1; | 2796 | rdev->saved_raid_disk = -1; |
2795 | clear_bit(In_sync, &rdev->flags); | 2797 | clear_bit(In_sync, &rdev->flags); |
2796 | clear_bit(Bitmap_sync, &rdev->flags); | 2798 | clear_bit(Bitmap_sync, &rdev->flags); |
2797 | remove_and_add_spares(rdev->mddev, rdev); | 2799 | err = rdev->mddev->pers-> |
2798 | if (rdev->raid_disk == -1) | 2800 | hot_add_disk(rdev->mddev, rdev); |
2799 | return -EBUSY; | 2801 | if (err) { |
2802 | rdev->raid_disk = -1; | ||
2803 | return err; | ||
2804 | } else | ||
2805 | sysfs_notify_dirent_safe(rdev->sysfs_state); | ||
2806 | if (sysfs_link_rdev(rdev->mddev, rdev)) | ||
2807 | /* failure here is OK */; | ||
2800 | /* don't wakeup anyone, leave that to userspace. */ | 2808 | /* don't wakeup anyone, leave that to userspace. */ |
2801 | } else { | 2809 | } else { |
2802 | if (slot >= rdev->mddev->raid_disks && | 2810 | if (slot >= rdev->mddev->raid_disks && |
@@ -4318,8 +4326,7 @@ action_store(struct mddev *mddev, const char *page, size_t len) | |||
4318 | } | 4326 | } |
4319 | mddev_unlock(mddev); | 4327 | mddev_unlock(mddev); |
4320 | } | 4328 | } |
4321 | } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || | 4329 | } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) |
4322 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) | ||
4323 | return -EBUSY; | 4330 | return -EBUSY; |
4324 | else if (cmd_match(page, "resync")) | 4331 | else if (cmd_match(page, "resync")) |
4325 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 4332 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
@@ -4332,8 +4339,12 @@ action_store(struct mddev *mddev, const char *page, size_t len) | |||
4332 | return -EINVAL; | 4339 | return -EINVAL; |
4333 | err = mddev_lock(mddev); | 4340 | err = mddev_lock(mddev); |
4334 | if (!err) { | 4341 | if (!err) { |
4335 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 4342 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) |
4336 | err = mddev->pers->start_reshape(mddev); | 4343 | err = -EBUSY; |
4344 | else { | ||
4345 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | ||
4346 | err = mddev->pers->start_reshape(mddev); | ||
4347 | } | ||
4337 | mddev_unlock(mddev); | 4348 | mddev_unlock(mddev); |
4338 | } | 4349 | } |
4339 | if (err) | 4350 | if (err) |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 2bea51edfab7..ca0b643fe3c1 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -566,7 +566,9 @@ static inline char * mdname (struct mddev * mddev) | |||
566 | static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev) | 566 | static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev) |
567 | { | 567 | { |
568 | char nm[20]; | 568 | char nm[20]; |
569 | if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) { | 569 | if (!test_bit(Replacement, &rdev->flags) && |
570 | !test_bit(Journal, &rdev->flags) && | ||
571 | mddev->kobj.sd) { | ||
570 | sprintf(nm, "rd%d", rdev->raid_disk); | 572 | sprintf(nm, "rd%d", rdev->raid_disk); |
571 | return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); | 573 | return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); |
572 | } else | 574 | } else |
@@ -576,7 +578,9 @@ static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev) | |||
576 | static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev) | 578 | static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev) |
577 | { | 579 | { |
578 | char nm[20]; | 580 | char nm[20]; |
579 | if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) { | 581 | if (!test_bit(Replacement, &rdev->flags) && |
582 | !test_bit(Journal, &rdev->flags) && | ||
583 | mddev->kobj.sd) { | ||
580 | sprintf(nm, "rd%d", rdev->raid_disk); | 584 | sprintf(nm, "rd%d", rdev->raid_disk); |
581 | sysfs_remove_link(&mddev->kobj, nm); | 585 | sysfs_remove_link(&mddev->kobj, nm); |
582 | } | 586 | } |
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index c573402033b2..b1ced58eb5e1 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c | |||
@@ -63,6 +63,11 @@ int lower_bound(struct btree_node *n, uint64_t key) | |||
63 | return bsearch(n, key, 0); | 63 | return bsearch(n, key, 0); |
64 | } | 64 | } |
65 | 65 | ||
66 | static int upper_bound(struct btree_node *n, uint64_t key) | ||
67 | { | ||
68 | return bsearch(n, key, 1); | ||
69 | } | ||
70 | |||
66 | void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, | 71 | void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, |
67 | struct dm_btree_value_type *vt) | 72 | struct dm_btree_value_type *vt) |
68 | { | 73 | { |
@@ -252,6 +257,16 @@ static void pop_frame(struct del_stack *s) | |||
252 | dm_tm_unlock(s->tm, f->b); | 257 | dm_tm_unlock(s->tm, f->b); |
253 | } | 258 | } |
254 | 259 | ||
260 | static void unlock_all_frames(struct del_stack *s) | ||
261 | { | ||
262 | struct frame *f; | ||
263 | |||
264 | while (unprocessed_frames(s)) { | ||
265 | f = s->spine + s->top--; | ||
266 | dm_tm_unlock(s->tm, f->b); | ||
267 | } | ||
268 | } | ||
269 | |||
255 | int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | 270 | int dm_btree_del(struct dm_btree_info *info, dm_block_t root) |
256 | { | 271 | { |
257 | int r; | 272 | int r; |
@@ -308,9 +323,13 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | |||
308 | pop_frame(s); | 323 | pop_frame(s); |
309 | } | 324 | } |
310 | } | 325 | } |
311 | |||
312 | out: | 326 | out: |
327 | if (r) { | ||
328 | /* cleanup all frames of del_stack */ | ||
329 | unlock_all_frames(s); | ||
330 | } | ||
313 | kfree(s); | 331 | kfree(s); |
332 | |||
314 | return r; | 333 | return r; |
315 | } | 334 | } |
316 | EXPORT_SYMBOL_GPL(dm_btree_del); | 335 | EXPORT_SYMBOL_GPL(dm_btree_del); |
@@ -392,6 +411,82 @@ int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root, | |||
392 | } | 411 | } |
393 | EXPORT_SYMBOL_GPL(dm_btree_lookup); | 412 | EXPORT_SYMBOL_GPL(dm_btree_lookup); |
394 | 413 | ||
414 | static int dm_btree_lookup_next_single(struct dm_btree_info *info, dm_block_t root, | ||
415 | uint64_t key, uint64_t *rkey, void *value_le) | ||
416 | { | ||
417 | int r, i; | ||
418 | uint32_t flags, nr_entries; | ||
419 | struct dm_block *node; | ||
420 | struct btree_node *n; | ||
421 | |||
422 | r = bn_read_lock(info, root, &node); | ||
423 | if (r) | ||
424 | return r; | ||
425 | |||
426 | n = dm_block_data(node); | ||
427 | flags = le32_to_cpu(n->header.flags); | ||
428 | nr_entries = le32_to_cpu(n->header.nr_entries); | ||
429 | |||
430 | if (flags & INTERNAL_NODE) { | ||
431 | i = lower_bound(n, key); | ||
432 | if (i < 0 || i >= nr_entries) { | ||
433 | r = -ENODATA; | ||
434 | goto out; | ||
435 | } | ||
436 | |||
437 | r = dm_btree_lookup_next_single(info, value64(n, i), key, rkey, value_le); | ||
438 | if (r == -ENODATA && i < (nr_entries - 1)) { | ||
439 | i++; | ||
440 | r = dm_btree_lookup_next_single(info, value64(n, i), key, rkey, value_le); | ||
441 | } | ||
442 | |||
443 | } else { | ||
444 | i = upper_bound(n, key); | ||
445 | if (i < 0 || i >= nr_entries) { | ||
446 | r = -ENODATA; | ||
447 | goto out; | ||
448 | } | ||
449 | |||
450 | *rkey = le64_to_cpu(n->keys[i]); | ||
451 | memcpy(value_le, value_ptr(n, i), info->value_type.size); | ||
452 | } | ||
453 | out: | ||
454 | dm_tm_unlock(info->tm, node); | ||
455 | return r; | ||
456 | } | ||
457 | |||
458 | int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root, | ||
459 | uint64_t *keys, uint64_t *rkey, void *value_le) | ||
460 | { | ||
461 | unsigned level; | ||
462 | int r = -ENODATA; | ||
463 | __le64 internal_value_le; | ||
464 | struct ro_spine spine; | ||
465 | |||
466 | init_ro_spine(&spine, info); | ||
467 | for (level = 0; level < info->levels - 1u; level++) { | ||
468 | r = btree_lookup_raw(&spine, root, keys[level], | ||
469 | lower_bound, rkey, | ||
470 | &internal_value_le, sizeof(uint64_t)); | ||
471 | if (r) | ||
472 | goto out; | ||
473 | |||
474 | if (*rkey != keys[level]) { | ||
475 | r = -ENODATA; | ||
476 | goto out; | ||
477 | } | ||
478 | |||
479 | root = le64_to_cpu(internal_value_le); | ||
480 | } | ||
481 | |||
482 | r = dm_btree_lookup_next_single(info, root, keys[level], rkey, value_le); | ||
483 | out: | ||
484 | exit_ro_spine(&spine); | ||
485 | return r; | ||
486 | } | ||
487 | |||
488 | EXPORT_SYMBOL_GPL(dm_btree_lookup_next); | ||
489 | |||
395 | /* | 490 | /* |
396 | * Splits a node by creating a sibling node and shifting half the nodes | 491 | * Splits a node by creating a sibling node and shifting half the nodes |
397 | * contents across. Assumes there is a parent node, and it has room for | 492 | * contents across. Assumes there is a parent node, and it has room for |
@@ -473,8 +568,10 @@ static int btree_split_sibling(struct shadow_spine *s, unsigned parent_index, | |||
473 | 568 | ||
474 | r = insert_at(sizeof(__le64), pn, parent_index + 1, | 569 | r = insert_at(sizeof(__le64), pn, parent_index + 1, |
475 | le64_to_cpu(rn->keys[0]), &location); | 570 | le64_to_cpu(rn->keys[0]), &location); |
476 | if (r) | 571 | if (r) { |
572 | unlock_block(s->info, right); | ||
477 | return r; | 573 | return r; |
574 | } | ||
478 | 575 | ||
479 | if (key < le64_to_cpu(rn->keys[0])) { | 576 | if (key < le64_to_cpu(rn->keys[0])) { |
480 | unlock_block(s->info, right); | 577 | unlock_block(s->info, right); |
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h index 11d8cf78621d..c74301fa5a37 100644 --- a/drivers/md/persistent-data/dm-btree.h +++ b/drivers/md/persistent-data/dm-btree.h | |||
@@ -110,6 +110,13 @@ int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root, | |||
110 | uint64_t *keys, void *value_le); | 110 | uint64_t *keys, void *value_le); |
111 | 111 | ||
112 | /* | 112 | /* |
113 | * Tries to find the first key where the bottom level key is >= to that | ||
114 | * given. Useful for skipping empty sections of the btree. | ||
115 | */ | ||
116 | int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root, | ||
117 | uint64_t *keys, uint64_t *rkey, void *value_le); | ||
118 | |||
119 | /* | ||
113 | * Insertion (or overwrite an existing value). O(ln(n)) | 120 | * Insertion (or overwrite an existing value). O(ln(n)) |
114 | */ | 121 | */ |
115 | int dm_btree_insert(struct dm_btree_info *info, dm_block_t root, | 122 | int dm_btree_insert(struct dm_btree_info *info, dm_block_t root, |
@@ -135,9 +142,10 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, | |||
135 | uint64_t *keys, dm_block_t *new_root); | 142 | uint64_t *keys, dm_block_t *new_root); |
136 | 143 | ||
137 | /* | 144 | /* |
138 | * Removes values between 'keys' and keys2, where keys2 is keys with the | 145 | * Removes a _contiguous_ run of values starting from 'keys' and not |
139 | * final key replaced with 'end_key'. 'end_key' is the one-past-the-end | 146 | * reaching keys2 (where keys2 is keys with the final key replaced with |
140 | * value. 'keys' may be altered. | 147 | * 'end_key'). 'end_key' is the one-past-the-end value. 'keys' may be |
148 | * altered. | ||
141 | */ | 149 | */ |
142 | int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root, | 150 | int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root, |
143 | uint64_t *keys, uint64_t end_key, | 151 | uint64_t *keys, uint64_t end_key, |
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 53091295fce9..fca6dbcf9a47 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c | |||
@@ -136,7 +136,7 @@ static int brb_push(struct bop_ring_buffer *brb, | |||
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result) | 139 | static int brb_peek(struct bop_ring_buffer *brb, struct block_op *result) |
140 | { | 140 | { |
141 | struct block_op *bop; | 141 | struct block_op *bop; |
142 | 142 | ||
@@ -147,6 +147,17 @@ static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result) | |||
147 | result->type = bop->type; | 147 | result->type = bop->type; |
148 | result->block = bop->block; | 148 | result->block = bop->block; |
149 | 149 | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int brb_pop(struct bop_ring_buffer *brb) | ||
154 | { | ||
155 | struct block_op *bop; | ||
156 | |||
157 | if (brb_empty(brb)) | ||
158 | return -ENODATA; | ||
159 | |||
160 | bop = brb->bops + brb->begin; | ||
150 | brb->begin = brb_next(brb, brb->begin); | 161 | brb->begin = brb_next(brb, brb->begin); |
151 | 162 | ||
152 | return 0; | 163 | return 0; |
@@ -211,7 +222,7 @@ static int apply_bops(struct sm_metadata *smm) | |||
211 | while (!brb_empty(&smm->uncommitted)) { | 222 | while (!brb_empty(&smm->uncommitted)) { |
212 | struct block_op bop; | 223 | struct block_op bop; |
213 | 224 | ||
214 | r = brb_pop(&smm->uncommitted, &bop); | 225 | r = brb_peek(&smm->uncommitted, &bop); |
215 | if (r) { | 226 | if (r) { |
216 | DMERR("bug in bop ring buffer"); | 227 | DMERR("bug in bop ring buffer"); |
217 | break; | 228 | break; |
@@ -220,6 +231,8 @@ static int apply_bops(struct sm_metadata *smm) | |||
220 | r = commit_bop(smm, &bop); | 231 | r = commit_bop(smm, &bop); |
221 | if (r) | 232 | if (r) |
222 | break; | 233 | break; |
234 | |||
235 | brb_pop(&smm->uncommitted); | ||
223 | } | 236 | } |
224 | 237 | ||
225 | return r; | 238 | return r; |
@@ -683,7 +696,6 @@ static struct dm_space_map bootstrap_ops = { | |||
683 | static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) | 696 | static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) |
684 | { | 697 | { |
685 | int r, i; | 698 | int r, i; |
686 | enum allocation_event ev; | ||
687 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | 699 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); |
688 | dm_block_t old_len = smm->ll.nr_blocks; | 700 | dm_block_t old_len = smm->ll.nr_blocks; |
689 | 701 | ||
@@ -705,11 +717,12 @@ static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) | |||
705 | * allocate any new blocks. | 717 | * allocate any new blocks. |
706 | */ | 718 | */ |
707 | do { | 719 | do { |
708 | for (i = old_len; !r && i < smm->begin; i++) { | 720 | for (i = old_len; !r && i < smm->begin; i++) |
709 | r = sm_ll_inc(&smm->ll, i, &ev); | 721 | r = add_bop(smm, BOP_INC, i); |
710 | if (r) | 722 | |
711 | goto out; | 723 | if (r) |
712 | } | 724 | goto out; |
725 | |||
713 | old_len = smm->begin; | 726 | old_len = smm->begin; |
714 | 727 | ||
715 | r = apply_bops(smm); | 728 | r = apply_bops(smm); |
@@ -754,7 +767,6 @@ int dm_sm_metadata_create(struct dm_space_map *sm, | |||
754 | { | 767 | { |
755 | int r; | 768 | int r; |
756 | dm_block_t i; | 769 | dm_block_t i; |
757 | enum allocation_event ev; | ||
758 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | 770 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); |
759 | 771 | ||
760 | smm->begin = superblock + 1; | 772 | smm->begin = superblock + 1; |
@@ -782,7 +794,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm, | |||
782 | * allocated blocks that they were built from. | 794 | * allocated blocks that they were built from. |
783 | */ | 795 | */ |
784 | for (i = superblock; !r && i < smm->begin; i++) | 796 | for (i = superblock; !r && i < smm->begin; i++) |
785 | r = sm_ll_inc(&smm->ll, i, &ev); | 797 | r = add_bop(smm, BOP_INC, i); |
786 | 798 | ||
787 | if (r) | 799 | if (r) |
788 | return r; | 800 | return r; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 41d70bc9ba2f..84e597e1c489 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1946,6 +1946,8 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) | |||
1946 | 1946 | ||
1947 | first = i; | 1947 | first = i; |
1948 | fbio = r10_bio->devs[i].bio; | 1948 | fbio = r10_bio->devs[i].bio; |
1949 | fbio->bi_iter.bi_size = r10_bio->sectors << 9; | ||
1950 | fbio->bi_iter.bi_idx = 0; | ||
1949 | 1951 | ||
1950 | vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9); | 1952 | vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9); |
1951 | /* now find blocks with errors */ | 1953 | /* now find blocks with errors */ |
@@ -1989,7 +1991,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) | |||
1989 | bio_reset(tbio); | 1991 | bio_reset(tbio); |
1990 | 1992 | ||
1991 | tbio->bi_vcnt = vcnt; | 1993 | tbio->bi_vcnt = vcnt; |
1992 | tbio->bi_iter.bi_size = r10_bio->sectors << 9; | 1994 | tbio->bi_iter.bi_size = fbio->bi_iter.bi_size; |
1993 | tbio->bi_rw = WRITE; | 1995 | tbio->bi_rw = WRITE; |
1994 | tbio->bi_private = r10_bio; | 1996 | tbio->bi_private = r10_bio; |
1995 | tbio->bi_iter.bi_sector = r10_bio->devs[i].addr; | 1997 | tbio->bi_iter.bi_sector = r10_bio->devs[i].addr; |