To support adding/removal of objects, we will need to update the object cache hierarchy we have built internally. Convert to using a Qlist for easier management.
Signed-off-by: Bandan Das <b...@redhat.com> --- hw/usb/dev-mtp.c | 67 +++++++++++++++++++++++++++++++++++++------------------- trace-events | 1 + 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 809b1cb..37dfa13 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -109,8 +109,9 @@ struct MTPObject { char *path; struct stat stat; MTPObject *parent; - MTPObject **children; uint32_t nchildren; + QLIST_HEAD(, MTPObject) children; + QLIST_ENTRY(MTPObject) list; bool have_children; QTAILQ_ENTRY(MTPObject) next; }; @@ -317,18 +318,24 @@ ignore: static void usb_mtp_object_free(MTPState *s, MTPObject *o) { - int i; + MTPObject *iter; + + if (o) { + trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path); - trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path); + QTAILQ_REMOVE(&s->objects, o, next); + if (o->parent) { + QLIST_REMOVE(o, list); + o->parent->nchildren--; + } - QTAILQ_REMOVE(&s->objects, o, next); - for (i = 0; i < o->nchildren; i++) { - usb_mtp_object_free(s, o->children[i]); + QLIST_FOREACH(iter, &o->children, list) { + usb_mtp_object_free(s, iter); + } + g_free(o->name); + g_free(o->path); + g_free(o); } - g_free(o->children); - g_free(o->name); - g_free(o->path); - g_free(o); } static MTPObject *usb_mtp_object_lookup(MTPState *s, uint32_t handle) @@ -343,6 +350,26 @@ static MTPObject *usb_mtp_object_lookup(MTPState *s, uint32_t handle) return NULL; } +static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject *o, + char *name) +{ + MTPObject *child = + usb_mtp_object_alloc(s, s->next_handle++, o, name); + + if (child) { + trace_usb_mtp_add_child(s->dev.addr, child->handle, child->path); + QLIST_INSERT_HEAD(&o->children, child, list); + o->nchildren++; + + if (child->format == FMT_ASSOCIATION) { + QLIST_INIT(&child->children); + } + + } + + return child; +} + static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) { struct dirent *entry; @@ -358,16 +385,9 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) return; } while ((entry = readdir(dir)) != NULL) { - if ((o->nchildren % 32) == 0) { - o->children = g_realloc(o->children, - (o->nchildren + 32) * sizeof(MTPObject *)); - } - o->children[o->nchildren] = - usb_mtp_object_alloc(s, s->next_handle++, o, entry->d_name); - if (o->children[o->nchildren] != NULL) { - o->nchildren++; - } + usb_mtp_add_child(s, o, entry->d_name); } + closedir(dir); } @@ -618,13 +638,15 @@ static MTPData *usb_mtp_get_object_handles(MTPState *s, MTPControl *c, MTPObject *o) { MTPData *d = usb_mtp_data_alloc(c); - uint32_t i, handles[o->nchildren]; + uint32_t i = 0, handles[o->nchildren]; + MTPObject *iter; trace_usb_mtp_op_get_object_handles(s->dev.addr, o->handle, o->path); - for (i = 0; i < o->nchildren; i++) { - handles[i] = o->children[i]->handle; + QLIST_FOREACH(iter, &o->children, list) { + handles[i++] = iter->handle; } + assert(i == o->nchildren); usb_mtp_add_u32_array(d, o->nchildren, handles); return d; @@ -885,6 +907,7 @@ static void usb_mtp_handle_reset(USBDevice *dev) trace_usb_mtp_reset(s->dev.addr); + usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); s->session = 0; usb_mtp_data_free(s->data_in); s->data_in = NULL; diff --git a/trace-events b/trace-events index 72136b9..ba4473d 100644 --- a/trace-events +++ b/trace-events @@ -552,6 +552,7 @@ usb_mtp_op_get_partial_object(int dev, uint32_t handle, const char *path, uint32 usb_mtp_op_unknown(int dev, uint32_t code) "dev %d, command code 0x%x" usb_mtp_object_alloc(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s" usb_mtp_object_free(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s" +usb_mtp_add_child(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s" # hw/usb/host-libusb.c usb_host_open_started(int bus, int addr) "dev %d:%d" -- 2.4.3