diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-03-11 19:55:30 -0900 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-01-18 21:38:36 -0900 |
commit | 24fd2569b66e3cf29486af6448e82f65db2bff43 (patch) | |
tree | 617c05fed935c9c41620a7cdbb139b2b9cf8d780 | |
parent | 020b1ed9f965be6a44952516f6a1966ee9ad642a (diff) |
bcache: slim down bch_read_bio
-rw-r--r-- | drivers/md/bcache/error.c | 15 | ||||
-rw-r--r-- | drivers/md/bcache/error.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/io.c | 199 | ||||
-rw-r--r-- | drivers/md/bcache/io_types.h | 25 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 3 |
5 files changed, 130 insertions, 114 deletions
diff --git a/drivers/md/bcache/error.c b/drivers/md/bcache/error.c index e550f7fad663..569348541132 100644 --- a/drivers/md/bcache/error.c +++ b/drivers/md/bcache/error.c @@ -74,23 +74,24 @@ void bch_account_io_completion(struct cache *ca) } /* IO error accounting and latency accounting: */ -void bch_account_bbio_completion(struct bbio *bio) +void bch_account_io_completion_time(struct cache *ca, + unsigned submit_time_us, int op) { struct cache_set *c; unsigned threshold; - if (!bio->ca) + if (!ca) return; - c = bio->ca->set; - threshold = op_is_write(bio_op(&bio->bio)) + c = ca->set; + threshold = op_is_write(op) ? c->congested_write_threshold_us : c->congested_read_threshold_us; - if (threshold && bio->submit_time_us) { + if (threshold && submit_time_us) { unsigned t = local_clock_us(); - int us = t - bio->submit_time_us; + int us = t - submit_time_us; int congested = atomic_read(&c->congested); if (us > (int) threshold) { @@ -103,7 +104,7 @@ void bch_account_bbio_completion(struct bbio *bio) atomic_inc(&c->congested); } - bch_account_io_completion(bio->ca); + bch_account_io_completion(ca); } void bch_nonfatal_io_error_work(struct work_struct *work) diff --git a/drivers/md/bcache/error.h b/drivers/md/bcache/error.h index ea67bb92aaec..be99a16f71d1 100644 --- a/drivers/md/bcache/error.h +++ b/drivers/md/bcache/error.h @@ -153,7 +153,7 @@ do { \ */ void bch_account_io_completion(struct cache *); -void bch_account_bbio_completion(struct bbio *); +void bch_account_io_completion_time(struct cache *, unsigned, int); void bch_nonfatal_io_error_work(struct work_struct *); diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index a9b61b8643cf..bd9304ccaaf3 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -188,8 +188,8 @@ void bch_bbio_endio(struct bbio *bio) struct closure *cl = bio->bio.bi_private; struct cache *ca = bio->ca; - bch_account_bbio_completion(bio); - + bch_account_io_completion_time(ca, bio->submit_time_us, + bio_op(&bio->bio)); bio_put(&bio->bio); if (ca) percpu_ref_put(&ca->ref); @@ -1475,9 +1475,12 @@ static int bio_uncompress_gzip(struct cache_set *c, return ret == Z_STREAM_END ? 0 : -EIO; } -static int bio_checksum_uncompress(struct bch_read_bio *rbio) +static int bio_checksum_uncompress(struct cache_set *c, + struct bch_read_bio *rbio) { - struct bio *bio = &rbio->bio.bio; + struct bio *src = &rbio->bio; + struct bio *dst = rbio->parent; + struct bvec_iter dst_iter = rbio->parent_iter; int ret = 0; /* @@ -1486,79 +1489,82 @@ static int bio_checksum_uncompress(struct bch_read_bio *rbio) * which was not necessarily the full extent if we were only bouncing * in order to promote */ - bio->bi_iter.bi_size = rbio->compressed_size << 9; - bio->bi_iter.bi_idx = 0; - bio->bi_iter.bi_bvec_done = 0; + src->bi_iter.bi_size = rbio->crc.compressed_size << 9; + src->bi_iter.bi_idx = 0; + src->bi_iter.bi_bvec_done = 0; - if (rbio->csum_type != BCH_CSUM_NONE && - rbio->csum != checksum_bio(bio, rbio->csum_type)) { - cache_nonfatal_io_error(rbio->bio.ca, "checksum error"); + if (rbio->crc.csum_type != BCH_CSUM_NONE && + rbio->crc.csum != checksum_bio(src, rbio->crc.csum_type)) { + cache_nonfatal_io_error(rbio->ca, "checksum error"); return -EIO; } - switch (rbio->compression_type) { + switch (rbio->crc.compression_type) { case BCH_COMPRESSION_NONE: if (rbio->bounce) { - bio_advance(bio, rbio->offset << 9); - bio_copy_data_iter(rbio->parent, rbio->parent_iter, - bio, bio->bi_iter); + bio_advance(src, rbio->crc.offset << 9); + bio_copy_data_iter(dst, dst_iter, + src, src->bi_iter); } break; case BCH_COMPRESSION_LZ4: - ret = bio_uncompress_lz4(rbio->c, - rbio->parent, - rbio->parent_iter, - bio, bio->bi_iter, - rbio->offset << 9, - rbio->uncompressed_size << 9); + ret = bio_uncompress_lz4(c, + dst, dst_iter, + src, src->bi_iter, + rbio->crc.offset << 9, + rbio->crc.uncompressed_size << 9); break; case BCH_COMPRESSION_GZIP: - ret = bio_uncompress_gzip(rbio->c, - rbio->parent, - rbio->parent_iter, - bio, bio->bi_iter, - rbio->offset << 9); + ret = bio_uncompress_gzip(c, + dst, dst_iter, + src, src->bi_iter, + rbio->crc.offset << 9); break; default: BUG(); } if (ret) - __bcache_io_error(rbio->c, "decompression error"); + __bcache_io_error(c, "decompression error"); return ret; } -static void bch_rbio_free(struct bch_read_bio *rbio) +static void bch_rbio_free(struct cache_set *c, struct bch_read_bio *rbio) { - struct bio *bio = &rbio->bio.bio; + struct bio *bio = &rbio->bio; + + BUG_ON(rbio->ca); if (rbio->promote) kfree(rbio->promote); if (rbio->bounce) - bch_bio_free_pages_pool(rbio->c, bio); + bch_bio_free_pages_pool(c, bio); bio_put(bio); } -static void bch_read_bio_done(struct bch_read_bio *rbio) +static void bch_rbio_done(struct cache_set *c, struct bch_read_bio *rbio) { + percpu_ref_put(&rbio->ca->ref); + rbio->ca = NULL; bio_endio(rbio->parent); - bch_rbio_free(rbio); + bch_rbio_free(c, rbio); } /* * Decide if we want to retry the read - returns true if read is being retried, * false if caller should pass error on up */ -static void bch_read_error_maybe_retry(struct bch_read_bio *rbio, int error) +static void bch_read_error_maybe_retry(struct cache_set *c, + struct bch_read_bio *rbio, + int error) { - struct cache_set *c = rbio->c; unsigned long flags; if ((error == -EINTR) && (rbio->flags & BCH_READ_RETRY_IF_STALE)) { - atomic_long_inc(&rbio->c->cache_read_races); + atomic_long_inc(&c->cache_read_races); goto retry; } @@ -1567,11 +1573,14 @@ static void bch_read_error_maybe_retry(struct bch_read_bio *rbio, int error) } rbio->parent->bi_error = error; - bch_read_bio_done(rbio); + bch_rbio_done(c, rbio); return; retry: + percpu_ref_put(&rbio->ca->ref); + rbio->ca = NULL; + spin_lock_irqsave(&c->read_retry_lock, flags); - bio_list_add(&c->read_retry_list, &rbio->bio.bio); + bio_list_add(&c->read_retry_list, &rbio->bio); spin_unlock_irqrestore(&c->read_retry_lock, flags); queue_work(c->wq, &c->read_retry_work); } @@ -1581,33 +1590,36 @@ static void cache_promote_done(struct closure *cl) struct cache_promote_op *op = container_of(cl, struct cache_promote_op, cl); - bch_rbio_free(op->orig_bio); + bch_rbio_free(op->iop.c, op->orig_bio); } /* Inner part that may run in process context */ -static void __bch_read_endio(struct bch_read_bio *rbio) +static void __bch_read_endio(struct cache_set *c, struct bch_read_bio *rbio) { int ret; - ret = bio_checksum_uncompress(rbio); + ret = bio_checksum_uncompress(c, rbio); if (ret) { - bch_read_error_maybe_retry(rbio, ret); + bch_read_error_maybe_retry(c, rbio, ret); return; } if (rbio->promote && - !test_bit(CACHE_SET_RO, &rbio->c->flags) && - !test_bit(CACHE_SET_STOPPING, &rbio->c->flags)) { + !test_bit(CACHE_SET_RO, &c->flags) && + !test_bit(CACHE_SET_STOPPING, &c->flags)) { struct closure *cl = &rbio->promote->cl; + percpu_ref_put(&rbio->ca->ref); + rbio->ca = NULL; + bio_endio(rbio->parent); rbio->parent = NULL; - closure_init(cl, &rbio->c->cl); - closure_call(&rbio->promote->iop.cl, bch_write, rbio->c->wq, cl); + closure_init(cl, &c->cl); + closure_call(&rbio->promote->iop.cl, bch_write, c->wq, cl); closure_return_with_destructor(cl, cache_promote_done); } else { - bch_read_bio_done(rbio); + bch_rbio_done(c, rbio); } } @@ -1625,39 +1637,38 @@ void bch_bio_decompress_work(struct work_struct *work) next = llist_next(list); rbio = container_of(list, struct bch_read_bio, list); - __bch_read_endio(rbio); + __bch_read_endio(d->c, rbio); } } static void bch_read_endio(struct bio *bio) { struct bch_read_bio *rbio = - container_of(bio, struct bch_read_bio, bio.bio); + container_of(bio, struct bch_read_bio, bio); + struct cache_set *c = rbio->ca->set; int stale = race_fault() || - ptr_stale(rbio->bio.ca, &rbio->bio.ptr) ? -EINTR : 0; + ptr_stale(rbio->ca, &rbio->ptr) ? -EINTR : 0; int error = bio->bi_error ?: stale; - bch_account_bbio_completion(&rbio->bio); - - cache_nonfatal_io_err_on(bio->bi_error, rbio->bio.ca, "data read"); + bch_account_io_completion_time(rbio->ca, rbio->submit_time_us, REQ_OP_READ); - percpu_ref_put(&rbio->bio.ca->ref); + cache_nonfatal_io_err_on(bio->bi_error, rbio->ca, "data read"); if (error) { - bch_read_error_maybe_retry(rbio, error); + bch_read_error_maybe_retry(c, rbio, error); return; } - if (rbio->compression_type != BCH_COMPRESSION_NONE) { + if (rbio->crc.compression_type != BCH_COMPRESSION_NONE) { struct bio_decompress_worker *d; preempt_disable(); - d = this_cpu_ptr(rbio->c->bio_decompress_worker); + d = this_cpu_ptr(c->bio_decompress_worker); llist_add(&rbio->list, &d->bio_list); queue_work(system_unbound_wq, &d->work); preempt_enable(); } else { - __bch_read_endio(rbio); + __bch_read_endio(c, rbio); } } @@ -1666,7 +1677,6 @@ void bch_read_extent_iter(struct cache_set *c, struct bio *orig, struct extent_pick_ptr *pick, unsigned skip, unsigned flags) { - struct bio *bio; struct bch_read_bio *rbio; struct cache_promote_op *promote_op = NULL; bool bounce = false, read_full = false; @@ -1692,49 +1702,52 @@ void bch_read_extent_iter(struct cache_set *c, struct bio *orig, } if (bounce) { - unsigned sectors = - !read_full ? bio_sectors(orig) - : pick->crc.compressed_size ?: k.k->size; - - bio = bio_alloc_bioset(GFP_NOIO, - DIV_ROUND_UP(sectors, PAGE_SECTORS), - &c->bio_read); - bch_bio_alloc_pages_pool(c, bio, sectors << 9); - } else { - bio = bio_clone_fast(orig, GFP_NOIO, &c->bio_read); - bio->bi_iter = iter; - } - - bio->bi_opf = orig->bi_opf; + unsigned sectors = read_full + ? (pick->crc.compressed_size ?: k.k->size) + : bio_sectors(orig); - rbio = container_of(bio, struct bch_read_bio, bio.bio); - memset(rbio, 0, offsetof(struct bch_read_bio, bio)); + rbio = container_of(bio_alloc_bioset(GFP_NOIO, + DIV_ROUND_UP(sectors, PAGE_SECTORS), + &c->bio_read), + struct bch_read_bio, bio); - rbio->csum = pick->crc.csum; - rbio->compressed_size = bio_sectors(bio); - rbio->uncompressed_size = pick->crc.uncompressed_size; - rbio->offset = pick->crc.offset; - rbio->csum_type = pick->crc.csum_type; - rbio->compression_type = pick->crc.compression_type; + bch_bio_alloc_pages_pool(c, &rbio->bio, sectors << 9); + } else { + rbio = container_of(bio_clone_fast(orig, + GFP_NOIO, &c->bio_read), + struct bch_read_bio, bio); + rbio->bio.bi_iter = iter; + } if (!(flags & BCH_READ_IS_LAST)) __bio_inc_remaining(orig); - rbio->c = c; - rbio->flags = flags; rbio->parent = orig; rbio->parent_iter = iter; rbio->inode = k.k->p.inode; + rbio->flags = flags; rbio->bounce = bounce; + rbio->crc = pick->crc; + /* + * crc.compressed_size will be 0 if there wasn't any checksum + * information, also we need to stash the original size of the bio if we + * bounced (which isn't necessarily the original key size, if we bounced + * only for promoting) + */ + rbio->crc.compressed_size = bio_sectors(&rbio->bio); + rbio->ptr = pick->ptr; + rbio->ca = pick->ca; rbio->promote = promote_op; - rbio->bio.ptr = pick->ptr; - bio->bi_end_io = bch_read_endio; - bch_bbio_prep(&rbio->bio, pick->ca); + + rbio->bio.bi_bdev = pick->ca->disk_sb.bdev; + rbio->bio.bi_opf = orig->bi_opf; + rbio->bio.bi_iter.bi_sector = pick->ptr.offset; + rbio->bio.bi_end_io = bch_read_endio; if (read_full) - rbio->offset += skip; + rbio->crc.offset += skip; else - bio->bi_iter.bi_sector += skip; + rbio->bio.bi_iter.bi_sector += skip; if (promote_op) { promote_op->orig_bio = rbio; @@ -1754,13 +1767,15 @@ void bch_read_extent_iter(struct cache_set *c, struct bio *orig, bio_sectors(orig)); } - __bio_clone_fast(&promote_op->bio.bio.bio, bio); + __bio_clone_fast(&promote_op->bio.bio.bio, &rbio->bio); } + rbio->submit_time_us = local_clock_us(); + #ifndef CONFIG_BCACHE_NO_IO - generic_make_request(bio); + generic_make_request(&rbio->bio); #else - bio_endio(bio); + bio_endio(&rbio->bio); #endif } @@ -1854,9 +1869,9 @@ static void bch_read_retry(struct cache_set *c, struct bch_read_bio *rbio) struct bvec_iter iter = rbio->parent_iter; u64 inode = rbio->inode; - trace_bcache_read_retry(&rbio->bio.bio); + trace_bcache_read_retry(&rbio->bio); - bch_rbio_free(rbio); + bch_rbio_free(c, rbio); bch_read_iter(c, parent, iter, inode); } @@ -1876,7 +1891,7 @@ void bch_read_retry_work(struct work_struct *work) if (!bio) break; - rbio = container_of(bio, struct bch_read_bio, bio.bio); + rbio = container_of(bio, struct bch_read_bio, bio); bch_read_retry(c, rbio); } } diff --git a/drivers/md/bcache/io_types.h b/drivers/md/bcache/io_types.h index 22f3b7d3a5e6..15926177b520 100644 --- a/drivers/md/bcache/io_types.h +++ b/drivers/md/bcache/io_types.h @@ -8,6 +8,7 @@ #include <linux/llist.h> #include <linux/workqueue.h> +/* XXX kill kill kill */ struct bbio { struct cache *ca; struct bch_extent_ptr ptr; @@ -36,23 +37,20 @@ struct bch_read_bio { */ u64 inode; - struct cache_set *c; - unsigned flags; - - /* fields align with bch_extent_crc64 */ - u64 bounce:1, - pad:2, - offset:17, - compressed_size:18, - uncompressed_size:18, - csum_type:4, - compression_type:4; - u64 csum; + unsigned submit_time_us; + u16 flags; + u8 bounce:1; + + struct bch_extent_crc64 crc; + struct bch_extent_ptr ptr; + struct cache *ca; struct cache_promote_op *promote; + /* bio_decompress_worker list */ struct llist_node list; - struct bbio bio; + + struct bio bio; }; struct bch_write_bio { @@ -113,6 +111,7 @@ struct bch_write_op { }; struct bio_decompress_worker { + struct cache_set *c; struct work_struct work; struct llist_head bio_list; }; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index e7a929cb0795..05c4abb4be32 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1129,7 +1129,7 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, sizeof(struct async_split)) || mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) || bioset_init(&c->btree_read_bio, 1, offsetof(struct bbio, bio)) || - bioset_init(&c->bio_read, 4, offsetof(struct bch_read_bio, bio.bio)) || + bioset_init(&c->bio_read, 4, offsetof(struct bch_read_bio, bio)) || bioset_init(&c->bio_write, 4, offsetof(struct bch_write_bio, bio.bio)) || mempool_init_page_pool(&c->bio_bounce_pages, CRC32_EXTENT_SIZE_MAX / PAGE_SECTORS, 0) || @@ -1151,6 +1151,7 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, struct bio_decompress_worker *d = per_cpu_ptr(c->bio_decompress_worker, cpu); + d->c = c; INIT_WORK(&d->work, bch_bio_decompress_work); init_llist_head(&d->bio_list); } |