test: oplock.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# oplock.c File Reference

`#include "FsRtlP.h"`

Go to the source code of this file.

## Classes

struct | _NONOPAQUE_OPLOCK
struct | _WAITING_IRP

## Defines

#define | Dbg (0x08000000)
#define | FILTER_OPLOCK_VALID_FLAGS
#define | NO_OPLOCK (0x00000001)
#define | LEVEL_I_OPLOCK (0x00000002)
#define | BATCH_OPLOCK (0x00000004)
#define | FILTER_OPLOCK (0x00000008)
#define | LEVEL_II_OPLOCK (0x00000010)
#define | OPLOCK_TYPE_MASK (0x0000001f)
#define | EXCLUSIVE (0x00000040)
#define | PENDING (0x00000080)
#define | OPLOCK_HELD_MASK (0x000000c0)
#define | BREAK_TO_II (0x00000100)
#define | BREAK_TO_NONE (0x00000200)
#define | BREAK_TO_II_TO_NONE (0x00000400)
#define | CLOSE_PENDING (0x00000800)
#define | OPLOCK_BREAK_MASK (0x00000f00)
#define | NoOplocksHeld (NO_OPLOCK)
#define | OplockIGranted (LEVEL_I_OPLOCK | EXCLUSIVE)
#define | OpBatchGranted (BATCH_OPLOCK | EXCLUSIVE)
#define | OpFilterGranted (FILTER_OPLOCK | EXCLUSIVE)
#define | OpFilterReqPending (FILTER_OPLOCK | EXCLUSIVE | PENDING )
#define | OplockBreakItoII (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_II)
#define | OpBatchBreaktoII (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_II)
#define | OpFilterBreaktoII (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_II)
#define | OplockBreakItoNone (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)
#define | OpBatchBreaktoNone (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)
#define | OpFilterBreaktoNone (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)
#define | OplockBreakItoIItoNone (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)
#define | OpBatchBreaktoIItoNone (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)
#define | OpFilterBreaktoIItoNone (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)
#define | OpBatchClosePending (BATCH_OPLOCK | EXCLUSIVE | CLOSE_PENDING)
#define | OpFilterClosePending (FILTER_OPLOCK | EXCLUSIVE | CLOSE_PENDING)
#define | OplockIIGranted (LEVEL_II_OPLOCK)
#define | MODULE_POOL_TAG ('orSF')

## Typedefs

typedef ULONG | OPLOCK_STATE
typedef _NONOPAQUE_OPLOCK | NONOPAQUE_OPLOCK
typedef _NONOPAQUE_OPLOCK * | PNONOPAQUE_OPLOCK
typedef _WAITING_IRP | WAITING_IRP
typedef _WAITING_IRP * | PWAITING_IRP

## Functions

PNONOPAQUE_OPLOCK | FsRtlAllocateOplock ()
NTSTATUS | FsRtlRequestExclusiveOplock (IN OUT PNONOPAQUE_OPLOCK *Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp OPTIONAL, IN OPLOCK_STATE NextOplockState)
NTSTATUS | FsRtlRequestOplockII (IN OUT PNONOPAQUE_OPLOCK *Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp)
NTSTATUS | FsRtlAcknowledgeOplockBreak (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp, IN BOOLEAN GrantLevelII)
NTSTATUS | FsRtlOpBatchBreakClosePending (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp)
NTSTATUS | FsRtlOplockBreakNotify (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp)
VOID | FsRtlOplockCleanup (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIO_STACK_LOCATION IrpSp)
NTSTATUS | FsRtlOplockBreakToII (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
NTSTATUS | FsRtlOplockBreakToNone (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIO_STACK_LOCATION IrpSp, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
VOID | FsRtlRemoveAndCompleteIrp (IN PLIST_ENTRY Link)
NTSTATUS | FsRtlWaitOnIrp (IN OUT PNONOPAQUE_OPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL, IN PKEVENT Event)
VOID | FsRtlCompletionRoutinePriv (IN PVOID Context, IN PIRP Irp)
VOID | FsRtlCancelWaitIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
VOID | FsRtlCancelOplockIIIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
VOID | FsRtlCancelExclusiveIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
VOID | FsRtlRemoveAndCompleteWaitIrp (IN PWAITING_IRP WaitingIrp)
VOID | FsRtlNotifyCompletion (IN PVOID Context, IN PIRP Irp)
VOID | FsRtlInitializeOplock (IN OUT POPLOCK Oplock)
VOID | FsRtlUninitializeOplock (IN OUT POPLOCK Oplock)
NTSTATUS | FsRtlOplockFsctrl (IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
NTSTATUS | FsRtlCheckOplock (IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
BOOLEAN | FsRtlOplockIsFastIoPossible (IN POPLOCK Oplock)
BOOLEAN | FsRtlCurrentBatchOplock (IN POPLOCK Oplock)

## Define Documentation

#define BATCH_OPLOCK (0x00000004)

| Definition at line 78 of file oplock.c. Referenced by FsRtlCheckOplock(), FsRtlCurrentBatchOplock(), and FsRtlOplockBreakToII().

#define BREAK_TO_II (0x00000100)

| Definition at line 89 of file oplock.c. Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakToII(), and FsRtlOplockBreakToNone().

#define BREAK_TO_II_TO_NONE (0x00000400)

| Definition at line 91 of file oplock.c. Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlOpBatchBreakClosePending(), and FsRtlOplockBreakToNone().

#define BREAK_TO_NONE (0x00000200)

| Definition at line 90 of file oplock.c. Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakToII(), and FsRtlOplockBreakToNone().

#define CLOSE_PENDING (0x00000800)

| Definition at line 92 of file oplock.c. Referenced by FsRtlOpBatchBreakClosePending().

#define Dbg (0x08000000)

| Definition at line 50 of file oplock.c.

#define EXCLUSIVE (0x00000040)

| Definition at line 84 of file oplock.c. Referenced by FsRtlOplockBreakToII(), and FsRtlOplockFsctrl().

#define FILTER_OPLOCK (0x00000008)

| Definition at line 79 of file oplock.c. Referenced by FsRtlCheckOplock(), and FsRtlCurrentBatchOplock().

#define FILTER_OPLOCK_VALID_FLAGS

Value:

    (     \
        FILE_READ_ATTRIBUTES            |   \
        FILE_WRITE_ATTRIBUTES           |   \
        FILE_READ_DATA                  |   \
        FILE_READ_EA                    |   \
        FILE_EXECUTE                    |   \
        SYNCHRONIZE                     |   \
        READ_CONTROL                        \
    )

Definition at line 57 of file oplock.c.

Referenced by FsRtlCheckOplock().

#define LEVEL_I_OPLOCK (0x00000002)

| Definition at line 77 of file oplock.c. Referenced by FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakToII(), and FsRtlOplockFsctrl().

#define LEVEL_II_OPLOCK (0x00000010)

| Definition at line 80 of file oplock.c. Referenced by FsRtlOplockBreakToNone(), FsRtlOplockIsFastIoPossible(), FsRtlRequestExclusiveOplock(), and FsRtlRequestOplockII().

#define MODULE_POOL_TAG ('orSF')

| Definition at line 235 of file oplock.c.

#define NO_OPLOCK (0x00000001)

| Definition at line 76 of file oplock.c. Referenced by FsRtlRequestExclusiveOplock(), and FsRtlRequestOplockII().

#define NoOplocksHeld (NO_OPLOCK)

| Definition at line 100 of file oplock.c. Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlAllocateOplock(), FsRtlCancelExclusiveIrp(), FsRtlCancelOplockIIIrp(), FsRtlCheckOplock(), FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakNotify(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), and FsRtlOplockCleanup().

#define OpBatchBreaktoII (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_II)

| Definition at line 108 of file oplock.c.

#define OpBatchBreaktoIItoNone (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)

| Definition at line 116 of file oplock.c.

#define OpBatchBreaktoNone (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)

| Definition at line 112 of file oplock.c.

#define OpBatchClosePending (BATCH_OPLOCK | EXCLUSIVE | CLOSE_PENDING)

| Definition at line 119 of file oplock.c.

#define OpBatchGranted (BATCH_OPLOCK | EXCLUSIVE)

| Definition at line 103 of file oplock.c.

#define OpFilterBreaktoII (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_II)

| Definition at line 109 of file oplock.c.

#define OpFilterBreaktoIItoNone (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)

| Definition at line 117 of file oplock.c.

#define OpFilterBreaktoNone (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)

| Definition at line 113 of file oplock.c.

#define OpFilterClosePending (FILTER_OPLOCK | EXCLUSIVE | CLOSE_PENDING)

| Definition at line 120 of file oplock.c.

#define OpFilterGranted (FILTER_OPLOCK | EXCLUSIVE)

| Definition at line 104 of file oplock.c.

#define OpFilterReqPending (FILTER_OPLOCK | EXCLUSIVE | PENDING )

| Definition at line 105 of file oplock.c. Referenced by FsRtlOplockFsctrl(), and FsRtlRequestExclusiveOplock().

#define OPLOCK_BREAK_MASK (0x00000f00)

| Definition at line 94 of file oplock.c. Referenced by FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakNotify(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), and FsRtlOplockIsFastIoPossible().

#define OPLOCK_HELD_MASK (0x000000c0)

| Definition at line 87 of file oplock.c.

#define OPLOCK_TYPE_MASK (0x0000001f)

| Definition at line 82 of file oplock.c.

#define OplockBreakItoII (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_II)

| Definition at line 107 of file oplock.c.

#define OplockBreakItoIItoNone (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)

| Definition at line 115 of file oplock.c.

#define OplockBreakItoNone (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)

| Definition at line 111 of file oplock.c.

#define OplockIGranted (LEVEL_I_OPLOCK | EXCLUSIVE)

| Definition at line 102 of file oplock.c.

#define OplockIIGranted (LEVEL_II_OPLOCK)

| Definition at line 122 of file oplock.c. Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlCheckOplock(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), FsRtlRequestExclusiveOplock(), and FsRtlRequestOplockII().

#define PENDING (0x00000080)

| Definition at line 85 of file oplock.c. Referenced by FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakNotify(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), and FsRtlRequestExclusiveOplock().

## Typedef Documentation

typedef struct _NONOPAQUE_OPLOCK NONOPAQUE_OPLOCK

| Referenced by FsRtlAllocateOplock().

typedef ULONG OPLOCK_STATE

| Definition at line 128 of file oplock.c. Referenced by FsRtlCheckOplock(), FsRtlOplockFsctrl(), and FsRtlOplockIsFastIoPossible().

typedef struct _NONOPAQUE_OPLOCK * PNONOPAQUE_OPLOCK

| Referenced by FsRtlAllocateOplock(), FsRtlCancelExclusiveIrp(), FsRtlCancelOplockIIIrp(), FsRtlCancelWaitIrp(), FsRtlCheckOplock(), FsRtlCurrentBatchOplock(), FsRtlOplockFsctrl(), FsRtlOplockIsFastIoPossible(), FsRtlRequestExclusiveOplock(), FsRtlRequestOplockII(), and FsRtlUninitializeOplock().

typedef struct _WAITING_IRP * PWAITING_IRP

| Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlCancelExclusiveIrp(), FsRtlCancelWaitIrp(), FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), FsRtlUninitializeOplock(), and FsRtlWaitOnIrp().

typedef struct _WAITING_IRP WAITING_IRP

## Function Documentation

NTSTATUS FsRtlAcknowledgeOplockBreak | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP | Irp,
|  | IN BOOLEAN | GrantLevelII
| ) |

Definition at line 1678 of file oplock.c.

References ASSERT, BREAK_TO_II, BREAK_TO_II_TO_NONE, BREAK_TO_NONE, _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), FALSE, FlagOn, FsRtlCancelOplockIIIrp(), FsRtlCompleteRequest, FsRtlRemoveAndCompleteWaitIrp(), IoAcquireCancelSpinLock(), IoIsOperationSynchronous(), IoMarkIrpPending, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, NoOplocksHeld, NTSTATUS(), NULL, ObDereferenceObject, OplockIIGranted, PWAITING_IRP, Status, _IRP::Tail, TRUE, and try_return.

Referenced by FsRtlOplockFsctrl().

    01687                    :
    01688
    01689     This routine is called when a user is acknowledging an Oplock I
    01690     break.  If the level 1 oplock was being broken to level 2, then
    01691     a check is made to insure that the level 2 has not been broken
    01692     in the meantime.
    01693
    01694     If an oplock 1 break is not in progress then this will be treated
    01695     as an asynchronous break request.  If this is an asynchronous break
    01696     request and the file object owns an outstanding level 1 oplock, then
    01697     the oplock will be broken at this point.
    01698
    01699     A spurious break request via a file object which does not (or did not)
    01700     own the level 1 oplock will generate a warning but will not affect
    01701     the oplock state.
    01702
    01703     At the end of an Oplock I break, all of the waiting irps are completed.
    01704
    01705 Arguments:
    01706
    01707     Oplock - Supplies a pointer to the non-opaque oplock structure for
    01708              this file.
    01709
    01710     IrpSp - This is the Irp stack location for the current Irp.
    01711
    01712     Irp - Supplies a pointer to the Irp which declares the requested
    01713           operation.
    01714
    01715     GrantLevelII - Indicates that this caller wants a level II oplock left
    01716         on the file.
    01717
    01718 Return Value:
    01719
    01720     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    01721     STATUS_CANCELLED if the Irp is cancelled before we return.
    01722
    01723 --*/
    01724
    01725 {
    01726     NTSTATUS Status;
    01727
    01728     BOOLEAN AcquiredMutex;
    01729
    01730     DebugTrace( +1, Dbg, "FsRtlAcknowledgeOplockBreak:  Entered\n", 0 );
    01731     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    01732     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    01733     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    01734
    01735     //
    01736     //  If there is no oplock structure, we complete this with invalid
    01737     //  oplock protocol.
    01738     //
    01739
    01740     if (Oplock == NULL) {
    01741
    01742         FsRtlCompleteRequest( Irp, STATUS_INVALID_OPLOCK_PROTOCOL );
    01743         DebugTrace( -1, Dbg, "FsRtlAcknowledgeOplockBreak:  Exit -> %08lx\n", STATUS_INVALID_OPLOCK_PROTOCOL );
    01744         return STATUS_INVALID_OPLOCK_PROTOCOL;
    01745     }
    01746
    01747     //
    01748     //  Grab the synchronization object for the oplock.
    01749     //
    01750
    01751     ExAcquireFastMutexUnsafe( Oplock->FastMutex );
    01752     AcquiredMutex = TRUE;
    01753
    01754     //
    01755     //  Use a try-finally to facilitate cleanup.
    01756     //
    01757
    01758     try {
    01759
    01760         BOOLEAN DereferenceFileObject = TRUE;
    01761
    01762         //
    01763         //  If a break is underway but this is not the owner of the
    01764         //  level 1 oplock, we complete the request and return a
    01765         //  warning.
    01766         //
    01767
    01768         if (Oplock->FileObject != IrpSp->FileObject) {
    01769
    01770             Status = STATUS_INVALID_OPLOCK_PROTOCOL;
    01771             DebugTrace(0,
    01772                        Dbg,
    01773                        "Not oplock owner -> %08lx\n",
    01774                        Status);
    01775
    01776             FsRtlCompleteRequest( Irp, Status );
    01777             try_return( Status );
    01778         }
    01779
    01780         //
    01781         //  If the user would like a level II and we are breaking to level II
    01782         //  then grant the oplock.
    01783         //
    01784
    01785         if (GrantLevelII &&
    01786             FlagOn( Oplock->OplockState, BREAK_TO_II )) {
    01787
    01788             PFAST_MUTEX OplockFastMutex = Oplock->FastMutex;
    01789
    01790             DebugTrace(0, Dbg, "OplockItoII\n", 0);
    01791
    01792             //
    01793             //  The acknowledgement should never be synchronous.
    01794             //
    01795
    01796             ASSERT( !IoIsOperationSynchronous( Irp ));
    01797
    01798             //
    01799             //  We need to add this Irp to the oplock II queue, change
    01800             //  the oplock state to Oplock II granted and set the
    01801             //  return value to STATUS_PENDING.
    01802             //
    01803
    01804
    01805             IoMarkIrpPending( Irp );
    01806
    01807             Irp->IoStatus.Status = STATUS_SUCCESS;
    01808
    01809             InsertHeadList( &Oplock->IrpOplocksII,
    01810                             &Irp->Tail.Overlay.ListEntry );
    01811
    01812             DereferenceFileObject = FALSE;
    01813
    01814             Oplock->OplockState = OplockIIGranted;
    01815
    01816             Irp->IoStatus.Information = (ULONG_PTR) Oplock;
    01817
    01818             IoAcquireCancelSpinLock( &Irp->CancelIrql );
    01819
    01820             //
    01821             //  Now if the irp is cancelled then we'll call the cancel
    01822             //  routine right now to do away with the irp, otherwise
    01823             //  we set the cancel routine
    01824             //
    01825
    01826             if (Irp->Cancel) {
    01827
    01828                 AcquiredMutex = FALSE;
    01829
    01830                 ExReleaseFastMutexUnsafe( OplockFastMutex );
    01831
    01832                 FsRtlCancelOplockIIIrp( NULL, Irp );
    01833
    01834             } else {
    01835
    01836                 IoSetCancelRoutine( Irp, FsRtlCancelOplockIIIrp );
    01837                 IoReleaseCancelSpinLock( Irp->CancelIrql );
    01838             }
    01839
    01840             Status = STATUS_PENDING;
    01841
    01842         //
    01843         //  We will break to none since this is the expected case for these
    01844         //  cases.
    01845         //
    01846
    01847         } else if (FlagOn( Oplock->OplockState, BREAK_TO_II | BREAK_TO_NONE )) {
    01848
    01849             //
    01850             //  We need to complete this Irp and return STATUS_SUCCESS.
    01851             //  We also set the oplock state to no oplocks held.
    01852             //
    01853
    01854             DebugTrace(0, Dbg, "OplockItoNone\n", 0);
    01855
    01856             Status = STATUS_SUCCESS;
    01857             FsRtlCompleteRequest( Irp, Status );
    01858             Oplock->OplockState = NoOplocksHeld;
    01859
    01860         //
    01861         //  In this case the user expects to be at level II.  He is
    01862         //  expecting this Irp to be completed when the LevelII Oplock
    01863         //  is broken.
    01864         //
    01865
    01866         } else if (FlagOn( Oplock->OplockState, BREAK_TO_II_TO_NONE )) {
    01867
    01868             DebugTrace(0, Dbg, "AcknowledgeOplockBreak:  OplockItoIItoNone\n", 0);
    01869
    01870             Status = STATUS_SUCCESS;
    01871             Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    01872             FsRtlCompleteRequest( Irp, Status );
    01873             Oplock->OplockState = NoOplocksHeld;
    01874
    01875         } else {
    01876
    01877             Status = STATUS_INVALID_OPLOCK_PROTOCOL;
    01878             DebugTrace(0,
    01879                        Dbg,
    01880                        "No break underway -> %08lx\n",
    01881                        Status);
    01882
    01883             FsRtlCompleteRequest( Irp, Status );
    01884             try_return( Status );
    01885         }
    01886
    01887         //
    01888         //  Complete the waiting Irps and cleanup the oplock structure.
    01889         //
    01890
    01891         while (!IsListEmpty( &Oplock->WaitingIrps )) {
    01892
    01893             PWAITING_IRP WaitingIrp;
    01894
    01895             //
    01896             //  Remove the entry found and complete the Irp.
    01897             //
    01898
    01899             WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
    01900                                             WAITING_IRP,
    01901                                             Links );
    01902
    01903             FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    01904         }
    01905
    01906         if (DereferenceFileObject) {
    01907
    01908             ObDereferenceObject( Oplock->FileObject );
    01909         }
    01910
    01911         Oplock->FileObject = NULL;
    01912
    01913     try_exit:  NOTHING;
    01914     } finally {
    01915
    01916         //
    01917         //  Give up the oplock synchronization object.
    01918         //
    01919
    01920         if (AcquiredMutex) {
    01921
    01922             ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    01923         }
    01924
    01925         DebugTrace( -1, Dbg, "FsRtlAcknowledgeOplockBreak:  Exit -> %08x\n", Status );
    01926     }
    01927
    01928     return Status;
    01929 }

