Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[sfrench/cifs-2.6.git] / block / blk-merge.c
index 845ef81311081e719ed3ca9409fad05a0c890bf7..b5c5c4a9e3f08d051a25d44e92689580d19cbce5 100644 (file)
@@ -220,7 +220,19 @@ new_segment:
                bvprv = bvec;
        } /* segments in rq */
 
-       if (q->dma_drain_size) {
+
+       if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
+           (rq->data_len & q->dma_pad_mask)) {
+               unsigned int pad_len = (q->dma_pad_mask & ~rq->data_len) + 1;
+
+               sg->length += pad_len;
+               rq->extra_len += pad_len;
+       }
+
+       if (q->dma_drain_size && q->dma_drain_needed(rq)) {
+               if (rq->cmd_flags & REQ_RW)
+                       memset(q->dma_drain_buffer, 0, q->dma_drain_size);
+
                sg->page_link &= ~0x02;
                sg = sg_next(sg);
                sg_set_page(sg, virt_to_page(q->dma_drain_buffer),
@@ -228,6 +240,7 @@ new_segment:
                            ((unsigned long)q->dma_drain_buffer) &
                            (PAGE_SIZE - 1));
                nsegs++;
+               rq->extra_len += q->dma_drain_size;
        }
 
        if (sg)
@@ -454,8 +467,14 @@ static int attempt_merge(struct request_queue *q, struct request *req,
        elv_merge_requests(q, req, next);
 
        if (req->rq_disk) {
+               struct hd_struct *part
+                       = get_part(req->rq_disk, req->sector);
                disk_round_stats(req->rq_disk);
                req->rq_disk->in_flight--;
+               if (part) {
+                       part_round_stats(part);
+                       part->in_flight--;
+               }
        }
 
        req->ioprio = ioprio_best(req->ioprio, next->ioprio);