bcache: fix wrong cache_misses statistics
authortang.junhui <tang.junhui@zte.com.cn>
Mon, 30 Oct 2017 21:46:34 +0000 (14:46 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Dec 2017 09:10:29 +0000 (10:10 +0100)
[ Upstream commit c157313791a999646901b3e3c6888514ebc36d62 ]

Currently, Cache missed IOs are identified by s->cache_miss, but actually,
there are many situations that missed IOs are not assigned a value for
s->cache_miss in cached_dev_cache_miss(), for example, a bypassed IO
(s->iop.bypass = 1), or the cache_bio allocate failed. In these situations,
it will go to out_put or out_submit, and s->cache_miss is null, which leads
bch_mark_cache_accounting() to treat this IO as a hit IO.

[ML: applied by 3-way merge]

Signed-off-by: tang.junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Reviewed-by: Coly Li <colyli@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/bcache/request.c

index 14d13ca..e9fbf2b 100644 (file)
@@ -463,6 +463,7 @@ struct search {
        unsigned                recoverable:1;
        unsigned                write:1;
        unsigned                read_dirty_data:1;
+       unsigned                cache_missed:1;
 
        unsigned long           start_time;
 
@@ -649,6 +650,7 @@ static inline struct search *search_alloc(struct bio *bio,
 
        s->orig_bio             = bio;
        s->cache_miss           = NULL;
+       s->cache_missed         = 0;
        s->d                    = d;
        s->recoverable          = 1;
        s->write                = op_is_write(bio_op(bio));
@@ -767,7 +769,7 @@ static void cached_dev_read_done_bh(struct closure *cl)
        struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
 
        bch_mark_cache_accounting(s->iop.c, s->d,
-                                 !s->cache_miss, s->iop.bypass);
+                                 !s->cache_missed, s->iop.bypass);
        trace_bcache_read(s->orig_bio, !s->cache_miss, s->iop.bypass);
 
        if (s->iop.status)
@@ -786,6 +788,8 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
        struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
        struct bio *miss, *cache_bio;
 
+       s->cache_missed = 1;
+
        if (s->cache_miss || s->iop.bypass) {
                miss = bio_next_split(bio, sectors, GFP_NOIO, s->d->bio_split);
                ret = miss == bio ? MAP_DONE : MAP_CONTINUE;