PNONOPAQUE_OPLOCK FsRtlAllocateOplock | ( |  | ) |

Definition at line 1221 of file oplock.c.

References Dbg, DebugTrace, ExFreePool(), ExInitializeFastMutex, _NONOPAQUE_OPLOCK::FastMutex, FsRtlpAllocatePool, _NONOPAQUE_OPLOCK::IrpOplocksII, NONOPAQUE_OPLOCK, NonPagedPool, NoOplocksHeld, NULL, _NONOPAQUE_OPLOCK::OplockState, PAGED_CODE, PagedPool, PNONOPAQUE_OPLOCK, and _NONOPAQUE_OPLOCK::WaitingIrps.

Referenced by FsRtlRequestExclusiveOplock(), and FsRtlRequestOplockII().

    01226                    :
    01227
    01228     This routine is called to initialize and allocate an opaque oplock
    01229     structure.  After allocation, the two events are set to the signalled
    01230     state.  The oplock state is set to NoOplocksHeld and the other
    01231     fields are filled with zeroes.
    01232
    01233     If the allocation fails, the appropriate status is raised.
    01234
    01235 Arguments:
    01236
    01237     None.
    01238
    01239 Return Value:
    01240
    01241     PNONOPAQUE_OPLOCK - A pointer to the allocated structure.
    01242
    01243 --*/
    01244
    01245 {
    01246     PNONOPAQUE_OPLOCK NewOplock = NULL;
    01247
    01248     PAGED_CODE();
    01249
    01250     DebugTrace( +1, Dbg, "FsRtlAllocateOplock:  Entered\n", 0);
    01251
    01252     //
    01253     //  Use a try-finally to facilitate cleanup.
    01254     //
    01255
    01256     try {
    01257
    01258         //
    01259         //  Raise an error status if the allocation is unsuccessful.
    01260         //  The structure is allocated out of non-paged pool.
    01261         //
    01262
    01263         NewOplock = FsRtlpAllocatePool( PagedPool, sizeof( NONOPAQUE_OPLOCK ));
    01264
    01265         RtlZeroMemory( NewOplock, sizeof( NONOPAQUE_OPLOCK ));
    01266
    01267         NewOplock->FastMutex = FsRtlpAllocatePool( NonPagedPool, sizeof( FAST_MUTEX ));
    01268
    01269         ExInitializeFastMutex( NewOplock->FastMutex );
    01270
    01271         InitializeListHead( &NewOplock->IrpOplocksII );
    01272         InitializeListHead( &NewOplock->WaitingIrps );
    01273
    01274         NewOplock->OplockState = NoOplocksHeld;
    01275
    01276     } finally {
    01277
    01278         //
    01279         //  Cleanup the oplock if abnormal termination.
    01280         //
    01281
    01282         if (AbnormalTermination() && NewOplock != NULL) {
    01283
    01284             ExFreePool( NewOplock );
    01285         }
    01286
    01287         DebugTrace(-1, Dbg, "GetOplockStructure:  Exit -> %08lx\n", NewOplock);
    01288     }
    01289
    01290     return NewOplock;
    01291 }

VOID FsRtlCancelExclusiveIrp | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp
| ) |

Definition at line 3519 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, _NONOPAQUE_OPLOCK::FastMutex, _NONOPAQUE_OPLOCK::FileObject, FsRtlCompleteRequest, FsRtlRemoveAndCompleteWaitIrp(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _NONOPAQUE_OPLOCK::IrpExclusiveOplock, NoOplocksHeld, NULL, ObDereferenceObject, _NONOPAQUE_OPLOCK::OplockState, PNONOPAQUE_OPLOCK, PWAITING_IRP, and _NONOPAQUE_OPLOCK::WaitingIrps.

Referenced by FsRtlRequestExclusiveOplock().

    03526                    :
    03527
    03528     This routine is called for either an exclusive or oplock I Irp.
    03529
    03530 Arguments:
    03531
    03532     DeviceObject - Ignored.
    03533
    03534     Irp - Supplies the Irp being cancelled.  A pointer to the
    03535           Oplock structure for the Irp is stored in the information
    03536           field of the Irp's Iosb.
    03537
    03538 Return Value:
    03539
    03540     None.
    03541
    03542 --*/
    03543
    03544 {
    03545     PNONOPAQUE_OPLOCK Oplock;
    03546
    03547     DebugTrace( +1, Dbg, "FsRtlCancelExclusiveIrp:  Entered\n", 0 );
    03548
    03549     Oplock = (PNONOPAQUE_OPLOCK) Irp->IoStatus.Information;
    03550
    03551     //
    03552     //  We now need to void the cancel routine and release the spinlock
    03553     //
    03554
    03555     IoSetCancelRoutine( Irp, NULL );
    03556     IoReleaseCancelSpinLock( Irp->CancelIrql );
    03557
    03558     //
    03559     //  Grab the synchronization object for this oplock.
    03560     //
    03561
    03562     ExAcquireFastMutex( Oplock->FastMutex );
    03563
    03564     try {
    03565
    03566         //
    03567         //  We look for the exclusive Irp, if present and cancelled
    03568         //  we complete it.
    03569         //
    03570
    03571         if ((Oplock->IrpExclusiveOplock != NULL) &&
    03572             (Oplock->IrpExclusiveOplock->Cancel)) {
    03573
    03574             FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_CANCELLED );
    03575             Oplock->IrpExclusiveOplock = NULL;
    03576
    03577             ObDereferenceObject( Oplock->FileObject );
    03578             Oplock->FileObject = NULL;
    03579             Oplock->OplockState = NoOplocksHeld;
    03580
    03581             //
    03582             //  Complete the waiting Irps.
    03583             //
    03584
    03585             while (!IsListEmpty( &Oplock->WaitingIrps )) {
    03586
    03587                 PWAITING_IRP WaitingIrp;
    03588
    03589                 //
    03590                 //  Remove the entry found and complete the Irp.
    03591                 //
    03592
    03593                 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
    03594                                                 WAITING_IRP,
    03595                                                 Links );
    03596
    03597                 FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    03598             }
    03599         }
    03600
    03601     } finally {
    03602
    03603         //
    03604         //  No matter how we exit we release the mutex
    03605         //
    03606
    03607         ExReleaseFastMutex( Oplock->FastMutex );
    03608
    03609         DebugTrace( -1, Dbg, "FsRtlCancelExclusiveIrp:  Exit\n", 0 );
    03610     }
    03611
    03612     return;
    03613
    03614     UNREFERENCED_PARAMETER( DeviceObject );
    03615 }

VOID FsRtlCancelOplockIIIrp | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp
| ) |

Definition at line 3396 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, FALSE, _NONOPAQUE_OPLOCK::FastMutex, FsRtlRemoveAndCompleteIrp(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _NONOPAQUE_OPLOCK::IrpOplocksII, NoOplocksHeld, NULL, _NONOPAQUE_OPLOCK::OplockState, PNONOPAQUE_OPLOCK, and TRUE.

Referenced by FsRtlAcknowledgeOplockBreak(), and FsRtlRequestOplockII().

    03403                    :
    03404
    03405     This routine is called for an Irp that is placed in the Oplock II
    03406     Irp queue.  We remove the Cancel routine from the specified Irp and
    03407     then call the completion routines for all the cancelled Irps on the
    03408     queue.
    03409
    03410 Arguments:
    03411
    03412     DeviceObject - Ignored.
    03413
    03414     Irp - Supplies the Irp being cancelled.  A pointer to the
    03415           Oplock structure for the Irp is stored in the information
    03416           field of the Irp's Iosb.
    03417
    03418 Return Value:
    03419
    03420     None.
    03421
    03422 --*/
    03423
    03424 {
    03425     PNONOPAQUE_OPLOCK Oplock;
    03426     BOOLEAN LevelIIIrps;
    03427
    03428     PLIST_ENTRY Links;
    03429
    03430     DebugTrace( +1, Dbg, "FsRtlCancelOplockIIIrp:  Entered\n", 0 );
    03431
    03432     Oplock = (PNONOPAQUE_OPLOCK) Irp->IoStatus.Information;
    03433
    03434     //
    03435     //  We now need to void the cancel routine and release the spinlock
    03436     //
    03437
    03438     IoSetCancelRoutine( Irp, NULL );
    03439     IoReleaseCancelSpinLock( Irp->CancelIrql );
    03440
    03441     LevelIIIrps = FALSE;
    03442
    03443     //
    03444     //  Iterate through all of the level II oplocks looking for a canceled one
    03445     //  We do this under the protection of the oplock mutex.
    03446     //
    03447
    03448     ExAcquireFastMutex( Oplock->FastMutex );
    03449
    03450     try {
    03451
    03452         for (Links = Oplock->IrpOplocksII.Flink;
    03453              Links != &Oplock->IrpOplocksII;
    03454              Links = Links->Flink ) {
    03455
    03456             PIRP OplockIIIrp;
    03457
    03458             //
    03459             //  Get a pointer to the Irp record
    03460             //
    03461
    03462             OplockIIIrp = CONTAINING_RECORD( Links, IRP, Tail.Overlay.ListEntry );
    03463
    03464             DebugTrace(0, Dbg, "FsRtlCancelOplockIIIrp, Loop top, Irp = %08lx\n", OplockIIIrp);
    03465
    03466             //
    03467             //  Check if the irp has been cancelled
    03468             //
    03469
    03470             if (OplockIIIrp->Cancel) {
    03471
    03472                 //
    03473                 //  Now we need to remove this waiter and call the
    03474                 //  completion routine.  But we must not mess up our link
    03475                 //  iteration so we need to back up link one step and
    03476                 //  then the next iteration will go to our current flink.
    03477                 //
    03478
    03479                 Links = Links->Blink;
    03480
    03481                 FsRtlRemoveAndCompleteIrp( Links->Flink );
    03482
    03483                 LevelIIIrps = TRUE;
    03484             }
    03485         }
    03486
    03487         //
    03488         //  If the list is now empty, change the oplock status to
    03489         //  no oplocks held.
    03490         //
    03491
    03492         if (LevelIIIrps && IsListEmpty( &Oplock->IrpOplocksII )) {
    03493
    03494             Oplock->OplockState = NoOplocksHeld;
    03495         }
    03496
    03497     } finally {
    03498
    03499         //
    03500         //  No matter how we exit we release the mutex
    03501         //
    03502
    03503         ExReleaseFastMutex( Oplock->FastMutex );
    03504
    03505         DebugTrace( -1, Dbg, "FsRtlCancelOplockIIIrp:  Exit\n", 0 );
    03506     }
    03507
    03508     return;
    03509
    03510     UNREFERENCED_PARAMETER( DeviceObject );
    03511 }

VOID FsRtlCancelWaitIrp | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp
| ) |

