]> xenbits.xensource.com Git - people/pauldu/xeniface.git/commitdiff
Indirect user space watch events through a thread
authorPaul Durrant <paul.durrant@citrix.com>
Tue, 8 Nov 2016 18:08:11 +0000 (18:08 +0000)
committerPaul Durrant <paul.durrant@citrix.com>
Tue, 8 Nov 2016 18:08:11 +0000 (18:08 +0000)
It is useful, for diagnostic purposes, to log the path of a user-space
registered watch when we are about to signal it. To do this create a
thread to handle each user-space watch.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
src/xeniface/ioctl_store.c
src/xeniface/ioctls.c
src/xeniface/ioctls.h

index 5bd4649899590e242476167d5f54069d33760b61..1725e0655b2a71203002980d7860562717001a4f 100644 (file)
@@ -428,6 +428,36 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+StoreWatch(
+    IN  PXENIFACE_THREAD    Self,
+    IN  PVOID               _Context
+    )
+{
+    PXENIFACE_STORE_CONTEXT Context = _Context;
+    PKEVENT                 Event;
+
+    Event = ThreadGetEvent(Self);
+
+    for (;;) {
+        (VOID) KeWaitForSingleObject(Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        KeClearEvent(Event);
+
+        if (ThreadIsAlerted(Self))
+            break;
+
+        XenIfaceDebugPrint(INFO, "%s\n", Context->Path);
+
+        KeSetEvent(Context->Event, IO_NO_INCREMENT, FALSE);
+    }
+
+    return STATUS_SUCCESS;
+}
+
 DECLSPEC_NOINLINE
 NTSTATUS
 IoctlStoreAddWatch(
@@ -483,17 +513,21 @@ IoctlStoreAddWatch(
 
     XenIfaceDebugPrint(TRACE, "> Path '%s', Event %p, FO %p\n", Path, In->Event, FileObject);
 
+    Context->Path = Path;
+
+    status = ThreadCreate(StoreWatch, Context, &Context->Thread);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
     status = XENBUS_STORE(WatchAdd,
                           &Fdo->StoreInterface,
                           NULL, // prefix
-                          Path,
-                          Context->Event,
+                          Context->Path,
+                          ThreadGetEvent(Context->Thread),
                           &Context->Watch);
 
     if (!NT_SUCCESS(status))
-        goto fail6;
-
-    __FreeCapturedBuffer(Path);
+        goto fail7;
 
     ExInterlockedInsertTailList(&Fdo->StoreWatchList, &Context->Entry, &Fdo->StoreWatchLock);
 
@@ -504,6 +538,13 @@ IoctlStoreAddWatch(
 
     return status;
 
+fail7:
+    __FreeCapturedBuffer(Context->Path);
+
+    XenIfaceDebugPrint(ERROR, "Fail7\n");
+    ThreadAlert(Context->Thread);
+    ThreadJoin(Context->Thread);
+
 fail6:
     XenIfaceDebugPrint(ERROR, "Fail6\n");
     ObDereferenceObject(Context->Event);
@@ -537,6 +578,8 @@ StoreFreeWatch(
 {
     NTSTATUS status;
 
+    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
     XenIfaceDebugPrint(TRACE, "Context %p, Watch %p, FO %p\n",
                        Context, Context->Watch, Context->FileObject);
 
@@ -546,6 +589,11 @@ StoreFreeWatch(
 
     ASSERT(NT_SUCCESS(status)); // this is fatal since we'd leave an active watch without cleaning it up
 
+    ThreadAlert(Context->Thread);
+    ThreadJoin(Context->Thread);
+
+    __FreeCapturedBuffer(Context->Path);
+
     ObDereferenceObject(Context->Event);
     RtlZeroMemory(Context, sizeof(XENIFACE_STORE_CONTEXT));
     ExFreePoolWithTag(Context, XENIFACE_POOL_TAG);
index e47ef6eb72f4fe27c0e4c0d1800f8cdb05ec2a62..8e5648b6e04f4ae11ea664541c1c6f30ad702a98 100644 (file)
@@ -157,6 +157,7 @@ XenIfaceCleanup(
     LIST_ENTRY ToFree;
 
     // store watches
+    InitializeListHead(&ToFree);
     KeAcquireSpinLock(&Fdo->StoreWatchLock, &Irql);
     Node = Fdo->StoreWatchList.Flink;
     while (Node->Flink != Fdo->StoreWatchList.Flink) {
@@ -169,10 +170,20 @@ XenIfaceCleanup(
 
         XenIfaceDebugPrint(TRACE, "Store context %p\n", StoreContext);
         RemoveEntryList(&StoreContext->Entry);
-        StoreFreeWatch(Fdo, StoreContext);
+        // StoreFreeWatch requires PASSIVE_LEVEL and we're inside a lock
+        InsertTailList(&ToFree, &StoreContext->Entry);
     }
     KeReleaseSpinLock(&Fdo->StoreWatchLock, Irql);
 
+    Node = ToFree.Flink;
+    while (Node->Flink != ToFree.Flink) {
+        StoreContext = CONTAINING_RECORD(Node, XENIFACE_STORE_CONTEXT, Entry);
+        Node = Node->Flink;
+
+        RemoveEntryList(&StoreContext->Entry);
+        StoreFreeWatch(Fdo, StoreContext);
+    }
+
     // event channels
     InitializeListHead(&ToFree);
     KeAcquireSpinLock(&Fdo->EvtchnLock, &Irql);
index 16af0a22481738cbef11a5b83d04ac76ad002a3b..c954e9e0feaa3912296277d3f80bb4d0f7d642d3 100644 (file)
@@ -48,6 +48,8 @@ typedef struct _XENIFACE_CONTEXT_ID {
 
 typedef struct _XENIFACE_STORE_CONTEXT {
     LIST_ENTRY             Entry;
+    PCHAR                  Path;
+    PXENIFACE_THREAD       Thread;
     PXENBUS_STORE_WATCH    Watch;
     PKEVENT                Event;
     PVOID                  FileObject;