2. A bio belongs to sda1 is issued and is merged into the request mentioned on step1 by ELEVATOR_BACK_MERGE. The first sector of the request is changed from sda2 region to sda1 region. However the two partition's hd_struct->in_flight are not changed.

The patch fixes the problem by caching the partition lookupinside the request structure, hence making sure that the incrementand decrement will always happen on the same partition struct. Thisalso speeds up IO with accounting enabled, since it cuts down onthe number of lookups we have to do.

Also add a refcount to struct hd_struct to keep the partition inmemory as long as users exist. We use kref_test_and_get() to ensurewe don't add a reference to a partition which is going away.

- if (!new_io)+ if (!new_io) {+ part = rq->part; part_stat_inc(cpu, part, merges[rw]);- else {+ } else {+ part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));+ if (!kref_test_and_get(&part->ref)) {+ /*+ * The partition is already being removed,+ * the request will be accounted on the disk only+ *+ * We take a reference on disk->part0 although that+ * partition will never be deleted, so we can treat+ * it as any other partition.+ */+ part = &rq->rq_disk->part0;+ kref_get(&part->ref);+ } part_round_stats(cpu, part); part_inc_in_flight(part, rw);+ rq->part = part; }