diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-03-20 01:14:27 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-03-20 01:14:54 -0400 |
commit | 8f39db9d3709afe944710f124111ec87467d25c7 (patch) | |
tree | 7ce3ac8d3b9d6fc47e9fc0a0edeb5c2e094242f0 /drivers/block/virtio_blk.c | |
parent | 5ee21a52c05b5670ceeaa502c15cf306e379f714 (diff) |
virtio-blk: use virtqueue_add_sgs on bio path
(This is a respin of Paolo Bonzini's patch, but it calls
virtqueue_add_sgs() instead of his multi-part API).
Move the creation of the request header and response footer to
__virtblk_add_req. vbr->sg only contains the data scatterlist,
the header/footer are added separately using virtqueue_add_sgs().
With this change, virtio-blk (with use_bio) is not relying anymore on
the virtio functions ignoring the end markers in a scatterlist.
The next patch will do the same for the other path.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Reviewed-by: Asias He <asias@redhat.com>
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r-- | drivers/block/virtio_blk.c | 58 |
1 files changed, 29 insertions, 29 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index b271650032fa..cfbe39d35277 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -62,6 +62,7 @@ struct virtblk_req | |||
62 | struct virtio_blk *vblk; | 62 | struct virtio_blk *vblk; |
63 | int flags; | 63 | int flags; |
64 | u8 status; | 64 | u8 status; |
65 | int nents; | ||
65 | struct scatterlist sg[]; | 66 | struct scatterlist sg[]; |
66 | }; | 67 | }; |
67 | 68 | ||
@@ -100,24 +101,36 @@ static inline struct virtblk_req *virtblk_alloc_req(struct virtio_blk *vblk, | |||
100 | return vbr; | 101 | return vbr; |
101 | } | 102 | } |
102 | 103 | ||
103 | static inline int __virtblk_add_req(struct virtqueue *vq, | 104 | static int __virtblk_add_req(struct virtqueue *vq, |
104 | struct virtblk_req *vbr, | 105 | struct virtblk_req *vbr) |
105 | unsigned long out, | ||
106 | unsigned long in) | ||
107 | { | 106 | { |
108 | return virtqueue_add_buf(vq, vbr->sg, out, in, vbr, GFP_ATOMIC); | 107 | struct scatterlist hdr, status, *sgs[3]; |
108 | unsigned int num_out = 0, num_in = 0; | ||
109 | |||
110 | sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr)); | ||
111 | sgs[num_out++] = &hdr; | ||
112 | |||
113 | if (vbr->nents) { | ||
114 | if (vbr->out_hdr.type & VIRTIO_BLK_T_OUT) | ||
115 | sgs[num_out++] = vbr->sg; | ||
116 | else | ||
117 | sgs[num_out + num_in++] = vbr->sg; | ||
118 | } | ||
119 | |||
120 | sg_init_one(&status, &vbr->status, sizeof(vbr->status)); | ||
121 | sgs[num_out + num_in++] = &status; | ||
122 | |||
123 | return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC); | ||
109 | } | 124 | } |
110 | 125 | ||
111 | static void virtblk_add_req(struct virtblk_req *vbr, | 126 | static void virtblk_add_req(struct virtblk_req *vbr) |
112 | unsigned int out, unsigned int in) | ||
113 | { | 127 | { |
114 | struct virtio_blk *vblk = vbr->vblk; | 128 | struct virtio_blk *vblk = vbr->vblk; |
115 | DEFINE_WAIT(wait); | 129 | DEFINE_WAIT(wait); |
116 | int ret; | 130 | int ret; |
117 | 131 | ||
118 | spin_lock_irq(vblk->disk->queue->queue_lock); | 132 | spin_lock_irq(vblk->disk->queue->queue_lock); |
119 | while (unlikely((ret = __virtblk_add_req(vblk->vq, vbr, | 133 | while (unlikely((ret = __virtblk_add_req(vblk->vq, vbr)) < 0)) { |
120 | out, in)) < 0)) { | ||
121 | prepare_to_wait_exclusive(&vblk->queue_wait, &wait, | 134 | prepare_to_wait_exclusive(&vblk->queue_wait, &wait, |
122 | TASK_UNINTERRUPTIBLE); | 135 | TASK_UNINTERRUPTIBLE); |
123 | 136 | ||
@@ -134,22 +147,18 @@ static void virtblk_add_req(struct virtblk_req *vbr, | |||
134 | 147 | ||
135 | static void virtblk_bio_send_flush(struct virtblk_req *vbr) | 148 | static void virtblk_bio_send_flush(struct virtblk_req *vbr) |
136 | { | 149 | { |
137 | unsigned int out = 0, in = 0; | ||
138 | |||
139 | vbr->flags |= VBLK_IS_FLUSH; | 150 | vbr->flags |= VBLK_IS_FLUSH; |
140 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; | 151 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; |
141 | vbr->out_hdr.sector = 0; | 152 | vbr->out_hdr.sector = 0; |
142 | vbr->out_hdr.ioprio = 0; | 153 | vbr->out_hdr.ioprio = 0; |
143 | sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr)); | 154 | vbr->nents = 0; |
144 | sg_set_buf(&vbr->sg[out + in++], &vbr->status, sizeof(vbr->status)); | ||
145 | 155 | ||
146 | virtblk_add_req(vbr, out, in); | 156 | virtblk_add_req(vbr); |
147 | } | 157 | } |
148 | 158 | ||
149 | static void virtblk_bio_send_data(struct virtblk_req *vbr) | 159 | static void virtblk_bio_send_data(struct virtblk_req *vbr) |
150 | { | 160 | { |
151 | struct virtio_blk *vblk = vbr->vblk; | 161 | struct virtio_blk *vblk = vbr->vblk; |
152 | unsigned int num, out = 0, in = 0; | ||
153 | struct bio *bio = vbr->bio; | 162 | struct bio *bio = vbr->bio; |
154 | 163 | ||
155 | vbr->flags &= ~VBLK_IS_FLUSH; | 164 | vbr->flags &= ~VBLK_IS_FLUSH; |
@@ -157,24 +166,15 @@ static void virtblk_bio_send_data(struct virtblk_req *vbr) | |||
157 | vbr->out_hdr.sector = bio->bi_sector; | 166 | vbr->out_hdr.sector = bio->bi_sector; |
158 | vbr->out_hdr.ioprio = bio_prio(bio); | 167 | vbr->out_hdr.ioprio = bio_prio(bio); |
159 | 168 | ||
160 | sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr)); | 169 | vbr->nents = blk_bio_map_sg(vblk->disk->queue, bio, vbr->sg); |
161 | 170 | if (vbr->nents) { | |
162 | num = blk_bio_map_sg(vblk->disk->queue, bio, vbr->sg + out); | 171 | if (bio->bi_rw & REQ_WRITE) |
163 | |||
164 | sg_set_buf(&vbr->sg[num + out + in++], &vbr->status, | ||
165 | sizeof(vbr->status)); | ||
166 | |||
167 | if (num) { | ||
168 | if (bio->bi_rw & REQ_WRITE) { | ||
169 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; | 172 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; |
170 | out += num; | 173 | else |
171 | } else { | ||
172 | vbr->out_hdr.type |= VIRTIO_BLK_T_IN; | 174 | vbr->out_hdr.type |= VIRTIO_BLK_T_IN; |
173 | in += num; | ||
174 | } | ||
175 | } | 175 | } |
176 | 176 | ||
177 | virtblk_add_req(vbr, out, in); | 177 | virtblk_add_req(vbr); |
178 | } | 178 | } |
179 | 179 | ||
180 | static void virtblk_bio_send_data_work(struct work_struct *work) | 180 | static void virtblk_bio_send_data_work(struct work_struct *work) |