* [Qemu-devel] [PATCH 0/5] usb-mtp write fixes
@ 2018-07-20 21:40 Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 1/5] dev-mtp: add support for canceling transaction Bandan Das
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Bandan Das @ 2018-07-20 21:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kraxel
Patch 1 adds support for canceling an ongoing transaction.
2,3 and 4 fix writes for large transfers. For > 4G file transfers,
the logic has been modified to check for the end of the data phase
by checking for a short packet. Patch 5 renames x-root to a more
meaningful rootdir.
Bandan Das (5):
dev-mtp: add support for canceling transaction
dev-mtp: fix buffer allocation for writing file contents
dev-mtp: retry write for incomplete transfers
dev-mtp: Add support for > 4GB file transfers
dev-mtp: rename x-root to rootdir
hw/usb/dev-mtp.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 79 insertions(+), 14 deletions(-)
--
2.14.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 1/5] dev-mtp: add support for canceling transaction
2018-07-20 21:40 [Qemu-devel] [PATCH 0/5] usb-mtp write fixes Bandan Das
@ 2018-07-20 21:40 ` Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 2/5] dev-mtp: fix buffer allocation for writing file contents Bandan Das
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Bandan Das @ 2018-07-20 21:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kraxel
The initiator can choose to cancel an ongoing request which
is specified by bRequest=0x64. If such a request arrives,
free up any pending state
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1ded7ac9a3..c40b0de0bb 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -82,6 +82,7 @@ enum mtp_code {
FMT_ASSOCIATION = 0x3001,
/* event codes */
+ EVT_CANCEL_TRANSACTION = 0x4001,
EVT_OBJ_ADDED = 0x4002,
EVT_OBJ_REMOVED = 0x4003,
EVT_OBJ_INFO_CHANGED = 0x4007,
@@ -1551,14 +1552,35 @@ static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p,
int length, uint8_t *data)
{
int ret;
+ MTPState *s = USB_MTP(dev);
+ uint16_t *event = (uint16_t *)data;
- ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
- if (ret >= 0) {
- return;
+ switch (request) {
+ case ClassInterfaceOutRequest | 0x64:
+ if (*event == EVT_CANCEL_TRANSACTION) {
+ g_free(s->result);
+ s->result = NULL;
+ usb_mtp_data_free(s->data_in);
+ s->data_in = NULL;
+ if (s->write_pending) {
+ g_free(s->dataset.filename);
+ s->write_pending = false;
+ }
+ usb_mtp_data_free(s->data_out);
+ s->data_out = NULL;
+ } else {
+ p->status = USB_RET_STALL;
+ }
+ break;
+ default:
+ ret = usb_desc_handle_control(dev, p, request,
+ value, index, length, data);
+ if (ret >= 0) {
+ return;
+ }
}
trace_usb_mtp_stall(dev->addr, "unknown control request");
- p->status = USB_RET_STALL;
}
static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
--
2.14.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 2/5] dev-mtp: fix buffer allocation for writing file contents
2018-07-20 21:40 [Qemu-devel] [PATCH 0/5] usb-mtp write fixes Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 1/5] dev-mtp: add support for canceling transaction Bandan Das
@ 2018-07-20 21:40 ` Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers Bandan Das
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Bandan Das @ 2018-07-20 21:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kraxel
usb_mtp_realloc() was being incorrectly used when allocating
buffer for incoming data. Set d->length only after resizing
the buffer.
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index c40b0de0bb..1b72603dc5 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1721,6 +1721,7 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
MTPData *d = s->data_out;
uint64_t dlen;
uint32_t data_len = p->iov.size;
+ uint64_t total_len;
if (!d) {
usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, 0,
@@ -1729,10 +1730,11 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
}
if (d->first) {
/* Total length of incoming data */
- d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
+ total_len = cpu_to_le32(container->length) - sizeof(mtp_container);
/* Length of data in this packet */
data_len -= sizeof(mtp_container);
- usb_mtp_realloc(d, d->length);
+ usb_mtp_realloc(d, total_len);
+ d->length += total_len;
d->offset = 0;
d->first = false;
}
--
2.14.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers
2018-07-20 21:40 [Qemu-devel] [PATCH 0/5] usb-mtp write fixes Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 1/5] dev-mtp: add support for canceling transaction Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 2/5] dev-mtp: fix buffer allocation for writing file contents Bandan Das
@ 2018-07-20 21:40 ` Bandan Das
2018-08-07 13:28 ` Gerd Hoffmann
2018-10-19 9:48 ` Thomas Huth
2018-07-20 21:40 ` [Qemu-devel] [PATCH 4/5] dev-mtp: Add support for > 4GB file transfers Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 5/5] dev-mtp: rename x-root to rootdir Bandan Das
4 siblings, 2 replies; 9+ messages in thread
From: Bandan Das @ 2018-07-20 21:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kraxel
For large buffers, write may not copy the full buffer. For example,
on Linux, write imposes a limit of 0x7ffff000. Note that this does
not fix >4G transfers but ~>2G files will transfer successfully.
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1b72603dc5..c8f6eb4e9e 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1602,6 +1602,24 @@ static void utf16_to_str(uint8_t len, uint16_t *arr, char *name)
g_free(wstr);
}
+/* Wrapper around write, returns 0 on failure */
+static uint64_t write_retry(int fd, void *buf, uint64_t size)
+{
+ uint64_t bytes_left = size, ret;
+
+ while (bytes_left > 0) {
+ ret = write(fd, buf, bytes_left);
+ if ((ret == -1) && (errno != EINTR || errno != EAGAIN ||
+ errno != EWOULDBLOCK)) {
+ break;
+ }
+ bytes_left -= ret;
+ buf += ret;
+ }
+
+ return size - bytes_left;
+}
+
static void usb_mtp_write_data(MTPState *s)
{
MTPData *d = s->data_out;
@@ -1644,8 +1662,8 @@ static void usb_mtp_write_data(MTPState *s)
goto success;
}
- rc = write(d->fd, d->data, s->dataset.size);
- if (rc == -1) {
+ rc = write_retry(d->fd, d->data, s->dataset.size);
+ if (!rc) {
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
0, 0, 0, 0);
goto done;
--
2.14.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 4/5] dev-mtp: Add support for > 4GB file transfers
2018-07-20 21:40 [Qemu-devel] [PATCH 0/5] usb-mtp write fixes Bandan Das
` (2 preceding siblings ...)
2018-07-20 21:40 ` [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers Bandan Das
@ 2018-07-20 21:40 ` Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 5/5] dev-mtp: rename x-root to rootdir Bandan Das
4 siblings, 0 replies; 9+ messages in thread
From: Bandan Das @ 2018-07-20 21:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kraxel
To support larger file transfers, rely on a short packet
to detect end of the data phase and rewrite d->length to
the size received
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index c8f6eb4e9e..2e3ea58da6 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -147,9 +147,12 @@ struct MTPData {
uint32_t trans;
uint64_t offset;
uint64_t length;
- uint32_t alloc;
+ uint64_t alloc;
uint8_t *data;
bool first;
+ /* Used for >4G file sizes */
+ bool pending;
+ uint64_t cached_length;
int fd;
};
@@ -1626,7 +1629,7 @@ static void usb_mtp_write_data(MTPState *s)
MTPObject *parent =
usb_mtp_object_lookup(s, s->dataset.parent_handle);
char *path = NULL;
- int rc = -1;
+ uint64_t rc;
mode_t mask = 0644;
assert(d != NULL);
@@ -1643,7 +1646,7 @@ static void usb_mtp_write_data(MTPState *s)
d->fd = mkdir(path, mask);
goto free;
}
- if (s->dataset.size < d->length) {
+ if ((s->dataset.size != 0xFFFFFFFF) && (s->dataset.size < d->length)) {
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
0, 0, 0, 0);
goto done;
@@ -1754,13 +1757,27 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
usb_mtp_realloc(d, total_len);
d->length += total_len;
d->offset = 0;
+ d->cached_length = total_len;
d->first = false;
+ d->pending = false;
+ }
+
+ if (d->pending) {
+ usb_mtp_realloc(d, d->cached_length);
+ d->length += d->cached_length;
+ d->pending = false;
}
if (d->length - d->offset > data_len) {
dlen = data_len;
} else {
dlen = d->length - d->offset;
+ /* Check for cached data for large files */
+ if ((s->dataset.size == 0xFFFFFFFF) && (dlen < p->iov.size)) {
+ usb_mtp_realloc(d, p->iov.size - dlen);
+ d->length += p->iov.size - dlen;
+ dlen = p->iov.size;
+ }
}
switch (d->code) {
@@ -1780,12 +1797,18 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
case CMD_SEND_OBJECT:
usb_packet_copy(p, d->data + d->offset, dlen);
d->offset += dlen;
- if (d->offset == d->length) {
+ if ((p->iov.size % 64) || !p->iov.size) {
+ assert((s->dataset.size == 0xFFFFFFFF) ||
+ (s->dataset.size == d->length));
+
usb_mtp_write_data(s);
usb_mtp_data_free(s->data_out);
s->data_out = NULL;
return;
}
+ if (d->offset == d->length) {
+ d->pending = true;
+ }
break;
default:
p->status = USB_RET_STALL;
--
2.14.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 5/5] dev-mtp: rename x-root to rootdir
2018-07-20 21:40 [Qemu-devel] [PATCH 0/5] usb-mtp write fixes Bandan Das
` (3 preceding siblings ...)
2018-07-20 21:40 ` [Qemu-devel] [PATCH 4/5] dev-mtp: Add support for > 4GB file transfers Bandan Das
@ 2018-07-20 21:40 ` Bandan Das
4 siblings, 0 replies; 9+ messages in thread
From: Bandan Das @ 2018-07-20 21:40 UTC (permalink / raw)
To: qemu-devel; +Cc: kraxel
x-root was renamed as such owing to the experimental nature of the
property; the underlying filesystem semantics were undecided
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 2e3ea58da6..3fdc4b0da1 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -2018,7 +2018,7 @@ static void usb_mtp_realize(USBDevice *dev, Error **errp)
QTAILQ_INIT(&s->objects);
if (s->desc == NULL) {
if (s->root == NULL) {
- error_setg(errp, "usb-mtp: x-root property must be configured");
+ error_setg(errp, "usb-mtp: rootdir property must be configured");
return;
}
s->desc = strrchr(s->root, '/');
@@ -2047,7 +2047,7 @@ static const VMStateDescription vmstate_usb_mtp = {
};
static Property mtp_properties[] = {
- DEFINE_PROP_STRING("x-root", MTPState, root),
+ DEFINE_PROP_STRING("rootdir", MTPState, root),
DEFINE_PROP_STRING("desc", MTPState, desc),
DEFINE_PROP_BOOL("readonly", MTPState, readonly, true),
DEFINE_PROP_END_OF_LIST(),
--
2.14.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers
2018-07-20 21:40 ` [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers Bandan Das
@ 2018-08-07 13:28 ` Gerd Hoffmann
2018-08-07 18:15 ` Bandan Das
2018-10-19 9:48 ` Thomas Huth
1 sibling, 1 reply; 9+ messages in thread
From: Gerd Hoffmann @ 2018-08-07 13:28 UTC (permalink / raw)
To: Bandan Das; +Cc: qemu-devel
On Fri, Jul 20, 2018 at 05:40:18PM -0400, Bandan Das wrote:
> For large buffers, write may not copy the full buffer. For example,
> on Linux, write imposes a limit of 0x7ffff000. Note that this does
> not fix >4G transfers but ~>2G files will transfer successfully.
Hmm, I guess it would be a good idea to write the file in smaller
pieces, so we don't need a 2G host buffer to let the guest write
a 2G file ...
(as incremental improvement on top of this series).
cheers,
Gerd
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers
2018-08-07 13:28 ` Gerd Hoffmann
@ 2018-08-07 18:15 ` Bandan Das
0 siblings, 0 replies; 9+ messages in thread
From: Bandan Das @ 2018-08-07 18:15 UTC (permalink / raw)
To: Gerd Hoffmann; +Cc: qemu-devel
Gerd Hoffmann <kraxel@redhat.com> writes:
> On Fri, Jul 20, 2018 at 05:40:18PM -0400, Bandan Das wrote:
>> For large buffers, write may not copy the full buffer. For example,
>> on Linux, write imposes a limit of 0x7ffff000. Note that this does
>> not fix >4G transfers but ~>2G files will transfer successfully.
>
> Hmm, I guess it would be a good idea to write the file in smaller
> pieces, so we don't need a 2G host buffer to let the guest write
> a 2G file ...
>
> (as incremental improvement on top of this series).
>
Sounds good, I will add this to my todo list.
> cheers,
> Gerd
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers
2018-07-20 21:40 ` [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers Bandan Das
2018-08-07 13:28 ` Gerd Hoffmann
@ 2018-10-19 9:48 ` Thomas Huth
1 sibling, 0 replies; 9+ messages in thread
From: Thomas Huth @ 2018-10-19 9:48 UTC (permalink / raw)
To: Bandan Das, qemu-devel; +Cc: kraxel
On 2018-07-20 23:40, Bandan Das wrote:
> For large buffers, write may not copy the full buffer. For example,
> on Linux, write imposes a limit of 0x7ffff000. Note that this does
> not fix >4G transfers but ~>2G files will transfer successfully.
>
> Signed-off-by: Bandan Das <bsd@redhat.com>
> ---
> hw/usb/dev-mtp.c | 22 ++++++++++++++++++++--
> 1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
> index 1b72603dc5..c8f6eb4e9e 100644
> --- a/hw/usb/dev-mtp.c
> +++ b/hw/usb/dev-mtp.c
> @@ -1602,6 +1602,24 @@ static void utf16_to_str(uint8_t len, uint16_t *arr, char *name)
> g_free(wstr);
> }
>
> +/* Wrapper around write, returns 0 on failure */
> +static uint64_t write_retry(int fd, void *buf, uint64_t size)
> +{
> + uint64_t bytes_left = size, ret;
> +
> + while (bytes_left > 0) {
> + ret = write(fd, buf, bytes_left);
> + if ((ret == -1) && (errno != EINTR || errno != EAGAIN ||
> + errno != EWOULDBLOCK)) {
Someone opened a bug ticket about this here:
https://bugs.launchpad.net/qemu/+bug/1798780
The check looks wrong, indeed - either "!=" should be "==" or "||"
should be "&&" here ?
Thomas
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-10-19 9:48 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-20 21:40 [Qemu-devel] [PATCH 0/5] usb-mtp write fixes Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 1/5] dev-mtp: add support for canceling transaction Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 2/5] dev-mtp: fix buffer allocation for writing file contents Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 3/5] dev-mtp: retry write for incomplete transfers Bandan Das
2018-08-07 13:28 ` Gerd Hoffmann
2018-08-07 18:15 ` Bandan Das
2018-10-19 9:48 ` Thomas Huth
2018-07-20 21:40 ` [Qemu-devel] [PATCH 4/5] dev-mtp: Add support for > 4GB file transfers Bandan Das
2018-07-20 21:40 ` [Qemu-devel] [PATCH 5/5] dev-mtp: rename x-root to rootdir Bandan Das
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.