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_OPLOCKPNONOPAQUE_OPLOCK
typedef _WAITING_IRP WAITING_IRP
typedef _WAITING_IRPPWAITING_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 }


Generated on Sat May 15 19:45:00 2004 for test by doxygen 1.3.7