Definition at line 3288 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, _NONOPAQUE_OPLOCK::FastMutex, FsRtlRemoveAndCompleteWaitIrp(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, _WAITING_IRP::Irp, Irp, NULL, PNONOPAQUE_OPLOCK, PWAITING_IRP, and _NONOPAQUE_OPLOCK::WaitingIrps.

Referenced by FsRtlWaitOnIrp().

    03295                    :
    03296
    03297     This routine is called for an Irp that is placed on the waiting
    03298     Irp queue.  We remove the Cancel routine from the specified Irp and
    03299     then call the completion routines for all the cancelled Irps on the
    03300     queue.
    03301
    03302 Arguments:
    03303
    03304     DeviceObject - Ignored.
    03305
    03306     Irp - Supplies the Irp being cancelled.  A pointer to the
    03307           Oplock structure for the Irp is stored in the information
    03308           field of the Irp's Iosb.
    03309
    03310 Return Value:
    03311
    03312     None.
    03313
    03314 --*/
    03315
    03316 {
    03317     PNONOPAQUE_OPLOCK Oplock;
    03318
    03319     PLIST_ENTRY Links;
    03320
    03321     DebugTrace( +1, Dbg, "FsRtlCancelWaitIrp:  Entered\n", 0 );
    03322
    03323     Oplock = (PNONOPAQUE_OPLOCK) Irp->IoStatus.Information;
    03324
    03325     //
    03326     //  We now need to void the cancel routine and release the spinlock
    03327     //
    03328
    03329     IoSetCancelRoutine( Irp, NULL );
    03330     IoReleaseCancelSpinLock( Irp->CancelIrql );
    03331
    03332     //
    03333     //  Iterate through all of the waiting locks looking for a canceled one
    03334     //  We do this under the protection of the oplock mutex.
    03335     //
    03336
    03337     ExAcquireFastMutex( Oplock->FastMutex );
    03338
    03339     try {
    03340
    03341         for (Links = Oplock->WaitingIrps.Flink;
    03342              Links != &Oplock->WaitingIrps;
    03343              Links = Links->Flink ) {
    03344
    03345             PWAITING_IRP WaitingIrp;
    03346
    03347             //
    03348             //  Get a pointer to the waiting Irp record
    03349             //
    03350
    03351             WaitingIrp = CONTAINING_RECORD( Links, WAITING_IRP, Links );
    03352
    03353             DebugTrace(0, Dbg, "FsRtlCancelWaitIrp, Loop top, WaitingIrp = %08lx\n", WaitingIrp);
    03354
    03355             //
    03356             //  Check if the irp has been cancelled
    03357             //
    03358
    03359             if (WaitingIrp->Irp->Cancel) {
    03360
    03361                 //
    03362                 //  Now we need to remove this waiter and call the
    03363                 //  completion routine.  But we must not mess up our link
    03364                 //  iteration so we need to back up link one step and
    03365                 //  then the next iteration will go to our current flink.
    03366                 //
    03367
    03368                 Links = Links->Blink;
    03369
    03370                 FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    03371             }
    03372         }
    03373
    03374     } finally {
    03375
    03376         //
    03377         //  No matter how we exit we release the mutex
    03378         //
    03379
    03380         ExReleaseFastMutex( Oplock->FastMutex );
    03381
    03382         DebugTrace( -1, Dbg, "FsRtlCancelWaitIrp:  Exit\n", 0 );
    03383     }
    03384
    03385     return;
    03386
    03387     UNREFERENCED_PARAMETER( DeviceObject );
    03388 }

NTSTATUS FsRtlCheckOplock | ( | IN POPLOCK | Oplock,
|  | IN PIRP | Irp,
|  | IN PVOID | Context,
|  | IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine | OPTIONAL,
|  | IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine | OPTIONAL
| ) |

Definition at line 823 of file oplock.c.

References BATCH_OPLOCK, Dbg, DebugTrace, FALSE, _NONOPAQUE_OPLOCK::FileObject, _IO_STACK_LOCATION::FileObject, FILTER_OPLOCK, FILTER_OPLOCK_VALID_FLAGS, FlagOn, _IRP::Flags, FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), IoGetCurrentIrpStackLocation, Irp, IRP_MJ_CLEANUP, IRP_MJ_CREATE, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_LOCK_CONTROL, IRP_MJ_READ, IRP_MJ_SET_INFORMATION, IRP_MJ_WRITE, IRP_PAGING_IO, _IO_STACK_LOCATION::MajorFunction, NoOplocksHeld, NTSTATUS(), NULL, OPLOCK_STATE, OplockIIGranted, _NONOPAQUE_OPLOCK::OplockState, _IO_STACK_LOCATION::Parameters, PNONOPAQUE_OPLOCK, Status, and TRUE.

Referenced by UdfCommonCleanup(), UdfCommonLockControl(), UdfCommonRead(), and UdfCompleteFcbOpen().

    00833                    :
    00834
    00835     This routine is called as a support routine from a file system.
    00836     It is used to synchronize I/O requests with the current Oplock
    00837     state of a file.  If the I/O operation will cause the Oplock to
    00838     break, that action is initiated.  If the operation cannot continue
    00839     until the Oplock break is complete, STATUS_PENDING is returned and
    00840     the caller supplied routine is called.
    00841
    00842 Arguments:
    00843
    00844     Oplock - Supplies a pointer to the non-opaque oplock structure for
    00845              this file.
    00846
    00847     Irp - Supplies a pointer to the Irp which declares the requested
    00848           operation.
    00849
    00850     Context - This value is passed as a parameter to the completion routine.
    00851
    00852     CompletionRoutine - This is the routine which is called if this
    00853                         Irp must wait for an Oplock to break.  This
    00854                         is a synchronous operation if not specified
    00855                         and we block in this thread waiting on
    00856                         an event.
    00857
    00858     PostIrpRoutine - This is the routine to call before we put anything
    00859                      on our waiting Irp queue.
    00860
    00861 Return Value:
    00862
    00863     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    00864     STATUS_PENDING if we return here but hold the Irp.
    00865     STATUS_CANCELLED if the Irp is cancelled before we return.
    00866
    00867 --*/
    00868
    00869 {
    00870     NTSTATUS Status = STATUS_SUCCESS;
    00871     PNONOPAQUE_OPLOCK ThisOplock = *Oplock;
    00872
    00873     PIO_STACK_LOCATION IrpSp;
    00874
    00875     DebugTrace( +1, Dbg, "FsRtlCheckOplock:  Entered\n", 0 );
    00876     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    00877     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    00878
    00879     //
    00880     //  If there is no oplock structure or this is system I/O, we allow
    00881     //  the operation to continue.  Otherwise we check the major function code.
    00882     //
    00883
    00884     if ((ThisOplock != NULL) &&
    00885         !FlagOn( Irp->Flags, IRP_PAGING_IO )) {
    00886
    00887         OPLOCK_STATE OplockState;
    00888         PFILE_OBJECT OplockFileObject;
    00889
    00890         BOOLEAN BreakToII;
    00891         BOOLEAN BreakToNone;
    00892
    00893         ULONG CreateDisposition;
    00894
    00895         //
    00896         //  Capture the file object first and then the oplock state to perform
    00897         //  the unsafe checks below.  We capture the file object first in case
    00898         //  there is an exclusive oplock break in progress.  Otherwise the oplock
    00899         //  state may indicate break in progress but it could complete by
    00900         //  the time we snap the file object.
    00901         //
    00902
    00903         OplockFileObject = ThisOplock->FileObject;
    00904         OplockState = ThisOplock->OplockState;
    00905
    00906         //
    00907         //  Examine the Irp for the appropriate action provided there are
    00908         //  current oplocks on the file.
    00909         //
    00910
    00911         if (OplockState != NoOplocksHeld) {
    00912
    00913             BreakToII = FALSE;
    00914             BreakToNone = FALSE;
    00915
    00916             IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00917
    00918             //
    00919             //  Determine whether we are going to BreakToII or BreakToNone.
    00920             //
    00921
    00922             switch (IrpSp->MajorFunction) {
    00923
    00924             case IRP_MJ_CREATE :
    00925
    00926                 //
    00927                 //  If we are opening for attribute access only, we
    00928                 //  return status success.  Always break the oplock if this caller
    00929                 //  wants a filter oplock.
    00930                 //
    00931
    00932                 if (!FlagOn( IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
    00933                              ~(FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE) ) &&
    00934                     !FlagOn( IrpSp->Parameters.Create.Options, FILE_RESERVE_OPFILTER )) {
    00935
    00936                     break;
    00937                 }
    00938
    00939                 //
    00940                 //  If there is a filter oplock granted and this create iS reading
    00941                 //  the file then don't break the oplock as long as we share
    00942                 //  for reads.
    00943                 //
    00944
    00945                 if (FlagOn( OplockState, FILTER_OPLOCK ) &&
    00946                     !FlagOn( IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
    00947                              ~FILTER_OPLOCK_VALID_FLAGS ) &&
    00948                     FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ )) {
    00949
    00950                     break;
    00951                 }
    00952
    00953                 //
    00954                 //  We we are superseding or overwriting, then break to none.
    00955                 //
    00956
    00957                 CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff;
    00958
    00959                 if ((CreateDisposition == FILE_SUPERSEDE) ||
    00960                     (CreateDisposition == FILE_OVERWRITE) ||
    00961                     (CreateDisposition == FILE_OVERWRITE_IF) ||
    00962                     FlagOn( IrpSp->Parameters.Create.Options, FILE_RESERVE_OPFILTER )) {
    00963
    00964                     BreakToNone = TRUE;
    00965
    00966                 } else {
    00967
    00968                     BreakToII = TRUE;
    00969                 }
    00970
    00971                 break;
    00972
    00973             case IRP_MJ_READ :
    00974
    00975                 //
    00976                 //  If a filter oplock has been granted then do nothing.
    00977                 //  We will assume the oplock will have been broken
    00978                 //  if this create needed to do that.
    00979                 //
    00980
    00981                 if (!FlagOn( OplockState, FILTER_OPLOCK )) {
    00982
    00983                     BreakToII = TRUE;
    00984                 }
    00985
    00986                 break;
    00987
    00988             case IRP_MJ_FLUSH_BUFFERS :
    00989
    00990                 BreakToII = TRUE;
    00991                 break;
    00992
    00993             case IRP_MJ_CLEANUP :
    00994
    00995                 FsRtlOplockCleanup( (PNONOPAQUE_OPLOCK) *Oplock,
    00996                                     IrpSp );
    00997
    00998                 break;
    00999
    01000             case IRP_MJ_LOCK_CONTROL :
    01001
    01002                 //
    01003                 //  If a filter oplock has been granted then do nothing.
    01004                 //  We will assume the oplock will have been broken
    01005                 //  if this create needed to do that.
    01006                 //
    01007
    01008                 if (FlagOn( OplockState, FILTER_OPLOCK )) {
    01009
    01010                     break;
    01011                 }
    01012
    01013             case IRP_MJ_WRITE :
    01014
    01015                 BreakToNone = TRUE;
    01016                 break;
    01017
    01018             case IRP_MJ_SET_INFORMATION :
    01019
    01020                 //
    01021                 //  We are only interested in calls that shrink the file size
    01022                 //  or breaking batch oplocks for the rename case.
    01023                 //
    01024
    01025                 switch (IrpSp->Parameters.SetFile.FileInformationClass) {
    01026
    01027                 case FileEndOfFileInformation :
    01028
    01029                     //
    01030                     //  Break immediately if this is the lazy writer callback.
    01031                     //
    01032
    01033                     if (IrpSp->Parameters.SetFile.AdvanceOnly) {
    01034
    01035                         break;
    01036                     }
    01037
    01038                 case FileAllocationInformation :
    01039
    01040                     BreakToNone = TRUE;
    01041                     break;
    01042
    01043                 case FileRenameInformation :
    01044                 case FileLinkInformation :
    01045
    01046                     if (FlagOn( OplockState, BATCH_OPLOCK | FILTER_OPLOCK )) {
    01047
    01048                         BreakToNone = TRUE;
    01049                     }
    01050
    01051                     break;
    01052                 }
    01053
    01054             case IRP_MJ_FILE_SYSTEM_CONTROL :
    01055
    01056                 //
    01057                 //  We need to break to none if this is a zeroing operation.
    01058                 //
    01059
    01060                 if (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_SET_ZERO_DATA) {
    01061
    01062                     BreakToNone = TRUE;
    01063                 }
    01064             }
    01065
    01066             if (BreakToII) {
    01067
    01068                 //
    01069                 //  If there are no outstanding oplocks or level II oplocks are held,
    01070                 //  we can return immediately.  If the first two tests fail then there
    01071                 //  is an exclusive oplock.  If the file objects match we allow the
    01072                 //  operation to continue.
    01073                 //
    01074
    01075                 if ((OplockState != OplockIIGranted) &&
    01076                     (OplockFileObject != IrpSp->FileObject)) {
    01077
    01078                     Status = FsRtlOplockBreakToII( (PNONOPAQUE_OPLOCK) *Oplock,
    01079                                                     IrpSp,
    01080                                                     Irp,
    01081                                                     Context,
    01082                                                     CompletionRoutine,
    01083                                                     PostIrpRoutine );
    01084                 }
    01085
    01086             } else if (BreakToNone) {
    01087
    01088                 //
    01089                 //  If there are no oplocks, we can return immediately.
    01090                 //  Otherwise if there is no level 2 oplock and this file
    01091                 //  object matches the owning file object then this write is
    01092                 //  on behalf of the owner of the oplock.
    01093                 //
    01094
    01095                 if ((OplockState == OplockIIGranted) ||
    01096                     (OplockFileObject != IrpSp->FileObject)) {
    01097
    01098                     Status = FsRtlOplockBreakToNone( (PNONOPAQUE_OPLOCK) *Oplock,
    01099                                                       IrpSp,
    01100                                                       Irp,
    01101                                                       Context,
    01102                                                       CompletionRoutine,
    01103                                                       PostIrpRoutine );
    01104                 }
    01105             }
    01106         }
    01107     }
    01108
    01109     DebugTrace( -1, Dbg, "FsRtlCheckOplock:  Exit -> %08lx\n", Status );
    01110
    01111     return Status;
    01112 }

VOID FsRtlCompletionRoutinePriv | ( | IN PVOID | Context,
|  | IN PIRP | Irp
| ) |

Definition at line 3241 of file oplock.c.

References Dbg, DebugTrace, FALSE, Irp, KeSetEvent(), and PAGED_CODE.

Referenced by FsRtlWaitOnIrp().

    03248                    :
    03249
    03250     This routine is called when an operation must be synchronous with
    03251     respect to the oplock package.  This routine will simply set the
    03252     event in the Signalled state, allowing some other thread to resume
    03253     execution.
    03254
    03255 Arguments:
    03256
    03257     Context - This is the event to signal.
    03258
    03259     Irp - Supplies a pointer to the Irp which declares the requested
    03260           operation.
    03261
    03262 Return Value:
    03263
    03264     None.
    03265
    03266 --*/
    03267
    03268 {
    03269     PAGED_CODE();
    03270
    03271     DebugTrace( +1, Dbg, "FsRtlCompletionRoutinePriv:  Entered\n", 0 );
    03272
    03273     KeSetEvent( (PKEVENT)Context, 0, FALSE );
    03274
    03275     DebugTrace( -1, Dbg, "FsRtlCompletionRoutinePriv:  Exit\n", 0 );
    03276
    03277     return;
    03278
    03279     UNREFERENCED_PARAMETER( Irp );
    03280 }

BOOLEAN FsRtlCurrentBatchOplock | ( | IN POPLOCK | Oplock | ) |

Definition at line 1169 of file oplock.c.

References BATCH_OPLOCK, Dbg, DebugTrace, FALSE, FILTER_OPLOCK, FlagOn, NULL, PAGED_CODE, PNONOPAQUE_OPLOCK, and TRUE.

Referenced by UdfCompleteFcbOpen().

    01175                    :
    01176
    01177     This routines indicates whether there are current outstanding
    01178     batch oplocks.
    01179
    01180 Arguments:
    01181
    01182     OpLock - Supplies the oplock being queried
    01183
    01184 Return Value:
    01185
    01186     BOOLEAN - TRUE if there are outstanding batch oplocks and FALSE otherwise
    01187
    01188 --*/
    01189
    01190 {
    01191     BOOLEAN BatchOplocks = FALSE;
    01192
    01193     PAGED_CODE();
    01194
    01195     DebugTrace(+1, Dbg, "FsRtlCurrentBatchOplock: Oplock -> %08lx\n", *Oplock);
    01196
    01197     //
    01198     //  There are not any current oplocks if the variable is null or
    01199     //  the state is no oplocks held.  We check whether there are batch
    01200     //  oplocks or filter oplocks which have not been broken.
    01201     //
    01202
    01203     if ((*Oplock != NULL) &&
    01204         FlagOn( ((PNONOPAQUE_OPLOCK) *Oplock)->OplockState,
    01205                 BATCH_OPLOCK | FILTER_OPLOCK )) {
    01206
    01207         BatchOplocks = TRUE;
    01208     }
    01209
    01210     DebugTrace(-1, Dbg, "FsRtlCurrentBatchOplock: Exit -> %08lx\n", BatchOplocks);
    01211
    01212     return BatchOplocks;
    01213 }

VOID FsRtlInitializeOplock | ( | IN OUT POPLOCK | Oplock | ) |

Definition at line 373 of file oplock.c.

