From nobody Wed May 1 23:13:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 155421076122447.1360725268097; Tue, 2 Apr 2019 06:12:41 -0700 (PDT) Received: from localhost ([127.0.0.1]:54079 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hBJDT-0007UO-Qs for importer@patchew.org; Tue, 02 Apr 2019 09:12:39 -0400 Received: from eggs.gnu.org ([209.51.188.92]:32817) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hBIw1-0007d5-Qy for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hBIvx-00041S-Iz for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33132) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hBIvv-0003x4-Jl for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:32 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DE0C1811DC for ; Tue, 2 Apr 2019 12:54:30 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-56.ams2.redhat.com [10.36.112.56]) by smtp.corp.redhat.com (Postfix) with ESMTP id 267826A486; Tue, 2 Apr 2019 12:54:25 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Date: Tue, 2 Apr 2019 13:54:15 +0100 Message-Id: <20190402125417.21573-2-berrange@redhat.com> In-Reply-To: <20190402125417.21573-1-berrange@redhat.com> References: <20190402125417.21573-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 02 Apr 2019 12:54:30 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 1/3] tests: refactor file monitor test to make it more understandable X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Bandan Das , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The current file monitor unit tests are too clever for their own good making it hard to understand the desired output. Instead of trying to infer the expected events, explicitly list the events we expect in the operation sequence. Instead of dynamically building a matrix of tests, just have one giant operation sequence that validates all scenarios in a single test. Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Daniel P. Berrang=C3=A9 --- tests/test-util-filemonitor.c | 534 +++++++++++++--------------------- 1 file changed, 208 insertions(+), 326 deletions(-) diff --git a/tests/test-util-filemonitor.c b/tests/test-util-filemonitor.c index 5d95cea5ee..ea3715a8f4 100644 --- a/tests/test-util-filemonitor.c +++ b/tests/test-util-filemonitor.c @@ -26,6 +26,9 @@ #include =20 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, @@ -38,20 +41,10 @@ typedef struct { int type; const char *filesrc; const char *filedst; + int watchid; + int eventid; } QFileMonitorTestOp; =20 -typedef struct { - const char *file; -} QFileMonitorTestWatch; - -typedef struct { - gsize nwatches; - const QFileMonitorTestWatch *watches; - - gsize nops; - const QFileMonitorTestOp *ops; -} QFileMonitorTestPlan; - typedef struct { int id; QFileMonitorEvent event; @@ -67,6 +60,7 @@ typedef struct { static QemuMutex evlock; static bool evstopping; static bool evrunning; +static bool debug; =20 /* * Main function for a background thread that is @@ -200,9 +194,125 @@ qemu_file_monitor_test_expect(QFileMonitorTestData *d= ata, =20 =20 static void -test_file_monitor_events(const void *opaque) +test_file_monitor_events(void) { - const QFileMonitorTestPlan *plan =3D opaque; + QFileMonitorTestOp ops[] =3D { + { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, + .filesrc =3D NULL, .watchid =3D 0 }, + { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, + .filesrc =3D "one.txt", .watchid =3D 1 }, + { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, + .filesrc =3D "two.txt", .watchid =3D 2 }, + + + { .type =3D QFILE_MONITOR_TEST_OP_CREATE, + .filesrc =3D "one.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 1, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_CREATE, + .filesrc =3D "two.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 2, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_CREATE, + .filesrc =3D "three.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "three.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, + .filesrc =3D "three.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "three.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_RENAME, + .filesrc =3D "one.txt", .filedst =3D "two.txt" }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 1, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 2, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_APPEND, + .filesrc =3D "two.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_MODIFIED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 2, + .eventid =3D QFILE_MONITOR_EVENT_MODIFIED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_TOUCH, + .filesrc =3D "two.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_ATTRIBUTES }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 2, + .eventid =3D QFILE_MONITOR_EVENT_ATTRIBUTES }, + + + { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, + .filesrc =3D "one.txt", .watchid =3D 1 }, + { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, + .filesrc =3D "one.txt", .watchid =3D 3 }, + { .type =3D QFILE_MONITOR_TEST_OP_CREATE, + .filesrc =3D "one.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 3, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, + .filesrc =3D "one.txt", .watchid =3D 3 }, + { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, + .filesrc =3D "one.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, + .filesrc =3D "two.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 2, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, + .filesrc =3D "two.txt", .watchid =3D 2 }, + { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, + .filesrc =3D NULL, .watchid =3D 0 }, + }; Error *local_err =3D NULL; GError *gerr =3D NULL; QFileMonitor *mon =3D qemu_file_monitor_new(&local_err); @@ -210,7 +320,7 @@ test_file_monitor_events(const void *opaque) GTimer *timer; gchar *dir =3D NULL; int err =3D -1; - gsize i, j; + gsize i; char *pathsrc =3D NULL; char *pathdst =3D NULL; QFileMonitorTestData data; @@ -248,33 +358,13 @@ test_file_monitor_events(const void *opaque) } =20 /* - * 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 =3D 0; i < plan->nwatches; i++) { - int watchid; - watchid =3D qemu_file_monitor_add_watch(mon, - dir, - plan->watches[i].file, - qemu_file_monitor_test_handl= er, - &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 =3D 0; i < plan->nops; i++) { - const QFileMonitorTestOp *op =3D &(plan->ops[i]); + for (i =3D 0; i < G_N_ELEMENTS(ops); i++) { + const QFileMonitorTestOp *op =3D &(ops[i]); int fd; + int watchid; struct utimbuf ubuf; =20 pathsrc =3D g_strdup_printf("%s/%s", dir, op->filesrc); @@ -283,7 +373,50 @@ test_file_monitor_events(const void *opaque) } =20 switch (op->type) { + case QFILE_MONITOR_TEST_OP_ADD_WATCH: + if (debug) { + g_printerr("Add watch %s %s %d\n", + dir, op->filesrc, op->watchid); + } + watchid =3D + qemu_file_monitor_add_watch(mon, + dir, + op->filesrc, + 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; + } + if (watchid !=3D op->watchid) { + g_printerr("Unexpected watch ID %d, wanted %d\n", + watchid, op->watchid); + goto cleanup; + } + break; + case QFILE_MONITOR_TEST_OP_DEL_WATCH: + if (debug) { + g_printerr("Del watch %s %d\n", dir, op->watchid); + } + qemu_file_monitor_remove_watch(mon, + dir, + op->watchid); + break; + case QFILE_MONITOR_TEST_OP_EVENT: + if (debug) { + g_printerr("Event id=3D%d event=3D%d file=3D%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 =3D open(pathsrc, O_WRONLY | O_CREAT, 0700); if (fd < 0) { g_printerr("Unable to create %s: %s", @@ -294,6 +427,9 @@ test_file_monitor_events(const void *opaque) break; =20 case QFILE_MONITOR_TEST_OP_APPEND: + if (debug) { + g_printerr("Append %s\n", pathsrc); + } fd =3D open(pathsrc, O_WRONLY | O_APPEND, 0700); if (fd < 0) { g_printerr("Unable to open %s: %s", @@ -311,6 +447,9 @@ test_file_monitor_events(const void *opaque) break; =20 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 +458,9 @@ test_file_monitor_events(const void *opaque) break; =20 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 +469,9 @@ test_file_monitor_events(const void *opaque) break; =20 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 +480,9 @@ test_file_monitor_events(const void *opaque) break; =20 case QFILE_MONITOR_TEST_OP_TOUCH: + if (debug) { + g_printerr("Touch %s\n", pathsrc); + } ubuf.actime =3D 1024; ubuf.modtime =3D 1025; if (utime(pathsrc, &ubuf) < 0) { @@ -353,92 +501,6 @@ test_file_monitor_events(const void *opaque) pathsrc =3D pathdst =3D NULL; } =20 - - /* - * Finally validate that we have received all the events - * we expect to see for the combination of watches and - * file operations - */ - for (i =3D 0; i < plan->nops; i++) { - const QFileMonitorTestOp *op =3D &(plan->ops[i]); - - switch (op->type) { - case QFILE_MONITOR_TEST_OP_CREATE: - for (j =3D 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 =3D 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->filesr= c)) - goto cleanup; - } - break; - - case QFILE_MONITOR_TEST_OP_RENAME: - for (j =3D 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 =3D 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 =3D 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->file= src)) - goto cleanup; - } - break; - - case QFILE_MONITOR_TEST_OP_UNLINK: - for (j =3D 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(); - } - } - err =3D 0; =20 cleanup: @@ -460,171 +522,36 @@ test_file_monitor_events(const void *opaque) } g_timer_destroy(timer); =20 - for (i =3D 0; i < plan->nops; i++) { - const QFileMonitorTestOp *op =3D &(plan->ops[i]); - pathsrc =3D g_strdup_printf("%s/%s", dir, op->filesrc); - unlink(pathsrc); - g_free(pathsrc); - if (op->filedst) { - pathdst =3D 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 =3D 0; i < G_N_ELEMENTS(ops); i++) { + const QFileMonitorTestOp *op =3D &(ops[i]); + char *path =3D g_strdup_printf("%s/%s", + dir, op->filesrc); + unlink(path); + g_free(path); + if (op->filedst) { + path =3D 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_free(dir); g_assert(err =3D=3D 0); } =20 =20 -/* - * 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[] =3D { - { NULL }, -}; - -static const QFileMonitorTestWatch watches_one[] =3D { - { "one.txt" }, -}; - -static const QFileMonitorTestWatch watches_two[] =3D { - { "two.txt" }, -}; - -static const QFileMonitorTestWatch watches_many[] =3D { - { 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[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", } -}; - -static const QFileMonitorTestOp ops_delete_one[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, - .filesrc =3D "one.txt", } -}; - -static const QFileMonitorTestOp ops_create_many[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "two.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "three.txt", } -}; - -static const QFileMonitorTestOp ops_rename_one[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_RENAME, - .filesrc =3D "one.txt", .filedst =3D "two.txt" } -}; - -static const QFileMonitorTestOp ops_rename_many[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "two.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_RENAME, - .filesrc =3D "one.txt", .filedst =3D "two.txt" } -}; - -static const QFileMonitorTestOp ops_append_one[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_APPEND, - .filesrc =3D "one.txt", }, -}; - -static const QFileMonitorTestOp ops_trunc_one[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_TRUNC, - .filesrc =3D "one.txt", }, -}; - -static const QFileMonitorTestOp ops_touch_one[] =3D { - { .type =3D QFILE_MONITOR_TEST_OP_CREATE, - .filesrc =3D "one.txt", }, - { .type =3D QFILE_MONITOR_TEST_OP_TOUCH, - .filesrc =3D "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 =3D { \ - .nops =3D G_N_ELEMENTS(ops_ ##o), \ - .ops =3D ops_ ##o, \ - .nwatches =3D G_N_ELEMENTS(watches_ ##w), \ - .watches =3D 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 +560,8 @@ int main(int argc, char **argv) =20 qemu_mutex_init(&evlock); =20 - /* - * 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_even= ts) - - 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 =3D getenv("FILEMONITOR_DEBUG") !=3D NULL; + g_test_add_func("/util/filemonitor", test_file_monitor_events); =20 return g_test_run(); } --=20 2.20.1 From nobody Wed May 1 23:13:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554210912957899.5897293104917; Tue, 2 Apr 2019 06:15:12 -0700 (PDT) Received: from localhost ([127.0.0.1]:54723 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hBJFp-00013e-7q for importer@patchew.org; Tue, 02 Apr 2019 09:15:05 -0400 Received: from eggs.gnu.org ([209.51.188.92]:32848) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hBIw8-0007ie-DC for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hBIw1-00044r-SX for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53118) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hBIvz-00041a-Tq for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:37 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 78E94C0B615A for ; Tue, 2 Apr 2019 12:54:33 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-56.ams2.redhat.com [10.36.112.56]) by smtp.corp.redhat.com (Postfix) with ESMTP id 68A896A486; Tue, 2 Apr 2019 12:54:31 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Date: Tue, 2 Apr 2019 13:54:16 +0100 Message-Id: <20190402125417.21573-3-berrange@redhat.com> In-Reply-To: <20190402125417.21573-1-berrange@redhat.com> References: <20190402125417.21573-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Tue, 02 Apr 2019 12:54:33 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 2/3] filemon: ensure watch IDs are unique to QFileMonitor scope X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Bandan Das , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The watch IDs are mistakenly only unique within the scope of the directory being monitored. This is not useful for clients which are monitoring multiple directories. They require watch IDs to be unique globally within the QFileMonitor scope. Reviewed-by: Marc-Andr=C3=A9 Lureau Tested-by: Bandan Das Reviewed-by: Bandan Das Signed-off-by: Daniel P. Berrang=C3=A9 --- tests/test-util-filemonitor.c | 116 +++++++++++++++++++++++++++++++--- util/filemonitor-inotify.c | 5 +- 2 files changed, 110 insertions(+), 11 deletions(-) diff --git a/tests/test-util-filemonitor.c b/tests/test-util-filemonitor.c index ea3715a8f4..71a7cf5de0 100644 --- a/tests/test-util-filemonitor.c +++ b/tests/test-util-filemonitor.c @@ -35,6 +35,8 @@ enum { 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, }; =20 typedef struct { @@ -298,6 +300,54 @@ test_file_monitor_events(void) .eventid =3D QFILE_MONITOR_EVENT_DELETED }, =20 =20 + { .type =3D QFILE_MONITOR_TEST_OP_MKDIR, + .filesrc =3D "fish", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "fish", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, + .filesrc =3D "fish/", .watchid =3D 4 }, + { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, + .filesrc =3D "fish/one.txt", .watchid =3D 5 }, + { .type =3D QFILE_MONITOR_TEST_OP_CREATE, + .filesrc =3D "fish/one.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 4, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 5, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, + .filesrc =3D "fish/one.txt", .watchid =3D 5 }, + { .type =3D QFILE_MONITOR_TEST_OP_RENAME, + .filesrc =3D "fish/one.txt", .filedst =3D "two.txt", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "one.txt", .watchid =3D 4, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "two.txt", .watchid =3D 2, + .eventid =3D QFILE_MONITOR_EVENT_CREATED }, + + + { .type =3D QFILE_MONITOR_TEST_OP_RMDIR, + .filesrc =3D "fish", }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "", .watchid =3D 4, + .eventid =3D QFILE_MONITOR_EVENT_IGNORED }, + { .type =3D QFILE_MONITOR_TEST_OP_EVENT, + .filesrc =3D "fish", .watchid =3D 0, + .eventid =3D QFILE_MONITOR_EVENT_DELETED }, + { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, + .filesrc =3D "fish", .watchid =3D 4 }, + + { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, .filesrc =3D "two.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, @@ -366,6 +416,8 @@ test_file_monitor_events(void) int fd; int watchid; struct utimbuf ubuf; + char *watchdir; + const char *watchfile; =20 pathsrc =3D g_strdup_printf("%s/%s", dir, op->filesrc); if (op->filedst) { @@ -378,13 +430,26 @@ test_file_monitor_events(void) g_printerr("Add watch %s %s %d\n", dir, op->filesrc, op->watchid); } + if (op->filesrc && strchr(op->filesrc, '/')) { + watchdir =3D g_strdup_printf("%s/%s", dir, op->filesrc); + watchfile =3D strrchr(watchdir, '/'); + *(char *)watchfile =3D '\0'; + watchfile++; + if (*watchfile =3D=3D '\0') { + watchfile =3D NULL; + } + } else { + watchdir =3D g_strdup(dir); + watchfile =3D op->filesrc; + } watchid =3D qemu_file_monitor_add_watch(mon, - dir, - op->filesrc, + watchdir, + watchfile, qemu_file_monitor_test_handler, &data, &local_err); + g_free(watchdir); if (watchid < 0) { g_printerr("Unable to add watch %s", error_get_pretty(local_err)); @@ -400,9 +465,17 @@ test_file_monitor_events(void) if (debug) { g_printerr("Del watch %s %d\n", dir, op->watchid); } + if (op->filesrc && strchr(op->filesrc, '/')) { + watchdir =3D g_strdup_printf("%s/%s", dir, op->filesrc); + watchfile =3D strrchr(watchdir, '/'); + *(char *)watchfile =3D '\0'; + } else { + watchdir =3D g_strdup(dir); + } qemu_file_monitor_remove_watch(mon, - dir, + watchdir, op->watchid); + g_free(watchdir); break; case QFILE_MONITOR_TEST_OP_EVENT: if (debug) { @@ -492,6 +565,28 @@ test_file_monitor_events(void) } break; =20 + 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(); } @@ -532,13 +627,18 @@ test_file_monitor_events(void) const QFileMonitorTestOp *op =3D &(ops[i]); char *path =3D g_strdup_printf("%s/%s", dir, op->filesrc); - unlink(path); - g_free(path); - if (op->filedst) { - path =3D g_strdup_printf("%s/%s", - dir, op->filedst); + if (op->type =3D=3D QFILE_MONITOR_TEST_OP_MKDIR) { + rmdir(path); + g_free(path); + } else { unlink(path); g_free(path); + if (op->filedst) { + path =3D g_strdup_printf("%s/%s", + dir, op->filedst); + unlink(path); + g_free(path); + } } } if (rmdir(dir) < 0) { diff --git a/util/filemonitor-inotify.c b/util/filemonitor-inotify.c index 3a72be037f..3eb29f860b 100644 --- a/util/filemonitor-inotify.c +++ b/util/filemonitor-inotify.c @@ -29,7 +29,7 @@ =20 struct QFileMonitor { int fd; - + int nextid; /* watch ID counter */ QemuMutex lock; /* protects dirs & idmap */ GHashTable *dirs; /* dirname =3D> QFileMonitorDir */ GHashTable *idmap; /* inotify ID =3D> dirname */ @@ -47,7 +47,6 @@ typedef struct { typedef struct { char *path; int id; /* inotify ID */ - int nextid; /* watch ID counter */ GArray *watches; /* QFileMonitorWatch elements */ } QFileMonitorDir; =20 @@ -277,7 +276,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon, } } =20 - watch.id =3D dir->nextid++; + watch.id =3D mon->nextid++; watch.filename =3D g_strdup(filename); watch.cb =3D cb; watch.opaque =3D opaque; --=20 2.20.1 From nobody Wed May 1 23:13:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554211084705583.854322087751; Tue, 2 Apr 2019 06:18:04 -0700 (PDT) Received: from localhost ([127.0.0.1]:55422 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hBJId-0003Qf-Hd for importer@patchew.org; Tue, 02 Apr 2019 09:17:59 -0400 Received: from eggs.gnu.org ([209.51.188.92]:32856) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hBIw9-0007jE-OK for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hBIw4-00046R-5V for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41210) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hBIw1-00043o-SO for qemu-devel@nongnu.org; Tue, 02 Apr 2019 08:54:38 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 58E6DF74C2 for ; Tue, 2 Apr 2019 12:54:35 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-56.ams2.redhat.com [10.36.112.56]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB11E60BEC; Tue, 2 Apr 2019 12:54:33 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Date: Tue, 2 Apr 2019 13:54:17 +0100 Message-Id: <20190402125417.21573-4-berrange@redhat.com> In-Reply-To: <20190402125417.21573-1-berrange@redhat.com> References: <20190402125417.21573-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 02 Apr 2019 12:54:35 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 3/3] filemon: fix watch IDs to avoid potential wraparound issues X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Bandan Das , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Watch IDs are allocated from incrementing a int counter against the QFileMonitor object. In very long life QEMU processes with a huge amount of USB MTP activity creating & deleting directories it is just about conceivable that the int counter can wrap around. This would result in incorrect behaviour of the file monitor watch APIs due to clashing watch IDs. Instead of trying to detect this situation, this patch changes the way watch IDs are allocated. It is turned into an int64_t variable where the high 32 bits are set from the underlying inotify "int" ID. This gives an ID that is guaranteed unique for the directory as a whole, and we can rely on the kernel to enforce this. QFileMonitor then sets the low 32 bits from a per-directory counter. The USB MTP device only sets watches on the directory as a whole, not files within, so there is no risk of guest triggered wrap around on the low 32 bits. Reviewed-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Daniel P. Berrang=C3=A9 --- authz/listfile.c | 2 +- hw/usb/dev-mtp.c | 10 +-- include/authz/listfile.h | 2 +- include/qemu/filemonitor.h | 16 ++--- tests/test-util-filemonitor.c | 130 +++++++++++++++++++--------------- util/filemonitor-inotify.c | 25 +++---- util/filemonitor-stub.c | 4 +- util/trace-events | 6 +- 8 files changed, 105 insertions(+), 90 deletions(-) diff --git a/authz/listfile.c b/authz/listfile.c index d4579767e7..bc2b58ef6d 100644 --- a/authz/listfile.c +++ b/authz/listfile.c @@ -93,7 +93,7 @@ qauthz_list_file_load(QAuthZListFile *fauthz, Error **err= p) =20 =20 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) diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 4dc1317e2e..ebf210fbf8 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -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; } =20 -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; =20 @@ -511,7 +511,7 @@ static MTPObject *usb_mtp_object_lookup_id(MTPState *s,= int id) return NULL; } =20 -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, MTPObje= ct *o) } =20 if (s->file_monitor) { - int id =3D qemu_file_monitor_add_watch(s->file_monitor, o->path, N= ULL, - file_monitor_event, s, &err); + int64_t id =3D qemu_file_monitor_add_watch(s->file_monitor, o->pat= h, NULL, + file_monitor_event, s, &e= rr); if (id =3D=3D -1) { error_report("usb-mtp: failed to add watch for %s: %s", o->pat= h, error_get_pretty(err)); diff --git a/include/authz/listfile.h b/include/authz/listfile.h index ebbd5a4288..0d618c903c 100644 --- a/include/authz/listfile.h +++ b/include/authz/listfile.h @@ -92,7 +92,7 @@ struct QAuthZListFile { char *filename; bool refresh; QFileMonitor *file_monitor; - int file_watch; + int64_t file_watch; }; =20 =20 diff --git a/include/qemu/filemonitor.h b/include/qemu/filemonitor.h index cd031832ed..64267d09b2 100644 --- a/include/qemu/filemonitor.h +++ b/include/qemu/filemonitor.h @@ -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); =20 /** * 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); =20 #endif /* QEMU_FILE_MONITOR_H */ diff --git a/tests/test-util-filemonitor.c b/tests/test-util-filemonitor.c index 71a7cf5de0..46e781c022 100644 --- a/tests/test-util-filemonitor.c +++ b/tests/test-util-filemonitor.c @@ -43,12 +43,12 @@ typedef struct { int type; const char *filesrc; const char *filedst; - int watchid; + int64_t *watchid; int eventid; } QFileMonitorTestOp; =20 typedef struct { - int id; + int64_t id; QFileMonitorEvent event; char *filename; } QFileMonitorTestRecord; @@ -90,7 +90,7 @@ qemu_file_monitor_test_event_loop(void *opaque G_GNUC_UNU= SED) * 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) @@ -156,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) { @@ -166,13 +166,14 @@ qemu_file_monitor_test_expect(QFileMonitorTestData *d= ata, rec =3D qemu_file_monitor_test_next_record(data); =20 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; } =20 if (id !=3D 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; } =20 @@ -198,170 +199,176 @@ qemu_file_monitor_test_expect(QFileMonitorTestData = *data, static void test_file_monitor_events(void) { + int64_t watch0 =3D 0; + int64_t watch1 =3D 0; + int64_t watch2 =3D 0; + int64_t watch3 =3D 0; + int64_t watch4 =3D 0; + int64_t watch5 =3D 0; QFileMonitorTestOp ops[] =3D { { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, - .filesrc =3D NULL, .watchid =3D 0 }, + .filesrc =3D NULL, .watchid =3D &watch0 }, { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, - .filesrc =3D "one.txt", .watchid =3D 1 }, + .filesrc =3D "one.txt", .watchid =3D &watch1 }, { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, - .filesrc =3D "two.txt", .watchid =3D 2 }, + .filesrc =3D "two.txt", .watchid =3D &watch2 }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_CREATE, .filesrc =3D "one.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 0, + .filesrc =3D "one.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 1, + .filesrc =3D "one.txt", .watchid =3D &watch1, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_CREATE, .filesrc =3D "two.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 0, + .filesrc =3D "two.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 2, + .filesrc =3D "two.txt", .watchid =3D &watch2, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_CREATE, .filesrc =3D "three.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "three.txt", .watchid =3D 0, + .filesrc =3D "three.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, .filesrc =3D "three.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "three.txt", .watchid =3D 0, + .filesrc =3D "three.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_RENAME, .filesrc =3D "one.txt", .filedst =3D "two.txt" }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 0, + .filesrc =3D "one.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 1, + .filesrc =3D "one.txt", .watchid =3D &watch1, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 0, + .filesrc =3D "two.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 2, + .filesrc =3D "two.txt", .watchid =3D &watch2, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_APPEND, .filesrc =3D "two.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 0, + .filesrc =3D "two.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_MODIFIED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 2, + .filesrc =3D "two.txt", .watchid =3D &watch2, .eventid =3D QFILE_MONITOR_EVENT_MODIFIED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_TOUCH, .filesrc =3D "two.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 0, + .filesrc =3D "two.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_ATTRIBUTES }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 2, + .filesrc =3D "two.txt", .watchid =3D &watch2, .eventid =3D QFILE_MONITOR_EVENT_ATTRIBUTES }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, - .filesrc =3D "one.txt", .watchid =3D 1 }, + .filesrc =3D "one.txt", .watchid =3D &watch1 }, { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, - .filesrc =3D "one.txt", .watchid =3D 3 }, + .filesrc =3D "one.txt", .watchid =3D &watch3 }, { .type =3D QFILE_MONITOR_TEST_OP_CREATE, .filesrc =3D "one.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 0, + .filesrc =3D "one.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 3, + .filesrc =3D "one.txt", .watchid =3D &watch3, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, - .filesrc =3D "one.txt", .watchid =3D 3 }, + .filesrc =3D "one.txt", .watchid =3D &watch3 }, { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, .filesrc =3D "one.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 0, + .filesrc =3D "one.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_MKDIR, .filesrc =3D "fish", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "fish", .watchid =3D 0, + .filesrc =3D "fish", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, - .filesrc =3D "fish/", .watchid =3D 4 }, + .filesrc =3D "fish/", .watchid =3D &watch4 }, { .type =3D QFILE_MONITOR_TEST_OP_ADD_WATCH, - .filesrc =3D "fish/one.txt", .watchid =3D 5 }, + .filesrc =3D "fish/one.txt", .watchid =3D &watch5 }, { .type =3D QFILE_MONITOR_TEST_OP_CREATE, .filesrc =3D "fish/one.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 4, + .filesrc =3D "one.txt", .watchid =3D &watch4, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 5, + .filesrc =3D "one.txt", .watchid =3D &watch5, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, - .filesrc =3D "fish/one.txt", .watchid =3D 5 }, + .filesrc =3D "fish/one.txt", .watchid =3D &watch5 }, { .type =3D QFILE_MONITOR_TEST_OP_RENAME, .filesrc =3D "fish/one.txt", .filedst =3D "two.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "one.txt", .watchid =3D 4, + .filesrc =3D "one.txt", .watchid =3D &watch4, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 0, + .filesrc =3D "two.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 2, + .filesrc =3D "two.txt", .watchid =3D &watch2, .eventid =3D QFILE_MONITOR_EVENT_CREATED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_RMDIR, .filesrc =3D "fish", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "", .watchid =3D 4, + .filesrc =3D "", .watchid =3D &watch4, .eventid =3D QFILE_MONITOR_EVENT_IGNORED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "fish", .watchid =3D 0, + .filesrc =3D "fish", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, - .filesrc =3D "fish", .watchid =3D 4 }, + .filesrc =3D "fish", .watchid =3D &watch4 }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_UNLINK, .filesrc =3D "two.txt", }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 0, + .filesrc =3D "two.txt", .watchid =3D &watch0, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, { .type =3D QFILE_MONITOR_TEST_OP_EVENT, - .filesrc =3D "two.txt", .watchid =3D 2, + .filesrc =3D "two.txt", .watchid =3D &watch2, .eventid =3D QFILE_MONITOR_EVENT_DELETED }, =20 =20 { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, - .filesrc =3D "two.txt", .watchid =3D 2 }, + .filesrc =3D "two.txt", .watchid =3D &watch2 }, { .type =3D QFILE_MONITOR_TEST_OP_DEL_WATCH, - .filesrc =3D NULL, .watchid =3D 0 }, + .filesrc =3D NULL, .watchid =3D &watch0 }, }; Error *local_err =3D NULL; GError *gerr =3D NULL; @@ -374,6 +381,7 @@ test_file_monitor_events(void) char *pathsrc =3D NULL; char *pathdst =3D NULL; QFileMonitorTestData data; + GHashTable *ids =3D g_hash_table_new(g_int64_hash, g_int64_equal); =20 qemu_mutex_init(&data.lock); data.records =3D NULL; @@ -414,7 +422,6 @@ test_file_monitor_events(void) for (i =3D 0; i < G_N_ELEMENTS(ops); i++) { const QFileMonitorTestOp *op =3D &(ops[i]); int fd; - int watchid; struct utimbuf ubuf; char *watchdir; const char *watchfile; @@ -427,8 +434,8 @@ test_file_monitor_events(void) switch (op->type) { case QFILE_MONITOR_TEST_OP_ADD_WATCH: if (debug) { - g_printerr("Add watch %s %s %d\n", - dir, op->filesrc, op->watchid); + g_printerr("Add watch %s %s\n", + dir, op->filesrc); } if (op->filesrc && strchr(op->filesrc, '/')) { watchdir =3D g_strdup_printf("%s/%s", dir, op->filesrc); @@ -442,7 +449,7 @@ test_file_monitor_events(void) watchdir =3D g_strdup(dir); watchfile =3D op->filesrc; } - watchid =3D + *op->watchid =3D qemu_file_monitor_add_watch(mon, watchdir, watchfile, @@ -450,20 +457,23 @@ test_file_monitor_events(void) &data, &local_err); g_free(watchdir); - if (watchid < 0) { + if (*op->watchid < 0) { g_printerr("Unable to add watch %s", error_get_pretty(local_err)); goto cleanup; } - if (watchid !=3D op->watchid) { - g_printerr("Unexpected watch ID %d, wanted %d\n", - watchid, op->watchid); + 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->watc= hid); goto cleanup; } + g_hash_table_add(ids, op->watchid); break; case QFILE_MONITOR_TEST_OP_DEL_WATCH: if (debug) { - g_printerr("Del watch %s %d\n", dir, op->watchid); + g_printerr("Del watch %s %" PRIx64 "\n", dir, *op->watchid= ); } if (op->filesrc && strchr(op->filesrc, '/')) { watchdir =3D g_strdup_printf("%s/%s", dir, op->filesrc); @@ -472,18 +482,19 @@ test_file_monitor_events(void) } else { watchdir =3D g_strdup(dir); } + g_hash_table_remove(ids, op->watchid); qemu_file_monitor_remove_watch(mon, watchdir, - op->watchid); + *op->watchid); g_free(watchdir); break; case QFILE_MONITOR_TEST_OP_EVENT: if (debug) { - g_printerr("Event id=3D%d event=3D%d file=3D%s\n", - op->watchid, op->eventid, op->filesrc); + g_printerr("Event id=3D%" PRIx64 " event=3D%d file=3D%s\n", + *op->watchid, op->eventid, op->filesrc); } if (!qemu_file_monitor_test_expect( - &data, op->watchid, op->eventid, op->filesrc)) + &data, *op->watchid, op->eventid, op->filesrc)) goto cleanup; break; case QFILE_MONITOR_TEST_OP_CREATE: @@ -596,6 +607,8 @@ test_file_monitor_events(void) pathsrc =3D pathdst =3D NULL; } =20 + g_assert_cmpint(g_hash_table_size(ids), =3D=3D, 0); + err =3D 0; =20 cleanup: @@ -647,6 +660,7 @@ test_file_monitor_events(void) abort(); } } + g_hash_table_unref(ids); g_free(dir); g_assert(err =3D=3D 0); } diff --git a/util/filemonitor-inotify.c b/util/filemonitor-inotify.c index 3eb29f860b..b5f4b93f3f 100644 --- a/util/filemonitor-inotify.c +++ b/util/filemonitor-inotify.c @@ -29,7 +29,6 @@ =20 struct QFileMonitor { int fd; - int nextid; /* watch ID counter */ QemuMutex lock; /* protects dirs & idmap */ GHashTable *dirs; /* dirname =3D> QFileMonitorDir */ GHashTable *idmap; /* inotify ID =3D> dirname */ @@ -37,7 +36,7 @@ struct QFileMonitor { =20 =20 typedef struct { - int id; /* watch ID */ + int64_t id; /* watch ID */ char *filename; /* optional filter */ QFileMonitorHandler cb; void *opaque; @@ -46,7 +45,8 @@ typedef struct { =20 typedef struct { char *path; - int id; /* inotify ID */ + int inotify_id; /* inotify ID */ + int next_file_id; /* file ID counter */ GArray *watches; /* QFileMonitorWatch elements */ } QFileMonitorDir; =20 @@ -126,7 +126,8 @@ static void qemu_file_monitor_watch(void *arg) g_assert_not_reached(); } =20 - 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 =3D 0; i < dir->watches->len; i++) { QFileMonitorWatch *watch =3D &g_array_index(dir->watches, QFileMonitorWatch, @@ -237,7 +238,7 @@ qemu_file_monitor_free(QFileMonitor *mon) g_idle_add((GSourceFunc)qemu_file_monitor_free_idle, mon); } =20 -int +int64_t qemu_file_monitor_add_watch(QFileMonitor *mon, const char *dirpath, const char *filename, @@ -247,7 +248,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon, { QFileMonitorDir *dir; QFileMonitorWatch watch; - int ret =3D -1; + int64_t ret =3D -1; =20 qemu_mutex_lock(&mon->lock); dir =3D g_hash_table_lookup(mon->dirs, dirpath); @@ -265,7 +266,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon, =20 dir =3D g_new0(QFileMonitorDir, 1); dir->path =3D g_strdup(dirpath); - dir->id =3D rv; + dir->inotify_id =3D rv; dir->watches =3D g_array_new(FALSE, TRUE, sizeof(QFileMonitorWatch= )); =20 g_hash_table_insert(mon->dirs, dir->path, dir); @@ -276,7 +277,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon, } } =20 - watch.id =3D mon->nextid++; + watch.id =3D (((int64_t)dir->inotify_id) << 32) | dir->next_file_id++; watch.filename =3D g_strdup(filename); watch.cb =3D cb; watch.opaque =3D opaque; @@ -297,7 +298,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon, =20 void qemu_file_monitor_remove_watch(QFileMonitor *mon, const char *dirpath, - int id) + int64_t id) { QFileMonitorDir *dir; gsize i; @@ -322,10 +323,10 @@ void qemu_file_monitor_remove_watch(QFileMonitor *mon, } =20 if (dir->watches->len =3D=3D 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); =20 - 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); =20 if (g_hash_table_size(mon->dirs) =3D=3D 0) { diff --git a/util/filemonitor-stub.c b/util/filemonitor-stub.c index 48268b2bb6..2c0e97edd8 100644 --- a/util/filemonitor-stub.c +++ b/util/filemonitor-stub.c @@ -38,7 +38,7 @@ qemu_file_monitor_free(QFileMonitor *mon G_GNUC_UNUSED) } =20 =20 -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_UNUS= ED, 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) { } diff --git a/util/trace-events b/util/trace-events index 56c27287be..9dbd237dad 100644 --- a/util/trace-events +++ b/util/trace-events @@ -22,13 +22,13 @@ buffer_move(const char *buf, size_t len, const char *fr= om) "%s: %zd bytes from % buffer_free(const char *buf, size_t len) "%s: capacity %zd" =20 # filemonitor-inotify.c -qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *fi= lename, void *cb, void *opaque, int id) "File monitor %p add watch dir=3D'%= s' file=3D'%s' cb=3D%p opaque=3D%p id=3D%u" -qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int id) "Fi= le monitor %p remove watch dir=3D'%s' id=3D%u" +qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *fi= lename, void *cb, void *opaque, int64_t id) "File monitor %p add watch dir= =3D'%s' file=3D'%s' cb=3D%p opaque=3D%p id=3D%" PRId64 +qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int64_t id)= "File monitor %p remove watch dir=3D'%s' id=3D%" PRId64 qemu_file_monitor_new(void *mon, int fd) "File monitor %p created fd=3D%d" qemu_file_monitor_enable_watch(void *mon, const char *dirpath, int id) "Fi= le monitor %p enable watch dir=3D'%s' id=3D%u" qemu_file_monitor_disable_watch(void *mon, const char *dirpath, int id) "F= le monitor %p disable watch dir=3D'%s' id=3D%u" qemu_file_monitor_event(void *mon, const char *dirpath, const char *filena= me, int mask, unsigned int id) "File monitor %p event dir=3D'%s' file=3D'%s= ' mask=3D0x%x id=3D%u" -qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *fil= ename, int ev, void *cb, void *opaque, unsigned int id) "File monitor %p di= spatch dir=3D'%s' file=3D'%s' ev=3D%d cb=3D%p opaque=3D%p id=3D%u" +qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *fil= ename, int ev, void *cb, void *opaque, int64_t id) "File monitor %p dispatc= h dir=3D'%s' file=3D'%s' ev=3D%d cb=3D%p opaque=3D%p id=3D%" PRId64 =20 # qemu-coroutine.c qemu_aio_coroutine_enter(void *ctx, void *from, void *to, void *opaque) "c= tx %p from %p to %p opaque %p" --=20 2.20.1