示例#1
0
static
VOID
PvfsNotifyProcessEvent(
    PVOID pContext
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PPVFS_NOTIFY_REPORT_RECORD pReport = (PPVFS_NOTIFY_REPORT_RECORD)pContext;
    PPVFS_FCB pParentFcb = NULL;
    PPVFS_FCB pCursor = NULL;
    PPVFS_FCB pReportParentFcb = NULL;

    BAIL_ON_INVALID_PTR(pReport, ntError);

    /* Simply walk up the ancestory and process the notify filter
       record on top if there is a match */

    pCursor = PvfsReferenceFCB(pReport->pFcb);
    pReportParentFcb = PvfsGetParentFCB(pReport->pFcb);

    while ((pParentFcb = PvfsGetParentFCB(pCursor)) != NULL)
    {
        PvfsReleaseFCB(&pCursor);

        /* Process buffers before Irp so we don't doubly report
           a change on a pending Irp that has requested buffering a
           change log (which shouldn't start until the existing Irp
           has been completed). */

        PvfsNotifyFullReportBuffer(pParentFcb, pReportParentFcb, pReport);
        PvfsNotifyFullReportIrp(pParentFcb, pReportParentFcb, pReport);

        pCursor = pParentFcb;
    }


error:
    if (pCursor)
    {
        PvfsReleaseFCB(&pCursor);
    }

    if (pReportParentFcb)
    {
        PvfsReleaseFCB(&pReportParentFcb);
    }

    if (pReport)
    {
        PvfsNotifyFullReportCtxFree(&pReport);
    }

    return;
}
示例#2
0
NTSTATUS
PvfsCreateFileCheckPendingDelete(
    PPVFS_FCB pFcb
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PPVFS_FCB pParentFcb = NULL;

    if (PvfsFcbIsPendingDelete(pFcb))
    {
        ntError = STATUS_DELETE_PENDING;
        BAIL_ON_NT_STATUS(ntError);
    }

    pParentFcb = PvfsGetParentFCB(pFcb);
    if (pParentFcb && PvfsFcbIsPendingDelete(pParentFcb))
    {
        ntError = STATUS_DELETE_PENDING;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = STATUS_SUCCESS;

cleanup:
    if (pParentFcb)
    {
        PvfsReleaseFCB(&pParentFcb);
    }


    return ntError;

error:
    goto cleanup;
}
示例#3
0
static
VOID
PvfsFreeFCB(
    PPVFS_FCB pFcb
    )
{
    if (pFcb)
    {
        LWIO_ASSERT(pFcb->BaseControlBlock.pBucket == NULL);
        LWIO_ASSERT(pFcb->BaseControlBlock.RefCount == 0);

        if (pFcb->pParentFcb)
        {
            PvfsReleaseFCB(&pFcb->pParentFcb);
        }

        RtlCStringFree(&pFcb->pszFilename);

        pthread_rwlock_destroy(&pFcb->rwScbLock);

        PvfsListDestroy(&pFcb->pScbList);
        PvfsListDestroy(&pFcb->pNotifyListIrp);
        PvfsListDestroy(&pFcb->pNotifyListBuffer);

        PvfsDestroyCB(&pFcb->BaseControlBlock);

        PVFS_FREE(&pFcb);

        InterlockedDecrement(&gPvfsDriverState.Counters.Fcb);
    }

    return;
}
示例#4
0
VOID
PvfsFreeCreateContext(
    IN OUT PVOID *ppContext
    )
{
    PPVFS_PENDING_CREATE pCreateCtx = NULL;

    if (ppContext && *ppContext)
    {
        pCreateCtx = (PPVFS_PENDING_CREATE)*ppContext;

        if (pCreateCtx->pIrpContext)
        {
            PvfsReleaseIrpContext(&pCreateCtx->pIrpContext);
        }

        if (pCreateCtx->pCcb)
        {
            PvfsReleaseCCB(pCreateCtx->pCcb);
        }

        if (pCreateCtx->pFcb)
        {
            PvfsReleaseFCB(&pCreateCtx->pFcb);
        }

        RtlCStringFree(&pCreateCtx->pszDiskFilename);
        RtlCStringFree(&pCreateCtx->pszOriginalFilename);

        PVFS_FREE(ppContext);
    }

    return;
}
示例#5
0
static
VOID
PvfsFreeIrpContext(
	PPVFS_IRP_CONTEXT *ppIrpContext
    )
{
    PPVFS_IRP_CONTEXT pIrpCtx = NULL;

    if (ppIrpContext && *ppIrpContext)
    {
        pIrpCtx = *ppIrpContext;

        if (pIrpCtx->pIrp &&
            PvfsIrpContextCheckFlag(pIrpCtx, PVFS_IRP_CTX_FLAG_PENDED))
        {
            pIrpCtx->pIrp->IoStatusBlock.Status = STATUS_FILE_CLOSED;
            PvfsAsyncIrpComplete(pIrpCtx);
        }

        if (pIrpCtx->pFcb)
        {
            PvfsReleaseFCB(&pIrpCtx->pFcb);
        }

        pthread_mutex_destroy(&pIrpCtx->Mutex);

        PVFS_FREE(ppIrpContext);

        InterlockedDecrement(&gPvfsIrpContextCount);
    }
}
示例#6
0
static
NTSTATUS
PvfsFindParentFCB(
    PPVFS_FCB *ppParentFcb,
    PCSTR pszFilename
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PPVFS_FCB pFcb = NULL;
    PSTR pszDirname = NULL;
    PPVFS_CB_TABLE_ENTRY pBucket = NULL;

    if (LwRtlCStringIsEqual(pszFilename, "/", TRUE))
    {
        ntError = STATUS_SUCCESS;
        *ppParentFcb = NULL;

        goto cleanup;
    }

    ntError = PvfsFileDirname(&pszDirname, pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCbTableGetBucket(&pBucket, &gPvfsDriverState.FcbTable, pszDirname);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCbTableLookup((PPVFS_CONTROL_BLOCK*)OUT_PPVOID(&pFcb), pBucket, pszDirname);
    if (ntError == STATUS_OBJECT_NAME_NOT_FOUND)
    {
        ntError = PvfsCreateFCB(
                      &pFcb,
                      pszDirname,
                      FALSE,
                      0,
                      0);
    }
    BAIL_ON_NT_STATUS(ntError);

    *ppParentFcb = PvfsReferenceFCB(pFcb);

cleanup:
    if (pFcb)
    {
        PvfsReleaseFCB(&pFcb);
    }

    if (pszDirname)
    {
        LwRtlCStringFree(&pszDirname);
    }

    return ntError;

error:

    goto cleanup;
}
示例#7
0
static
VOID
PvfsNotifyFullReportCtxFree(
    PPVFS_NOTIFY_REPORT_RECORD *ppReport
    )
{
    PPVFS_NOTIFY_REPORT_RECORD pReport = NULL;

    if (ppReport && *ppReport)
    {
        pReport = (PPVFS_NOTIFY_REPORT_RECORD)*ppReport;

        if (pReport->pFcb)
        {
            PvfsReleaseFCB(&pReport->pFcb);
        }

        LwRtlCStringFree(&pReport->pszFilename);

        PVFS_FREE(ppReport);
    }

    return;
}
示例#8
0
NTSTATUS
PvfsCcbSetFileBasicInformation(
    PPVFS_CCB pCcb,
    PFILE_BASIC_INFORMATION pFileInfo
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    LONG64 WriteTime = 0;
    LONG64 AccessTime = 0;
    FILE_NOTIFY_CHANGE NotifyFilter = FILE_NOTIFY_CHANGE_LAST_WRITE |
                                      FILE_NOTIFY_CHANGE_LAST_ACCESS;
    PVFS_STAT Stat = {0};
    BOOLEAN fcbControlLocked = FALSE;
    PPVFS_FCB pFcb = PvfsReferenceFCB(pCcb->pScb->pOwnerFcb);

    if (PvfsIsDefaultStream(pCcb->pScb))
    {
        ntError = PvfsValidatePathSCB(pCcb->pScb, &pCcb->FileId);
    }
    else
    {
        // Have to grab the base file object
        LWIO_LOCK_MUTEX(fcbControlLocked, &pFcb->BaseControlBlock.Mutex);

        ntError = PvfsValidatePathFCB(pFcb, &pFcb->FileId);
        BAIL_ON_NT_STATUS(ntError);

        LWIO_UNLOCK_MUTEX(fcbControlLocked, &pFcb->BaseControlBlock.Mutex);
    }

    /* We cant's set the Change Time so ignore it */

    WriteTime  = pFileInfo->LastWriteTime;
    AccessTime = pFileInfo->LastAccessTime;

    /* Ignore 0xffffffff */

    if (WriteTime == (LONG64)-1) {
        WriteTime = 0;
    }

    if (AccessTime == (LONG64)-1) {
        AccessTime = 0;
    }

    /* Save for "sticky" WriteTime sematics */

    if (WriteTime != 0)
    {
        PvfsSetLastWriteTimeFCB(pFcb, WriteTime);
    }

    /* Check if we need to preserve any original timestamps */

    if (WriteTime == 0 || AccessTime == 0)
    {
        if (PvfsIsDefaultStream(pCcb->pScb))
        {
            ntError = PvfsSysFstat(pCcb->fd, &Stat);
        }
        else
        {
            // Have to grab the stat() on the base file object
            ntError = PvfsSysStatByFcb(pFcb, &Stat);
        }
        BAIL_ON_NT_STATUS(ntError);

        if (WriteTime == 0)
        {
            NotifyFilter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;

            ntError = PvfsUnixToWinTime(&WriteTime, Stat.s_mtime);
            BAIL_ON_NT_STATUS(ntError);
        }

        if (AccessTime == 0)
        {
            NotifyFilter &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;

            ntError = PvfsUnixToWinTime(&AccessTime, Stat.s_atime);
            BAIL_ON_NT_STATUS(ntError);
        }
    }

    ntError = PvfsSysUtimeByFcb(pFcb, WriteTime, AccessTime);
    BAIL_ON_NT_STATUS(ntError);

    if (pFileInfo->FileAttributes != 0)
    {
        ntError = PvfsSetFileAttributes(pCcb, pFileInfo->FileAttributes);
        BAIL_ON_NT_STATUS(ntError);
    }

    if (NotifyFilter != 0)
    {
        PvfsNotifyScheduleFullReport(
            pFcb,
            NotifyFilter,
            FILE_ACTION_MODIFIED,
            pFcb->pszFilename);
    }

error:
    LWIO_UNLOCK_MUTEX(fcbControlLocked, &pFcb->BaseControlBlock.Mutex);

    if (pFcb)
    {
        PvfsReleaseFCB(&pFcb);
    }

    return ntError;
}
示例#9
0
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(&currentFileName, 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;
}
示例#10
0
NTSTATUS
PvfsCreateFCB(
    OUT PPVFS_FCB *ppFcb,
    IN PCSTR pszFilename,
    IN BOOLEAN bCheckShareAccess,
    IN FILE_SHARE_FLAGS SharedAccess,
    IN ACCESS_MASK DesiredAccess
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PPVFS_FCB pFcb = NULL;
    BOOLEAN bBucketLocked = FALSE;
    PPVFS_CB_TABLE_ENTRY pBucket = NULL;
    PPVFS_FCB pParentFcb = NULL;

    ntError = PvfsFindParentFCB(&pParentFcb, pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCbTableGetBucket(&pBucket, &gPvfsDriverState.FcbTable, (PVOID)pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    /* Protect against adding a duplicate */

    LWIO_LOCK_RWMUTEX_EXCLUSIVE(bBucketLocked, &pBucket->rwLock);

    ntError = PvfsCbTableLookup_inlock(
                  (PPVFS_CONTROL_BLOCK*)OUT_PPVOID(&pFcb),
                  pBucket,
                  pszFilename);
    if (ntError == STATUS_SUCCESS)
    {
        LWIO_UNLOCK_RWMUTEX(bBucketLocked, &pBucket->rwLock);

        /* If we have success, then we are good.  If we have a sharing
           violation, give the caller a chance to break the oplock and
           we'll try again when the create is resumed. */

        if (ntError == STATUS_SUCCESS ||
            ntError == STATUS_SHARING_VIOLATION)
        {
            *ppFcb = PvfsReferenceFCB(pFcb);
        }

        goto cleanup;
    }

    ntError = PvfsAllocateFCB(&pFcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = RtlCStringDuplicate(&pFcb->pszFilename, pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    pFcb->pParentFcb = pParentFcb ? PvfsReferenceFCB(pParentFcb) : NULL;

    // New FCB so BaseControlBlock.Mutext locking is not necessary

    ntError = PvfsCbTableAdd_inlock(
                  pBucket,
                  pFcb->pszFilename,
                  (PPVFS_CONTROL_BLOCK)pFcb);
    BAIL_ON_NT_STATUS(ntError);

    /* Return a reference to the FCB */

    *ppFcb = PvfsReferenceFCB(pFcb);

cleanup:
    LWIO_UNLOCK_RWMUTEX(bBucketLocked, &pBucket->rwLock);

    if (pParentFcb)
    {
        PvfsReleaseFCB(&pParentFcb);
    }

    if (pFcb)
    {
        PvfsReleaseFCB(&pFcb);
    }

    return ntError;

error:
    goto cleanup;
}