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(
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);
return status;
+fail7:
+ __FreeCapturedBuffer(Context->Path);
+
+ XenIfaceDebugPrint(ERROR, "Fail7\n");
+ ThreadAlert(Context->Thread);
+ ThreadJoin(Context->Thread);
+
fail6:
XenIfaceDebugPrint(ERROR, "Fail6\n");
ObDereferenceObject(Context->Event);
{
NTSTATUS status;
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
XenIfaceDebugPrint(TRACE, "Context %p, Watch %p, FO %p\n",
Context, Context->Watch, Context->FileObject);
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);
LIST_ENTRY ToFree;
// store watches
+ InitializeListHead(&ToFree);
KeAcquireSpinLock(&Fdo->StoreWatchLock, &Irql);
Node = Fdo->StoreWatchList.Flink;
while (Node->Flink != Fdo->StoreWatchList.Flink) {
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);