NTSTATUS PvfsScheduleCancelNotify( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_IRP_CONTEXT pIrpCtx = NULL; BAIL_ON_INVALID_PTR(pIrpContext->pScb, ntError); pIrpCtx = PvfsReferenceIrpContext(pIrpContext); ntError = LwRtlQueueWorkItem( gPvfsDriverState.ThreadPool, PvfsNotifyCleanIrpList, pIrpCtx, LW_SCHEDULE_HIGH_PRIORITY); BAIL_ON_NT_STATUS(ntError); error: if (!NT_SUCCESS(ntError)) { if (pIrpCtx) { PvfsReleaseIrpContext(&pIrpCtx); } } return ntError; }
VOID PvfsNotifyScheduleFullReport( PPVFS_FCB pFcb, FILE_NOTIFY_CHANGE Filter, FILE_ACTION Action, PCSTR pszFilename ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_NOTIFY_REPORT_RECORD pReport = NULL; BAIL_ON_INVALID_PTR(pFcb, ntError); ntError = PvfsAllocateMemory( OUT_PPVOID(&pReport), sizeof(PVFS_NOTIFY_REPORT_RECORD), FALSE); BAIL_ON_NT_STATUS(ntError); pReport->pFcb = PvfsReferenceFCB(pFcb); pReport->Filter = Filter; pReport->Action = Action; ntError = LwRtlCStringDuplicate(&pReport->pszFilename, pszFilename); BAIL_ON_NT_STATUS(ntError); ntError = LwRtlQueueWorkItem( gPvfsDriverState.ThreadPool, PvfsNotifyProcessEvent, pReport, 0); BAIL_ON_NT_STATUS(ntError); error: if (!NT_SUCCESS(ntError)) { if (pReport) { PvfsNotifyFullReportCtxFree(&pReport); } } return; }
VOID LwSmTableNotifyEntryStateChanged( PSM_TABLE_ENTRY pEntry, LW_SERVICE_STATE state ) { DWORD error = ERROR_SUCCESS; BOOLEAN bLocked = FALSE; PSM_LINK pLink = NULL; PSM_LINK pNext = NULL; PSM_ENTRY_NOTIFY pNotify = NULL; PSTR pServiceName = NULL; time_t now = 0; LOCK(bLocked, pEntry->pLock); for (pLink = LwSmLinkBegin(&pEntry->waiters); LwSmLinkValid(&pEntry->waiters, pLink); pLink = pNext) { pNext = LwSmLinkNext(pLink); pNotify = STRUCT_FROM_MEMBER(pLink, SM_ENTRY_NOTIFY, link); LwSmLinkRemove(pLink); pNotify->pfnNotifyEntryStateChange(state, pNotify->pData); LwFreeMemory(pNotify); } pthread_cond_broadcast(pEntry->pEvent); if (state == LW_SERVICE_STATE_DEAD && gState.bWatchdog) { now = time(NULL); if (now == (time_t) -1) { error = LwErrnoToWin32Error(errno); BAIL_ON_ERROR(error); } error = LwWc16sToMbs(pEntry->pInfo->pwszName, &pServiceName); BAIL_ON_ERROR(error); if (pEntry->StartAttempts >= 1 && (now - pEntry->LastRestartPeriod) > RESTART_PERIOD) { pEntry->StartAttempts = 1; pEntry->LastRestartPeriod = now; } if (pEntry->StartAttempts > 0 && pEntry->StartAttempts < RESTART_LIMIT) { pEntry->StartAttempts++; pEntry->dwRefCount++; SM_LOG_WARNING( "Restarting dead service: %s (attempt %u/%u)", pServiceName, (unsigned int) pEntry->StartAttempts, (unsigned int) RESTART_LIMIT); error = LwNtStatusToWin32Error(LwRtlQueueWorkItem(gpPool, LwSmTableWatchdog, pEntry, 0)); if (error) { pEntry->dwRefCount--; } BAIL_ON_ERROR(error); } else if (pEntry->StartAttempts >= 1) { SM_LOG_ERROR( "Service died: %s (restarted %u times in %lu seconds)", pServiceName, (unsigned int) pEntry->StartAttempts, (unsigned long) (now - pEntry->LastRestartPeriod)); } else { SM_LOG_ERROR( "Service failed to start: %s", pServiceName); } } error: UNLOCK(bLocked, pEntry->pLock); LW_SAFE_FREE_MEMORY(pServiceName); }
static BOOLEAN RdrProcessSessionSetupResponse2( PRDR_OP_CONTEXT pContext, NTSTATUS status, PVOID pParam ) { PRDR_SESSION2 pSession = pContext->State.TreeConnect.pSession2; PSMB_PACKET pPacket = pParam; BOOLEAN bSessionLocked = FALSE; BOOLEAN bFreeContext = FALSE; BAIL_ON_NT_STATUS(status); LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex); if (pPacket) { status = pPacket->pSMB2Header->error; if (status == STATUS_MORE_PROCESSING_REQUIRED) { status = STATUS_SUCCESS; } BAIL_ON_NT_STATUS(status); pSession->ullSessionId = pPacket->pSMB2Header->ullSessionId; } /* Save the packet on the context for RdrNegotiateGssContextWorkItem2 */ pContext->State.TreeConnect.pPacket = pPacket; pPacket = NULL; /* Dispatch a work item to negotiate the GSS context in a separate thread. Because GSS-API could potentially block in a network call (KRB5) or an IPC call (NTLM), calling into it directly from the socket task could cause a deadlock. */ status = LwRtlQueueWorkItem( gRdrRuntime.pThreadPool, RdrNegotiateGssContextWorkItem2, pContext, 0); BAIL_ON_NT_STATUS(status); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); cleanup: LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex); if (status != STATUS_PENDING) { RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL); bFreeContext = TRUE; } if (bFreeContext) { RdrFreeTreeConnectContext(pContext); } RdrFreePacket(pPacket); return FALSE; error: if (status != STATUS_PENDING && pSession) { LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex); RdrSession2Invalidate(pSession, status); RdrSession2Release(pSession); } goto cleanup; }
NTSTATUS RdrTreeConnect( PCWSTR pwszHostname, PCWSTR pwszSharename, PIO_CREDS pCreds, uid_t Uid, BOOLEAN bStopOnDfs, PRDR_OP_CONTEXT pContinue ) { NTSTATUS status = STATUS_SUCCESS; PRDR_OP_CONTEXT pContext = NULL; BOOLEAN bSocketLocked = FALSE; PRDR_SOCKET pSocket = NULL; status = RdrCreateContext(pContinue->pIrp, &pContext); BAIL_ON_NT_STATUS(status); LWIO_LOG_DEBUG("Tree connect context %p will continue %p\n", pContext, pContinue); pContext->State.TreeConnect.Uid = Uid; pContext->State.TreeConnect.bStopOnDfs = bStopOnDfs; pContext->State.TreeConnect.pContinue = pContinue; status = LwRtlWC16StringDuplicate( &pContext->State.TreeConnect.pwszSharename, pwszSharename); BAIL_ON_NT_STATUS(status); pContext->State.TreeConnect.pCreds = pCreds; status = RdrSocketFindOrCreate( pwszHostname, &pSocket); BAIL_ON_NT_STATUS(status); pContext->State.TreeConnect.pSocket = pSocket; LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex); switch (pSocket->state) { case RDR_SOCKET_STATE_NOT_READY: pSocket->state = RDR_SOCKET_STATE_CONNECTING; LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); /* Add extra reference to socket for work item */ RdrSocketRetain(pSocket); status = LwRtlQueueWorkItem( gRdrRuntime.pThreadPool, RdrSocketConnectWorkItem, pSocket, 0); if (status) { /* Nevermind */ RdrSocketRelease(pSocket); } BAIL_ON_NT_STATUS(status); pContext->Continue = RdrProcessNegotiateResponse; status = RdrTransceiveNegotiate(pContext, pSocket); BAIL_ON_NT_STATUS(status); break; case RDR_SOCKET_STATE_CONNECTING: case RDR_SOCKET_STATE_NEGOTIATING: pContext->Continue = RdrNegotiateComplete; LwListInsertTail(&pSocket->StateWaiters, &pContext->Link); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); break; case RDR_SOCKET_STATE_READY: LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); RdrNegotiateComplete(pContext, STATUS_SUCCESS, pSocket); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); break; case RDR_SOCKET_STATE_ERROR: status = pSocket->error; BAIL_ON_NT_STATUS(status); break; } cleanup: LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); if (status != STATUS_PENDING) { RdrFreeTreeConnectContext(pContext); } return status; error: if (status != STATUS_PENDING && pSocket) { LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); RdrSocketInvalidate(pSocket, status); RdrSocketRelease(pSocket); } goto cleanup; }
static VOID MainTask( PLW_TASK pTask, PVOID pContext, LW_TASK_EVENT_MASK WakeMask, PLW_TASK_EVENT_MASK pWaitMask, PLONG64 pllTime ) { NTSTATUS status = STATUS_SUCCESS; siginfo_t info; if (WakeMask & LW_TASK_EVENT_CANCEL) { *pWaitMask = LW_TASK_EVENT_COMPLETE; goto cleanup; } else if (WakeMask & LW_TASK_EVENT_INIT) { status = LwRtlSetTaskUnixSignal(pTask, SIGTERM, TRUE); BAIL_ON_ERROR(status); status = LwRtlSetTaskUnixSignal(pTask, SIGINT, TRUE); BAIL_ON_ERROR(status); status = LwRtlSetTaskUnixSignal(pTask, SIGHUP, TRUE); BAIL_ON_ERROR(status); status = LwRtlQueueWorkItem(gpPool, Startup, NULL, 0); BAIL_ON_ERROR(status); *pWaitMask = LW_TASK_EVENT_UNIX_SIGNAL; } else if (WakeMask & LW_TASK_EVENT_UNIX_SIGNAL) { while (LwRtlNextTaskUnixSignal(pTask, &info)) { switch(info.si_signo) { case SIGTERM: case SIGINT: SM_LOG_VERBOSE(info.si_signo == SIGINT ? "Shutting down on SIGINT" : "Shutting down on SIGTERM"); /* Shutting down stops all running services, which is a blocking operation */ status = LwRtlQueueWorkItem(gpPool, Shutdown, NULL, 0); BAIL_ON_ERROR(status); *pWaitMask = LW_TASK_EVENT_COMPLETE; goto cleanup; case SIGHUP: SM_LOG_VERBOSE("Refreshing configuration on SIGHUP"); /* Refreshing config reads from the registry, which is a blocking operation */ status = LwRtlQueueWorkItem(gpPool, RefreshConfig, NULL, 0); BAIL_ON_ERROR(status); break; default: break; } } *pWaitMask = LW_TASK_EVENT_UNIX_SIGNAL; } cleanup: return; error: if (status) { LwRtlExitMain(status); *pWaitMask = LW_TASK_EVENT_COMPLETE; } goto cleanup; }