References Dbg, DebugTrace, and PAGED_CODE.

    00379                    :
    00380
    00381     This routine initializes a new OPLOCK structure.  This call must
    00382     precede any other call to this entry point with this OPLOCK
    00383     structure.  In addition, this routine will have exclusive access
    00384     to the Oplock structure.
    00385
    00386 Arguments:
    00387
    00388     Oplock - Supplies the address of an opaque OPLOCK structure.
    00389
    00390 Return Value:
    00391
    00392     None.
    00393
    00394 --*/
    00395
    00396 {
    00397     UNREFERENCED_PARAMETER( Oplock );
    00398
    00399     PAGED_CODE();
    00400
    00401     DebugTrace(+1, Dbg, "FsRtlInitializeOplock:  Oplock -> %08lx\n", *Oplock );
    00402
    00403     //
    00404     //  No action is taken at this time.
    00405     //
    00406
    00407     DebugTrace(-1, Dbg, "FsRtlInitializeOplock:  Exit\n", 0);
    00408     return;
    00409 }

VOID FsRtlNotifyCompletion | ( | IN PVOID | Context,
|  | IN PIRP | Irp
| ) |

Definition at line 3698 of file oplock.c.

References Dbg, DebugTrace, FsRtlCompleteRequest, _IRP::IoStatus, Irp, and PAGED_CODE.

Referenced by FsRtlOplockBreakNotify().

    03705                    :
    03706
    03707     This is the completion routine called when a break notify Irp is to
    03708     be completed.  We simply call FsRtlComplete request to dispose of the
    03709     Irp.
    03710
    03711 Arguments:
    03712
    03713     Context - Ignored.
    03714
    03715     Irp - Irp used to request break notify.
    03716
    03717 Return Value:
    03718
    03719     None.
    03720
    03721 --*/
    03722
    03723 {
    03724     PAGED_CODE();
    03725
    03726     DebugTrace( +1, Dbg, "FsRtlNotifyCompletion:  Entered\n", 0 );
    03727
    03728     //
    03729     //  Call FsRtlCompleteRequest using the value in the Irp.
    03730     //
    03731
    03732     FsRtlCompleteRequest( Irp, Irp->IoStatus.Status );
    03733
    03734     DebugTrace( -1, Dbg, "FsRtlNotifyCompletion:  Exit\n", 0 );
    03735
    03736     return;
    03737 }
    }

NTSTATUS FsRtlOpBatchBreakClosePending | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP | Irp
| ) |

Definition at line 1937 of file oplock.c.

References BREAK_TO_II, BREAK_TO_II_TO_NONE, BREAK_TO_NONE, ClearFlag, CLOSE_PENDING, Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), FlagOn, FsRtlCompleteRequest, FsRtlRemoveAndCompleteWaitIrp(), Irp, LEVEL_I_OPLOCK, NoOplocksHeld, NTSTATUS(), NULL, ObDereferenceObject, OPLOCK_BREAK_MASK, PAGED_CODE, PENDING, PWAITING_IRP, SetFlag, Status, and TRUE.

Referenced by FsRtlOplockFsctrl().

    01945                    :
    01946
    01947     This routine is called when a user is acknowledging a batch oplock
    01948     break or Level I oplock break.  In this case the user is planning
    01949     to close the file as well and doesn't need a level II oplock.
    01950
    01951 Arguments:
    01952
    01953     Oplock - Supplies a pointer to the non-opaque oplock structure for
    01954              this file.
    01955
    01956     IrpSp - This is the Irp stack location for the current Irp.
    01957
    01958     Irp - Supplies a pointer to the Irp which declares the requested
    01959           operation.
    01960
    01961 Return Value:
    01962
    01963     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    01964     STATUS_CANCELLED if the Irp is cancelled before we return.
    01965
    01966 --*/
    01967
    01968 {
    01969     NTSTATUS Status = STATUS_SUCCESS;
    01970
    01971     BOOLEAN AcquiredMutex;
    01972
    01973     PAGED_CODE();
    01974
    01975     DebugTrace( +1, Dbg, "FsRtlOpBatchBreakClosePending:  Entered\n", 0 );
    01976     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    01977     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    01978     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    01979
    01980     //
    01981     //  If there is no oplock structure, we complete this with invalid
    01982     //  oplock protocol.
    01983     //
    01984
    01985     if (Oplock == NULL) {
    01986
    01987         FsRtlCompleteRequest( Irp, STATUS_INVALID_OPLOCK_PROTOCOL );
    01988         DebugTrace( -1, Dbg, "FsRtlOpBatchClosePending:  Exit -> %08lx\n", STATUS_INVALID_OPLOCK_PROTOCOL );
    01989         return STATUS_INVALID_OPLOCK_PROTOCOL;
    01990     }
    01991
    01992     //
    01993     //  Grab the synchronization object for the oplock.
    01994     //
    01995
    01996     ExAcquireFastMutexUnsafe( Oplock->FastMutex );
    01997     AcquiredMutex = TRUE;
    01998
    01999     //
    02000     //  Use a try_finally to facilitate cleanup.
    02001     //
    02002
    02003     try {
    02004
    02005         //
    02006         //  If a break is underway but this is not the owner of the
    02007         //  level 1 oplock, we complete the request and return a
    02008         //  warning.
    02009         //
    02010
    02011         if (Oplock->FileObject != IrpSp->FileObject) {
    02012
    02013             Status = STATUS_INVALID_OPLOCK_PROTOCOL;
    02014             DebugTrace(0,
    02015                        Dbg,
    02016                        "Not oplock owner -> %08lx\n",
    02017                        Status);
    02018
    02019         } else {
    02020
    02021             //
    02022             //  If this is an opbatch operation we want to note that a
    02023             //  close is pending.  For an exclusive oplock we set the state to
    02024             //  no oplocsk held.  There must be a break in progress to
    02025             //  process however.
    02026             //
    02027
    02028             if (FlagOn( Oplock->OplockState,
    02029                         BREAK_TO_II | BREAK_TO_NONE | BREAK_TO_II_TO_NONE )) {
    02030
    02031                 //
    02032                 //  Break all oplocks for an exclusive oplock.
    02033                 //
    02034
    02035                 if (FlagOn( Oplock->OplockState, LEVEL_I_OPLOCK | PENDING )) {
    02036
    02037                     //
    02038                     //  Clean up the oplock structure and complete all waiting Irps.
    02039                     //
    02040
    02041                     if (FlagOn( Oplock->OplockState, LEVEL_I_OPLOCK )) {
    02042
    02043                         ObDereferenceObject( Oplock->FileObject );
    02044                     }
    02045
    02046                     Oplock->OplockState = NoOplocksHeld;
    02047                     Oplock->FileObject = NULL;
    02048
    02049                     while (!IsListEmpty( &Oplock->WaitingIrps )) {
    02050
    02051                         PWAITING_IRP WaitingIrp;
    02052
    02053                         //
    02054                         //  Remove the entry found and complete the Irp.
    02055                         //
    02056
    02057                         WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
    02058                                                         WAITING_IRP,
    02059                                                         Links );
    02060
    02061                         FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    02062                     }
    02063
    02064                 //
    02065                 //  Set the state to close pending for batch and filter
    02066                 //  oplocks.
    02067                 //
    02068
    02069                 } else {
    02070
    02071                     ClearFlag( Oplock->OplockState, OPLOCK_BREAK_MASK );
    02072                     SetFlag( Oplock->OplockState, CLOSE_PENDING );
    02073                 }
    02074
    02075             } else {
    02076
    02077                 Status = STATUS_INVALID_OPLOCK_PROTOCOL;
    02078                 DebugTrace(0,
    02079                            Dbg,
    02080                            "No break underway -> %08lx\n",
    02081                            Status);
    02082             }
    02083         }
    02084
    02085         //
    02086         //  We simply complete this request.
    02087         //
    02088
    02089         FsRtlCompleteRequest( Irp, Status );
    02090
    02091     } finally {
    02092
    02093         //
    02094         //  Release the synchronization object.
    02095         //
    02096
    02097         ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    02098
    02099         DebugTrace(-1, Dbg, "FsRtlOpBatchBreakClosePending:  Exit -> %08lx\n", Status);
    02100     }
    02101
    02102     return Status;
    02103 }

NTSTATUS FsRtlOplockBreakNotify | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP | Irp
| ) |

Definition at line 2111 of file oplock.c.

References Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), FALSE, FlagOn, FsRtlCompleteRequest, FsRtlNotifyCompletion(), FsRtlWaitOnIrp(), _IRP::IoStatus, Irp, NoOplocksHeld, NTSTATUS(), NULL, OPLOCK_BREAK_MASK, PAGED_CODE, PENDING, Status, TRUE, and try_return.

Referenced by FsRtlOplockFsctrl().

    02119                    :
    02120
    02121     This routine is called when the Irp refers the user request to
    02122     be notified when there is no level 1 oplock break in progress.
    02123     Under any other condition this routine completes immediately with
    02124     STATUS_SUCCESS.  Otherwise we simply add this Irp to the list
    02125     of Irp's waiting for the break to complete.
    02126
    02127 Arguments:
    02128
    02129     Oplock - Supplies a pointer to the non-opaque oplock structure for
    02130              this file.
    02131
    02132     IrpSp - This is the Irp stack location for the current Irp.
    02133
    02134     Irp - Supplies a pointer to the Irp which declares the requested
    02135           operation.
    02136
    02137 Return Value:
    02138
    02139     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    02140     STATUS_PENDING if we return here but hold the Irp.
    02141     STATUS_CANCELLED if the Irp is cancelled before we return.
    02142
    02143 --*/
    02144
    02145 {
    02146     NTSTATUS Status;
    02147
    02148     BOOLEAN AcquiredMutex;
    02149
    02150     PAGED_CODE();
    02151
    02152     DebugTrace( +1, Dbg, "FsRtlOplockBreakNotify:  Entered\n", 0 );
    02153     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    02154     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    02155     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    02156
    02157     //
    02158     //  If there is no oplock structure, we complete this with status success.
    02159     //
    02160
    02161     if (Oplock == NULL) {
    02162
    02163         FsRtlCompleteRequest( Irp, STATUS_SUCCESS );
    02164         DebugTrace( -1, Dbg, "FsRtlOpBatchClosePending:  Exit -> %08lx\n", STATUS_SUCCESS );
    02165         return STATUS_SUCCESS;
    02166     }
    02167
    02168     //
    02169     //  Grap the synchronization object.
    02170     //
    02171
    02172     ExAcquireFastMutexUnsafe( Oplock->FastMutex );
    02173     AcquiredMutex = TRUE;
    02174
    02175     //
    02176     //  Use a try-finally to facilitate cleanup.
    02177     //
    02178
    02179     try {
    02180
    02181         //
    02182         //  If there are no outstanding level 1 oplocks breaks underway
    02183         //  or batch oplock breaks underway we complete immediately.
    02184         //
    02185
    02186         if (!FlagOn( Oplock->OplockState, OPLOCK_BREAK_MASK )) {
    02187
    02188             DebugTrace(0,
    02189                        Dbg,
    02190                        "No exclusive oplock break underway\n",
    02191                        0);
    02192
    02193             FsRtlCompleteRequest( Irp, STATUS_SUCCESS );
    02194             try_return( Status = STATUS_SUCCESS );
    02195
    02196         } else if (FlagOn( Oplock->OplockState, PENDING )) {
    02197
    02198             Oplock->OplockState = NoOplocksHeld;
    02199             Oplock->FileObject = NULL;
    02200
    02201             FsRtlCompleteRequest( Irp, STATUS_SUCCESS );
    02202             try_return( Status = STATUS_SUCCESS );
    02203         }
    02204
    02205         //
    02206         //  Otherwise we need to add this Irp to the list of Irp's waiting
    02207         //  for the oplock break to complete.
    02208         //
    02209
    02210         AcquiredMutex = FALSE;
    02211
    02212         //
    02213         //  Initialize the return value to status success.
    02214         //
    02215
    02216         Irp->IoStatus.Status = STATUS_SUCCESS;
    02217
    02218         Status = FsRtlWaitOnIrp( Oplock,
    02219                                  Irp,
    02220                                  NULL,
    02221                                  FsRtlNotifyCompletion,
    02222                                  NULL,
    02223                                  NULL );
    02224
    02225     try_exit:  NOTHING;
    02226     } finally {
    02227
    02228         //
    02229         //  Give up the synchronization event if we haven't done so.
    02230         //
    02231
    02232         if (AcquiredMutex) {
    02233
    02234             ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    02235         }
    02236
    02237         DebugTrace( -1, Dbg, "FsRtlOplockBreakNotify:  Exit -> %08lx\n", Status );
    02238     }
    02239
    02240     return Status;
    02241 }

NTSTATUS FsRtlOplockBreakToII | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP | Irp,
|  | IN PVOID | Context,
|  | IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine | OPTIONAL,
|  | IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine | OPTIONAL
| ) |

Definition at line 2454 of file oplock.c.

References BATCH_OPLOCK, BREAK_TO_II, BREAK_TO_NONE, _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, Event(), ExAcquireFastMutexUnsafe(), EXCLUSIVE, ExReleaseFastMutexUnsafe(), FALSE, FlagOn, FsRtlCompleteRequest, FsRtlRemoveAndCompleteWaitIrp(), FsRtlWaitOnIrp(), IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, IRP_MJ_CREATE, LEVEL_I_OPLOCK, NoOplocksHeld, NTSTATUS(), NULL, ObDereferenceObject, OPLOCK_BREAK_MASK, PENDING, PWAITING_IRP, SetFlag, Status, TRUE, and try_return.

