Ejemplo n.º 1
0
VOID
PvfsZctCloseCcb(
    IN PPVFS_CCB pCcb
    )
{
    BOOLEAN bMutexLocked = FALSE;
    PLW_LIST_LINKS pZctCtxLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    PPVFS_ZCT_CONTEXT pZctContext = NULL;

    LWIO_LOCK_MUTEX(bMutexLocked, &pCcb->FileMutex);

    pZctCtxLink = PvfsListTraverse(pCcb->pZctContextList, NULL);

    while (pZctCtxLink)
    {
        pZctContext = LW_STRUCT_FROM_FIELD(
                          pZctCtxLink,
                          PVFS_ZCT_CONTEXT,
                          CcbLinks);

        pNextLink = PvfsListTraverse(pCcb->pZctContextList, pZctCtxLink);
        PvfsListRemoveItem(pCcb->pZctContextList, pZctCtxLink);
        pZctCtxLink = pNextLink;

        PvfsFreeZctContext(&pZctContext);
    }

    LWIO_UNLOCK_MUTEX(bMutexLocked, &pCcb->FileMutex);
}
Ejemplo n.º 2
0
static
VOID
PvfsNotifyFullReportBuffer(
    PPVFS_FCB pFcb,
    PPVFS_FCB pReportParentFcb,
    PPVFS_NOTIFY_REPORT_RECORD pReport
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    for (pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, NULL);
         pFilterLink;
         pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, pFilterLink))
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        /* Match the filter and depth */

        if ((pFilter->NotifyFilter & pReport->Filter) &&
            ((pFcb == pReportParentFcb) || pFilter->bWatchTree))
        {
            ntError = PvfsNotifyReportBuffer(
                          &pFilter->Buffer,
                          pReport->Action,
                          pReport->pszFilename);
            break;
        }
    }

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

    return;
}
Ejemplo n.º 3
0
static
VOID
PvfsNotifyCleanIrpList(
    PVOID pContext
    )
{
    PPVFS_IRP_CONTEXT pIrpCtx = (PPVFS_IRP_CONTEXT)pContext;
    PPVFS_FCB pFcb = NULL;
    BOOLEAN bFcbLocked = FALSE;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    BOOLEAN bFound = FALSE;

    LWIO_ASSERT(pIrpCtx->pScb->pOwnerFcb);

    // We have the IrpCtx->Scb's reference so no need to take another
    pFcb = pIrpCtx->pScb->pOwnerFcb;

    LWIO_LOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

    pFilterLink = PvfsListTraverse(pFcb->pNotifyListIrp, NULL);

    while (pFilterLink)
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        pNextLink = PvfsListTraverse(pFcb->pNotifyListIrp, pFilterLink);

        if (pFilter->pIrpContext != pIrpCtx)
        {
            pFilterLink = pNextLink;
            continue;
        }

        bFound = TRUE;

        PvfsListRemoveItem(pFcb->pNotifyListIrp, pFilterLink);
        pFilterLink = NULL;

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

        pFilter->pIrpContext->pIrp->IoStatusBlock.Status = STATUS_CANCELLED;

        PvfsCompleteIrpContext(pFilter->pIrpContext);

        PvfsFreeNotifyRecord(&pFilter);

        /* Can only be one IrpContext match so we are done */
    }

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

    if (!bFound)
    {
        pIrpCtx->pIrp->IoStatusBlock.Status = STATUS_CANCELLED;

        PvfsCompleteIrpContext(pIrpCtx);
    }

    if (pIrpCtx)
    {
        PvfsReleaseIrpContext(&pIrpCtx);
    }

    return;
}
Ejemplo n.º 4
0
static
VOID
PvfsNotifyFullReportIrp(
    PPVFS_FCB pFcb,
    PPVFS_FCB pReportParentFcb,
    PPVFS_NOTIFY_REPORT_RECORD pReport
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bActive = FALSE;
    BOOLEAN bLocked =  FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    pFilterLink = PvfsListTraverse(pFcb->pNotifyListIrp, NULL);

    while(pFilterLink)
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        pNextLink = PvfsListTraverse(pFcb->pNotifyListIrp, pFilterLink);

        /* Continue if we don't match the filter and depth */

        if (!((pFilter->NotifyFilter & pReport->Filter) &&
              ((pFcb == pReportParentFcb) || pFilter->bWatchTree)))
        {
            pFilter = NULL;
            pFilterLink = pNextLink;

            continue;
        }

        PvfsListRemoveItem(pFcb->pNotifyListIrp, pFilterLink);

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

        pFilterLink = NULL;

        PvfsQueueCancelIrpIfRequested(pFilter->pIrpContext);

        bActive = PvfsIrpContextMarkIfNotSetFlag(
                      pFilter->pIrpContext,
                      PVFS_IRP_CTX_FLAG_CANCELLED,
                      PVFS_IRP_CTX_FLAG_ACTIVE);

        if (!bActive)
        {
            PvfsFreeNotifyRecord(&pFilter);
            pFilterLink = pNextLink;

            continue;
        }

        ntError = PvfsNotifyReportIrp(
                      pFilter->pIrpContext,
                      pReport->Action,
                      pReport->pszFilename);
        BAIL_ON_NT_STATUS(ntError);

        /* If we have been asked to buffer changes, move the Fitler Record
           to the buffer list */

        if (pFilter->Buffer.Length > 0)
        {
            LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);
            ntError = PvfsListAddTail(pFcb->pNotifyListBuffer, pFilterLink);
            LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

            BAIL_ON_NT_STATUS(ntError);

            pFilter = NULL;
        }

        /* We only process on matching IRP */
        break;
    }

