VOID PvfsReleaseFCB( PPVFS_FCB *ppFcb ) { NTSTATUS ntError = STATUS_SUCCESS; BOOLEAN bucketLocked = FALSE; BOOLEAN fcbLocked = FALSE; PPVFS_FCB pFcb = NULL; PPVFS_CB_TABLE_ENTRY pBucket = NULL; LONG refCount = 0; LWIO_ASSERT((ppFcb != NULL) && (*ppFcb != NULL)); pFcb = *ppFcb; // It is important to lock the ScbTable here so that there is no window // between the refcount check and the remove. Otherwise another open request // could search and locate the SCB in the tree and return free()'d memory. // However, if the SCB has no bucket pointer, it has already been removed // from the ScbTable so locking is unnecessary. */ LWIO_LOCK_MUTEX(fcbLocked, &pFcb->BaseControlBlock.Mutex); pBucket = pFcb->BaseControlBlock.pBucket; if (pBucket) { LWIO_LOCK_RWMUTEX_EXCLUSIVE(bucketLocked, &pBucket->rwLock); } refCount = InterlockedDecrement(&pFcb->BaseControlBlock.RefCount); LWIO_ASSERT(refCount >= 0); if (refCount == 0) { LWIO_ASSERT(PvfsListIsEmpty(pFcb->pScbList)); if (pBucket) { ntError = PvfsCbTableRemove_inlock( (PPVFS_CONTROL_BLOCK)pFcb, pFcb->pszFilename); LWIO_ASSERT(ntError == STATUS_SUCCESS); LWIO_UNLOCK_RWMUTEX(bucketLocked, &pBucket->rwLock); } LWIO_UNLOCK_MUTEX(fcbLocked, &pFcb->BaseControlBlock.Mutex); PvfsFreeFCB(pFcb); } LWIO_UNLOCK_RWMUTEX(bucketLocked, &pBucket->rwLock); LWIO_UNLOCK_MUTEX(fcbLocked, &pFcb->BaseControlBlock.Mutex); *ppFcb = NULL; return; }
VOID SrvTreeRundown( PLWIO_SRV_TREE pTree ) { BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); LwRtlRBTreeTraverse( pTree->pAsyncStateCollection, LWRTL_TREE_TRAVERSAL_TYPE_IN_ORDER, SrvTreeRundownAsyncStatesRbTreeVisit, NULL); if (pTree->pAsyncStateCollection) { LwRtlRBTreeRemoveAll(pTree->pAsyncStateCollection); } LwRtlRBTreeTraverse( pTree->pFileCollection, LWRTL_TREE_TRAVERSAL_TYPE_IN_ORDER, SrvTreeRundownFileRbTreeVisit, NULL); LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); }
NTSTATUS PvfsRemoveFileObject( IN PPVFS_FCB pFcb ) { NTSTATUS status = STATUS_SUCCESS; PPVFS_CB_TABLE_ENTRY fcbBucket = NULL; BOOLEAN fcbBucketLocked = FALSE; if (pFcb->BaseControlBlock.pBucket == NULL) { status = STATUS_SUCCESS; goto cleanup; } status = PvfsRemoveStreamObjects(pFcb); LWIO_ASSERT(STATUS_SUCCESS == status); fcbBucket = pFcb->BaseControlBlock.pBucket; LWIO_LOCK_RWMUTEX_EXCLUSIVE(fcbBucketLocked, &fcbBucket->rwLock); status = PvfsCbTableRemove_inlock( (PPVFS_CONTROL_BLOCK)pFcb, pFcb->pszFilename); LWIO_ASSERT(status == STATUS_SUCCESS); LWIO_UNLOCK_RWMUTEX(fcbBucketLocked, &fcbBucket->rwLock); cleanup: LWIO_UNLOCK_RWMUTEX(fcbBucketLocked, &fcbBucket->rwLock); return status; }
NTSTATUS SrvTreeRemoveFile( PLWIO_SRV_TREE pTree, USHORT fid ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_FILE pFile = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); pFile = pTree->lruFile[ fid % SRV_LRU_CAPACITY ]; if (pFile && (pFile->fid == fid)) { pTree->lruFile[ fid % SRV_LRU_CAPACITY ] = NULL; } ntStatus = LwRtlRBTreeRemove( pTree->pFileCollection, &fid); BAIL_ON_NT_STATUS(ntStatus); pTree->ulNumOpenFiles--; cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: goto cleanup; }
NTSTATUS SrvSession2SetPrincipalName( PLWIO_SRV_SESSION_2 pSession, PCSTR pszClientPrincipal ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); if (!pszClientPrincipal) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } SRV_SAFE_FREE_MEMORY(pSession->pwszClientPrincipalName); ntStatus = SMBMbsToWc16s( pszClientPrincipal, &pSession->pwszClientPrincipalName); BAIL_ON_NT_STATUS(ntStatus); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: goto cleanup; }
NTSTATUS SrvSession2CreateTree( PLWIO_SRV_SESSION_2 pSession, PSRV_SHARE_INFO pShareInfo, PLWIO_SRV_TREE_2* ppTree ) { NTSTATUS ntStatus = 0; PLWIO_SRV_TREE_2 pTree = NULL; BOOLEAN bInLock = FALSE; ULONG ulTid = 0; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); ntStatus = SrvSession2UpdateLastActivityTime_inlock(pSession); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvSession2AcquireTreeId_inlock( pSession, &ulTid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvTree2Create( ulTid, pShareInfo, &pTree); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlRBTreeAdd( pSession->pTreeCollection, &pTree->ulTid, pTree); BAIL_ON_NT_STATUS(ntStatus); pTree->ullUid = pSession->ullUid; pTree->ulConnectionResourceId = pSession->ulConnectionResourceId; *ppTree = SrvTree2Acquire(pTree); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: *ppTree = NULL; if (pTree) { SrvTree2Release(pTree); } goto cleanup; }
VOID SrvTree2ClearInParent( PLWIO_SRV_TREE_2 pTree ) { BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); LWIO_ASSERT(IsSetFlag(pTree->objectFlags, SRV_OBJECT_FLAG_IN_PARENT)); ClearFlag(pTree->objectFlags, SRV_OBJECT_FLAG_IN_PARENT); LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); }
VOID PvfsSetLastWriteTimeFCB( PPVFS_FCB pFcb, LONG64 LastWriteTime ) { BOOLEAN bLocked = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bLocked, &pFcb->BaseControlBlock.RwLock); pFcb->LastWriteTime = LastWriteTime; LWIO_UNLOCK_RWMUTEX(bLocked, &pFcb->BaseControlBlock.RwLock); }
BOOLEAN SrvTree2IsInParent( PLWIO_SRV_TREE_2 pTree ) { BOOLEAN bIsInParent = FALSE; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); bIsInParent = SrvTree2IsInParent_inlock(pTree); LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return bIsInParent; }
NTSTATUS SrvElementsResetStats( VOID ) { BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gSrvElements.statsLock); memset(&gSrvElements.stats, 0, sizeof(gSrvElements.stats)); LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.statsLock); return STATUS_SUCCESS; }
LONG64 PvfsClearLastWriteTimeFCB( PPVFS_FCB pFcb ) { BOOLEAN bLocked = FALSE; LONG64 LastWriteTime = 0; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bLocked, &pFcb->BaseControlBlock.RwLock); LastWriteTime = pFcb->LastWriteTime; pFcb->LastWriteTime = 0; LWIO_UNLOCK_RWMUTEX(bLocked, &pFcb->BaseControlBlock.RwLock); return LastWriteTime; }
NTSTATUS SrvTreeAddAsyncState( PLWIO_SRV_TREE pTree, PLWIO_ASYNC_STATE pAsyncState ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; PLWIO_ASYNC_STATE pAsyncState1 = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); ntStatus = LwRtlRBTreeFind( pTree->pAsyncStateCollection, &pAsyncState->ullAsyncId, (PVOID*)&pAsyncState1); switch (ntStatus) { case STATUS_NOT_FOUND: ntStatus = LwRtlRBTreeAdd( pTree->pAsyncStateCollection, &pAsyncState->ullAsyncId, pAsyncState); BAIL_ON_NT_STATUS(ntStatus); SrvAsyncStateAcquire(pAsyncState); break; case STATUS_SUCCESS: ntStatus = STATUS_DUPLICATE_OBJECTID; break; default: ; } BAIL_ON_NT_STATUS(ntStatus); error: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; }
VOID SrvSession2SetUserFlags( PLWIO_SRV_SESSION_2 pSession, ULONG Flags ) { BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); SetFlag(pSession->ulUserFlags, Flags); LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return; }
VOID SrvTree2Rundown( PLWIO_SRV_TREE_2 pTree ) { BOOLEAN bInLock = FALSE; BOOLEAN bDoRundown = FALSE; BOOLEAN bIsInParent = FALSE; PLWIO_SRV_FILE_2 pRundownFileList = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); if (!SrvTree2IsRundown_inlock(pTree)) { SrvTree2SetRundown_inlock(pTree); bDoRundown = TRUE; bIsInParent = SrvTree2IsInParent_inlock(pTree); SrvEnumFile2Collection( pTree->pFileCollection, SrvTree2GatherRundownFileListCallback, &pRundownFileList); } LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); if (bIsInParent) { SrvSession2RemoveTree(pTree->pSession, pTree); } if (bDoRundown) { if (pTree->resource.ulResourceId) { PSRV_RESOURCE pResource = NULL; SrvElementsUnregisterResource(pTree->resource.ulResourceId, &pResource); pTree->resource.ulResourceId = 0; } // Cannot rundown with lock held as they self-remove SrvTree2RundownFileList(pRundownFileList); } }
NTSTATUS SrvElementsUnregisterResource( ULONG ulResourceId, /* IN */ PSRV_RESOURCE* ppResource /* OUT OPTIONAL*/ ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; PSRV_RESOURCE pResource = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gSrvElements.resources.mutex); if (ppResource) { ntStatus = LwRtlRBTreeFind( gSrvElements.resources.pResources, &ulResourceId, (PVOID*)&pResource); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = LwRtlRBTreeRemove( gSrvElements.resources.pResources, &ulResourceId); BAIL_ON_NT_STATUS(ntStatus); if (ppResource) { *ppResource = pResource; } cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.resources.mutex); return ntStatus; error: if (ppResource) { *ppResource = NULL; } goto cleanup; }
static NTSTATUS SrvSession2UpdateLastActivityTime( PLWIO_SRV_SESSION_2 pSession ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); ntStatus = SrvSession2UpdateLastActivityTime_inlock(pSession); LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; }
NTSTATUS SrvElementsResetStats( VOID ) { BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gSrvElements.statsLock); gSrvElements.stats.llMaxNumConnections = gSrvElements.stats.llNumConnections; gSrvElements.stats.llMaxNumSessions = gSrvElements.stats.llNumSessions; gSrvElements.stats.llMaxNumTreeConnects = gSrvElements.stats.llNumTreeConnects; gSrvElements.stats.llMaxNumOpenFiles = gSrvElements.stats.llNumOpenFiles; LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.statsLock); return STATUS_SUCCESS; }
NTSTATUS SrvElementsRegisterResource( PSRV_RESOURCE pResource, /* IN OUT */ PULONG pulResourceId /* IN OUT OPTIONAL */ ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gSrvElements.resources.mutex); ntStatus = SrvElementsResourceAcquireId_inlock( &gSrvElements.resources, &pResource->ulResourceId); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlRBTreeAdd( gSrvElements.resources.pResources, &pResource->ulResourceId, pResource); BAIL_ON_NT_STATUS(ntStatus); if (pulResourceId) { *pulResourceId = pResource->ulResourceId; } cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.resources.mutex); return ntStatus; error: if (pulResourceId) { *pulResourceId = 0; } pResource->ulResourceId = 0; goto cleanup; }
VOID SrvSession2Rundown( PLWIO_SRV_SESSION_2 pSession ) { BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); SrvSession2UpdateLastActivityTime_inlock(pSession); LwRtlRBTreeTraverse( pSession->pTreeCollection, LWRTL_TREE_TRAVERSAL_TYPE_IN_ORDER, SrvSession2RundownTreeRbTreeVisit, NULL); LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); }
NTSTATUS SrvTreeRemoveAsyncState( PLWIO_SRV_TREE pTree, ULONG64 ullAsyncId ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); ntStatus = LwRtlRBTreeRemove( pTree->pAsyncStateCollection, &ullAsyncId); LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; }
NTSTATUS SrvTree2RemoveFile( PLWIO_SRV_TREE_2 pTree, PLWIO_SRV_FILE_2 pFile ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_FILE_2 pCachedFile = NULL; PSMB2_FID pFid = &pFile->fid; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); if (SrvFile2IsInParent(pFile)) { pCachedFile = pTree->lruFile[ pFid->ullVolatileId % SRV_LRU_CAPACITY ]; if (pCachedFile && (pCachedFile->fid.ullPersistentId == pFid->ullPersistentId) && (pCachedFile->fid.ullVolatileId == pFid->ullVolatileId)) { pTree->lruFile[ pFid->ullVolatileId % SRV_LRU_CAPACITY ] = NULL; } // removal automatically releases reference ntStatus = LwRtlRBTreeRemove(pTree->pFileCollection, pFid); BAIL_ON_NT_STATUS(ntStatus); SrvFile2ClearInParent(pFile); pTree->ulNumOpenFiles--; } cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: goto cleanup; }
NTSTATUS SrvElementsConfigRefresh( VOID ) { NTSTATUS ntStatus = STATUS_SUCCESS; SRV_ELEMENTS_CONFIG config = { 0 }; PSRV_ELEMENTS_CONFIG pConfig = &config; LWIO_CONFIG_TABLE configTable[] = SRV_ELEMENTS_CONFIG_TABLE_INITIALIZER; ULONG ulNumConfig = sizeof(configTable) / sizeof(LWIO_CONFIG_TABLE); BOOLEAN bInLock = FALSE; SrvElementsConfigGetDefaults(pConfig); ntStatus = LwIoProcessConfig( "Services\\lwio\\Parameters\\Drivers\\srv\\smb2", "Policy\\Services\\lwio\\Parameters\\Drivers\\srv\\smb2", configTable, ulNumConfig, TRUE); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gSrvElements.configLock); SrvElementsConfigFree(&gSrvElements.config); memcpy(&gSrvElements.config, pConfig, sizeof(SRV_ELEMENTS_CONFIG)); LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.configLock); cleanup: return ntStatus; error: SrvElementsConfigFree(pConfig); goto cleanup; }
NTSTATUS SrvSession2RemoveTree( PLWIO_SRV_SESSION_2 pSession, ULONG ulTid ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_TREE_2 pTree = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); ntStatus = SrvSession2UpdateLastActivityTime_inlock(pSession); BAIL_ON_NT_STATUS(ntStatus); pTree = pSession->lruTree[ ulTid % SRV_LRU_CAPACITY ]; if (pTree && (pTree->ulTid == ulTid)) { pSession->lruTree[ ulTid % SRV_LRU_CAPACITY ] = NULL; } ntStatus = LwRtlRBTreeRemove( pSession->pTreeCollection, &ulTid); BAIL_ON_NT_STATUS(ntStatus); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: goto cleanup; }
NTSTATUS PvfsRenameFCB( PPVFS_FCB pFcb, PPVFS_CCB pCcb, PPVFS_FILE_NAME pNewFilename ) { NTSTATUS ntError = STATUS_SUCCESS; PPVFS_CB_TABLE fcbTable = &gPvfsDriverState.FcbTable; PPVFS_FCB pNewParentFcb = NULL; PPVFS_FCB pOldParentFcb = NULL; PPVFS_FCB pTargetFcb = NULL; PPVFS_CB_TABLE_ENTRY pTargetBucket = NULL; PPVFS_CB_TABLE_ENTRY pCurrentBucket = NULL; BOOLEAN currentFcbControl = FALSE; BOOLEAN targetFcbListLocked = FALSE; BOOLEAN targetBucketLocked = FALSE; BOOLEAN currentBucketLocked = FALSE; BOOLEAN fcbRwLocked = FALSE; BOOLEAN renameLock = FALSE; PPVFS_FILE_NAME currentFileName = NULL; /* If the target has an existing SCB, remove it from the Table and let the existing ref counters play out (e.g. pending change notifies. */ BAIL_ON_INVALID_PTR(pNewFilename, ntError); ntError = PvfsFindParentFCB(&pNewParentFcb, pNewFilename->FileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsAllocateFileNameFromScb(¤tFileName, pCcb->pScb); BAIL_ON_NT_STATUS(ntError); // Obtain all locks for the rename LWIO_LOCK_RWMUTEX_EXCLUSIVE(renameLock, &fcbTable->rwLock); LWIO_LOCK_MUTEX(currentFcbControl, &pFcb->BaseControlBlock.Mutex); pCurrentBucket = pFcb->BaseControlBlock.pBucket; ntError = PvfsCbTableGetBucket( &pTargetBucket, fcbTable, pNewFilename->FileName); BAIL_ON_NT_STATUS(ntError); LWIO_LOCK_RWMUTEX_EXCLUSIVE(currentBucketLocked, &pCurrentBucket->rwLock); if (pCurrentBucket != pTargetBucket) { LWIO_LOCK_RWMUTEX_EXCLUSIVE(targetBucketLocked, &pTargetBucket->rwLock); } // Do the rename work now ntError = PvfsCbTableLookup_inlock( (PPVFS_CONTROL_BLOCK*)OUT_PPVOID(&pTargetFcb), pTargetBucket, pNewFilename->FileName); if (ntError == STATUS_SUCCESS) { if (pTargetFcb != pFcb) { // Remove an existing FCB for the target file/stream (if one exists) // But make sure it is a different FCB LWIO_LOCK_RWMUTEX_SHARED(targetFcbListLocked, &pTargetFcb->rwScbLock); if (pTargetFcb->OpenHandleCount > 0 ) { // if TargetScb has open handles cannot rename // This except in the batch-oplock case ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } LWIO_UNLOCK_RWMUTEX(targetFcbListLocked, &pTargetFcb->rwScbLock); // TODO - How to get the Control Mutex without violating the // lock heirarchy? Does it matter at all ? ntError = PvfsRemoveStreamObjects(pTargetFcb); LWIO_ASSERT(STATUS_SUCCESS == ntError); ntError = PvfsCbTableRemove_inlock( (PPVFS_CONTROL_BLOCK)pTargetFcb, pTargetFcb->pszFilename); LWIO_ASSERT(STATUS_SUCCESS == ntError); } } ntError = PvfsSysRenameByFileName(currentFileName, pNewFilename); // Ignore the error here and continue ntError = PvfsPathCacheRemove(currentFileName); // Ignore the error here and continue /* Remove the SCB from the table, update the lookup key, and then re-add. Otherwise you will get memory corruption as a freed pointer gets left in the Table because if cannot be located using the current (updated) filename. Another reason to use the dev/inode pair instead if we could solve the "Create New File" issue. */ // Remove FCB ntError = PvfsCbTableRemove_inlock( (PPVFS_CONTROL_BLOCK)pFcb, pFcb->pszFilename); LWIO_ASSERT(STATUS_SUCCESS == ntError); // Rename FCB & Update parent links LWIO_LOCK_RWMUTEX_EXCLUSIVE(fcbRwLocked, &pFcb->BaseControlBlock.RwLock); LwRtlCStringFree(&pFcb->pszFilename); ntError = LwRtlCStringDuplicate(&pFcb->pszFilename, pNewFilename->FileName); BAIL_ON_NT_STATUS(ntError); if (pNewParentFcb != pFcb->pParentFcb) { pOldParentFcb = pFcb->pParentFcb; pFcb->pParentFcb = pNewParentFcb; pNewParentFcb = NULL; } LWIO_UNLOCK_RWMUTEX(fcbRwLocked, &pFcb->BaseControlBlock.RwLock); // Re-Add SCB ntError = PvfsCbTableAdd_inlock( pTargetBucket, pFcb->pszFilename, (PPVFS_CONTROL_BLOCK)pFcb); BAIL_ON_NT_STATUS(ntError); error: // Release all locks .. Whew! LWIO_UNLOCK_RWMUTEX(targetFcbListLocked, &pTargetFcb->rwScbLock); LWIO_UNLOCK_RWMUTEX(targetBucketLocked, &pTargetBucket->rwLock); LWIO_UNLOCK_RWMUTEX(currentBucketLocked, &pCurrentBucket->rwLock); LWIO_UNLOCK_RWMUTEX(fcbRwLocked, &pFcb->BaseControlBlock.RwLock); LWIO_UNLOCK_MUTEX(currentFcbControl, &pFcb->BaseControlBlock.Mutex); LWIO_UNLOCK_RWMUTEX(renameLock, &fcbTable->rwLock); if (pNewParentFcb) { PvfsReleaseFCB(&pNewParentFcb); } if (pOldParentFcb) { PvfsReleaseFCB(&pOldParentFcb); } if (pTargetFcb) { PvfsReleaseFCB(&pTargetFcb); } if (currentFileName) { PvfsFreeFileName(currentFileName); } return ntError; }
NTSTATUS PvfsRemoveStreamObjects( IN PPVFS_FCB pFcb ) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN scbBucketLocked = FALSE; BOOLEAN scbLocked = FALSE; PLW_LIST_LINKS scbCursorLink = NULL; PPVFS_SCB scbCursor = NULL; PPVFS_FILE_NAME streamName = NULL; PSTR fullStreamName = NULL; PPVFS_CB_TABLE_ENTRY scbCursorBucket = NULL; for (scbCursorLink = PvfsListTraverse(pFcb->pScbList, NULL); scbCursorLink; scbCursorLink = PvfsListTraverse(pFcb->pScbList, scbCursorLink)) { scbCursor = LW_STRUCT_FROM_FIELD( scbCursorLink, PVFS_SCB, FcbList); LWIO_ASSERT(scbCursor->OpenHandleCount == 0); status = PvfsAllocateFileNameFromScb(&streamName, scbCursor); BAIL_ON_NT_STATUS(status); status = PvfsAllocateCStringFromFileName(&fullStreamName, streamName); BAIL_ON_NT_STATUS(status); LWIO_LOCK_MUTEX(scbLocked, &scbCursor->BaseControlBlock.Mutex); scbCursorBucket = scbCursor->BaseControlBlock.pBucket; LWIO_LOCK_RWMUTEX_EXCLUSIVE(scbBucketLocked, &scbCursorBucket->rwLock); status = PvfsCbTableRemove_inlock( (PPVFS_CONTROL_BLOCK)scbCursor, fullStreamName); LWIO_ASSERT(STATUS_SUCCESS == status); LWIO_UNLOCK_RWMUTEX(scbBucketLocked, &scbCursorBucket->rwLock); LWIO_UNLOCK_MUTEX(scbLocked, &scbCursor->BaseControlBlock.Mutex); if (streamName) { PvfsFreeFileName(streamName); streamName = NULL; } if (fullStreamName) { LwRtlCStringFree(&fullStreamName); } } error: LWIO_UNLOCK_RWMUTEX(scbBucketLocked, &scbCursorBucket->rwLock); LWIO_UNLOCK_MUTEX(scbLocked, &scbCursor->BaseControlBlock.Mutex); if (streamName) { PvfsFreeFileName(streamName); } if (fullStreamName) { LwRtlCStringFree(&fullStreamName); } return status; }
NTSTATUS SrvTreeCreateFile( PLWIO_SRV_TREE pTree, PWSTR pwszFilename, PIO_FILE_HANDLE phFile, PIO_FILE_NAME* ppFilename, ACCESS_MASK desiredAccess, LONG64 allocationSize, FILE_ATTRIBUTES fileAttributes, FILE_SHARE_FLAGS shareAccess, FILE_CREATE_DISPOSITION createDisposition, FILE_CREATE_OPTIONS createOptions, PLWIO_SRV_FILE* ppFile ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_FILE pFile = NULL; USHORT fid = 0; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); ntStatus = SrvTreeAcquireFileId_inlock( pTree, &fid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvFileCreate( fid, pwszFilename, phFile, ppFilename, desiredAccess, allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, &pFile); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlRBTreeAdd( pTree->pFileCollection, &pFile->fid, pFile); BAIL_ON_NT_STATUS(ntStatus); pFile->resource.pAttributes->treeId.usTid = pTree->tid; pFile->resource.pAttributes->sessionId.usUid = pTree->uid; pFile->resource.pAttributes->ulConnectionResourceId = pTree->ulConnectionResourceId; pTree->ulNumOpenFiles++; *ppFile = SrvFileAcquire(pFile); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: *ppFile = NULL; if (pFile) { SrvFileRelease(pFile); } goto cleanup; }
static NTSTATUS SrvShareDbCreate( VOID ) { NTSTATUS ntStatus = 0; PSRV_SHARE_DB_CONTEXT pDbContext = NULL; PSTR pszError = NULL; BOOLEAN bExists = FALSE; PCSTR pszShareDBPath = LWIO_SRV_SHARE_DB; PCSTR pszShareDBDir = LWIO_SRV_DB_DIR; BOOLEAN bInLock = FALSE; ntStatus = SMBCheckFileExists(pszShareDBPath, &bExists); BAIL_ON_NT_STATUS(ntStatus); // TODO: Implement an upgrade scenario if (bExists) { goto cleanup; } ntStatus = SMBCheckDirectoryExists(pszShareDBDir, &bExists); BAIL_ON_NT_STATUS(ntStatus); if (!bExists) { mode_t cacheDirMode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; /* Allow go+rx to the base folder */ ntStatus = SMBCreateDirectory(pszShareDBDir, cacheDirMode); BAIL_ON_NT_STATUS(ntStatus); } /* restrict access to u+rwx to the db folder */ ntStatus = SMBChangeOwnerAndPermissions(pszShareDBDir, 0, 0, S_IRWXU); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareDbAcquireContext(&pDbContext); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gShareRepository_lwshare.dbMutex); ntStatus = sqlite3_exec( pDbContext->pDbHandle, DB_QUERY_CREATE_SHARES_TABLE, NULL, NULL, &pszError); BAIL_ON_LWIO_SRV_SQLITE_ERROR_DB(ntStatus, pDbContext->pDbHandle); ntStatus = SMBChangeOwnerAndPermissions( pszShareDBPath, 0, 0, S_IRWXU); BAIL_ON_NT_STATUS(ntStatus); cleanup: if (pDbContext) { SrvShareDbReleaseContext(pDbContext); } LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex); return ntStatus; error: if (pszError) { LWIO_LOG_ERROR("%s", pszError); sqlite3_free(pszError); } goto cleanup; }
NTSTATUS SrvShareDbDelete( IN HANDLE hRepository, IN PWSTR pwszShareName ) { NTSTATUS ntStatus = 0; PSRV_SHARE_DB_CONTEXT pDbContext = (PSRV_SHARE_DB_CONTEXT)hRepository; PSTR pszShareName = NULL; BOOLEAN bInLock = FALSE; if (IsNullOrEmptyString(pwszShareName)) { ntStatus = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvWc16sToMbs(pwszShareName, &pszShareName); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gShareRepository_lwshare.dbMutex); if (!pDbContext->pDeleteStmt) { PCSTR pszQueryTemplate = "DELETE FROM " LWIO_SRV_SHARES_DB_TABLE_NAME \ " WHERE UPPER(" LWIO_SRV_SHARES_DB_COL_NAME ") = UPPER(?1)"; ntStatus = sqlite3_prepare_v2( pDbContext->pDbHandle, pszQueryTemplate, -1, &pDbContext->pDeleteStmt, NULL); BAIL_ON_LWIO_SRV_SQLITE_ERROR_DB(ntStatus, pDbContext->pDbHandle); } ntStatus = sqlite3_bind_text( pDbContext->pDeleteStmt, 1, pszShareName, -1, SQLITE_TRANSIENT); BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pDbContext->pDeleteStmt); if ((ntStatus = sqlite3_step(pDbContext->pDeleteStmt)) == SQLITE_DONE) { ntStatus = STATUS_SUCCESS; } BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pDbContext->pDeleteStmt); cleanup: if (pDbContext) { if (pDbContext->pDeleteStmt) { sqlite3_reset(pDbContext->pDeleteStmt); } } LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex); SRV_SAFE_FREE_MEMORY(pszShareName); return ntStatus; error: goto cleanup; }
NTSTATUS SrvShareDbAdd( IN HANDLE hRepository, IN PWSTR pwszShareName, IN PWSTR pwszPath, IN PWSTR pwszComment, IN PBYTE pSecDesc, IN ULONG ulSecDescLen, IN PWSTR pwszService, IN ULONG ulFlags ) { NTSTATUS ntStatus = 0; PSRV_SHARE_DB_CONTEXT pDbContext = NULL; PSTR pszShareName = NULL; PSTR pszPath = NULL; PSTR pszComment = NULL; PSTR pszService = NULL; BOOLEAN bInLock = FALSE; if (pwszShareName) { ntStatus = SrvWc16sToMbs(pwszShareName, &pszShareName); BAIL_ON_NT_STATUS(ntStatus); } if (pwszPath) { ntStatus = SrvWc16sToMbs(pwszPath, &pszPath); BAIL_ON_NT_STATUS(ntStatus); } if (pwszComment) { ntStatus = SrvWc16sToMbs(pwszComment, &pszComment); BAIL_ON_NT_STATUS(ntStatus); } if (pwszService) { ntStatus = SrvWc16sToMbs(pwszService, &pszService); BAIL_ON_NT_STATUS(ntStatus); } LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gShareRepository_lwshare.dbMutex); pDbContext = (PSRV_SHARE_DB_CONTEXT)hRepository; ntStatus = SrvShareDbAdd_inlock( pDbContext, pszShareName, pszPath, pszComment, pSecDesc, ulSecDescLen, pszService, ulFlags); BAIL_ON_NT_STATUS(ntStatus); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex); SRV_SAFE_FREE_MEMORY(pszShareName); SRV_SAFE_FREE_MEMORY(pszPath); SRV_SAFE_FREE_MEMORY(pszComment); SRV_SAFE_FREE_MEMORY(pszService); return ntStatus; error: goto cleanup; }
NTSTATUS SrvTree2CreateFile( PLWIO_SRV_TREE_2 pTree, PWSTR pwszFilename, PIO_FILE_HANDLE phFile, PIO_FILE_NAME* ppFilename, ACCESS_MASK desiredAccess, LONG64 allocationSize, FILE_ATTRIBUTES fileAttributes, FILE_SHARE_FLAGS shareAccess, FILE_CREATE_DISPOSITION createDisposition, FILE_CREATE_OPTIONS createOptions, PLWIO_SRV_FILE_2* ppFile ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_FILE_2 pFile = NULL; SMB2_FID fid = {0}; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); if (SrvTree2IsRundown_inlock(pTree)) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvTree2AcquireFileId_inlock( pTree, &fid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvFile2Create( pTree, &fid, pwszFilename, phFile, ppFilename, desiredAccess, allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, &pFile); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvTree2AddFile_inlock(pTree, pFile); BAIL_ON_NT_STATUS(ntStatus); SrvFile2BlockIdleTimeout(pFile); *ppFile = pFile; cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); *ppFile = NULL; if (pFile) { SrvFile2Rundown(pFile); SrvFile2Release(pFile); } goto cleanup; }