Referenced by FsRtlCheckOplock().

    02465                    :
    02466
    02467     This routine is a generic worker routine which is called when an
    02468     operation will cause all oplocks to be broken to level II before the
    02469     operation can proceed.
    02470
    02471 Arguments:
    02472
    02473     Oplock - Supplies a pointer to the non-opaque oplock structure for
    02474              this file.
    02475
    02476     IrpSp - This is the Irp stack location for the current Irp.
    02477
    02478     Irp - Supplies a pointer to the Irp which declares the requested
    02479           operation.
    02480
    02481     Context - This value is passed as a parameter to the completion routine.
    02482
    02483     CompletionRoutine - This is the routine which is called if this
    02484                         Irp must wait for an Oplock to break.  This
    02485                         is a synchronous operation if not specified
    02486                         and we block in this thread waiting on
    02487                         an event.
    02488
    02489     PostIrpRoutine - This is the routine to call before we put anything
    02490                      on our waiting Irp queue.
    02491
    02492 Return Value:
    02493
    02494     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    02495     STATUS_PENDING if we return here but hold the Irp.
    02496     STATUS_CANCELLED if the Irp is cancelled before we return.
    02497
    02498 --*/
    02499
    02500 {
    02501     KEVENT Event;
    02502     NTSTATUS Status;
    02503
    02504     BOOLEAN AcquiredMutex;
    02505
    02506     DebugTrace( +1, Dbg, "CheckOplockBreakToII:  Entered\n", 0 );
    02507     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    02508     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    02509     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    02510
    02511     //
    02512     //  Grap the synchronization object.
    02513     //
    02514
    02515     ExAcquireFastMutexUnsafe( Oplock->FastMutex );
    02516     AcquiredMutex = TRUE;
    02517
    02518     //
    02519     //  Use a try-finally to facilitate cleanup.
    02520     //
    02521
    02522     try {
    02523
    02524         //
    02525         //  If there are no outstanding oplocks or level II oplocks are held,
    02526         //  we can return immediately.
    02527         //
    02528
    02529         if (!FlagOn( Oplock->OplockState, EXCLUSIVE )) {
    02530
    02531             DebugTrace(0,
    02532                        Dbg,
    02533                        "No oplocks or level II oplocks on file\n",
    02534                        0);
    02535
    02536             try_return( Status = STATUS_SUCCESS );
    02537         }
    02538
    02539         //
    02540         //  At this point there is an exclusive oplock break in progress.
    02541         //  If this file object owns that oplock, we allow the operation
    02542         //  to continue.
    02543         //
    02544
    02545         if (Oplock->FileObject == IrpSp->FileObject) {
    02546
    02547             DebugTrace(0,
    02548                        Dbg,
    02549                        "Handle owns level 1 oplock\n",
    02550                        0);
    02551
    02552             try_return( Status = STATUS_SUCCESS );
    02553         }
    02554
    02555         //
    02556         //  If there is currently an exclusive oplock held then complete
    02557         //  the exclusive irp.
    02558         //
    02559
    02560         if (!FlagOn( Oplock->OplockState, PENDING | OPLOCK_BREAK_MASK )) {
    02561
    02562             PIRP IrpExclusive = Oplock->IrpExclusiveOplock;
    02563
    02564             DebugTrace(0,
    02565                        Dbg,
    02566                        "Breaking exclusive oplock\n",
    02567                        0);
    02568
    02569             IoAcquireCancelSpinLock( &IrpExclusive->CancelIrql );
    02570             IoSetCancelRoutine( IrpExclusive, NULL );
    02571             IoReleaseCancelSpinLock( IrpExclusive->CancelIrql );
    02572
    02573             //
    02574             //  If the Irp has been cancelled, we complete the Irp with
    02575             //  status cancelled and break the oplock completely.
    02576             //
    02577
    02578             if (IrpExclusive->Cancel) {
    02579
    02580                 IrpExclusive->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    02581                 FsRtlCompleteRequest( IrpExclusive, STATUS_CANCELLED );
    02582                 Oplock->OplockState = NoOplocksHeld;
    02583                 Oplock->IrpExclusiveOplock = NULL;
    02584
    02585                 ObDereferenceObject( Oplock->FileObject );
    02586                 Oplock->FileObject = NULL;
    02587
    02588                 //
    02589                 //  Release any waiting irps.
    02590                 //
    02591
    02592                 while (!IsListEmpty( &Oplock->WaitingIrps )) {
    02593
    02594                     PWAITING_IRP WaitingIrp;
    02595
    02596                     WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
    02597                                                     WAITING_IRP,
    02598                                                     Links );
    02599
    02600                     FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    02601                 }
    02602
    02603                 try_return( Status = STATUS_SUCCESS );
    02604
    02605             } else {
    02606
    02607                 NTSTATUS CompletionStatus;
    02608
    02609                 if (FlagOn( Oplock->OplockState, LEVEL_I_OPLOCK | BATCH_OPLOCK )) {
    02610
    02611                     SetFlag( Oplock->OplockState, BREAK_TO_II );
    02612                     CompletionStatus = FILE_OPLOCK_BROKEN_TO_LEVEL_2;
    02613
    02614                 } else {
    02615
    02616                     SetFlag( Oplock->OplockState, BREAK_TO_NONE );
    02617                     CompletionStatus = FILE_OPLOCK_BROKEN_TO_NONE;
    02618                 }
    02619
    02620                 Oplock->IrpExclusiveOplock->IoStatus.Information = CompletionStatus;
    02621                 FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_SUCCESS );
    02622                 Oplock->IrpExclusiveOplock = NULL;
    02623             }
    02624
    02625         //
    02626         //  If there is a pending opfilter request then clear the request.
    02627         //
    02628
    02629         } else if (FlagOn( Oplock->OplockState, PENDING )) {
    02630
    02631             Oplock->OplockState = NoOplocksHeld;
    02632             Oplock->FileObject = NULL;
    02633
    02634             try_return( Status = STATUS_SUCCESS );
    02635         }
    02636
    02637         //
    02638         //  If this is an open operation and the user doesn't want to
    02639         //  block, we will complete the operation now.
    02640         //
    02641
    02642         if ((IrpSp->MajorFunction == IRP_MJ_CREATE) &&
    02643             FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) {
    02644
    02645             DebugTrace( 0, Dbg, "Don't block open\n", 0 );
    02646
    02647             try_return( Status = STATUS_OPLOCK_BREAK_IN_PROGRESS );
    02648         }
    02649
    02650         //
    02651         //  If we get here that means that this operation can't continue
    02652         //  until the oplock break is complete.
    02653         //
    02654         //  FsRtlWaitOnIrp will release the mutex.
    02655         //
    02656
    02657         AcquiredMutex = FALSE;
    02658
    02659         Status = FsRtlWaitOnIrp( Oplock,
    02660                                  Irp,
    02661                                  Context,
    02662                                  CompletionRoutine,
    02663                                  PostIrpRoutine,
    02664                                  &Event );
    02665
    02666     try_exit:  NOTHING;
    02667     } finally {
    02668
    02669         //
    02670         //  Give up the synchronization event if we haven't done so.
    02671         //
    02672
    02673         if (AcquiredMutex) {
    02674
    02675             ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    02676         }
    02677
    02678         DebugTrace( -1, Dbg, "FsRtlOplockBreakToII:  Exit -> %08lx\n", Status );
    02679     }
    02680
    02681     return Status;
    02682 }

NTSTATUS FsRtlOplockBreakToNone | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP | Irp,
|  | IN PVOID | Context,
|  | IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine | OPTIONAL,
|  | IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine | OPTIONAL
| ) |

Definition at line 2690 of file oplock.c.

References BREAK_TO_II, BREAK_TO_II_TO_NONE, BREAK_TO_NONE, _IRP::Cancel, _IRP::CancelIrql, ClearFlag, Dbg, DebugTrace, Event(), ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), FALSE, FlagOn, FsRtlCompleteRequest, FsRtlRemoveAndCompleteIrp(), FsRtlRemoveAndCompleteWaitIrp(), FsRtlWaitOnIrp(), IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, IRP_MJ_CREATE, LEVEL_II_OPLOCK, NoOplocksHeld, NTSTATUS(), NULL, ObDereferenceObject, OPLOCK_BREAK_MASK, OplockIIGranted, PENDING, PWAITING_IRP, SetFlag, Status, TRUE, and try_return.

Referenced by FsRtlCheckOplock().

    02701                    :
    02702
    02703     This routine is a generic worker routine which is called when an
    02704     operation will cause all oplocks to be broken before the operation can
    02705     proceed.
    02706
    02707 Arguments:
    02708
    02709     Oplock - Supplies a pointer to the non-opaque oplock structure for
    02710              this file.
    02711
    02712     IrpSp - This is the Irp stack location for the current Irp.
    02713
    02714     Irp - Supplies a pointer to the Irp which declares the requested
    02715           operation.
    02716
    02717     Context - This value is passed as a parameter to the completion routine.
    02718
    02719     CompletionRoutine - This is the routine which is called if this
    02720                         Irp must wait for an Oplock to break.  This
    02721                         is a synchronous operation if not specified
    02722                         and we block in this thread waiting on
    02723                         an event.
    02724
    02725     PostIrpRoutine - This is the routine to call before we put anything
    02726                      on our waiting Irp queue.
    02727
    02728 Return Value:
    02729
    02730     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    02731     STATUS_PENDING if we return here but hold the Irp.
    02732     STATUS_CANCELLED if the Irp is cancelled before we return.
    02733
    02734 --*/
    02735
    02736 {
    02737     KEVENT Event;
    02738     NTSTATUS Status;
    02739
    02740     BOOLEAN AcquiredMutex;
    02741
    02742     DebugTrace( +1, Dbg, "CheckOplockBreakToNone:  Entered\n", 0 );
    02743     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    02744     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    02745     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    02746
    02747     //
    02748     //  Grap the synchronization object.
    02749     //
    02750
    02751     ExAcquireFastMutexUnsafe( Oplock->FastMutex );
    02752     AcquiredMutex = TRUE;
    02753
    02754     //
    02755     //  Use a try-finally to facilitate cleanup.
    02756     //
    02757
    02758     try {
    02759
    02760         //
    02761         //  If there are no outstanding oplocks, we can return immediately.
    02762         //
    02763
    02764         if (Oplock->OplockState == NoOplocksHeld) {
    02765
    02766             DebugTrace(0,
    02767                        Dbg,
    02768                        "No oplocks on file\n",
    02769                        0);
    02770
    02771             try_return( Status = STATUS_SUCCESS );
    02772         }
    02773
    02774         //
    02775         //  If there is an exclusive oplock held, we begin the break to none.
    02776         //
    02777
    02778         if (!FlagOn( Oplock->OplockState,
    02779                      LEVEL_II_OPLOCK | PENDING | OPLOCK_BREAK_MASK )) {
    02780
    02781             PIRP IrpExclusive = Oplock->IrpExclusiveOplock;
    02782
    02783             DebugTrace(0,
    02784                        Dbg,
    02785                        "Breaking exclusive oplock\n",
    02786                        0);
    02787
    02788             IoAcquireCancelSpinLock( &IrpExclusive->CancelIrql );
    02789             IoSetCancelRoutine( IrpExclusive, NULL );
    02790             IoReleaseCancelSpinLock( IrpExclusive->CancelIrql );
    02791
    02792             //
    02793             //  If the Irp has been cancelled, we complete the Irp with
    02794             //  status cancelled and break the oplock completely.
    02795             //
    02796
    02797             if (IrpExclusive->Cancel) {
    02798
    02799                 IrpExclusive->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    02800                 FsRtlCompleteRequest( IrpExclusive, STATUS_CANCELLED );
    02801                 Oplock->OplockState = NoOplocksHeld;
    02802                 Oplock->IrpExclusiveOplock = NULL;
    02803
    02804                 ObDereferenceObject( Oplock->FileObject );
    02805                 Oplock->FileObject = NULL;
    02806
    02807                 //
    02808                 //  Release any waiting irps.
    02809                 //
    02810
    02811                 while (!IsListEmpty( &Oplock->WaitingIrps )) {
    02812
    02813                     PWAITING_IRP WaitingIrp;
    02814
    02815                     WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
    02816                                                     WAITING_IRP,
    02817                                                     Links );
    02818
    02819                     FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    02820                 }
    02821
    02822                 try_return( Status = STATUS_SUCCESS );
    02823
    02824             } else {
    02825
    02826                 Oplock->IrpExclusiveOplock->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    02827                 FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_SUCCESS );
    02828                 Oplock->IrpExclusiveOplock = NULL;
    02829
    02830                 SetFlag( Oplock->OplockState, BREAK_TO_NONE );
    02831             }
    02832
    02833         //
    02834         //  If there are level II oplocks, this will break all of them.
    02835         //
    02836
    02837         } else if (Oplock->OplockState == OplockIIGranted) {
    02838
    02839             DebugTrace(0,
    02840                        Dbg,
    02841                        "Breaking all level 2 oplocks\n",
    02842                        0);
    02843
    02844             while (!IsListEmpty( &Oplock->IrpOplocksII )) {
    02845
    02846                 //
    02847                 //  Remove and complete this Irp with STATUS_SUCCESS.
    02848                 //
    02849
    02850                 FsRtlRemoveAndCompleteIrp( Oplock->IrpOplocksII.Flink );
    02851             }
    02852
    02853             //
    02854             //  Set the oplock state to no oplocks held.
    02855             //
    02856
    02857             Oplock->OplockState = NoOplocksHeld;
    02858
    02859             try_return( Status = STATUS_SUCCESS );
    02860
    02861         //
    02862         //  If we are currently breaking to level II then change that
    02863         //  to BreakToIIToNone.
    02864         //
    02865
    02866         } else if (FlagOn( Oplock->OplockState, BREAK_TO_II )) {
    02867
    02868             ClearFlag( Oplock->OplockState, BREAK_TO_II );
    02869             SetFlag( Oplock->OplockState, BREAK_TO_II_TO_NONE );
    02870
    02871         //
    02872         //  If there is a pending opfilter request then clear that request.
    02873         //
    02874
    02875         } else if (FlagOn( Oplock->OplockState, PENDING )) {
    02876
    02877             Oplock->OplockState = NoOplocksHeld;
    02878             Oplock->FileObject = NULL;
    02879
    02880             try_return( Status = STATUS_SUCCESS );
    02881         }
    02882
    02883         //
    02884         //  At this point there is already an exclusive oplock break in progress.
    02885         //  If this file object owns that oplock, we allow the operation
    02886         //  to continue.
    02887         //
    02888
    02889         if (Oplock->FileObject == IrpSp->FileObject) {
    02890
    02891             DebugTrace(0,
    02892                        Dbg,
    02893                        "Handle owns level 1 oplock\n",
    02894                        0);
    02895
    02896             try_return( Status = STATUS_SUCCESS );
    02897         }
    02898
    02899         //
    02900         //  If this is an open operation and the user doesn't want to
    02901         //  block, we will complete the operation now.
    02902         //
    02903
    02904         if ((IrpSp->MajorFunction == IRP_MJ_CREATE) &&
    02905             FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) {
    02906
    02907             DebugTrace( 0, Dbg, "Don't block open\n", 0 );
    02908
    02909             try_return( Status = STATUS_OPLOCK_BREAK_IN_PROGRESS );
    02910         }
    02911
    02912         //
    02913         //  If we get here that means that this operation can't continue
    02914         //  until the oplock break is complete.
    02915         //
    02916         //  FsRtlWaitOnIrp will release the mutex.
    02917         //
    02918
    02919         AcquiredMutex = FALSE;
    02920
    02921         Status = FsRtlWaitOnIrp( Oplock,
    02922                                  Irp,
    02923                                  Context,
    02924                                  CompletionRoutine,
    02925                                  PostIrpRoutine,
    02926                                  &Event );
    02927
    02928     try_exit:  NOTHING;
    02929     } finally {
    02930
    02931         //
    02932         //  Give up the synchronization event if we haven't done so.
    02933         //
    02934
    02935         if (AcquiredMutex) {
    02936
    02937             ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    02938         }
    02939
    02940         DebugTrace( -1, Dbg, "CheckOplockBreakToNone:  Exit -> %08lx\n", Status );
    02941     }
    02942
    02943     return Status;
    02944 }

VOID FsRtlOplockCleanup | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp
| ) |

Definition at line 2249 of file oplock.c.

References _IRP::CancelIrql, Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), _IO_STACK_LOCATION::FileObject, FlagOn, FsRtlCompleteRequest, FsRtlRemoveAndCompleteIrp(), FsRtlRemoveAndCompleteWaitIrp(), IoAcquireCancelSpinLock(), IoGetCurrentIrpStackLocation, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, NoOplocksHeld, NULL, ObDereferenceObject, OPLOCK_BREAK_MASK, OplockIIGranted, PENDING, PWAITING_IRP, and try_return.