cleanup:
    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    if (pFilter)
    {
        PvfsFreeNotifyRecord(&pFilter);
    }

    return;

error:
    goto cleanup;
}
Ejemplo n.º 5
0
static
NTSTATUS
PvfsNotifyReportBufferedChanges(
    PPVFS_CCB pCcb,
    PPVFS_FCB pFcb,
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    FILE_NOTIFY_CHANGE Filter = pIrpContext->pIrp->Args.ReadDirectoryChange.NotifyFilter;
    PVOID pBuffer = pIrpContext->pIrp->Args.ReadDirectoryChange.Buffer;
    ULONG Length = pIrpContext->pIrp->Args.ReadDirectoryChange.Length;
    PLW_LIST_LINKS pFilterLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    /* See if we have any changes to report immediately */

    for (pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, NULL);
         pFilterLink;
         pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, pFilterLink))
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        /* To return the buffered changes, we have to match the handle
           and the filter */

        if ((pFilter->NotifyFilter != Filter) || (pFilter->pCcb != pCcb))
        {
            continue;
        }

        /* We have a match to check to see if we have anything */

        if ((pFilter->Buffer.Length == 0) ||
            (pFilter->Buffer.Offset == 0))
        {
            ntError = STATUS_NOT_FOUND;
            BAIL_ON_NT_STATUS(ntError);
        }

        /* We have changes....Do we have enough space?  Have we already
           overflowed the buffer? */

        ntError = pFilter->Buffer.Status;
        BAIL_ON_NT_STATUS(ntError);

        if (pFilter->Buffer.Offset > Length)
        {
            PvfsNotifyClearBufferedChanges(&pFilter->Buffer);

            ntError = STATUS_NOTIFY_ENUM_DIR;
            BAIL_ON_NT_STATUS(ntError);
        }

        memcpy(pBuffer, pFilter->Buffer.pData, pFilter->Buffer.Offset);
        pIrpContext->pIrp->IoStatusBlock.BytesTransferred = pFilter->Buffer.Offset;

        PvfsNotifyClearBufferedChanges(&pFilter->Buffer);
    }

    if (pFilterLink == NULL)
    {
        ntError = STATUS_NOT_FOUND;
        BAIL_ON_NT_STATUS(ntError);
    }


cleanup:
    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    return ntError;

error:
    goto cleanup;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
