@@ -61,6 +61,7 @@ struct rbd_aio_cb {
struct tcmulib_cmd *tcmulib_cmd;
int64_t length;
+ bool is_read;
char *bounce_buffer;
};
@@ -451,13 +452,13 @@ static void tcmu_rbd_close(struct tcmu_device *dev)
* allocation errors.
*/
-static void rbd_finish_aio_read(rbd_completion_t completion,
+static void tcmu_rbd_finish_aio(rbd_completion_t completion,
struct rbd_aio_cb *aio_cb)
{
struct tcmu_device *dev = aio_cb->dev;
- struct tcmulib_cmd *tcmulib_cmd = aio_cb->tcmulib_cmd;
- struct iovec *iovec = tcmulib_cmd->iovec;
- size_t iov_cnt = tcmulib_cmd->iov_cnt;
+ struct tcmulib_cmd *cmd = aio_cb->tcmulib_cmd;
+ struct iovec *iovec = cmd->iovec;
+ size_t iov_cnt = cmd->iov_cnt;
int64_t ret;
int tcmu_r;
@@ -465,29 +466,92 @@ static void rbd_finish_aio_read(rbd_completion_t completion,
rbd_aio_release(completion);
if (ret == -ESHUTDOWN) {
- tcmu_r = tcmu_set_sense_data(tcmulib_cmd->sense_buf,
+ tcmu_r = tcmu_set_sense_data(cmd->sense_buf,
NOT_READY, ASC_PORT_IN_STANDBY,
NULL);
} else if (ret < 0) {
- tcmu_r = tcmu_set_sense_data(tcmulib_cmd->sense_buf,
- MEDIUM_ERROR, ASC_READ_ERROR, NULL);
+ tcmu_r = tcmu_set_sense_data(cmd->sense_buf, MEDIUM_ERROR,
+ aio_cb->is_read ? ASC_READ_ERROR :
+ ASC_WRITE_ERROR, NULL);
} else {
+ if (aio_cb->is_read && aio_cb->bounce_buffer)
+ tcmu_memcpy_into_iovec(iovec, iov_cnt,
+ aio_cb->bounce_buffer,
+ aio_cb->length);
tcmu_r = SAM_STAT_GOOD;
- tcmu_memcpy_into_iovec(iovec, iov_cnt,
- aio_cb->bounce_buffer, aio_cb->length);
}
- tcmulib_cmd->done(dev, tcmulib_cmd, tcmu_r);
+ cmd->done(dev, cmd, tcmu_r);
- free(aio_cb->bounce_buffer);
+ if (aio_cb->bounce_buffer)
+ free(aio_cb->bounce_buffer);
free(aio_cb);
}
-static int tcmu_rbd_read(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
- struct iovec *iov, size_t iov_cnt, size_t length,
- off_t offset)
+#ifdef LIBRBD_SUPPORTS_IOVEC
+
+static rbd_image_t tcmu_dev_to_image(struct tcmu_device *dev)
+{
+ struct tcmu_rbd_state *state = tcmu_get_dev_private(dev);
+ return state->image;
+}
+
+#define tcmu_rbd_aio_read(dev, aio_cb, completion, iov, iov_cnt, length, offset)
+ rbd_aio_readv(tcmu_dev_to_image(dev), iov, iov_cnt, offset, completion);
+
+#define tcmu_rbd_aio_write(dev, aio_cb, completion, iov, iov_cnt, length, offset
+ rbd_aio_writev(tcmu_dev_to_image(dev), iov, iov_cnt, offset, completion);
+
+#else
+
+static int tcmu_rbd_aio_read(struct tcmu_device *dev, struct rbd_aio_cb *aio_cb,
+ rbd_completion_t completion, struct iovec *iov,
+ size_t iov_cnt, size_t length, off_t offset)
{
struct tcmu_rbd_state *state = tcmu_get_dev_private(dev);
+ int ret;
+
+ aio_cb->bounce_buffer = malloc(length);
+ if (!aio_cb->bounce_buffer) {
+ tcmu_dev_err(dev, "Could not allocate bounce buffer.\n");
+ return -ENOMEM;
+ }
+
+ ret = rbd_aio_read(state->image, offset, length, aio_cb->bounce_buffer,
+ completion);
+ if (ret < 0)
+ free(aio_cb->bounce_buffer);
+ return ret;
+}
+
+static int tcmu_rbd_aio_write(struct tcmu_device *dev, struct rbd_aio_cb *aio_cb,
+ rbd_completion_t completion, struct iovec *iov,
+ size_t iov_cnt, size_t length, off_t offset)
+{
+ struct tcmu_rbd_state *state = tcmu_get_dev_private(dev);
+ int ret;
+
+ aio_cb->bounce_buffer = malloc(length);
+ if (!aio_cb->bounce_buffer) {
+ tcmu_dev_err(dev, "Failed to allocate bounce buffer.\n");
+ return -ENOMEM;;
+ }
+
+ tcmu_memcpy_from_iovec(aio_cb->bounce_buffer, length, iov, iov_cnt);
+
+ ret = rbd_aio_write(state->image, offset,
+ length, aio_cb->bounce_buffer, completion);
+ if (ret < 0)
+ free(aio_cb->bounce_buffer);
+ return ret;
+}
+
+#endif
+
+static int tcmu_rbd_read(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
+ struct iovec *iov, size_t iov_cnt, size_t length,
+ off_t offset)
+{
struct rbd_aio_cb *aio_cb;
rbd_completion_t completion;
ssize_t ret;
@@ -501,21 +565,15 @@ static int tcmu_rbd_read(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
aio_cb->dev = dev;
aio_cb->length = length;
aio_cb->tcmulib_cmd = cmd;
+ aio_cb->is_read = 1;
- aio_cb->bounce_buffer = malloc(length);
- if (!aio_cb->bounce_buffer) {
- tcmu_dev_err(dev, "Could not allocate bounce buffer.\n");
+ ret = rbd_aio_create_completion(aio_cb, (rbd_callback_t)
+ tcmu_rbd_finish_aio, &completion);
+ if (ret < 0)
goto out_free_aio_cb;
- }
- ret = rbd_aio_create_completion
- (aio_cb, (rbd_callback_t) rbd_finish_aio_read, &completion);
- if (ret < 0) {
- goto out_free_bounce_buffer;
- }
-
- ret = rbd_aio_read(state->image, offset, length, aio_cb->bounce_buffer,
- completion);
+ ret = tcmu_rbd_aio_read(dev, aio_cb, completion, iov, iov_cnt,
+ length, offset);
if (ret < 0) {
goto out_remove_tracked_aio;
}
@@ -524,51 +582,17 @@ static int tcmu_rbd_read(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
out_remove_tracked_aio:
rbd_aio_release(completion);
-out_free_bounce_buffer:
- free(aio_cb->bounce_buffer);
out_free_aio_cb:
free(aio_cb);
out:
return SAM_STAT_TASK_SET_FULL;
}
-static void rbd_finish_aio_generic(rbd_completion_t completion,
- struct rbd_aio_cb *aio_cb)
-{
- struct tcmu_device *dev = aio_cb->dev;
- struct tcmulib_cmd *tcmulib_cmd = aio_cb->tcmulib_cmd;
- int64_t ret;
- int tcmu_r;
-
- ret = rbd_aio_get_return_value(completion);
- rbd_aio_release(completion);
-
- if (ret == -ESHUTDOWN) {
- tcmu_r = tcmu_set_sense_data(tcmulib_cmd->sense_buf,
- NOT_READY, ASC_PORT_IN_STANDBY,
- NULL);
- } else if (ret < 0) {
- tcmu_r = tcmu_set_sense_data(tcmulib_cmd->sense_buf,
- MEDIUM_ERROR, ASC_WRITE_ERROR,
- NULL);
- } else {
- tcmu_r = SAM_STAT_GOOD;
- }
-
- tcmulib_cmd->done(dev, tcmulib_cmd, tcmu_r);
-
- if (aio_cb->bounce_buffer) {
- free(aio_cb->bounce_buffer);
- }
- free(aio_cb);
-}
-
static int tcmu_rbd_write(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
struct iovec *iov, size_t iov_cnt, size_t length,
off_t offset)
{
- struct tcmu_rbd_state *state = tcmu_get_dev_private(dev);
struct rbd_aio_cb *aio_cb;
rbd_completion_t completion;
ssize_t ret;
@@ -583,22 +607,14 @@ static int tcmu_rbd_write(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
aio_cb->length = length;
aio_cb->tcmulib_cmd = cmd;
- aio_cb->bounce_buffer = malloc(length);
- if (!aio_cb->bounce_buffer) {
- tcmu_dev_err(dev, "Failed to allocate bounce buffer.\n");
- goto out_free_aio_cb;
- }
-
- tcmu_memcpy_from_iovec(aio_cb->bounce_buffer, length, iov, iov_cnt);
-
- ret = rbd_aio_create_completion
- (aio_cb, (rbd_callback_t) rbd_finish_aio_generic, &completion);
+ ret = rbd_aio_create_completion(aio_cb, (rbd_callback_t)
+ tcmu_rbd_finish_aio, &completion);
if (ret < 0) {
- goto out_free_bounce_buffer;
+ goto out_free_aio_cb;
}
- ret = rbd_aio_write(state->image, offset,
- length, aio_cb->bounce_buffer, completion);
+ ret = tcmu_rbd_aio_write(dev, aio_cb, completion, iov, iov_cnt,
+ length, offset);
if (ret < 0) {
goto out_remove_tracked_aio;
}
@@ -607,8 +623,6 @@ static int tcmu_rbd_write(struct tcmu_device *dev, struct tcmulib_cmd *cmd,
out_remove_tracked_aio:
rbd_aio_release(completion);
-out_free_bounce_buffer:
- free(aio_cb->bounce_buffer);
out_free_aio_cb:
free(aio_cb);
out:
@@ -632,8 +646,8 @@ static int tcmu_rbd_flush(struct tcmu_device *dev, struct tcmulib_cmd *cmd)
aio_cb->tcmulib_cmd = cmd;
aio_cb->bounce_buffer = NULL;
- ret = rbd_aio_create_completion
- (aio_cb, (rbd_callback_t) rbd_finish_aio_generic, &completion);
+ ret = rbd_aio_create_completion(aio_cb, (rbd_callback_t)
+ tcmu_rbd_finish_aio, &completion);
if (ret < 0) {
goto out_free_aio_cb;
}