Referenced by FsRtlCheckOplock().

    02256                    :
    02257
    02258     This routine is called to coordinate a cleanup operation with the
    02259     oplock state for a file.  If there is no level 1 oplock for the
    02260     file, then there is no action to take.  If the file object in this
    02261     Irp matches the file object used in granting the level 1 oplock,
    02262     then the close operation will terminate the oplock.  If this
    02263     cleanup refers to a file object which has a level II oplock, then
    02264     that Irp is completed and removed from the list of level II
    02265     oplocked Irps.
    02266
    02267
    02268 Arguments:
    02269
    02270     Oplock - Supplies a pointer to the non-opaque oplock structure for
    02271              this file.
    02272
    02273     IrpSp - This is the Irp stack location for the current Irp.
    02274
    02275 Return Value:
    02276
    02277     None.
    02278
    02279 --*/
    02280
    02281 {
    02282     DebugTrace( +1, Dbg, "FsRtlOplockCleanup:  Entered\n", 0 );
    02283     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    02284     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    02285
    02286     //
    02287     //  Grab the synchronization object for the oplock.
    02288     //
    02289
    02290     ExAcquireFastMutexUnsafe( Oplock->FastMutex );
    02291
    02292     //
    02293     //  Use a try-finally to facilitate cleanup.
    02294     //
    02295
    02296     try {
    02297
    02298         //
    02299         //  If the oplock has no oplock held we return immediately.
    02300         //
    02301
    02302         if (Oplock->OplockState == NoOplocksHeld) {
    02303
    02304             DebugTrace(0,
    02305                        Dbg,
    02306                        "No oplocks on file\n",
    02307                        0);
    02308
    02309             try_return( NOTHING );
    02310         }
    02311
    02312         //
    02313         //  If level II oplocks are held, check if this matches any of them.
    02314         //
    02315
    02316         if (Oplock->OplockState == OplockIIGranted) {
    02317
    02318             PLIST_ENTRY Link;
    02319             PIRP Irp;
    02320             PIO_STACK_LOCATION NextIrpSp;
    02321
    02322             DebugTrace(0,
    02323                        Dbg,
    02324                        "File has level 2 oplocks\n",
    02325                        0);
    02326
    02327             for (Link = Oplock->IrpOplocksII.Flink;
    02328                  Link != &Oplock->IrpOplocksII;
    02329                  Link = Link->Flink) {
    02330
    02331                 Irp = CONTAINING_RECORD( Link, IRP, Tail.Overlay.ListEntry );
    02332
    02333                 NextIrpSp = IoGetCurrentIrpStackLocation( Irp );
    02334
    02335                 //
    02336                 //  If the file objects match, then emove the entry found and complete the Irp.
    02337                 //
    02338
    02339                 if (IrpSp->FileObject == NextIrpSp->FileObject) {
    02340
    02341                     //
    02342                     //  Back up to remember this link.
    02343                     //
    02344
    02345                     Link = Link->Blink;
    02346
    02347                     //
    02348                     //
    02349
    02350                     FsRtlRemoveAndCompleteIrp( Link->Flink );
    02351                 }
    02352             }
    02353
    02354             //
    02355             //  If all the level II oplocks are gone, then the state is
    02356             //  no oplocks held.
    02357             //
    02358
    02359             if (IsListEmpty( &Oplock->IrpOplocksII )) {
    02360
    02361                 Oplock->OplockState = NoOplocksHeld;
    02362             }
    02363
    02364             try_return( NOTHING );
    02365         }
    02366
    02367         //
    02368         //  If this file object matches that used to request an exclusive
    02369         //  oplock, we completely close the oplock break.
    02370         //
    02371
    02372         if (IrpSp->FileObject == Oplock->FileObject) {
    02373
    02374             DebugTrace(0,
    02375                        Dbg,
    02376                        "Handle owns level 1 oplock\n",
    02377                        0);
    02378
    02379             //
    02380             //  If an oplock break is not in progress, we initiate one and
    02381             //  complete the exclusive Irp immediately.
    02382             //
    02383
    02384             if (!FlagOn( Oplock->OplockState, OPLOCK_BREAK_MASK | PENDING )) {
    02385
    02386                 PIRP ExclusiveIrp = Oplock->IrpExclusiveOplock;
    02387
    02388                 DebugTrace(0,
    02389                            Dbg,
    02390                            "Initiate oplock break\n",
    02391                            0);
    02392
    02393                 IoAcquireCancelSpinLock( &ExclusiveIrp->CancelIrql );
    02394
    02395                 IoSetCancelRoutine( ExclusiveIrp, NULL );
    02396                 IoReleaseCancelSpinLock( ExclusiveIrp->CancelIrql );
    02397
    02398                 ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    02399
    02400                 FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_SUCCESS );
    02401
    02402                 Oplock->IrpExclusiveOplock = NULL;
    02403             }
    02404
    02405             //
    02406             //  Clean up the oplock structure and complete all waiting Irps.
    02407             //  Don't do this if this is a pending opfilter request.
    02408             //
    02409
    02410             if (!FlagOn( Oplock->OplockState, PENDING )) {
    02411
    02412                 ObDereferenceObject( IrpSp->FileObject );
    02413             }
    02414
    02415             Oplock->FileObject = NULL;
    02416             Oplock->OplockState = NoOplocksHeld;
    02417
    02418             while (!IsListEmpty( &Oplock->WaitingIrps )) {
    02419
    02420                 PWAITING_IRP WaitingIrp;
    02421
    02422                 //
    02423                 //  Remove the entry found and complete the Irp.
    02424                 //
    02425
    02426                 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
    02427                                                 WAITING_IRP,
    02428                                                 Links );
    02429
    02430                 FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
    02431             }
    02432         }
    02433
    02434     try_exit:  NOTHING;
    02435     } finally {
    02436
    02437         //
    02438         //  Give up the oplock synchronization object.
    02439         //
    02440
    02441         ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    02442         DebugTrace( +1, Dbg, "FsRtlOplockCleanup:  Exit\n", 0 );
    02443     }
    02444
    02445     return;
    02446 }

NTSTATUS FsRtlOplockFsctrl | ( | IN POPLOCK | Oplock,
|  | IN PIRP | Irp,
|  | IN ULONG | OpenCount
| ) |

Definition at line 581 of file oplock.c.

References Dbg, DebugTrace, EXCLUSIVE, FALSE, _IO_STACK_LOCATION::FileObject, FlagOn, _IRP::Flags, _FILE_OBJECT::Flags, FO_CLEANUP_COMPLETE, FsRtlAcknowledgeOplockBreak(), FsRtlCompleteRequest, FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakNotify(), FsRtlRequestExclusiveOplock(), FsRtlRequestOplockII(), IoGetCurrentIrpStackLocation, IoIsOperationSynchronous(), Irp, IRP_INPUT_OPERATION, IRP_MJ_CREATE, LEVEL_I_OPLOCK, _IO_STACK_LOCATION::MajorFunction, NTSTATUS(), NULL, OpFilterReqPending, OPLOCK_STATE, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PNONOPAQUE_OPLOCK, SetFlag, Status, and TRUE.

Referenced by UdfOplockRequest().

    00589                    :
    00590
    00591     This is the interface with the filesystems for Fsctl calls, it handles
    00592     oplock requests, break acknowledgement and break notify.
    00593
    00594 Arguments:
    00595
    00596     Oplock - Supplies the address of the opaque OPLOCK structure.
    00597
    00598     Irp - Supplies a pointer to the Irp which declares the requested
    00599           operation.
    00600
    00601     OpenCount - This is the number of user handles on the file if we are requsting
    00602         an exclusive oplock.  A non-zero value for a level II request indicates
    00603         that there are locks on the file.
    00604
    00605 Return Value:
    00606
    00607     NTSTATUS - Returns the result of this operation.  If this is an Oplock
    00608                request which is granted, then STATUS_PENDING is returned.
    00609                If the Oplock isn't granted then STATUS_OPLOCK_NOT_GRANTED
    00610                is returned.  If this is an Oplock I break to no oplock,
    00611                then STATUS_SUCCESS.  If this is an Oplock I break to
    00612                Oplock II then STATUS_PENDING is returned.  Other
    00613                error codes returned depend on the nature of the error.
    00614
    00615                STATUS_CANCELLED is returned if the Irp is cancelled during
    00616                this operation.
    00617
    00618                STATUS_SUCCESS is returned if this is a create asking for
    00619                a filter oplock.
    00620
    00621 --*/
    00622
    00623 {
    00624     NTSTATUS Status;
    00625     PIO_STACK_LOCATION IrpSp;
    00626     OPLOCK_STATE OplockState;
    00627
    00628     PAGED_CODE();
    00629
    00630     //
    00631     //  Get the current IRP stack location
    00632     //
    00633
    00634     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00635
    00636     DebugTrace(+1, Dbg, "FsRtlOplockFsctrl:  Entered\n", 0);
    00637     DebugTrace( 0, Dbg, "FsRtlOplockFsctrl:  Oplock      -> %08lx\n", *Oplock );
    00638     DebugTrace( 0, Dbg, "FsRtlOplockFsctrl:  Irp         -> %08lx\n", Irp );
    00639
    00640     //
    00641     //  Check if this is the create case where the user is requesting a pending
    00642     //  filter oplock.
    00643     //
    00644
    00645     if (IrpSp->MajorFunction == IRP_MJ_CREATE) {
    00646
    00647         //
    00648         //  Check that all the conditions hold to grant this oplock.
    00649         //  The conditions that must hold are:
    00650         //
    00651         //      - This is the only opener of the file.
    00652         //      - Desired Access must be exactly FILE_READ_ATTRIBUTES.
    00653         //          This will insure an asynch open since the SYNCHRONIZE
    00654         //          flag can't be set.
    00655         //      - Share access is precisely
    00656         //          (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
    00657         //
    00658
    00659         if ((OpenCount != 1) ||
    00660             (FlagOn( IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
    00661                      ~(FILE_READ_ATTRIBUTES))) ||
    00662             ((IrpSp->Parameters.Create.ShareAccess &
    00663               (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)) !=
    00664              (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE))) {
    00665
    00666             Status = STATUS_OPLOCK_NOT_GRANTED;
    00667
    00668         } else {
    00669
    00670             Status = FsRtlRequestExclusiveOplock( (PNONOPAQUE_OPLOCK *) Oplock,
    00671                                                   IrpSp,
    00672                                                   NULL,
    00673                                                   OpFilterReqPending );
    00674         }
    00675
    00676     //
    00677     //  Case on the FsControlFile code control code.
    00678     //
    00679
    00680     } else {
    00681
    00682         //
    00683         //  Assume this is an OplockLevel I.
    00684         //
    00685         //  NOTE - This code depends on the defined bits for these oplock types.
    00686         //      FILTER_OPLOCK = 4 * LEVEL_I_OPLOCK
    00687         //      BATCH_OPLOCK = 2 * LEVEL_I_OPLOCK
    00688         //
    00689
    00690         OplockState = LEVEL_I_OPLOCK;
    00691
    00692         switch (IrpSp->Parameters.FileSystemControl.FsControlCode) {
    00693
    00694         case FSCTL_REQUEST_FILTER_OPLOCK :
    00695
    00696             OplockState *= 2;
    00697
    00698         case FSCTL_REQUEST_BATCH_OPLOCK :
    00699
    00700             OplockState *= 2;
    00701
    00702         case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
    00703
    00704             //
    00705             //  Set the other flags for an exclusive oplock.
    00706             //
    00707
    00708             SetFlag( OplockState, EXCLUSIVE );
    00709
    00710             //
    00711             //  We short circuit the request if this request is treated
    00712             //  synchronously or the open count is not 1.  Otherwise the Io system
    00713             //  will hold the return code until the Irp is completed.
    00714             //
    00715             //  Also fail this if the flag is set which indicates that
    00716             //  the IO system should copy data back to a user's buffer.
    00717             //
    00718             //  If cleanup has occurrred on this file, then we refuse
    00719             //  the oplock request.
    00720             //
    00721
    00722             if ((OpenCount != 1) ||
    00723                 IoIsOperationSynchronous( Irp ) ||
    00724                 FlagOn( Irp->Flags, IRP_INPUT_OPERATION ) ||
    00725                 FlagOn( IrpSp->FileObject->Flags, FO_CLEANUP_COMPLETE )) {
    00726
    00727                 FsRtlCompleteRequest( Irp, STATUS_OPLOCK_NOT_GRANTED );
    00728                 Status = STATUS_OPLOCK_NOT_GRANTED;
    00729
    00730             } else {
    00731
    00732                 Status = FsRtlRequestExclusiveOplock( (PNONOPAQUE_OPLOCK *) Oplock,
    00733                                                       IrpSp,
    00734                                                       Irp,
    00735                                                       OplockState );
    00736             }
    00737
    00738             break;
    00739
    00740         case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
    00741
    00742             //
    00743             //  We short circuit the request if this request is treated
    00744             //  synchronously.  Otherwise the Io system will hold the return
    00745             //  code until the Irp is completed.
    00746             //
    00747             //  If cleanup has occurrred on this file, then we refuse
    00748             //  the oplock request.
    00749             //
    00750             //  Also fail this if the flag is set which indicates that
    00751             //  the IO system should copy data back to a user's buffer.
    00752             //
    00753             //  A non-zero open count in this case indicates that there are
    00754             //  file locks on the file.  We will also fail the request in
    00755             //  this case.
    00756             //
    00757
    00758             if ((OpenCount != 0) ||
    00759                 IoIsOperationSynchronous( Irp ) ||
    00760                 FlagOn( Irp->Flags, IRP_INPUT_OPERATION ) ||
    00761                 FlagOn( IrpSp->FileObject->Flags, FO_CLEANUP_COMPLETE )) {
    00762
    00763                 FsRtlCompleteRequest( Irp, STATUS_OPLOCK_NOT_GRANTED );
    00764                 Status = STATUS_OPLOCK_NOT_GRANTED;
    00765
    00766             } else {
    00767
    00768                 Status = FsRtlRequestOplockII( (PNONOPAQUE_OPLOCK *) Oplock,
    00769                                                IrpSp,
    00770                                                Irp );
    00771             }
    00772
    00773             break;
    00774
    00775         case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
    00776
    00777             Status = FsRtlAcknowledgeOplockBreak( (PNONOPAQUE_OPLOCK) *Oplock,
    00778                                                   IrpSp,
    00779                                                   Irp,
    00780                                                   TRUE );
    00781             break;
    00782
    00783         case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
    00784
    00785             Status = FsRtlAcknowledgeOplockBreak( (PNONOPAQUE_OPLOCK) *Oplock,
    00786                                                   IrpSp,
    00787                                                   Irp,
    00788                                                   FALSE );
    00789             break;
    00790
    00791         case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
    00792
    00793             Status = FsRtlOpBatchBreakClosePending( (PNONOPAQUE_OPLOCK) *Oplock,
    00794                                                     IrpSp,
    00795                                                     Irp );
    00796             break;
    00797
    00798         case FSCTL_OPLOCK_BREAK_NOTIFY :
    00799
    00800             Status = FsRtlOplockBreakNotify( (PNONOPAQUE_OPLOCK) *Oplock,
    00801                                              IrpSp,
    00802                                              Irp );
    00803             break;
    00804
    00805         default :
    00806
    00807             DebugTrace( 0,
    00808                         Dbg,
    00809                         "Invalid Control Code\n",
    00810                         0);
    00811
    00812             FsRtlCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
    00813             Status = STATUS_INVALID_PARAMETER;
    00814         }
    00815     }
    00816
    00817     DebugTrace(-1, Dbg, "FsRtlOplockFsctrl:  Exit -> %08lx\n", Status );
    00818     return Status;
    00819 }

BOOLEAN FsRtlOplockIsFastIoPossible | ( | IN POPLOCK | Oplock | ) |

Definition at line 1116 of file oplock.c.

References Dbg, DebugTrace, FALSE, FlagOn, LEVEL_II_OPLOCK, NULL, OPLOCK_BREAK_MASK, OPLOCK_STATE, PAGED_CODE, PNONOPAQUE_OPLOCK, and TRUE.

Referenced by UdfFastLock(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), and UdfFastUnlockSingle().

    01122                    :
    01123
    01124     This routine indicates to the caller where there are any outstanding
    01125     oplocks which prevent fast Io from happening.
    01126
    01127 Arguments:
    01128
    01129     OpLock - Supplies the oplock being queried
    01130
    01131 Return Value:
    01132
    01133     BOOLEAN - TRUE if there are outstanding oplocks and FALSE otherwise
    01134
    01135 --*/
    01136
    01137 {
    01138     BOOLEAN FastIoPossible = TRUE;
    01139
    01140     PAGED_CODE();
    01141
    01142     DebugTrace(+1, Dbg, "FsRtlOplockIsFastIoPossible: Oplock -> %08lx\n", *Oplock);
    01143
    01144     //
    01145     //  There are not any current oplocks if the variable is null or
    01146     //  the state is no oplocks held.  If an exclusive oplock was granted
    01147     //  but no break is in progress then allow the Fast IO.
    01148     //
    01149
    01150     if (*Oplock != NULL) {
    01151
    01152         OPLOCK_STATE OplockState;
    01153
    01154         OplockState = ((PNONOPAQUE_OPLOCK) *Oplock)->OplockState;
    01155
    01156         if (FlagOn( OplockState, LEVEL_II_OPLOCK | OPLOCK_BREAK_MASK )) {
    01157
    01158             FastIoPossible = FALSE;
    01159         }
    01160     }
    01161
    01162     DebugTrace(-1, Dbg, "FsRtlOplockIsFastIoPossible: Exit -> %08lx\n", FastIoPossible);
    01163
    01164     return FastIoPossible;
    01165 }

VOID FsRtlRemoveAndCompleteIrp | ( | IN PLIST_ENTRY | Link | ) |

Definition at line 2952 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, _IO_STACK_LOCATION::FileObject, FsRtlCompleteRequest, IoAcquireCancelSpinLock(), IoGetCurrentIrpStackLocation, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, NULL, and ObDereferenceObject.