static
NTSTATUS
PvfsRenameFile(
    PPVFS_CCB pCcb,
    PPVFS_FILE_NAME pNewFileName
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PPVFS_CB_TABLE scbTable = &gPvfsDriverState.ScbTable;
    PPVFS_CB_TABLE_ENTRY pTargetBucket = NULL;
    PPVFS_CB_TABLE_ENTRY pCurrentBucket = NULL;
    BOOLEAN renameLock = FALSE;
    BOOLEAN targetBucketLock = FALSE;
    BOOLEAN currentBucketLock = FALSE;
    PPVFS_FCB pFcb = NULL;
    PLW_LIST_LINKS scbCursorLink = NULL;
    PPVFS_SCB scbCursor = NULL;
    BOOLEAN scbMutexLock = FALSE;
    BOOLEAN fcbListLocked = FALSE;
    PPVFS_FILE_NAME origTargetFileName = NULL;
    PPVFS_FILE_NAME scbCursorFileName = NULL;
    PSTR origFullStreamName = NULL;
    PSTR newFullStreamName = NULL;

    // The CCB holds out reference down the chain so no need to take a new one
    pFcb = pCcb->pScb->pOwnerFcb;

    ntError = PvfsAllocateFileNameFromScb(&origTargetFileName, pCcb->pScb);
    BAIL_ON_NT_STATUS(ntError);

    LWIO_LOCK_RWMUTEX_EXCLUSIVE(renameLock, &scbTable->rwLock);
    LWIO_LOCK_RWMUTEX_SHARED(fcbListLocked, &pFcb->rwScbLock);

    ntError = PvfsRenameFCB(pFcb, pCcb, pNewFileName);
    BAIL_ON_NT_STATUS(ntError);

    for (scbCursorLink = PvfsListTraverse(pFcb->pScbList, NULL);
         scbCursorLink;
         scbCursorLink = PvfsListTraverse(pFcb->pScbList, scbCursorLink))
    {
        scbCursor = LW_STRUCT_FROM_FIELD(
                          scbCursorLink,
                          PVFS_SCB,
                          FcbList);

        ntError = PvfsAllocateFileNameFromScb(&scbCursorFileName, scbCursor);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsAllocateCStringFromFileName(
                      &newFullStreamName,
                      scbCursorFileName);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsRenameBaseFileName(
                      scbCursorFileName,
                      PvfsGetCStringBaseFileName(origTargetFileName));
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsAllocateCStringFromFileName(
                      &origFullStreamName,
                      scbCursorFileName);
        BAIL_ON_NT_STATUS(ntError);

        pCurrentBucket = scbCursor->BaseControlBlock.pBucket;

        ntError = PvfsCbTableGetBucket(&pTargetBucket, scbTable, newFullStreamName);
        BAIL_ON_NT_STATUS(ntError);

        LWIO_LOCK_MUTEX(scbMutexLock, &scbCursor->BaseControlBlock.Mutex);
        LWIO_LOCK_RWMUTEX_EXCLUSIVE(currentBucketLock, &pCurrentBucket->rwLock);
        if (pCurrentBucket != pTargetBucket)
        {
            // Will be moved to a new bucket in the table
            LWIO_LOCK_RWMUTEX_EXCLUSIVE(targetBucketLock, &pTargetBucket->rwLock);
        }

        ntError = PvfsCbTableRemove_inlock(
                      (PPVFS_CONTROL_BLOCK)scbCursor,
                      origFullStreamName);
        LWIO_ASSERT(STATUS_SUCCESS == ntError);

        ntError = PvfsCbTableAdd_inlock(
                      pTargetBucket,
                      newFullStreamName,
                     (PPVFS_CONTROL_BLOCK)scbCursor);
        if (STATUS_SUCCESS != ntError)
        {
            LWIO_LOG_ERROR(
                "Failed to rename stream \"%s\" (%s)\n",
                newFullStreamName,
                LwNtStatusToName(ntError));
        }

        LWIO_UNLOCK_RWMUTEX(targetBucketLock, &pTargetBucket->rwLock);
        LWIO_UNLOCK_RWMUTEX(currentBucketLock, &pCurrentBucket->rwLock);
        LWIO_UNLOCK_MUTEX(scbMutexLock, &scbCursor->BaseControlBlock.Mutex);

        if (origFullStreamName)
        {
            LwRtlCStringFree(&origFullStreamName);
        }
        if (newFullStreamName)
        {
            LwRtlCStringFree(&newFullStreamName);
        }
    }

error:
    LWIO_UNLOCK_MUTEX(scbMutexLock, &scbCursor->BaseControlBlock.Mutex);
    LWIO_UNLOCK_RWMUTEX(targetBucketLock, &pTargetBucket->rwLock);
    LWIO_UNLOCK_RWMUTEX(currentBucketLock, &pCurrentBucket->rwLock);

    LWIO_UNLOCK_RWMUTEX(fcbListLocked, &pFcb->rwScbLock);
    LWIO_UNLOCK_RWMUTEX(renameLock, &scbTable->rwLock);

    if (origTargetFileName)
    {
        PvfsFreeFileName(origTargetFileName);
    }
    if (origFullStreamName)
    {
        LwRtlCStringFree(&origFullStreamName);
    }
    if (newFullStreamName)
    {
        LwRtlCStringFree(&newFullStreamName);
    }

    return ntError;
}