The internal inotify APIs allow alot of conditional statements to be cleared out, and provide a simpler callback for handling events.
Signed-off-by: Daniel P. Berrangé <berra...@redhat.com> --- hw/usb/dev-mtp.c | 238 +++++++++++++++++++---------------------------- 1 file changed, 97 insertions(+), 141 deletions(-) diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 560c61c7c1..d7188b2b62 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -15,13 +15,11 @@ #include <dirent.h> #include <sys/statvfs.h> -#ifdef CONFIG_INOTIFY1 -#include <sys/inotify.h> -#include "qemu/main-loop.h" -#endif + #include "qemu-common.h" #include "qemu/iov.h" +#include "qemu/inotify.h" #include "trace.h" #include "hw/usb.h" #include "desc.h" @@ -123,7 +121,6 @@ enum { EP_EVENT, }; -#ifdef CONFIG_INOTIFY1 typedef struct MTPMonEntry MTPMonEntry; struct MTPMonEntry { @@ -132,7 +129,6 @@ struct MTPMonEntry { QTAILQ_ENTRY(MTPMonEntry) next; }; -#endif struct MTPControl { uint16_t code; @@ -158,10 +154,8 @@ struct MTPObject { char *name; char *path; struct stat stat; -#ifdef CONFIG_INOTIFY1 /* inotify watch cookie */ int watchfd; -#endif MTPObject *parent; uint32_t nchildren; QLIST_HEAD(, MTPObject) children; @@ -184,11 +178,8 @@ struct MTPState { bool readonly; QTAILQ_HEAD(, MTPObject) objects; -#ifdef CONFIG_INOTIFY1 - /* inotify descriptor */ - int inotifyfd; + QInotify *inotify; QTAILQ_HEAD(events, MTPMonEntry) events; -#endif /* Responder is expecting a write operation */ bool write_pending; struct { @@ -368,7 +359,7 @@ static const USBDesc desc = { /* ----------------------------------------------------------------------- */ static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle, - MTPObject *parent, char *name) + MTPObject *parent, const char *name) { MTPObject *o = g_new0(MTPObject, 1); @@ -450,7 +441,7 @@ static MTPObject *usb_mtp_object_lookup(MTPState *s, uint32_t handle) } static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject *o, - char *name) + const char *name) { MTPObject *child = usb_mtp_object_alloc(s, s->next_handle++, o, name); @@ -469,10 +460,14 @@ static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject *o, } static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent, - char *name, int len) + const char *name, int len) { MTPObject *iter; + if (len == -1) { + len = strlen(name); + } + QLIST_FOREACH(iter, &parent->children, list) { if (strncmp(iter->name, name, len) == 0) { return iter; @@ -482,7 +477,6 @@ static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent, return NULL; } -#ifdef CONFIG_INOTIFY1 static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd) { MTPObject *iter; @@ -496,126 +490,100 @@ static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd) return NULL; } -static void inotify_watchfn(void *arg) +static void inotify_watchfn(int wd, + uint32_t mask, + const char *name, + void *opaque) { - MTPState *s = arg; - ssize_t bytes; - /* From the man page: atleast one event can be read */ - int pos; - char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; - - for (;;) { - bytes = read(s->inotifyfd, buf, sizeof(buf)); - pos = 0; - - if (bytes <= 0) { - /* Better luck next time */ + MTPState *s = opaque; + int watchfd = 0; + MTPObject *parent = usb_mtp_object_lookup_wd(s, wd); + MTPMonEntry *entry = NULL; + MTPObject *o; + + mask &= (IN_CREATE | IN_DELETE | + IN_MODIFY | IN_IGNORED); + + if (!parent) { + return; + } + + switch (mask) { + case IN_CREATE: + if (usb_mtp_object_lookup_name(parent, name, -1)) { + /* Duplicate create event */ + return; + } + entry = g_new0(MTPMonEntry, 1); + entry->handle = s->next_handle; + entry->event = EVT_OBJ_ADDED; + o = usb_mtp_add_child(s, parent, name); + if (!o) { + g_free(entry); return; } + o->watchfd = watchfd; + trace_usb_mtp_inotify_event(s->dev.addr, name, + mask, "Obj Added"); + break; + case IN_DELETE: /* - * TODO: Ignore initiator initiated events. - * For now we are good because the store is RO + * The kernel issues a IN_IGNORED event + * when a dir containing a watchpoint is + * deleted, so we don't have to delete the + * watchpoint */ - while (bytes > 0) { - char *p = buf + pos; - struct inotify_event *event = (struct inotify_event *)p; - int watchfd = 0; - uint32_t mask = event->mask & (IN_CREATE | IN_DELETE | - IN_MODIFY | IN_IGNORED); - MTPObject *parent = usb_mtp_object_lookup_wd(s, event->wd); - MTPMonEntry *entry = NULL; - MTPObject *o; - - pos = pos + sizeof(struct inotify_event) + event->len; - bytes = bytes - pos; - - if (!parent) { - continue; - } - - switch (mask) { - case IN_CREATE: - if (usb_mtp_object_lookup_name - (parent, event->name, event->len)) { - /* Duplicate create event */ - continue; - } - entry = g_new0(MTPMonEntry, 1); - entry->handle = s->next_handle; - entry->event = EVT_OBJ_ADDED; - o = usb_mtp_add_child(s, parent, event->name); - if (!o) { - g_free(entry); - continue; - } - o->watchfd = watchfd; - trace_usb_mtp_inotify_event(s->dev.addr, event->name, - event->mask, "Obj Added"); - break; - - case IN_DELETE: - /* - * The kernel issues a IN_IGNORED event - * when a dir containing a watchpoint is - * deleted, so we don't have to delete the - * watchpoint - */ - o = usb_mtp_object_lookup_name(parent, event->name, event->len); - if (!o) { - continue; - } - entry = g_new0(MTPMonEntry, 1); - entry->handle = o->handle; - entry->event = EVT_OBJ_REMOVED; - trace_usb_mtp_inotify_event(s->dev.addr, o->path, - event->mask, "Obj Deleted"); - usb_mtp_object_free(s, o); - break; - - case IN_MODIFY: - o = usb_mtp_object_lookup_name(parent, event->name, event->len); - if (!o) { - continue; - } - entry = g_new0(MTPMonEntry, 1); - entry->handle = o->handle; - entry->event = EVT_OBJ_INFO_CHANGED; - trace_usb_mtp_inotify_event(s->dev.addr, o->path, - event->mask, "Obj Modified"); - break; - - case IN_IGNORED: - trace_usb_mtp_inotify_event(s->dev.addr, parent->path, - event->mask, "Obj parent dir ignored"); - break; - - default: - fprintf(stderr, "usb-mtp: failed to parse inotify event\n"); - continue; - } + o = usb_mtp_object_lookup_name(parent, name, -1); + if (!o) { + return; + } + entry = g_new0(MTPMonEntry, 1); + entry->handle = o->handle; + entry->event = EVT_OBJ_REMOVED; + trace_usb_mtp_inotify_event(s->dev.addr, o->path, + mask, "Obj Deleted"); + usb_mtp_object_free(s, o); + break; - if (entry) { - QTAILQ_INSERT_HEAD(&s->events, entry, next); - } + case IN_MODIFY: + o = usb_mtp_object_lookup_name(parent, name, -1); + if (!o) { + return; } + entry = g_new0(MTPMonEntry, 1); + entry->handle = o->handle; + entry->event = EVT_OBJ_INFO_CHANGED; + trace_usb_mtp_inotify_event(s->dev.addr, o->path, + mask, "Obj Modified"); + break; + + case IN_IGNORED: + trace_usb_mtp_inotify_event(s->dev.addr, parent->path, + mask, "Obj parent dir ignored"); + break; + + default: + fprintf(stderr, "usb-mtp: failed to parse inotify event\n"); + return; + } + + if (entry) { + QTAILQ_INSERT_HEAD(&s->events, entry, next); } } static int usb_mtp_inotify_init(MTPState *s) { - int fd; - - fd = inotify_init1(IN_NONBLOCK); - if (fd == -1) { + s->inotify = qemu_inotify_new(inotify_watchfn, + s, + NULL, + &error_abort); + if (!s->inotify) { return 1; } QTAILQ_INIT(&s->events); - s->inotifyfd = fd; - - qemu_set_fd_handler(fd, inotify_watchfn, NULL, s); - return 0; } @@ -623,12 +591,7 @@ static void usb_mtp_inotify_cleanup(MTPState *s) { MTPMonEntry *e, *p; - if (!s->inotifyfd) { - return; - } - - qemu_set_fd_handler(s->inotifyfd, NULL, NULL, s); - close(s->inotifyfd); + qemu_inotify_free(s->inotify); QTAILQ_FOREACH_SAFE(e, &s->events, next, p) { QTAILQ_REMOVE(&s->events, e, next); @@ -636,14 +599,17 @@ static void usb_mtp_inotify_cleanup(MTPState *s) } } -static int usb_mtp_add_watch(int inotifyfd, char *path) +static int usb_mtp_add_watch(MTPState *s, char *path) { +#ifdef CONFIG_INOTIFY1 uint32_t mask = IN_CREATE | IN_DELETE | IN_MODIFY | IN_ISDIR; - return inotify_add_watch(inotifyfd, path, mask); -} + return qemu_inotify_add_watch(s->inotify, path, mask, NULL); +#else + return -1; #endif +} static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) { @@ -659,8 +625,8 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) if (!dir) { return; } -#ifdef CONFIG_INOTIFY1 - int watchfd = usb_mtp_add_watch(s->inotifyfd, o->path); + + int watchfd = usb_mtp_add_watch(s, o->path); if (watchfd == -1) { fprintf(stderr, "usb-mtp: failed to add watch for %s\n", o->path); } else { @@ -668,7 +634,7 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) 0, "Watch Added"); o->watchfd = watchfd; } -#endif + while ((entry = readdir(dir)) != NULL) { usb_mtp_add_child(s, o, entry->d_name); } @@ -1172,13 +1138,11 @@ enum { /* Assumes that children, if any, have been already freed */ static void usb_mtp_object_free_one(MTPState *s, MTPObject *o) { -#ifndef CONFIG_INOTIFY1 assert(o->nchildren == 0); QTAILQ_REMOVE(&s->objects, o, next); g_free(o->name); g_free(o->path); g_free(o); -#endif } static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans) @@ -1304,19 +1268,15 @@ static void usb_mtp_command(MTPState *s, MTPControl *c) trace_usb_mtp_op_open_session(s->dev.addr); s->session = c->argv[0]; usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root); -#ifdef CONFIG_INOTIFY1 if (usb_mtp_inotify_init(s)) { fprintf(stderr, "usb-mtp: file monitoring init failed\n"); } -#endif break; case CMD_CLOSE_SESSION: trace_usb_mtp_op_close_session(s->dev.addr); s->session = 0; s->next_handle = 0; -#ifdef CONFIG_INOTIFY1 usb_mtp_inotify_cleanup(s); -#endif usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); assert(QTAILQ_EMPTY(&s->objects)); break; @@ -1529,9 +1489,7 @@ static void usb_mtp_handle_reset(USBDevice *dev) trace_usb_mtp_reset(s->dev.addr); -#ifdef CONFIG_INOTIFY1 usb_mtp_inotify_cleanup(s); -#endif usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); s->session = 0; usb_mtp_data_free(s->data_in); @@ -1891,7 +1849,6 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) } break; case EP_EVENT: -#ifdef CONFIG_INOTIFY1 if (!QTAILQ_EMPTY(&s->events)) { struct MTPMonEntry *e = QTAILQ_LAST(&s->events, events); uint32_t handle; @@ -1915,7 +1872,6 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) g_free(e); return; } -#endif p->status = USB_RET_NAK; return; default: -- 2.17.0