Commit 53766def authored by Anton Ivanov's avatar Anton Ivanov Committed by Richard Weinberger

um: Clean-up command processing in UML UBD driver

Clean-up command processing and return BLK_STS_NOTSUP for
uknown commands.
Signed-off-by: default avatarAnton Ivanov <anton.ivanov@cambridgegreys.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent a43c8316
...@@ -1306,65 +1306,82 @@ static int ubd_queue_one_vec(struct blk_mq_hw_ctx *hctx, struct request *req, ...@@ -1306,65 +1306,82 @@ static int ubd_queue_one_vec(struct blk_mq_hw_ctx *hctx, struct request *req,
io_req->fds[0] = dev->fd; io_req->fds[0] = dev->fd;
io_req->error = 0; io_req->error = 0;
if (req_op(req) != REQ_OP_FLUSH) { if (bvec != NULL) {
io_req->fds[1] = dev->fd;
io_req->cow_offset = -1;
io_req->offset = off;
io_req->length = bvec->bv_len;
io_req->sector_mask = 0;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
io_req->buffer = page_address(bvec->bv_page) + bvec->bv_offset; io_req->buffer = page_address(bvec->bv_page) + bvec->bv_offset;
io_req->sectorsize = SECTOR_SIZE; io_req->length = bvec->bv_len;
} else {
if (dev->cow.file) { io_req->buffer = NULL;
cowify_req(io_req, dev->cow.bitmap, io_req->length = blk_rq_bytes(req);
dev->cow.bitmap_offset, dev->cow.bitmap_len);
}
} }
io_req->sectorsize = SECTOR_SIZE;
io_req->fds[1] = dev->fd;
io_req->cow_offset = -1;
io_req->offset = off;
io_req->sector_mask = 0;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
if (dev->cow.file)
cowify_req(io_req, dev->cow.bitmap,
dev->cow.bitmap_offset, dev->cow.bitmap_len);
ret = os_write_file(thread_fd, &io_req, sizeof(io_req)); ret = os_write_file(thread_fd, &io_req, sizeof(io_req));
if (ret != sizeof(io_req)) { if (ret != sizeof(io_req)) {
if (ret != -EAGAIN) if (ret != -EAGAIN)
pr_err("write to io thread failed: %d\n", -ret); pr_err("write to io thread failed: %d\n", -ret);
kfree(io_req); kfree(io_req);
} }
return ret; return ret;
} }
static int queue_rw_req(struct blk_mq_hw_ctx *hctx, struct request *req)
{
struct req_iterator iter;
struct bio_vec bvec;
int ret;
u64 off = (u64)blk_rq_pos(req) << SECTOR_SHIFT;
rq_for_each_segment(bvec, req, iter) {
ret = ubd_queue_one_vec(hctx, req, off, &bvec);
if (ret < 0)
return ret;
off += bvec.bv_len;
}
return 0;
}
static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx, static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd) const struct blk_mq_queue_data *bd)
{ {
struct ubd *ubd_dev = hctx->queue->queuedata; struct ubd *ubd_dev = hctx->queue->queuedata;
struct request *req = bd->rq; struct request *req = bd->rq;
int ret = 0; int ret = 0, res = BLK_STS_OK;
blk_mq_start_request(req); blk_mq_start_request(req);
spin_lock_irq(&ubd_dev->lock); spin_lock_irq(&ubd_dev->lock);
if (req_op(req) == REQ_OP_FLUSH) { switch (req_op(req)) {
/* operations with no lentgth/offset arguments */
case REQ_OP_FLUSH:
ret = ubd_queue_one_vec(hctx, req, 0, NULL); ret = ubd_queue_one_vec(hctx, req, 0, NULL);
} else { break;
struct req_iterator iter; case REQ_OP_READ:
struct bio_vec bvec; case REQ_OP_WRITE:
u64 off = (u64)blk_rq_pos(req) << SECTOR_SHIFT; ret = queue_rw_req(hctx, req);
break;
rq_for_each_segment(bvec, req, iter) { default:
ret = ubd_queue_one_vec(hctx, req, off, &bvec); WARN_ON_ONCE(1);
if (ret < 0) res = BLK_STS_NOTSUPP;
goto out;
off += bvec.bv_len;
}
} }
out:
spin_unlock_irq(&ubd_dev->lock); spin_unlock_irq(&ubd_dev->lock);
if (ret < 0) if (ret < 0)
blk_mq_requeue_request(req, true); blk_mq_requeue_request(req, true);
return BLK_STS_OK; return res;
} }
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment