diff options
author | Kent Overstreet <kmo@daterainc.com> | 2013-10-31 18:43:22 -0400 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2013-11-11 00:56:41 -0500 |
commit | 48a915a87f0bd98c3d68d029acf223a2e5116f07 (patch) | |
tree | d821604169acc801b655b04c1de1cc5672169ec4 /drivers/md/bcache/super.c | |
parent | 17e21a9f248d3d330acdfb2405c23b8d84c9c23a (diff) |
bcache: Better full stripe scanning
The old scanning-by-stripe code burned too much CPU, this should be
better.
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
Diffstat (limited to 'drivers/md/bcache/super.c')
-rw-r--r-- | drivers/md/bcache/super.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 4813ef67cef5..43fcfe38be11 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c | |||
@@ -738,6 +738,10 @@ static void bcache_device_free(struct bcache_device *d) | |||
738 | mempool_destroy(d->unaligned_bvec); | 738 | mempool_destroy(d->unaligned_bvec); |
739 | if (d->bio_split) | 739 | if (d->bio_split) |
740 | bioset_free(d->bio_split); | 740 | bioset_free(d->bio_split); |
741 | if (is_vmalloc_addr(d->full_dirty_stripes)) | ||
742 | vfree(d->full_dirty_stripes); | ||
743 | else | ||
744 | kfree(d->full_dirty_stripes); | ||
741 | if (is_vmalloc_addr(d->stripe_sectors_dirty)) | 745 | if (is_vmalloc_addr(d->stripe_sectors_dirty)) |
742 | vfree(d->stripe_sectors_dirty); | 746 | vfree(d->stripe_sectors_dirty); |
743 | else | 747 | else |
@@ -757,8 +761,12 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size, | |||
757 | 761 | ||
758 | d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size); | 762 | d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size); |
759 | 763 | ||
760 | if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) | 764 | if (!d->nr_stripes || |
765 | d->nr_stripes > INT_MAX || | ||
766 | d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) { | ||
767 | pr_err("nr_stripes too large"); | ||
761 | return -ENOMEM; | 768 | return -ENOMEM; |
769 | } | ||
762 | 770 | ||
763 | n = d->nr_stripes * sizeof(atomic_t); | 771 | n = d->nr_stripes * sizeof(atomic_t); |
764 | d->stripe_sectors_dirty = n < PAGE_SIZE << 6 | 772 | d->stripe_sectors_dirty = n < PAGE_SIZE << 6 |
@@ -767,6 +775,13 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size, | |||
767 | if (!d->stripe_sectors_dirty) | 775 | if (!d->stripe_sectors_dirty) |
768 | return -ENOMEM; | 776 | return -ENOMEM; |
769 | 777 | ||
778 | n = BITS_TO_LONGS(d->nr_stripes) * sizeof(unsigned long); | ||
779 | d->full_dirty_stripes = n < PAGE_SIZE << 6 | ||
780 | ? kzalloc(n, GFP_KERNEL) | ||
781 | : vzalloc(n); | ||
782 | if (!d->full_dirty_stripes) | ||
783 | return -ENOMEM; | ||
784 | |||
770 | if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) || | 785 | if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) || |
771 | !(d->unaligned_bvec = mempool_create_kmalloc_pool(1, | 786 | !(d->unaligned_bvec = mempool_create_kmalloc_pool(1, |
772 | sizeof(struct bio_vec) * BIO_MAX_PAGES)) || | 787 | sizeof(struct bio_vec) * BIO_MAX_PAGES)) || |