Referenced by FsRtlCancelOplockIIIrp(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), and FsRtlRequestExclusiveOplock().

    02958                    :
    02959
    02960     This routine is called to remove an Irp from a list of Irps linked
    02961     with the Tail.ListEntry field and complete them with STATUS_CANCELLED
    02962     if the Irp has been cancelled, STATUS_SUCCESS otherwise.
    02963
    02964 Arguments:
    02965
    02966     Link - Supplies the entry to remove from the list.
    02967
    02968 Return Value:
    02969
    02970     None.
    02971
    02972 --*/
    02973
    02974 {
    02975     PIRP Irp;
    02976     PIO_STACK_LOCATION OplockIIIrpSp;
    02977
    02978     DebugTrace( +1, Dbg, "FsRtlRemoveAndCompleteIrp:  Entered\n", 0 );
    02979
    02980     //
    02981     //  Reference the Irp.
    02982     //
    02983
    02984     Irp = CONTAINING_RECORD( Link, IRP, Tail.Overlay.ListEntry );
    02985
    02986     //
    02987     //  Get the stack location and dereference the file object.
    02988     //
    02989
    02990     OplockIIIrpSp = IoGetCurrentIrpStackLocation( Irp );
    02991     ObDereferenceObject( OplockIIIrpSp->FileObject );
    02992
    02993     //
    02994     //  Clear the cancel routine in the irp.
    02995     //
    02996
    02997     IoAcquireCancelSpinLock( &Irp->CancelIrql );
    02998
    02999     IoSetCancelRoutine( Irp, NULL );
    03000     IoReleaseCancelSpinLock( Irp->CancelIrql );
    03001
    03002     //
    03003     // Remove this from the list.
    03004     //
    03005
    03006     RemoveEntryList( Link );
    03007
    03008     //
    03009     //  Complete the oplock Irp.
    03010     //
    03011
    03012     Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    03013
    03014     FsRtlCompleteRequest( Irp, Irp->Cancel ? STATUS_CANCELLED : STATUS_SUCCESS );
    03015
    03016     DebugTrace( -1, Dbg, "FsRtlRemoveAndCompleteIrp:  Exit\n", 0 );
    03017 }

VOID FsRtlRemoveAndCompleteWaitIrp | ( | IN PWAITING_IRP | WaitingIrp | ) |

Definition at line 3623 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, ExFreePool(), IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, NULL, and PAGED_CODE.

Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlCancelExclusiveIrp(), FsRtlCancelWaitIrp(), FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), and FsRtlOplockCleanup().

    03629                    :
    03630
    03631     This routine is called to remove and perform any neccessary cleanup
    03632     for an Irp stored on the waiting Irp list in an oplock structure.
    03633
    03634 Arguments:
    03635
    03636     WaitingIrp - This is the auxilary structure attached to the Irp
    03637                  being completed.
    03638
    03639 Return Value:
    03640
    03641     None.
    03642
    03643 --*/
    03644
    03645 {
    03646     PIRP Irp;
    03647
    03648     PAGED_CODE();
    03649
    03650     DebugTrace( +1, Dbg, "FsRtlRemoveAndCompleteWaitIrp:  Entered\n", 0 );
    03651
    03652     //
    03653     //  Remove the Irp from the queue.
    03654     //
    03655
    03656     RemoveEntryList( &WaitingIrp->Links );
    03657
    03658     Irp = WaitingIrp->Irp;
    03659
    03660     IoAcquireCancelSpinLock( &Irp->CancelIrql );
    03661
    03662     IoSetCancelRoutine( Irp, NULL );
    03663     IoReleaseCancelSpinLock( Irp->CancelIrql );
    03664
    03665     //
    03666     //  Restore the information field.
    03667     //
    03668
    03669     Irp->IoStatus.Information = WaitingIrp->Information;
    03670
    03671     Irp->IoStatus.Status = (Irp->Cancel
    03672                             ? STATUS_CANCELLED
    03673                             : STATUS_SUCCESS);
    03674
    03675     //
    03676     //  Call the completion routine in the Waiting Irp.
    03677     //
    03678
    03679     WaitingIrp->CompletionRoutine( WaitingIrp->Context, Irp );
    03680
    03681     //
    03682     //  And free up pool
    03683     //
    03684
    03685     ExFreePool( WaitingIrp );
    03686
    03687     DebugTrace( -1, Dbg, "FsRtlRemoveAndCompleteWaitIrp:  Exit\n", 0 );
    03688
    03689     return;
    03690 }

NTSTATUS FsRtlRequestExclusiveOplock | ( | IN OUT PNONOPAQUE_OPLOCK * | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP Irp | OPTIONAL,
|  | IN OPLOCK_STATE | NextOplockState
| ) |

Definition at line 1299 of file oplock.c.

References ASSERT, _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), FALSE, _NONOPAQUE_OPLOCK::FastMutex, _NONOPAQUE_OPLOCK::FileObject, FlagOn, FsRtlAllocateOplock(), FsRtlCancelExclusiveIrp(), FsRtlCompleteRequest, FsRtlRemoveAndCompleteIrp(), IoAcquireCancelSpinLock(), IoMarkIrpPending, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _NONOPAQUE_OPLOCK::IrpExclusiveOplock, _NONOPAQUE_OPLOCK::IrpOplocksII, LEVEL_II_OPLOCK, NO_OPLOCK, NTSTATUS(), NULL, ObReferenceObject, OpFilterReqPending, OplockIIGranted, _NONOPAQUE_OPLOCK::OplockState, PENDING, PNONOPAQUE_OPLOCK, Status, and TRUE.

Referenced by FsRtlOplockFsctrl().

    01308                    :
    01309
    01310     This routine is called whenever a user is requesting either a batch/filter
    01311     oplock or a level I oplock.  The request is granted if there are currently
    01312     no oplocks on the file or we are completing the filter oplock request.
    01313
    01314     NOTE - We already know that the open count on this file is exactly one.
    01315         If the caller is requesting a PendingFilter Oplock then the state
    01316         must be NoOplockHeld.
    01317
    01318 Arguments:
    01319
    01320     Oplock - Supplies a pointer to the non-opaque oplock structure for
    01321              this file.
    01322
    01323     IrpSp - This is the Irp stack location for the current Irp.
    01324
    01325     Irp - Supplies a pointer to the Irp which declares the requested
    01326           operation.  This is not specified if we are granting a pending
    01327           filter oplock (during a create).
    01328
    01329     NextOplockState - Indicates the type of oplock being requested.
    01330
    01331 Return Value:
    01332
    01333     STATUS_PENDING if the oplock is granted (although it may be immediately cancelled).
    01334     STATUS_SUCCESS if a pending filter oplock is requested and tentatively granted.
    01335     STATUS_OPLOCK_NOT_GRANTED if the request is denied.
    01336
    01337 --*/
    01338
    01339 {
    01340     NTSTATUS Status;
    01341
    01342     PNONOPAQUE_OPLOCK ThisOplock;
    01343
    01344     BOOLEAN AcquiredMutex;
    01345     BOOLEAN BreakOpFilter = FALSE;
    01346
    01347     PLIST_ENTRY Link;
    01348
    01349     DebugTrace( +1, Dbg, "FsRtlRequestExclusiveOplock:  Entered\n", 0 );
    01350     DebugTrace(  0, Dbg, "Oplock        -> %08lx\n", Oplock );
    01351     DebugTrace(  0, Dbg, "IrpSp         -> %08lx\n", IrpSp );
    01352     DebugTrace(  0, Dbg, "Irp           -> %08lx\n", Irp );
    01353     DebugTrace(  0, Dbg, "BatchOplock   -> %01x\n",  BatchOplock );
    01354
    01355     //
    01356     //  We can grant the oplock if no one else owns a level I or level II
    01357     //  oplock on this file.  If the oplock pointer is NULL then there
    01358     //  are no oplocks on the file.  Otherwise we need to check the
    01359     //  oplock state in an existing oplock structure.
    01360     //
    01361
    01362     if (*Oplock == NULL) {
    01363
    01364         DebugTrace( 0,
    01365                     Dbg,
    01366                     "Oplock currently not allocated\n",
    01367                     0);
    01368
    01369         ThisOplock = FsRtlAllocateOplock();
    01370         *Oplock = ThisOplock;
    01371
    01372     } else {
    01373
    01374         ThisOplock = *Oplock;
    01375     }
    01376
    01377     //
    01378     //  Grab the synchronization object for the oplock.
    01379     //
    01380
    01381     ExAcquireFastMutexUnsafe( ThisOplock->FastMutex );
    01382
    01383     AcquiredMutex = TRUE;
    01384
    01385     //
    01386     //  Use a try-finally to facilitate cleanup.
    01387     //
    01388
    01389     try {
    01390
    01391         //
    01392         //  If we are requesting a PendingFilter Oplock then it must be
    01393         //  safe to grant.  There is only one open handle and we are in
    01394         //  the process of opening it.
    01395         //
    01396
    01397         if (NextOplockState == OpFilterReqPending) {
    01398
    01399             ASSERT( FlagOn( ThisOplock->OplockState, NO_OPLOCK | PENDING ));
    01400
    01401             ThisOplock->IrpExclusiveOplock = Irp;
    01402             ThisOplock->FileObject = IrpSp->FileObject;
    01403
    01404             ThisOplock->OplockState = OpFilterReqPending;
    01405             Status = STATUS_SUCCESS;
    01406
    01407         //
    01408         //  If the current oplock state is no oplocks held then we
    01409         //  will grant the oplock to this requestor.  If the state is
    01410         //  either of the OpFilter states then also grant the request.
    01411         //  We won't check for a matching file object because there can
    01412         //  only be one file object.  Grant the request anyway.
    01413         //
    01414         //  If the current state is OplockII granted then it must
    01415         //  be owned by this request.  Break the oplock II and grant
    01416         //  the exclusive lock.
    01417         //
    01418
    01419         } else if (FlagOn( ThisOplock->OplockState,
    01420                            LEVEL_II_OPLOCK | NO_OPLOCK | PENDING )) {
    01421
    01422             PFAST_MUTEX OplockFastMutex;
    01423
    01424             if (ThisOplock->OplockState == OplockIIGranted) {
    01425
    01426                 ASSERT( ThisOplock->IrpOplocksII.Flink == ThisOplock->IrpOplocksII.Blink );
    01427
    01428                 FsRtlRemoveAndCompleteIrp( ThisOplock->IrpOplocksII.Flink );
    01429             }
    01430
    01431             //
    01432             //  Put the address of the fast mutex on the stack.
    01433             //
    01434
    01435             OplockFastMutex = ThisOplock->FastMutex;
    01436
    01437             //
    01438             //  We store this Irp in the Oplocks structure.
    01439             //  We set the oplock state to the correct exclusive oplock.
    01440             //
    01441
    01442             ThisOplock->IrpExclusiveOplock = Irp;
    01443             ThisOplock->FileObject = IrpSp->FileObject;
    01444             ThisOplock->OplockState = NextOplockState;
    01445
    01446             IoMarkIrpPending( Irp );
    01447
    01448             ObReferenceObject( IrpSp->FileObject );
    01449
    01450             Irp->IoStatus.Information = (ULONG_PTR) ThisOplock;
    01451
    01452             IoAcquireCancelSpinLock( &Irp->CancelIrql );
    01453
    01454             //
    01455             //  Now if the irp is cancelled then we'll call the cancel
    01456             //  routine right now to do away with the irp, otherwise
    01457             //  we set the cancel routine
    01458             //
    01459
    01460             if (Irp->Cancel) {
    01461
    01462                 AcquiredMutex = FALSE;
    01463
    01464                 ExReleaseFastMutexUnsafe( OplockFastMutex );
    01465
    01466                 FsRtlCancelExclusiveIrp( NULL, Irp );
    01467
    01468             } else {
    01469
    01470                 IoSetCancelRoutine( Irp, FsRtlCancelExclusiveIrp );
    01471                 IoReleaseCancelSpinLock( Irp->CancelIrql );
    01472             }
    01473
    01474             Status = STATUS_PENDING;
    01475
    01476         } else {
    01477
    01478             //
    01479             //  We'll complete the Irp with the Oplock not granted message
    01480             //  and return that value as a status.
    01481             //
    01482
    01483             if (ARGUMENT_PRESENT( Irp )) {
    01484
    01485                 FsRtlCompleteRequest( Irp, STATUS_OPLOCK_NOT_GRANTED );
    01486             }
    01487
    01488             Status = STATUS_OPLOCK_NOT_GRANTED;
    01489         }
    01490
    01491     } finally {
    01492
    01493         //
    01494         //  Give up the oplock synchronization object.
    01495         //
    01496
    01497         if (AcquiredMutex) {
    01498
    01499             ExReleaseFastMutexUnsafe( ThisOplock->FastMutex );
    01500         }
    01501
    01502         DebugTrace( +1, Dbg, "FsRtlRequestExclusiveOplock:  Exit\n", 0 );
    01503     }
    01504
    01505     return Status;
    01506 }

NTSTATUS FsRtlRequestOplockII | ( | IN OUT PNONOPAQUE_OPLOCK * | Oplock,
|  | IN PIO_STACK_LOCATION | IrpSp,
|  | IN PIRP | Irp
| ) |

Definition at line 1514 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExReleaseFastMutexUnsafe(), FALSE, _NONOPAQUE_OPLOCK::FastMutex, FlagOn, FsRtlAllocateOplock(), FsRtlCancelOplockIIIrp(), FsRtlCompleteRequest, IoAcquireCancelSpinLock(), IoMarkIrpPending, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _NONOPAQUE_OPLOCK::IrpOplocksII, LEVEL_II_OPLOCK, NO_OPLOCK, NTSTATUS(), NULL, ObReferenceObject, OplockIIGranted, _NONOPAQUE_OPLOCK::OplockState, PNONOPAQUE_OPLOCK, Status, _IRP::Tail, and TRUE.

Referenced by FsRtlOplockFsctrl().

    01522                    :
    01523
    01524     This routine is called when a user is requesting an Oplock II on an
    01525     open file.  The request is granted if there are currently no
    01526     level 1 oplocks on the file and an oplock break is not in progress.
    01527
    01528 Arguments:
    01529
    01530     Oplock - Supplies a pointer to the non-opaque oplock structure for
    01531              this file.
    01532
    01533     IrpSp - This is the Irp stack location for the current Irp.
    01534
    01535     Irp - Supplies a pointer to the Irp which declares the requested
    01536           operation.
    01537
    01538 Return Value:
    01539
    01540     STATUS_PENDING if the oplock is granted.
    01541     STATUS_OPLOCK_NOT_GRANTED if the request is denied.
    01542
    01543 --*/
    01544
    01545 {
    01546     NTSTATUS Status;
    01547
    01548     PNONOPAQUE_OPLOCK ThisOplock;
    01549
    01550     BOOLEAN AcquiredMutex;
    01551
    01552     DebugTrace( +1, Dbg, "FsRtlRequestOplockII:  Entered\n", 0 );
    01553     DebugTrace(  0, Dbg, "Oplock    -> %08lx\n", Oplock );
    01554     DebugTrace(  0, Dbg, "IrpSp     -> %08lx\n", IrpSp );
    01555     DebugTrace(  0, Dbg, "Irp       -> %08lx\n", Irp );
    01556
    01557     //
    01558     //  We can grant the oplock if no one else owns a level I
    01559     //  oplock on this file.  If the oplock pointer is NULL then there
    01560     //  are no oplocks on the file.  Otherwise we need to check the
    01561     //  oplock state in an existing oplock structure.
    01562     //
    01563
    01564     if (*Oplock == NULL) {
    01565
    01566         DebugTrace( 0,
    01567                     Dbg,
    01568                     "Oplock currently not allocated\n",
    01569                     0);
    01570
    01571         ThisOplock = FsRtlAllocateOplock();
    01572         *Oplock = ThisOplock;
    01573
    01574     } else {
    01575
    01576         ThisOplock = *Oplock;
    01577     }
    01578
    01579     //
    01580     //  Grab the synchronization object for the oplock.
    01581     //
    01582
    01583     ExAcquireFastMutexUnsafe( ThisOplock->FastMutex );
    01584
    01585     AcquiredMutex = TRUE;
    01586
    01587     //
    01588     //  Use a try-finally to facilitate cleanup.
    01589     //
    01590
    01591     try {
    01592
    01593         //
    01594         //  If the current oplock state is no oplocks held or OplockIIGranted
    01595         //  then we will grant the oplock to this requestor.
    01596         //
    01597
    01598         if (FlagOn( ThisOplock->OplockState, NO_OPLOCK | LEVEL_II_OPLOCK )) {
    01599
    01600             PFAST_MUTEX OplockFastMutex = ThisOplock->FastMutex;
    01601
    01602             //
    01603             //  We store this Irp in the Oplocks structure.
    01604             //  We set the oplock state to 'OplockIIGranted'.
    01605             //
    01606
    01607             IoMarkIrpPending( Irp );
    01608
    01609             Irp->IoStatus.Status = STATUS_SUCCESS;
    01610
    01611             InsertHeadList( &ThisOplock->IrpOplocksII,
    01612                             &Irp->Tail.Overlay.ListEntry );
    01613
    01614             Irp->IoStatus.Information = (ULONG_PTR) ThisOplock;
    01615
    01616             ThisOplock->OplockState = OplockIIGranted;
    01617
    01618             ObReferenceObject( IrpSp->FileObject );
    01619
    01620             IoAcquireCancelSpinLock( &Irp->CancelIrql );
    01621
    01622             //
    01623             //  Now if the irp is cancelled then we'll call the cancel
    01624             //  routine right now to do away with the irp, otherwise
    01625             //  we set the cancel routine
    01626             //
    01627
    01628             if (Irp->Cancel) {
    01629
    01630                 AcquiredMutex = FALSE;
    01631
    01632                 ExReleaseFastMutexUnsafe( OplockFastMutex );
    01633
    01634                 FsRtlCancelOplockIIIrp( NULL, Irp );
    01635
    01636             } else {
    01637
    01638                 IoSetCancelRoutine( Irp, FsRtlCancelOplockIIIrp );
    01639                 IoReleaseCancelSpinLock( Irp->CancelIrql );
    01640             }
    01641
    01642             Status = STATUS_PENDING;
    01643
    01644         } else {
    01645
    01646             //
    01647             //  We'll complete the Irp with the Oplock not granted message
    01648             //  and return that value as a status.
    01649             //
    01650
    01651             FsRtlCompleteRequest( Irp, STATUS_OPLOCK_NOT_GRANTED );
    01652             Status = STATUS_OPLOCK_NOT_GRANTED;
    01653         }
    01654
    01655     } finally {
    01656
    01657         //
    01658         //  Give up the oplock synchronization object.
    01659         //
    01660
    01661         if (AcquiredMutex) {
    01662
    01663             ExReleaseFastMutexUnsafe( ThisOplock->FastMutex );
    01664         }
    01665
    01666         DebugTrace( +1, Dbg, "FsRtlRequestOplockII:  Exit\n", 0 );
    01667     }
    01668
    01669     return Status;
    01670 }

