windows-nt/Source/XPSP1/NT/base/fs/srv/blklock.c
2020-09-26 16:20:57 +08:00

414 lines
8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
blklock.c
Abstract:
This module implements routines for managing byte range lock blocks.
Author:
Andy Herron (andyhe) 15-Nov-1999
Revision History:
--*/
#include "precomp.h"
#include "blklock.tmh"
#pragma hdrstop
#ifdef INCLUDE_SMB_PERSISTENT
#define BugCheckFileId SRV_FILE_BLKLOCK
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, SrvAllocateLock )
#pragma alloc_text( PAGE, SrvFindAndReferenceLock )
#pragma alloc_text( PAGE, SrvCloseLock )
#pragma alloc_text( PAGE, SrvCloseLocksOnRfcb )
#pragma alloc_text( PAGE, SrvDereferenceLock )
#endif
VOID
SrvAllocateLock (
OUT PBYTELOCK *Lock,
IN PRFCB Rfcb,
IN LARGE_INTEGER Offset,
IN LARGE_INTEGER Length,
IN BOOLEAN Exclusive
)
/*++
Routine Description:
This function allocates a lock block from the FSP heap.
Arguments:
Lock - Returns a pointer to the lock block, or NULL if
no heap space was available.
Rfcb - file which owns this lock. MFCB lock will be taken to insert lock
into list.
Offset - offset of lock in file.
Length - lock length.
Exclusive - is this a shared or exclusive lock?
Return Value:
None.
--*/
{
PBYTELOCK lock;
PNONPAGED_MFCB npMfcb;
PAGED_CODE( );
if ( ! Rfcb->PersistentHandle ) {
*Lock = NULL;
return;
}
//
// Attempt to allocate from the heap.
//
lock = ALLOCATE_HEAP( sizeof(BYTELOCK), BlockTypeByteRangeLock );
*Lock = lock;
if ( lock == NULL ) {
INTERNAL_ERROR(
ERROR_LEVEL_EXPECTED,
"SrvAllocateLock: Unable to allocate %d bytes from heap",
sizeof(BYTELOCK),
NULL
);
return;
}
IF_DEBUG(HEAP) {
SrvPrint1( "SrvAllocateLock: Allocated byte range lock at %lx\n", lock );
}
RtlZeroMemory( lock, sizeof(BYTELOCK) );
SET_BLOCK_TYPE_STATE_SIZE( lock, BlockTypeByteRangeLock, BlockStateActive, BlockTypeByteRangeLock );
lock->BlockHeader.ReferenceCount = 2; // allow for Active status and caller's pointer
lock->Rfcb = Rfcb;
lock->LockOffset.QuadPart = Offset.QuadPart;
lock->LockLength.QuadPart = Length.QuadPart;
lock->Exclusive = Exclusive;
INITIALIZE_REFERENCE_HISTORY( lock );
npMfcb = Rfcb->Lfcb->Mfcb->NonpagedMfcb;
ACQUIRE_LOCK( &npMfcb->Lock );
SrvInsertHeadList( &Rfcb->PagedRfcb->ByteRangeLocks, &lock->RfcbListEntry );
RELEASE_LOCK( &npMfcb->Lock );
// INCREMENT_DEBUG_STAT( SrvDbgStatistics.SessionInfo.Allocations );
return;
} // SrvAllocateLock
PBYTELOCK
SrvFindAndReferenceLock (
IN PRFCB Rfcb,
IN LARGE_INTEGER Offset,
IN LARGE_INTEGER Length,
IN BOOLEAN Exclusive
)
/*++
Routine Description:
This function finds a lock, references it and returns it.
Arguments:
Rfcb - file which owns this lock. MFCB lock will be taken to insert lock
into list.
Offset - offset of lock in file.
Length - lock length.
Exclusive - is this a shared or exclusive lock?
Return Value:
PBYTELOCK - pointer to lock structure, null if doesn't exist.
--*/
{
PBYTELOCK lock = NULL;
PLIST_ENTRY listEntry;
PLIST_ENTRY listHead;
PNONPAGED_MFCB npMfcb;
PAGED_CODE( );
if (! Rfcb->PersistentHandle ) {
return NULL;
}
npMfcb = Rfcb->Lfcb->Mfcb->NonpagedMfcb;
ACQUIRE_LOCK( &npMfcb->Lock );
listHead = &Rfcb->PagedRfcb->ByteRangeLocks;
listEntry = listHead->Flink;
while (listEntry != listHead) {
lock = CONTAINING_RECORD( listEntry,
BYTELOCK,
RfcbListEntry
);
if ( GET_BLOCK_STATE(lock) == BlockStateActive &&
lock->LockOffset.QuadPart == Offset.QuadPart &&
lock->LockLength.QuadPart == Length.QuadPart &&
lock->Exclusive == Exclusive ) {
IF_DEBUG(REFCNT) {
SrvPrint2( "Referencing byte lock 0x%lx; old refcnt %lx\n",
lock, lock->BlockHeader.ReferenceCount );
}
ASSERT( GET_BLOCK_TYPE( lock ) == BlockTypeByteRangeLock );
ASSERT( lock->BlockHeader.ReferenceCount > 0 );
InterlockedIncrement( &lock->BlockHeader.ReferenceCount );
break;
}
lock = NULL;
listEntry = listEntry->Flink;
}
RELEASE_LOCK( &npMfcb->Lock );
return lock;
} // SrvFindAndReferenceLock
VOID
SrvCloseLock (
IN PBYTELOCK Lock,
IN BOOLEAN HaveLock
)
/*++
Routine Description:
This routine closes out the byte range lock block.
Arguments:
Lock - Supplies a pointer to the lock block that is to be closed.
Return Value:
None.
--*/
{
PNONPAGED_MFCB npMfcb;
PAGED_CODE( );
ASSERT( Lock->Rfcb != NULL );
if (!HaveLock) {
npMfcb = Lock->Rfcb->Lfcb->Mfcb->NonpagedMfcb;
ACQUIRE_LOCK( &npMfcb->Lock );
}
if ( GET_BLOCK_STATE(Lock) == BlockStateActive ) {
IF_DEBUG(BLOCK1) SrvPrint1( "Closing byte lock at 0x%lx\n", Lock );
SET_BLOCK_STATE( Lock, BlockStateClosing );
SrvRemoveEntryList( &Rfcb->PagedRfcb->ByteRangeLocks, &Lock->RfcbListEntry );
if (!HaveLock) {
RELEASE_LOCK( &npMfcb->Lock );
}
// if ( we're in the state file ) {
//
// remove us from state file.
// }
Lock->Rfcb = NULL;
//
// Dereference the lock (to indicate that it's no longer
// open).
//
SrvDereferenceLock( Lock );
} else {
if (!HaveLock) {
RELEASE_LOCK( &npMfcb->Lock );
}
}
return;
} // SrvCloseLock
VOID
SrvCloseLocksOnRfcb (
IN PRFCB Rfcb
)
/*++
Routine Description:
This function closes all locks on an RFCB. It walks the RFCB's
list of locks, calling SrvCloseLock as appropriate.
Arguments:
Rfcb - Supplies a pointer to a Rfcb Block
Return Value:
None.
--*/
{
PBYTELOCK lock;
PLIST_ENTRY listEntry;
PLIST_ENTRY listHead;
PNONPAGED_MFCB npMfcb;
PAGED_CODE( );
if (! Rfcb->PersistentHandle ) {
return;
}
npMfcb = Rfcb->Lfcb->Mfcb->NonpagedMfcb;
ACQUIRE_LOCK( &npMfcb->Lock );
listHead = &Rfcb->PagedRfcb->ByteRangeLocks;
listEntry = listHead->Flink;
while (listEntry != listHead) {
lock = CONTAINING_RECORD( listEntry,
BYTELOCK,
RfcbListEntry
);
listEntry = listEntry->Flink;
SrvCloseLock( lock, TRUE );
}
RELEASE_LOCK( &npMfcb->Lock );
return;
} // SrvCloseLocksOnRfcb
VOID SRVFASTCALL
SrvDereferenceLock (
IN PBYTELOCK Lock
)
/*++
Routine Description:
This function decrements the reference count on a lock. If the
reference count goes to zero, the lock block is deleted.
Arguments:
Lock - Address of lock
Return Value:
None.
--*/
{
LONG result;
PAGED_CODE( );
//
// Enter a critical section and decrement the reference count on the
// block.
//
IF_DEBUG(REFCNT) {
SrvPrint2( "Dereferencing byte lock 0x%lx; old refcnt %lx\n",
Lock, Lock->BlockHeader.ReferenceCount );
}
ASSERT( GET_BLOCK_TYPE( Lock ) == BlockTypeByteRangeLock );
ASSERT( Lock->BlockHeader.ReferenceCount > 0 );
result = InterlockedDecrement(
&Lock->BlockHeader.ReferenceCount
);
if ( result == 0 ) {
ASSERT( GET_BLOCK_STATE(Lock) == BlockStateClosing );
//
// Free the session block.
//
DEBUG SET_BLOCK_TYPE_STATE_SIZE( Lock, BlockTypeGarbage, BlockStateDead, -1 );
DEBUG Lock->BlockHeader.ReferenceCount = -1;
FREE_HEAP( Lock );
IF_DEBUG(HEAP) {
SrvPrint1( "SrvDereferenceLock: Freed session byte lock at 0x%lx\n", Lock );
}
}
return;
} // SrvDereferenceLock
#endif // def INCLUDE_SMB_PERSISTENT
// blklock.c eof