filemon: various fixes / improvements to file monitor for USB MTP
Ensure watch IDs unique within a monitor and avoid integer wraparound issues when many watches are set & unset over time. -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJco1tUAAoJEL6G67QVEE/f9xYP/2OTsAk6dHCcWqc///jXN0JW OLcnpmjuh5KgUmOrs7NIRYRo2DARrhNDDXckHjDuX2HmnzoTB5p7DXLWMPgAzxj6 o83yxYT0Qqw79wxqbDmJ1y3kUVka1r94wCmmvUmxQZjLbDk8u2ytNUDbEOVlM0VJ R7T800j8PhbY1pg9PiJJZonm7dxZAVNSCF4AgkrJVIes6MqhvNUhVsck5q/CC3yi 0jkglsiVTyXjKpJsioM9VhQXeqiHfFl3qjcPi0XQ99lVpTMFysNd4UdnVXhNs9NI Xe52yQ7NG3fEggUivtFBmvVplNOg09K6U2vkyk9z8S1WTLZsbabwvwSvkVPW3Ty0 QaDgI6wNSiBb7Lfl2bbUR6X3j9QXUn8bhlczBsorS4uU4+NdHGyERsZLKLZazYYz 5t+xm4YBGJhtlt8IglNBjtaJFBuqgjrBEuBkfpevB2ocioWnU6APOdwWkKlSe3+r EuKFUcbhRiRAGO05DjntNkePigb66IVkSiJXd4uSid/+akn5kQ19PSD8tXdfvZ7h 8HYTnWZa3OSLd7tZlwRzimnKuVSIsSnj+NobkIs8HSS3N7oN1t4FC5jH9D6GmK0R djQs6a5mHQbonrc0dXxlb+P8u6I+ppxznPpfL/aQJ4pFM18V6gmcZEQluhwALNe9 rdPUnCudC/9SUNpMf3rI =qriK -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/berrange/tags/filemon-next-pull-request' into staging filemon: various fixes / improvements to file monitor for USB MTP Ensure watch IDs unique within a monitor and avoid integer wraparound issues when many watches are set & unset over time. # gpg: Signature made Tue 02 Apr 2019 13:53:40 BST # gpg: using RSA key BE86EBB415104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [full] # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" [full] # Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF * remotes/berrange/tags/filemon-next-pull-request: filemon: fix watch IDs to avoid potential wraparound issues filemon: ensure watch IDs are unique to QFileMonitor scope tests: refactor file monitor test to make it more understandable Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
436960c959
@ -93,7 +93,7 @@ qauthz_list_file_load(QAuthZListFile *fauthz, Error **errp)
|
||||
|
||||
|
||||
static void
|
||||
qauthz_list_file_event(int wd G_GNUC_UNUSED,
|
||||
qauthz_list_file_event(int64_t wd G_GNUC_UNUSED,
|
||||
QFileMonitorEvent ev G_GNUC_UNUSED,
|
||||
const char *name G_GNUC_UNUSED,
|
||||
void *opaque)
|
||||
|
@ -170,7 +170,7 @@ struct MTPObject {
|
||||
char *path;
|
||||
struct stat stat;
|
||||
/* file monitor watch id */
|
||||
int watchid;
|
||||
int64_t watchid;
|
||||
MTPObject *parent;
|
||||
uint32_t nchildren;
|
||||
QLIST_HEAD(, MTPObject) children;
|
||||
@ -498,7 +498,7 @@ static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MTPObject *usb_mtp_object_lookup_id(MTPState *s, int id)
|
||||
static MTPObject *usb_mtp_object_lookup_id(MTPState *s, int64_t id)
|
||||
{
|
||||
MTPObject *iter;
|
||||
|
||||
@ -511,7 +511,7 @@ static MTPObject *usb_mtp_object_lookup_id(MTPState *s, int id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void file_monitor_event(int id,
|
||||
static void file_monitor_event(int64_t id,
|
||||
QFileMonitorEvent ev,
|
||||
const char *name,
|
||||
void *opaque)
|
||||
@ -625,8 +625,8 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
|
||||
}
|
||||
|
||||
if (s->file_monitor) {
|
||||
int id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL,
|
||||
file_monitor_event, s, &err);
|
||||
int64_t id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL,
|
||||
file_monitor_event, s, &err);
|
||||
if (id == -1) {
|
||||
error_report("usb-mtp: failed to add watch for %s: %s", o->path,
|
||||
error_get_pretty(err));
|
||||
|
@ -92,7 +92,7 @@ struct QAuthZListFile {
|
||||
char *filename;
|
||||
bool refresh;
|
||||
QFileMonitor *file_monitor;
|
||||
int file_watch;
|
||||
int64_t file_watch;
|
||||
};
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@ typedef enum {
|
||||
* empty.
|
||||
*
|
||||
*/
|
||||
typedef void (*QFileMonitorHandler)(int id,
|
||||
typedef void (*QFileMonitorHandler)(int64_t id,
|
||||
QFileMonitorEvent event,
|
||||
const char *filename,
|
||||
void *opaque);
|
||||
@ -103,12 +103,12 @@ void qemu_file_monitor_free(QFileMonitor *mon);
|
||||
*
|
||||
* Returns: a positive integer watch ID, or -1 on error
|
||||
*/
|
||||
int qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
const char *filename,
|
||||
QFileMonitorHandler cb,
|
||||
void *opaque,
|
||||
Error **errp);
|
||||
int64_t qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
const char *filename,
|
||||
QFileMonitorHandler cb,
|
||||
void *opaque,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_file_monitor_remove_watch:
|
||||
@ -123,6 +123,6 @@ int qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
*/
|
||||
void qemu_file_monitor_remove_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
int id);
|
||||
int64_t id);
|
||||
|
||||
#endif /* QEMU_FILE_MONITOR_H */
|
||||
|
@ -26,34 +26,29 @@
|
||||
#include <utime.h>
|
||||
|
||||
enum {
|
||||
QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
QFILE_MONITOR_TEST_OP_EVENT,
|
||||
QFILE_MONITOR_TEST_OP_CREATE,
|
||||
QFILE_MONITOR_TEST_OP_APPEND,
|
||||
QFILE_MONITOR_TEST_OP_TRUNC,
|
||||
QFILE_MONITOR_TEST_OP_RENAME,
|
||||
QFILE_MONITOR_TEST_OP_TOUCH,
|
||||
QFILE_MONITOR_TEST_OP_UNLINK,
|
||||
QFILE_MONITOR_TEST_OP_MKDIR,
|
||||
QFILE_MONITOR_TEST_OP_RMDIR,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
const char *filesrc;
|
||||
const char *filedst;
|
||||
int64_t *watchid;
|
||||
int eventid;
|
||||
} QFileMonitorTestOp;
|
||||
|
||||
typedef struct {
|
||||
const char *file;
|
||||
} QFileMonitorTestWatch;
|
||||
|
||||
typedef struct {
|
||||
gsize nwatches;
|
||||
const QFileMonitorTestWatch *watches;
|
||||
|
||||
gsize nops;
|
||||
const QFileMonitorTestOp *ops;
|
||||
} QFileMonitorTestPlan;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int64_t id;
|
||||
QFileMonitorEvent event;
|
||||
char *filename;
|
||||
} QFileMonitorTestRecord;
|
||||
@ -67,6 +62,7 @@ typedef struct {
|
||||
static QemuMutex evlock;
|
||||
static bool evstopping;
|
||||
static bool evrunning;
|
||||
static bool debug;
|
||||
|
||||
/*
|
||||
* Main function for a background thread that is
|
||||
@ -94,7 +90,7 @@ qemu_file_monitor_test_event_loop(void *opaque G_GNUC_UNUSED)
|
||||
* an ordered list of all events that it receives
|
||||
*/
|
||||
static void
|
||||
qemu_file_monitor_test_handler(int id,
|
||||
qemu_file_monitor_test_handler(int64_t id,
|
||||
QFileMonitorEvent event,
|
||||
const char *filename,
|
||||
void *opaque)
|
||||
@ -160,7 +156,7 @@ qemu_file_monitor_test_next_record(QFileMonitorTestData *data)
|
||||
*/
|
||||
static bool
|
||||
qemu_file_monitor_test_expect(QFileMonitorTestData *data,
|
||||
int id,
|
||||
int64_t id,
|
||||
QFileMonitorEvent event,
|
||||
const char *filename)
|
||||
{
|
||||
@ -170,13 +166,14 @@ qemu_file_monitor_test_expect(QFileMonitorTestData *data,
|
||||
rec = qemu_file_monitor_test_next_record(data);
|
||||
|
||||
if (!rec) {
|
||||
g_printerr("Missing event watch id %d event %d file %s\n",
|
||||
g_printerr("Missing event watch id %" PRIx64 " event %d file %s\n",
|
||||
id, event, filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id != rec->id) {
|
||||
g_printerr("Expected watch id %d but got %d\n", id, rec->id);
|
||||
g_printerr("Expected watch id %" PRIx64 " but got %" PRIx64 "\n",
|
||||
id, rec->id);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -200,9 +197,179 @@ qemu_file_monitor_test_expect(QFileMonitorTestData *data,
|
||||
|
||||
|
||||
static void
|
||||
test_file_monitor_events(const void *opaque)
|
||||
test_file_monitor_events(void)
|
||||
{
|
||||
const QFileMonitorTestPlan *plan = opaque;
|
||||
int64_t watch0 = 0;
|
||||
int64_t watch1 = 0;
|
||||
int64_t watch2 = 0;
|
||||
int64_t watch3 = 0;
|
||||
int64_t watch4 = 0;
|
||||
int64_t watch5 = 0;
|
||||
QFileMonitorTestOp ops[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
.filesrc = NULL, .watchid = &watch0 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
.filesrc = "one.txt", .watchid = &watch1 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
.filesrc = "two.txt", .watchid = &watch2 },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch1,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch2,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "three.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "three.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_UNLINK,
|
||||
.filesrc = "three.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "three.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_RENAME,
|
||||
.filesrc = "one.txt", .filedst = "two.txt" },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch1,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch2,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_APPEND,
|
||||
.filesrc = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_MODIFIED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch2,
|
||||
.eventid = QFILE_MONITOR_EVENT_MODIFIED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_TOUCH,
|
||||
.filesrc = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_ATTRIBUTES },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch2,
|
||||
.eventid = QFILE_MONITOR_EVENT_ATTRIBUTES },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
.filesrc = "one.txt", .watchid = &watch1 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
.filesrc = "one.txt", .watchid = &watch3 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch3,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
.filesrc = "one.txt", .watchid = &watch3 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_UNLINK,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_MKDIR,
|
||||
.filesrc = "fish", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "fish", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
.filesrc = "fish/", .watchid = &watch4 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_ADD_WATCH,
|
||||
.filesrc = "fish/one.txt", .watchid = &watch5 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "fish/one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch4,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch5,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
.filesrc = "fish/one.txt", .watchid = &watch5 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_RENAME,
|
||||
.filesrc = "fish/one.txt", .filedst = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "one.txt", .watchid = &watch4,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch2,
|
||||
.eventid = QFILE_MONITOR_EVENT_CREATED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_RMDIR,
|
||||
.filesrc = "fish", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "", .watchid = &watch4,
|
||||
.eventid = QFILE_MONITOR_EVENT_IGNORED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "fish", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
.filesrc = "fish", .watchid = &watch4 },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_UNLINK,
|
||||
.filesrc = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch0,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_EVENT,
|
||||
.filesrc = "two.txt", .watchid = &watch2,
|
||||
.eventid = QFILE_MONITOR_EVENT_DELETED },
|
||||
|
||||
|
||||
{ .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
.filesrc = "two.txt", .watchid = &watch2 },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_DEL_WATCH,
|
||||
.filesrc = NULL, .watchid = &watch0 },
|
||||
};
|
||||
Error *local_err = NULL;
|
||||
GError *gerr = NULL;
|
||||
QFileMonitor *mon = qemu_file_monitor_new(&local_err);
|
||||
@ -210,10 +377,11 @@ test_file_monitor_events(const void *opaque)
|
||||
GTimer *timer;
|
||||
gchar *dir = NULL;
|
||||
int err = -1;
|
||||
gsize i, j;
|
||||
gsize i;
|
||||
char *pathsrc = NULL;
|
||||
char *pathdst = NULL;
|
||||
QFileMonitorTestData data;
|
||||
GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal);
|
||||
|
||||
qemu_mutex_init(&data.lock);
|
||||
data.records = NULL;
|
||||
@ -248,34 +416,15 @@ test_file_monitor_events(const void *opaque)
|
||||
}
|
||||
|
||||
/*
|
||||
* First register all the directory / file watches
|
||||
* we're interested in seeing events against
|
||||
* Run through the operation sequence validating events
|
||||
* as we go
|
||||
*/
|
||||
for (i = 0; i < plan->nwatches; i++) {
|
||||
int watchid;
|
||||
watchid = qemu_file_monitor_add_watch(mon,
|
||||
dir,
|
||||
plan->watches[i].file,
|
||||
qemu_file_monitor_test_handler,
|
||||
&data,
|
||||
&local_err);
|
||||
if (watchid < 0) {
|
||||
g_printerr("Unable to add watch %s",
|
||||
error_get_pretty(local_err));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Now invoke all the file operations (create,
|
||||
* delete, rename, chmod, etc). These operations
|
||||
* will trigger the various file monitor events
|
||||
*/
|
||||
for (i = 0; i < plan->nops; i++) {
|
||||
const QFileMonitorTestOp *op = &(plan->ops[i]);
|
||||
for (i = 0; i < G_N_ELEMENTS(ops); i++) {
|
||||
const QFileMonitorTestOp *op = &(ops[i]);
|
||||
int fd;
|
||||
struct utimbuf ubuf;
|
||||
char *watchdir;
|
||||
const char *watchfile;
|
||||
|
||||
pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
|
||||
if (op->filedst) {
|
||||
@ -283,7 +432,75 @@ test_file_monitor_events(const void *opaque)
|
||||
}
|
||||
|
||||
switch (op->type) {
|
||||
case QFILE_MONITOR_TEST_OP_ADD_WATCH:
|
||||
if (debug) {
|
||||
g_printerr("Add watch %s %s\n",
|
||||
dir, op->filesrc);
|
||||
}
|
||||
if (op->filesrc && strchr(op->filesrc, '/')) {
|
||||
watchdir = g_strdup_printf("%s/%s", dir, op->filesrc);
|
||||
watchfile = strrchr(watchdir, '/');
|
||||
*(char *)watchfile = '\0';
|
||||
watchfile++;
|
||||
if (*watchfile == '\0') {
|
||||
watchfile = NULL;
|
||||
}
|
||||
} else {
|
||||
watchdir = g_strdup(dir);
|
||||
watchfile = op->filesrc;
|
||||
}
|
||||
*op->watchid =
|
||||
qemu_file_monitor_add_watch(mon,
|
||||
watchdir,
|
||||
watchfile,
|
||||
qemu_file_monitor_test_handler,
|
||||
&data,
|
||||
&local_err);
|
||||
g_free(watchdir);
|
||||
if (*op->watchid < 0) {
|
||||
g_printerr("Unable to add watch %s",
|
||||
error_get_pretty(local_err));
|
||||
goto cleanup;
|
||||
}
|
||||
if (debug) {
|
||||
g_printerr("Watch ID %" PRIx64 "\n", *op->watchid);
|
||||
}
|
||||
if (g_hash_table_contains(ids, op->watchid)) {
|
||||
g_printerr("Watch ID %" PRIx64 "already exists", *op->watchid);
|
||||
goto cleanup;
|
||||
}
|
||||
g_hash_table_add(ids, op->watchid);
|
||||
break;
|
||||
case QFILE_MONITOR_TEST_OP_DEL_WATCH:
|
||||
if (debug) {
|
||||
g_printerr("Del watch %s %" PRIx64 "\n", dir, *op->watchid);
|
||||
}
|
||||
if (op->filesrc && strchr(op->filesrc, '/')) {
|
||||
watchdir = g_strdup_printf("%s/%s", dir, op->filesrc);
|
||||
watchfile = strrchr(watchdir, '/');
|
||||
*(char *)watchfile = '\0';
|
||||
} else {
|
||||
watchdir = g_strdup(dir);
|
||||
}
|
||||
g_hash_table_remove(ids, op->watchid);
|
||||
qemu_file_monitor_remove_watch(mon,
|
||||
watchdir,
|
||||
*op->watchid);
|
||||
g_free(watchdir);
|
||||
break;
|
||||
case QFILE_MONITOR_TEST_OP_EVENT:
|
||||
if (debug) {
|
||||
g_printerr("Event id=%" PRIx64 " event=%d file=%s\n",
|
||||
*op->watchid, op->eventid, op->filesrc);
|
||||
}
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, *op->watchid, op->eventid, op->filesrc))
|
||||
goto cleanup;
|
||||
break;
|
||||
case QFILE_MONITOR_TEST_OP_CREATE:
|
||||
if (debug) {
|
||||
g_printerr("Create %s\n", pathsrc);
|
||||
}
|
||||
fd = open(pathsrc, O_WRONLY | O_CREAT, 0700);
|
||||
if (fd < 0) {
|
||||
g_printerr("Unable to create %s: %s",
|
||||
@ -294,6 +511,9 @@ test_file_monitor_events(const void *opaque)
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_APPEND:
|
||||
if (debug) {
|
||||
g_printerr("Append %s\n", pathsrc);
|
||||
}
|
||||
fd = open(pathsrc, O_WRONLY | O_APPEND, 0700);
|
||||
if (fd < 0) {
|
||||
g_printerr("Unable to open %s: %s",
|
||||
@ -311,6 +531,9 @@ test_file_monitor_events(const void *opaque)
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_TRUNC:
|
||||
if (debug) {
|
||||
g_printerr("Truncate %s\n", pathsrc);
|
||||
}
|
||||
if (truncate(pathsrc, 4) < 0) {
|
||||
g_printerr("Unable to truncate %s: %s",
|
||||
pathsrc, strerror(errno));
|
||||
@ -319,6 +542,9 @@ test_file_monitor_events(const void *opaque)
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_RENAME:
|
||||
if (debug) {
|
||||
g_printerr("Rename %s -> %s\n", pathsrc, pathdst);
|
||||
}
|
||||
if (rename(pathsrc, pathdst) < 0) {
|
||||
g_printerr("Unable to rename %s to %s: %s",
|
||||
pathsrc, pathdst, strerror(errno));
|
||||
@ -327,6 +553,9 @@ test_file_monitor_events(const void *opaque)
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_UNLINK:
|
||||
if (debug) {
|
||||
g_printerr("Unlink %s\n", pathsrc);
|
||||
}
|
||||
if (unlink(pathsrc) < 0) {
|
||||
g_printerr("Unable to unlink %s: %s",
|
||||
pathsrc, strerror(errno));
|
||||
@ -335,6 +564,9 @@ test_file_monitor_events(const void *opaque)
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_TOUCH:
|
||||
if (debug) {
|
||||
g_printerr("Touch %s\n", pathsrc);
|
||||
}
|
||||
ubuf.actime = 1024;
|
||||
ubuf.modtime = 1025;
|
||||
if (utime(pathsrc, &ubuf) < 0) {
|
||||
@ -344,6 +576,28 @@ test_file_monitor_events(const void *opaque)
|
||||
}
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_MKDIR:
|
||||
if (debug) {
|
||||
g_printerr("Mkdir %s\n", pathsrc);
|
||||
}
|
||||
if (mkdir(pathsrc, 0700) < 0) {
|
||||
g_printerr("Unable to mkdir %s: %s",
|
||||
pathsrc, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_RMDIR:
|
||||
if (debug) {
|
||||
g_printerr("Rmdir %s\n", pathsrc);
|
||||
}
|
||||
if (rmdir(pathsrc) < 0) {
|
||||
g_printerr("Unable to rmdir %s: %s",
|
||||
pathsrc, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
@ -353,91 +607,7 @@ test_file_monitor_events(const void *opaque)
|
||||
pathsrc = pathdst = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finally validate that we have received all the events
|
||||
* we expect to see for the combination of watches and
|
||||
* file operations
|
||||
*/
|
||||
for (i = 0; i < plan->nops; i++) {
|
||||
const QFileMonitorTestOp *op = &(plan->ops[i]);
|
||||
|
||||
switch (op->type) {
|
||||
case QFILE_MONITOR_TEST_OP_CREATE:
|
||||
for (j = 0; j < plan->nwatches; j++) {
|
||||
if (plan->watches[j].file &&
|
||||
!g_str_equal(plan->watches[j].file, op->filesrc))
|
||||
continue;
|
||||
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, j, QFILE_MONITOR_EVENT_CREATED, op->filesrc))
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_APPEND:
|
||||
case QFILE_MONITOR_TEST_OP_TRUNC:
|
||||
for (j = 0; j < plan->nwatches; j++) {
|
||||
if (plan->watches[j].file &&
|
||||
!g_str_equal(plan->watches[j].file, op->filesrc))
|
||||
continue;
|
||||
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, j, QFILE_MONITOR_EVENT_MODIFIED, op->filesrc))
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_RENAME:
|
||||
for (j = 0; j < plan->nwatches; j++) {
|
||||
if (plan->watches[j].file &&
|
||||
!g_str_equal(plan->watches[j].file, op->filesrc))
|
||||
continue;
|
||||
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, j, QFILE_MONITOR_EVENT_DELETED, op->filesrc))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (j = 0; j < plan->nwatches; j++) {
|
||||
if (plan->watches[j].file &&
|
||||
!g_str_equal(plan->watches[j].file, op->filedst))
|
||||
continue;
|
||||
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, j, QFILE_MONITOR_EVENT_CREATED, op->filedst))
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_TOUCH:
|
||||
for (j = 0; j < plan->nwatches; j++) {
|
||||
if (plan->watches[j].file &&
|
||||
!g_str_equal(plan->watches[j].file, op->filesrc))
|
||||
continue;
|
||||
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, j, QFILE_MONITOR_EVENT_ATTRIBUTES, op->filesrc))
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case QFILE_MONITOR_TEST_OP_UNLINK:
|
||||
for (j = 0; j < plan->nwatches; j++) {
|
||||
if (plan->watches[j].file &&
|
||||
!g_str_equal(plan->watches[j].file, op->filesrc))
|
||||
continue;
|
||||
|
||||
if (!qemu_file_monitor_test_expect(
|
||||
&data, j, QFILE_MONITOR_EVENT_DELETED, op->filesrc))
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
g_assert_cmpint(g_hash_table_size(ids), ==, 0);
|
||||
|
||||
err = 0;
|
||||
|
||||
@ -460,171 +630,42 @@ test_file_monitor_events(const void *opaque)
|
||||
}
|
||||
g_timer_destroy(timer);
|
||||
|
||||
for (i = 0; i < plan->nops; i++) {
|
||||
const QFileMonitorTestOp *op = &(plan->ops[i]);
|
||||
pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
|
||||
unlink(pathsrc);
|
||||
g_free(pathsrc);
|
||||
if (op->filedst) {
|
||||
pathdst = g_strdup_printf("%s/%s", dir, op->filedst);
|
||||
unlink(pathdst);
|
||||
g_free(pathdst);
|
||||
}
|
||||
}
|
||||
|
||||
qemu_file_monitor_free(mon);
|
||||
g_list_foreach(data.records,
|
||||
(GFunc)qemu_file_monitor_test_record_free, NULL);
|
||||
g_list_free(data.records);
|
||||
qemu_mutex_destroy(&data.lock);
|
||||
if (dir) {
|
||||
rmdir(dir);
|
||||
for (i = 0; i < G_N_ELEMENTS(ops); i++) {
|
||||
const QFileMonitorTestOp *op = &(ops[i]);
|
||||
char *path = g_strdup_printf("%s/%s",
|
||||
dir, op->filesrc);
|
||||
if (op->type == QFILE_MONITOR_TEST_OP_MKDIR) {
|
||||
rmdir(path);
|
||||
g_free(path);
|
||||
} else {
|
||||
unlink(path);
|
||||
g_free(path);
|
||||
if (op->filedst) {
|
||||
path = g_strdup_printf("%s/%s",
|
||||
dir, op->filedst);
|
||||
unlink(path);
|
||||
g_free(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rmdir(dir) < 0) {
|
||||
g_printerr("Failed to remove %s: %s\n",
|
||||
dir, strerror(errno));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
g_hash_table_unref(ids);
|
||||
g_free(dir);
|
||||
g_assert(err == 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set of structs which define which file name patterns
|
||||
* we're trying to watch against. NULL, means all files
|
||||
* in the directory
|
||||
*/
|
||||
static const QFileMonitorTestWatch watches_any[] = {
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const QFileMonitorTestWatch watches_one[] = {
|
||||
{ "one.txt" },
|
||||
};
|
||||
|
||||
static const QFileMonitorTestWatch watches_two[] = {
|
||||
{ "two.txt" },
|
||||
};
|
||||
|
||||
static const QFileMonitorTestWatch watches_many[] = {
|
||||
{ NULL },
|
||||
{ "one.txt" },
|
||||
{ "two.txt" },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Various sets of file operations we're going to
|
||||
* trigger and validate events for
|
||||
*/
|
||||
static const QFileMonitorTestOp ops_create_one[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", }
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_delete_one[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_UNLINK,
|
||||
.filesrc = "one.txt", }
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_create_many[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "three.txt", }
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_rename_one[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_RENAME,
|
||||
.filesrc = "one.txt", .filedst = "two.txt" }
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_rename_many[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "two.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_RENAME,
|
||||
.filesrc = "one.txt", .filedst = "two.txt" }
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_append_one[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_APPEND,
|
||||
.filesrc = "one.txt", },
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_trunc_one[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_TRUNC,
|
||||
.filesrc = "one.txt", },
|
||||
};
|
||||
|
||||
static const QFileMonitorTestOp ops_touch_one[] = {
|
||||
{ .type = QFILE_MONITOR_TEST_OP_CREATE,
|
||||
.filesrc = "one.txt", },
|
||||
{ .type = QFILE_MONITOR_TEST_OP_TOUCH,
|
||||
.filesrc = "one.txt", },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* No we define data sets for the combinatorial
|
||||
* expansion of file watches and operation sets
|
||||
*/
|
||||
#define PLAN_DATA(o, w) \
|
||||
static const QFileMonitorTestPlan plan_ ## o ## _ ## w = { \
|
||||
.nops = G_N_ELEMENTS(ops_ ##o), \
|
||||
.ops = ops_ ##o, \
|
||||
.nwatches = G_N_ELEMENTS(watches_ ##w), \
|
||||
.watches = watches_ ## w, \
|
||||
}
|
||||
|
||||
PLAN_DATA(create_one, any);
|
||||
PLAN_DATA(create_one, one);
|
||||
PLAN_DATA(create_one, two);
|
||||
PLAN_DATA(create_one, many);
|
||||
|
||||
PLAN_DATA(delete_one, any);
|
||||
PLAN_DATA(delete_one, one);
|
||||
PLAN_DATA(delete_one, two);
|
||||
PLAN_DATA(delete_one, many);
|
||||
|
||||
PLAN_DATA(create_many, any);
|
||||
PLAN_DATA(create_many, one);
|
||||
PLAN_DATA(create_many, two);
|
||||
PLAN_DATA(create_many, many);
|
||||
|
||||
PLAN_DATA(rename_one, any);
|
||||
PLAN_DATA(rename_one, one);
|
||||
PLAN_DATA(rename_one, two);
|
||||
PLAN_DATA(rename_one, many);
|
||||
|
||||
PLAN_DATA(rename_many, any);
|
||||
PLAN_DATA(rename_many, one);
|
||||
PLAN_DATA(rename_many, two);
|
||||
PLAN_DATA(rename_many, many);
|
||||
|
||||
PLAN_DATA(append_one, any);
|
||||
PLAN_DATA(append_one, one);
|
||||
PLAN_DATA(append_one, two);
|
||||
PLAN_DATA(append_one, many);
|
||||
|
||||
PLAN_DATA(trunc_one, any);
|
||||
PLAN_DATA(trunc_one, one);
|
||||
PLAN_DATA(trunc_one, two);
|
||||
PLAN_DATA(trunc_one, many);
|
||||
|
||||
PLAN_DATA(touch_one, any);
|
||||
PLAN_DATA(touch_one, one);
|
||||
PLAN_DATA(touch_one, two);
|
||||
PLAN_DATA(touch_one, many);
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
@ -633,53 +674,8 @@ int main(int argc, char **argv)
|
||||
|
||||
qemu_mutex_init(&evlock);
|
||||
|
||||
/*
|
||||
* Register test cases for the combinatorial
|
||||
* expansion of file watches and operation sets
|
||||
*/
|
||||
#define PLAN_REGISTER(o, w) \
|
||||
g_test_add_data_func("/util/filemonitor/" # o "/" # w, \
|
||||
&plan_ ## o ## _ ## w, test_file_monitor_events)
|
||||
|
||||
PLAN_REGISTER(create_one, any);
|
||||
PLAN_REGISTER(create_one, one);
|
||||
PLAN_REGISTER(create_one, two);
|
||||
PLAN_REGISTER(create_one, many);
|
||||
|
||||
PLAN_REGISTER(delete_one, any);
|
||||
PLAN_REGISTER(delete_one, one);
|
||||
PLAN_REGISTER(delete_one, two);
|
||||
PLAN_REGISTER(delete_one, many);
|
||||
|
||||
PLAN_REGISTER(create_many, any);
|
||||
PLAN_REGISTER(create_many, one);
|
||||
PLAN_REGISTER(create_many, two);
|
||||
PLAN_REGISTER(create_many, many);
|
||||
|
||||
PLAN_REGISTER(rename_one, any);
|
||||
PLAN_REGISTER(rename_one, one);
|
||||
PLAN_REGISTER(rename_one, two);
|
||||
PLAN_REGISTER(rename_one, many);
|
||||
|
||||
PLAN_REGISTER(rename_many, any);
|
||||
PLAN_REGISTER(rename_many, one);
|
||||
PLAN_REGISTER(rename_many, two);
|
||||
PLAN_REGISTER(rename_many, many);
|
||||
|
||||
PLAN_REGISTER(append_one, any);
|
||||
PLAN_REGISTER(append_one, one);
|
||||
PLAN_REGISTER(append_one, two);
|
||||
PLAN_REGISTER(append_one, many);
|
||||
|
||||
PLAN_REGISTER(trunc_one, any);
|
||||
PLAN_REGISTER(trunc_one, one);
|
||||
PLAN_REGISTER(trunc_one, two);
|
||||
PLAN_REGISTER(trunc_one, many);
|
||||
|
||||
PLAN_REGISTER(touch_one, any);
|
||||
PLAN_REGISTER(touch_one, one);
|
||||
PLAN_REGISTER(touch_one, two);
|
||||
PLAN_REGISTER(touch_one, many);
|
||||
debug = getenv("FILEMONITOR_DEBUG") != NULL;
|
||||
g_test_add_func("/util/filemonitor", test_file_monitor_events);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
struct QFileMonitor {
|
||||
int fd;
|
||||
|
||||
QemuMutex lock; /* protects dirs & idmap */
|
||||
GHashTable *dirs; /* dirname => QFileMonitorDir */
|
||||
GHashTable *idmap; /* inotify ID => dirname */
|
||||
@ -37,7 +36,7 @@ struct QFileMonitor {
|
||||
|
||||
|
||||
typedef struct {
|
||||
int id; /* watch ID */
|
||||
int64_t id; /* watch ID */
|
||||
char *filename; /* optional filter */
|
||||
QFileMonitorHandler cb;
|
||||
void *opaque;
|
||||
@ -46,8 +45,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
int id; /* inotify ID */
|
||||
int nextid; /* watch ID counter */
|
||||
int inotify_id; /* inotify ID */
|
||||
int next_file_id; /* file ID counter */
|
||||
GArray *watches; /* QFileMonitorWatch elements */
|
||||
} QFileMonitorDir;
|
||||
|
||||
@ -127,7 +126,8 @@ static void qemu_file_monitor_watch(void *arg)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
trace_qemu_file_monitor_event(mon, dir->path, name, ev->mask, dir->id);
|
||||
trace_qemu_file_monitor_event(mon, dir->path, name, ev->mask,
|
||||
dir->inotify_id);
|
||||
for (i = 0; i < dir->watches->len; i++) {
|
||||
QFileMonitorWatch *watch = &g_array_index(dir->watches,
|
||||
QFileMonitorWatch,
|
||||
@ -238,7 +238,7 @@ qemu_file_monitor_free(QFileMonitor *mon)
|
||||
g_idle_add((GSourceFunc)qemu_file_monitor_free_idle, mon);
|
||||
}
|
||||
|
||||
int
|
||||
int64_t
|
||||
qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
const char *filename,
|
||||
@ -248,7 +248,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
{
|
||||
QFileMonitorDir *dir;
|
||||
QFileMonitorWatch watch;
|
||||
int ret = -1;
|
||||
int64_t ret = -1;
|
||||
|
||||
qemu_mutex_lock(&mon->lock);
|
||||
dir = g_hash_table_lookup(mon->dirs, dirpath);
|
||||
@ -266,7 +266,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
|
||||
dir = g_new0(QFileMonitorDir, 1);
|
||||
dir->path = g_strdup(dirpath);
|
||||
dir->id = rv;
|
||||
dir->inotify_id = rv;
|
||||
dir->watches = g_array_new(FALSE, TRUE, sizeof(QFileMonitorWatch));
|
||||
|
||||
g_hash_table_insert(mon->dirs, dir->path, dir);
|
||||
@ -277,7 +277,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
}
|
||||
}
|
||||
|
||||
watch.id = dir->nextid++;
|
||||
watch.id = (((int64_t)dir->inotify_id) << 32) | dir->next_file_id++;
|
||||
watch.filename = g_strdup(filename);
|
||||
watch.cb = cb;
|
||||
watch.opaque = opaque;
|
||||
@ -298,7 +298,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
|
||||
void qemu_file_monitor_remove_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
int id)
|
||||
int64_t id)
|
||||
{
|
||||
QFileMonitorDir *dir;
|
||||
gsize i;
|
||||
@ -323,10 +323,10 @@ void qemu_file_monitor_remove_watch(QFileMonitor *mon,
|
||||
}
|
||||
|
||||
if (dir->watches->len == 0) {
|
||||
inotify_rm_watch(mon->fd, dir->id);
|
||||
trace_qemu_file_monitor_disable_watch(mon, dir->path, dir->id);
|
||||
inotify_rm_watch(mon->fd, dir->inotify_id);
|
||||
trace_qemu_file_monitor_disable_watch(mon, dir->path, dir->inotify_id);
|
||||
|
||||
g_hash_table_remove(mon->idmap, GINT_TO_POINTER(dir->id));
|
||||
g_hash_table_remove(mon->idmap, GINT_TO_POINTER(dir->inotify_id));
|
||||
g_hash_table_remove(mon->dirs, dir->path);
|
||||
|
||||
if (g_hash_table_size(mon->dirs) == 0) {
|
||||
|
@ -38,7 +38,7 @@ qemu_file_monitor_free(QFileMonitor *mon G_GNUC_UNUSED)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int64_t
|
||||
qemu_file_monitor_add_watch(QFileMonitor *mon G_GNUC_UNUSED,
|
||||
const char *dirpath G_GNUC_UNUSED,
|
||||
const char *filename G_GNUC_UNUSED,
|
||||
@ -54,6 +54,6 @@ qemu_file_monitor_add_watch(QFileMonitor *mon G_GNUC_UNUSED,
|
||||
void
|
||||
qemu_file_monitor_remove_watch(QFileMonitor *mon G_GNUC_UNUSED,
|
||||
const char *dirpath G_GNUC_UNUSED,
|
||||
int id G_GNUC_UNUSED)
|
||||
int64_t id G_GNUC_UNUSED)
|
||||
{
|
||||
}
|
||||
|
@ -22,13 +22,13 @@ buffer_move(const char *buf, size_t len, const char *from) "%s: %zd bytes from %
|
||||
buffer_free(const char *buf, size_t len) "%s: capacity %zd"
|
||||
|
||||
# filemonitor-inotify.c
|
||||
qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *filename, void *cb, void *opaque, int id) "File monitor %p add watch dir='%s' file='%s' cb=%p opaque=%p id=%u"
|
||||
qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int id) "File monitor %p remove watch dir='%s' id=%u"
|
||||
qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *filename, void *cb, void *opaque, int64_t id) "File monitor %p add watch dir='%s' file='%s' cb=%p opaque=%p id=%" PRId64
|
||||
qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int64_t id) "File monitor %p remove watch dir='%s' id=%" PRId64
|
||||
qemu_file_monitor_new(void *mon, int fd) "File monitor %p created fd=%d"
|
||||
qemu_file_monitor_enable_watch(void *mon, const char *dirpath, int id) "File monitor %p enable watch dir='%s' id=%u"
|
||||
qemu_file_monitor_disable_watch(void *mon, const char *dirpath, int id) "Fle monitor %p disable watch dir='%s' id=%u"
|
||||
qemu_file_monitor_event(void *mon, const char *dirpath, const char *filename, int mask, unsigned int id) "File monitor %p event dir='%s' file='%s' mask=0x%x id=%u"
|
||||
qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *filename, int ev, void *cb, void *opaque, unsigned int id) "File monitor %p dispatch dir='%s' file='%s' ev=%d cb=%p opaque=%p id=%u"
|
||||
qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *filename, int ev, void *cb, void *opaque, int64_t id) "File monitor %p dispatch dir='%s' file='%s' ev=%d cb=%p opaque=%p id=%" PRId64
|
||||
|
||||
# qemu-coroutine.c
|
||||
qemu_aio_coroutine_enter(void *ctx, void *from, void *to, void *opaque) "ctx %p from %p to %p opaque %p"
|
||||
|
Loading…
Reference in New Issue
Block a user