VOID FsRtlUninitializeOplock | ( | IN OUT POPLOCK | Oplock | ) |

Definition at line 413 of file oplock.c.

References _IRP::CancelIrql, _WAITING_IRP::CompletionRoutine, _WAITING_IRP::Context, Dbg, DebugTrace, ExAcquireFastMutexUnsafe(), ExFreePool(), ExReleaseFastMutexUnsafe(), _NONOPAQUE_OPLOCK::FastMutex, _NONOPAQUE_OPLOCK::FileObject, FsRtlCompleteRequest, IoAcquireCancelSpinLock(), IoGetCurrentIrpStackLocation, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _WAITING_IRP::Irp, _NONOPAQUE_OPLOCK::IrpExclusiveOplock, _NONOPAQUE_OPLOCK::IrpOplocksII, NULL, ObDereferenceObject, PNONOPAQUE_OPLOCK, PWAITING_IRP, and _NONOPAQUE_OPLOCK::WaitingIrps.

Referenced by UdfDeleteFcb().

    00419                    :
    00420
    00421     This routine uninitializes an OPLOCK structure.  After calling this
    00422     routine, the OPLOCK structure must be reinitialized before being
    00423     used again.
    00424
    00425 Arguments:
    00426
    00427     Oplock - Supplies the address of an opaque OPLOCK structure.
    00428
    00429 Return Value:
    00430
    00431     None.
    00432
    00433 --*/
    00434
    00435
    00436 {
    00437     PNONOPAQUE_OPLOCK ThisOplock;
    00438
    00439     DebugTrace(+1, Dbg, "FsRtlUninitializeOplock:  Oplock -> %08lx\n", *Oplock );
    00440
    00441     //
    00442     //  If the Oplock structure has not been allocated, there is no action
    00443     //  to take.
    00444     //
    00445
    00446     if (*Oplock != NULL) {
    00447
    00448         //
    00449         //  Remove this from the user's structure.
    00450         //
    00451
    00452         ThisOplock = (PNONOPAQUE_OPLOCK) *Oplock;
    00453
    00454         *Oplock = NULL;
    00455
    00456         //
    00457         //  Grab the waiting lock queue mutex to exclude anyone from messing
    00458         //  with the queue while we're using it
    00459         //
    00460
    00461         ExAcquireFastMutexUnsafe( ThisOplock->FastMutex );
    00462
    00463         try {
    00464
    00465             PIRP Irp;
    00466
    00467             //
    00468             //  Release any waiting Irps held.
    00469             //
    00470
    00471             while (!IsListEmpty( &ThisOplock->WaitingIrps )) {
    00472
    00473                 PWAITING_IRP WaitingIrp;
    00474                 PIRP ThisIrp;
    00475
    00476                 WaitingIrp = CONTAINING_RECORD( ThisOplock->WaitingIrps.Flink,
    00477                                                 WAITING_IRP,
    00478                                                 Links );
    00479
    00480                 RemoveHeadList( &ThisOplock->WaitingIrps );
    00481
    00482                 ThisIrp = WaitingIrp->Irp;
    00483
    00484                 IoAcquireCancelSpinLock( &ThisIrp->CancelIrql );
    00485
    00486                 IoSetCancelRoutine( ThisIrp, NULL );
    00487                 IoReleaseCancelSpinLock( ThisIrp->CancelIrql );
    00488
    00489                 ThisIrp->IoStatus.Information = 0;
    00490
    00491                 //
    00492                 //  Call the completion routine in the Waiting Irp.
    00493                 //
    00494
    00495                 WaitingIrp->CompletionRoutine( WaitingIrp->Context,
    00496                                                WaitingIrp->Irp );
    00497
    00498                 ExFreePool( WaitingIrp );
    00499             }
    00500
    00501             //
    00502             //  Release any oplock II irps held.
    00503             //
    00504
    00505             while (!IsListEmpty( &ThisOplock->IrpOplocksII )) {
    00506
    00507                 Irp = CONTAINING_RECORD( ThisOplock->IrpOplocksII.Flink,
    00508                                          IRP,
    00509                                          Tail.Overlay.ListEntry );
    00510
    00511                 RemoveHeadList( &ThisOplock->IrpOplocksII );
    00512
    00513                 IoAcquireCancelSpinLock( &Irp->CancelIrql );
    00514
    00515                 IoSetCancelRoutine( Irp, NULL );
    00516                 IoReleaseCancelSpinLock( Irp->CancelIrql );
    00517
    00518                 //
    00519                 //  Complete the oplock II Irp.
    00520                 //
    00521
    00522                 ObDereferenceObject( IoGetCurrentIrpStackLocation( Irp )->FileObject );
    00523
    00524                 Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    00525                 FsRtlCompleteRequest( Irp, STATUS_SUCCESS );
    00526             }
    00527
    00528             //
    00529             //  Release any exclusive oplock held.
    00530             //
    00531
    00532             if (ThisOplock->IrpExclusiveOplock != NULL) {
    00533
    00534                 Irp = ThisOplock->IrpExclusiveOplock;
    00535
    00536                 IoAcquireCancelSpinLock( &Irp->CancelIrql );
    00537
    00538                 IoSetCancelRoutine( Irp, NULL );
    00539                 IoReleaseCancelSpinLock( Irp->CancelIrql );
    00540
    00541                 Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
    00542                 FsRtlCompleteRequest( Irp, STATUS_SUCCESS );
    00543
    00544                 ThisOplock->IrpExclusiveOplock = NULL;
    00545
    00546                 if (ThisOplock->FileObject != NULL) {
    00547
    00548                     ObDereferenceObject( ThisOplock->FileObject );
    00549                 }
    00550             }
    00551
    00552         } finally {
    00553
    00554             //
    00555             //  No matter how we complete the preceding statements we will
    00556             //  now release the waiting lock queue mutex
    00557             //
    00558
    00559             ExReleaseFastMutexUnsafe( ThisOplock->FastMutex );
    00560         }
    00561
    00562         //
    00563         //  Deallocate the mutex.
    00564         //
    00565
    00566         ExFreePool( ThisOplock->FastMutex );
    00567
    00568         //
    00569         //  Deallocate the Oplock structure.
    00570         //
    00571
    00572         ExFreePool( ThisOplock );
    00573     }
    00574
    00575     DebugTrace( -1, Dbg, "FsRtlUninitializeOplock:  Exit\n", 0 );
    00576     return;
    00577 }

NTSTATUS FsRtlWaitOnIrp | ( | IN OUT PNONOPAQUE_OPLOCK | Oplock,
|  | IN PIRP | Irp,
|  | IN PVOID | Context,
|  | IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine | OPTIONAL,
|  | IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine | OPTIONAL,
|  | IN PKEVENT | Event
| ) |

Definition at line 3025 of file oplock.c.

References _IRP::Cancel, _IRP::CancelIrql, _WAITING_IRP::CompletionRoutine, _WAITING_IRP::Context, Dbg, DebugTrace, Event(), Executive, ExReleaseFastMutexUnsafe(), FALSE, FsRtlCancelWaitIrp(), FsRtlCompletionRoutinePriv(), FsRtlpAllocatePool, _WAITING_IRP::Information, IoAcquireCancelSpinLock(), IoMarkIrpPending, IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _WAITING_IRP::Irp, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _WAITING_IRP::Links, NTSTATUS(), NULL, PagedPool, PWAITING_IRP, Status, and TRUE.

Referenced by FsRtlOplockBreakNotify(), FsRtlOplockBreakToII(), and FsRtlOplockBreakToNone().

    03036                    :
    03037
    03038     This routine is called to create a Wait Irp structure and attach it
    03039     to the current Irp.  The Irp is then added to the list of Irps waiting
    03040     for an oplock break.  We check if the Irp has been cancelled and if
    03041     so we call our cancel routine to perform the work.
    03042
    03043     This routine is holding the Mutex for the oplock on entry and
    03044     must give it up on exit.
    03045
    03046 Arguments:
    03047
    03048     Oplock - Supplies a pointer to the non-opaque oplock structure for
    03049              this file.
    03050
    03051     Irp - Supplies a pointer to the Irp which declares the requested
    03052           operation.
    03053
    03054     Context - This value is passed as a parameter to the completion routine.
    03055
    03056     CompletionRoutine - This is the routine which is called if this
    03057                         Irp must wait for an Oplock to break.  This
    03058                         is a synchronous operation if not specified
    03059                         and we block in this thread waiting on
    03060                         an event.
    03061
    03062     PostIrpRoutine - This is the routine to call before we put anything
    03063                      on our waiting Irp queue.
    03064
    03065     Event - If there is no user completion routine, this thread will
    03066             block using this event.
    03067
    03068 Return Value:
    03069
    03070     STATUS_SUCCESS if we can complete the operation on exiting this thread.
    03071     STATUS_PENDING if we return here but hold the Irp.
    03072     STATUS_CANCELLED if the Irp is cancelled before we return.
    03073
    03074 --*/
    03075
    03076 {
    03077     BOOLEAN AcquiredMutex;
    03078     NTSTATUS Status;
    03079
    03080     PWAITING_IRP WaitingIrp;
    03081
    03082     DebugTrace( +1, Dbg, "FsRtlWaitOnIrp:   Entered\n", 0 );
    03083
    03084     //
    03085     //  Remember that we have the mutex.
    03086     //
    03087
    03088     AcquiredMutex = TRUE;
    03089
    03090     //
    03091     //  Use a try-finally to facilitate cleanup.
    03092     //
    03093
    03094     try {
    03095
    03096         PFAST_MUTEX OplockFastMutex = Oplock->FastMutex;
    03097
    03098         //
    03099         //  Allocate and initialize the Wait Irp structure.
    03100         //
    03101
    03102         WaitingIrp = FsRtlpAllocatePool( PagedPool, sizeof( WAITING_IRP ));
    03103
    03104         WaitingIrp->Irp = Irp;
    03105
    03106         WaitingIrp->Context = Context;
    03107         WaitingIrp->Information = (ULONG) Irp->IoStatus.Information;
    03108
    03109         //
    03110         //  Take appropriate action if depending on the value of the
    03111         //  completion routine.
    03112         //
    03113
    03114         if (ARGUMENT_PRESENT( CompletionRoutine )) {
    03115
    03116             WaitingIrp->CompletionRoutine = CompletionRoutine;
    03117             WaitingIrp->Context = Context;
    03118
    03119         } else {
    03120
    03121             WaitingIrp->CompletionRoutine = FsRtlCompletionRoutinePriv;
    03122             WaitingIrp->Context = Event;
    03123
    03124             KeInitializeEvent( Event, NotificationEvent, FALSE );
    03125         }
    03126
    03127         //
    03128         //  Call the file system's post Irp code.
    03129         //
    03130
    03131         if (ARGUMENT_PRESENT( PostIrpRoutine )) {
    03132
    03133             PostIrpRoutine( Context, Irp );
    03134         }
    03135
    03136         //
    03137         //  Initialize the return value to status success.
    03138         //
    03139
    03140         Irp->IoStatus.Status = STATUS_SUCCESS;
    03141
    03142         //
    03143         //  We put this into the Waiting Irp queue.
    03144         //
    03145
    03146         InsertTailList( &Oplock->WaitingIrps, &WaitingIrp->Links );
    03147
    03148         //
    03149         //  We grab the cancel spinlock and store the address of the oplock.
    03150         //
    03151
    03152         IoAcquireCancelSpinLock( &Irp->CancelIrql );
    03153         Irp->IoStatus.Information = (ULONG_PTR) Oplock;
    03154
    03155         //
    03156         //  If the Irp is cancelled then we'll call the cancel routine
    03157         //  right now to do away with the Waiting Irp structure.
    03158         //
    03159
    03160         if (Irp->Cancel) {
    03161
    03162             ExReleaseFastMutexUnsafe( OplockFastMutex );
    03163             AcquiredMutex = FALSE;
    03164
    03165             if (ARGUMENT_PRESENT( CompletionRoutine )) {
    03166
    03167                 IoMarkIrpPending( Irp );
    03168                 Status = STATUS_PENDING;
    03169
    03170             } else {
    03171
    03172                 Status = STATUS_CANCELLED;
    03173             }
    03174
    03175             FsRtlCancelWaitIrp( NULL, Irp );
    03176
    03177         //
    03178         //  Otherwise, we set the cancel routine and decide whether we
    03179         //  are going to wait on our local event.
    03180         //
    03181
    03182         } else {
    03183
    03184             IoSetCancelRoutine( Irp, FsRtlCancelWaitIrp );
    03185             IoReleaseCancelSpinLock( Irp->CancelIrql );
    03186
    03187             //
    03188             //  If we wait on the event, we pull the return code out of
    03189             //  the Irp.
    03190             //
    03191
    03192             if (!ARGUMENT_PRESENT( CompletionRoutine )) {
    03193
    03194                 AcquiredMutex = FALSE;
    03195
    03196                 ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    03197
    03198                 KeWaitForSingleObject( Event,
    03199                                        Executive,
    03200                                        KernelMode,
    03201                                        FALSE,
    03202                                        NULL );
    03203
    03204                 Status = Irp->IoStatus.Status;
    03205
    03206             //
    03207             //  Otherwise, we return STATUS_PENDING.
    03208             //
    03209
    03210             } else {
    03211
    03212                 IoMarkIrpPending( Irp );
    03213
    03214                 Status = STATUS_PENDING;
    03215             }
    03216         }
    03217
    03218     } finally {
    03219
    03220         //
    03221         //  Release the Mutex if we have not done so.
    03222         //
    03223
    03224         if (AcquiredMutex) {
    03225
    03226             ExReleaseFastMutexUnsafe( Oplock->FastMutex );
    03227         }
    03228
    03229         DebugTrace( -1, Dbg, "FsRtlWaitOnIrp:   Exit\n", 0 );
    03230     }
    03231
    03232     return Status;
    03233 }