}
 EXPORT_SYMBOL_GPL(bio_check_pages_dirty);
 
-void generic_start_io_acct(struct request_queue *q, int rw,
+void generic_start_io_acct(struct request_queue *q, int op,
                           unsigned long sectors, struct hd_struct *part)
 {
+       const int sgrp = op_stat_group(op);
        int cpu = part_stat_lock();
 
        part_round_stats(q, cpu, part);
-       part_stat_inc(cpu, part, ios[rw]);
-       part_stat_add(cpu, part, sectors[rw], sectors);
-       part_inc_in_flight(q, part, rw);
+       part_stat_inc(cpu, part, ios[sgrp]);
+       part_stat_add(cpu, part, sectors[sgrp], sectors);
+       part_inc_in_flight(q, part, op_is_write(op));
 
        part_stat_unlock();
 }
 EXPORT_SYMBOL(generic_start_io_acct);
 
-void generic_end_io_acct(struct request_queue *q, int rw,
+void generic_end_io_acct(struct request_queue *q, int req_op,
                         struct hd_struct *part, unsigned long start_time)
 {
        unsigned long duration = jiffies - start_time;
+       const int sgrp = op_stat_group(req_op);
        int cpu = part_stat_lock();
 
-       part_stat_add(cpu, part, ticks[rw], duration);
+       part_stat_add(cpu, part, ticks[sgrp], duration);
        part_round_stats(q, cpu, part);
-       part_dec_in_flight(q, part, rw);
+       part_dec_in_flight(q, part, op_is_write(req_op));
 
        part_stat_unlock();
 }
 
 void blk_account_io_completion(struct request *req, unsigned int bytes)
 {
        if (blk_do_io_stat(req)) {
-               const int rw = rq_data_dir(req);
+               const int sgrp = op_stat_group(req_op(req));
                struct hd_struct *part;
                int cpu;
 
                cpu = part_stat_lock();
                part = req->part;
-               part_stat_add(cpu, part, sectors[rw], bytes >> 9);
+               part_stat_add(cpu, part, sectors[sgrp], bytes >> 9);
                part_stat_unlock();
        }
 }
         */
        if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
                unsigned long duration;
-               const int rw = rq_data_dir(req);
+               const int sgrp = op_stat_group(req_op(req));
                struct hd_struct *part;
                int cpu;
 
                cpu = part_stat_lock();
                part = req->part;
 
-               part_stat_inc(cpu, part, ios[rw]);
-               part_stat_add(cpu, part, ticks[rw], duration);
+               part_stat_inc(cpu, part, ios[sgrp]);
+               part_stat_add(cpu, part, ticks[sgrp], duration);
                part_round_stats(req->q, cpu, part);
-               part_dec_in_flight(req->q, part, rw);
+               part_dec_in_flight(req->q, part, rq_data_dir(req));
 
                hd_struct_put(part);
                part_stat_unlock();
 
 {
        struct request_queue *q = device->rq_queue;
 
-       generic_start_io_acct(q, bio_data_dir(req->master_bio),
+       generic_start_io_acct(q, bio_op(req->master_bio),
                                req->i.size >> 9, &device->vdisk->part0);
 }
 
 {
        struct request_queue *q = device->rq_queue;
 
-       generic_end_io_acct(q, bio_data_dir(req->master_bio),
+       generic_end_io_acct(q, bio_op(req->master_bio),
                            &device->vdisk->part0, req->start_jif);
 }
 
 
 
 static void disk_stats_start(struct rsxx_cardinfo *card, struct bio *bio)
 {
-       generic_start_io_acct(card->queue, bio_data_dir(bio), bio_sectors(bio),
+       generic_start_io_acct(card->queue, bio_op(bio), bio_sectors(bio),
                             &card->gendisk->part0);
 }
 
                                struct bio *bio,
                                unsigned long start_time)
 {
-       generic_end_io_acct(card->queue, bio_data_dir(bio),
-                               &card->gendisk->part0, start_time);
+       generic_end_io_acct(card->queue, bio_op(bio),
+                           &card->gendisk->part0, start_time);
 }
 
 static void bio_dma_done_cb(struct rsxx_cardinfo *card,
 
                        int offset, unsigned int op, struct bio *bio)
 {
        unsigned long start_time = jiffies;
-       int rw_acct = op_is_write(op) ? REQ_OP_WRITE : REQ_OP_READ;
        struct request_queue *q = zram->disk->queue;
        int ret;
 
-       generic_start_io_acct(q, rw_acct, bvec->bv_len >> SECTOR_SHIFT,
+       generic_start_io_acct(q, op, bvec->bv_len >> SECTOR_SHIFT,
                        &zram->disk->part0);
 
        if (!op_is_write(op)) {
                ret = zram_bvec_write(zram, bvec, index, offset, bio);
        }
 
-       generic_end_io_acct(q, rw_acct, &zram->disk->part0, start_time);
+       generic_end_io_acct(q, op, &zram->disk->part0, start_time);
 
        zram_slot_lock(zram, index);
        zram_accessed(zram, index);
 
        int nr_entries = pblk_get_secs(bio);
        int i, ret;
 
-       generic_start_io_acct(q, WRITE, bio_sectors(bio), &pblk->disk->part0);
+       generic_start_io_acct(q, REQ_OP_WRITE, bio_sectors(bio),
+                             &pblk->disk->part0);
 
        /* Update the write buffer head (mem) with the entries that we can
         * write. The write in itself cannot fail, so there is no need to
        pblk_rl_inserted(&pblk->rl, nr_entries);
 
 out:
-       generic_end_io_acct(q, WRITE, &pblk->disk->part0, start_time);
+       generic_end_io_acct(q, REQ_OP_WRITE, &pblk->disk->part0, start_time);
        pblk_write_should_kick(pblk);
        return ret;
 }
 
        struct bio *int_bio = rqd->bio;
        unsigned long start_time = r_ctx->start_time;
 
-       generic_end_io_acct(dev->q, READ, &pblk->disk->part0, start_time);
+       generic_end_io_acct(dev->q, REQ_OP_READ, &pblk->disk->part0, start_time);
 
        if (rqd->error)
                pblk_log_read_err(pblk, rqd);
                return NVM_IO_ERR;
        }
 
-       generic_start_io_acct(q, READ, bio_sectors(bio), &pblk->disk->part0);
+       generic_start_io_acct(q, REQ_OP_READ, bio_sectors(bio),
+                             &pblk->disk->part0);
 
        bitmap_zero(read_bitmap, nr_secs);
 
 
 static void bio_complete(struct search *s)
 {
        if (s->orig_bio) {
-               generic_end_io_acct(s->d->disk->queue,
-                                   bio_data_dir(s->orig_bio),
+               generic_end_io_acct(s->d->disk->queue, bio_op(s->orig_bio),
                                    &s->d->disk->part0, s->start_time);
 
                trace_bcache_request_end(s->d, s->orig_bio);
        bio->bi_end_io = ddip->bi_end_io;
        bio->bi_private = ddip->bi_private;
 
-       generic_end_io_acct(ddip->d->disk->queue,
-                           bio_data_dir(bio),
+       generic_end_io_acct(ddip->d->disk->queue, bio_op(bio),
                            &ddip->d->disk->part0, ddip->start_time);
 
        if (bio->bi_status) {
        }
 
        atomic_set(&dc->backing_idle, 0);
-       generic_start_io_acct(q, rw, bio_sectors(bio), &d->disk->part0);
+       generic_start_io_acct(q, bio_op(bio), bio_sectors(bio), &d->disk->part0);
 
        bio_set_dev(bio, dc->bdev);
        bio->bi_iter.bi_sector += dc->sb.data_offset;
        struct search *s;
        struct closure *cl;
        struct bcache_device *d = bio->bi_disk->private_data;
-       int rw = bio_data_dir(bio);
 
        if (unlikely(d->c && test_bit(CACHE_SET_IO_DISABLE, &d->c->flags))) {
                bio->bi_status = BLK_STS_IOERR;
                return BLK_QC_T_NONE;
        }
 
-       generic_start_io_acct(q, rw, bio_sectors(bio), &d->disk->part0);
+       generic_start_io_acct(q, bio_op(bio), bio_sectors(bio), &d->disk->part0);
 
        s = search_alloc(bio, d);
        cl = &s->cl;
                                      flash_dev_nodata,
                                      bcache_wq);
                return BLK_QC_T_NONE;
-       } else if (rw) {
+       } else if (bio_data_dir(bio)) {
                bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys,
                                        &KEY(d->id, bio->bi_iter.bi_sector, 0),
                                        &KEY(d->id, bio_end_sector(bio), 0));
 
 
        io->start_time = jiffies;
 
-       generic_start_io_acct(md->queue, rw, bio_sectors(bio), &dm_disk(md)->part0);
+       generic_start_io_acct(md->queue, bio_op(bio), bio_sectors(bio),
+                             &dm_disk(md)->part0);
 
        atomic_set(&dm_disk(md)->part0.in_flight[rw],
                   atomic_inc_return(&md->pending[rw]));
        int pending;
        int rw = bio_data_dir(bio);
 
-       generic_end_io_acct(md->queue, rw, &dm_disk(md)->part0, io->start_time);
+       generic_end_io_acct(md->queue, bio_op(bio), &dm_disk(md)->part0,
+                           io->start_time);
 
        if (unlikely(dm_stats_used(&md->stats)))
                dm_stats_account_io(&md->stats, bio_data_dir(bio),
 
 static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
 {
        const int rw = bio_data_dir(bio);
+       const int sgrp = op_stat_group(bio_op(bio));
        struct mddev *mddev = q->queuedata;
        unsigned int sectors;
        int cpu;
        md_handle_request(mddev, bio);
 
        cpu = part_stat_lock();
-       part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-       part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);
+       part_stat_inc(cpu, &mddev->gendisk->part0, ios[sgrp]);
+       part_stat_add(cpu, &mddev->gendisk->part0, sectors[sgrp], sectors);
        part_stat_unlock();
 
        return BLK_QC_T_NONE;
 
                return false;
 
        *start = jiffies;
-       generic_start_io_acct(disk->queue, bio_data_dir(bio),
-                             bio_sectors(bio), &disk->part0);
+       generic_start_io_acct(disk->queue, bio_op(bio), bio_sectors(bio),
+                             &disk->part0);
        return true;
 }
 static inline void nd_iostat_end(struct bio *bio, unsigned long start)
 {
        struct gendisk *disk = bio->bi_disk;
 
-       generic_end_io_acct(disk->queue, bio_data_dir(bio), &disk->part0,
-                               start);
+       generic_end_io_acct(disk->queue, bio_op(bio), &disk->part0, start);
 }
 static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector,
                unsigned int len)
 
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 
-void generic_start_io_acct(struct request_queue *q, int rw,
+void generic_start_io_acct(struct request_queue *q, int op,
                                unsigned long sectors, struct hd_struct *part);
-void generic_end_io_acct(struct request_queue *q, int rw,
+void generic_end_io_acct(struct request_queue *q, int op,
                                struct hd_struct *part,
                                unsigned long start_time);
 
 
                (op & (REQ_SYNC | REQ_FUA | REQ_PREFLUSH));
 }
 
+static inline int op_stat_group(unsigned int op)
+{
+       return op_is_write(op);
+}
+
 typedef unsigned int blk_qc_t;
 #define BLK_QC_T_NONE          -1U
 #define BLK_QC_T_SHIFT         16