/**************************************************************************** | | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. | All Rights Reserved. | | This program is free software; you can redistribute it and/or | modify it under the terms of version 2 of the GNU General Public | License as published by the Free Software Foundation. | | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU General Public License | along with this program; if not, contact Novell, Inc. | | To contact Novell about this file by physical or electronic mail, | you may find current contact information at www.novell.com | |*************************************************************************** | | NetWare Advance File Services (NSS) Initialization module | |--------------------------------------------------------------------------- | | $Author: taysom $ | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ | | $RCSfile$ | $Revision: 465 $ | |--------------------------------------------------------------------------- | This module is used to: | Common lock definitions needed by byte range locks, logical or record | locks, and file name locks. | | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! | | This header file should ONLY be used for NSS internal development. | This includes Semantic Agents (SA) and Loadable Storage Services (LSS). | Any other use may cause conflicts which NSS will NOT fix. +-------------------------------------------------------------------------*/ #ifndef _COMNLOCK_H_ #define _COMNLOCK_H_ #ifndef _OMNI_H #include #endif #ifndef _RBPTREE_H_ #include #endif #ifndef _COMNBEASTS_H_ #include #endif #ifndef _PSSCONNECTION_H_ #include #endif #ifdef __cplusplus extern "C" { #endif /* Pre-define struct(s) so Linux compiler doesn't complain */ struct LockByteRangeMsg_s; struct LockSetMsg_s; struct UnlockByteRangeMsg_s; typedef enum LockType_t { LK_BYTERANGE, LK_LOGICAL, LK_FILENAME } LockType_t; typedef enum LockState_t { LK_IDLE, LK_WAITING, LK_LOCKED } LockState_t; typedef struct Reply_s Reply_s; struct Reply_s { FsmLite_s fsm; /* Fsm for callbacks */ OneShot_s alarm; /* Limits how long we wait for locks*/ voidfunc_t saCallBack; /* Semantic Agent specific call back*/ voidfunc_t userCallBack; /* Call back function */ ADDR userData; /* What we pass back to the user */ }; typedef struct LockSet_s { Reply_s reply; /* Reply for lock set requests */ RBP_Node_s *setRoot; /* Locks in this lock set */ NINT waiting; /* Num locks we are waiting for */ STATUS saStatus; /* Status from the Semantic Agent */ NINT otherSAs; /* Other SAs we are waiting for */ } LockSet_s; typedef struct LockHeader_s { Reply_s reply; /* Reply for single lock requests */ LockSet_s *lockSet; /* Lock is a member of this set */ RBP_Node_s sibling; /* Other byte range locks for task */ DQhead_t waiters; /* Those waiting for the lock */ DQlink_t waiting; /* Waiting for lock (could use waiters) */ BOOL waitForever; /* How long to wait if blocked */ BYTE mode; /* Mode of the lock (S, X, N) */ BYTE state; /* Lock state (LockState_t) */ BYTE reserved[2]; } LockHeader_s; typedef struct ByteRangeLock_s { LockHeader_s head; RBP_Node_s startHeld; /* Starting offset tree for held locks */ RBP_Node_s endHeld; /* Ending offset tree for held locks */ QUAD start; /* Starting address for byte range lock */ QUAD end; /* Ending address for byte range lock */ ADDR lockData; /* compared when finding a lock */ NamedBeast_s *beast; /* Beast for byte range lock */ FileHandle_s *fh; /* File handle that owns the lock */ } ByteRangeLock_s; #if NSS_DEBUG IS_ENABLED #define INIT_REPLY(_reply) \ { \ static NINT instance = 0; \ \ FSMLITE_INIT( &(_reply)->fsm, WHERE, instance); \ ++instance; \ INIT_ONESHOT((_reply)->alarm); \ (_reply)->saCallBack = NULL; \ } #else #define INIT_REPLY(_reply) \ { \ FSMLITE_INIT( &(_reply)->fsm, NULL, 0); \ INIT_ONESHOT((_reply)->alarm); \ (_reply)->saCallBack = NULL; \ } #endif #define COPY_CALLBACKS(_reply, _msg) \ { \ (_reply)->saCallBack = (_msg)->saCallBack; \ (_reply)->userCallBack = (_msg)->userCallBack; \ (_reply)->userData = (_msg)->userData; \ } /* * INIT_LOCKHEAD initializes the lock header and * sets its initialize state to FREE. Assumes fields * are all already set to 0. */ #define INIT_LOCKHEAD(_head, _lockSet, _mode, _waitForever) \ { \ INIT_REPLY( &((_head)->reply)); \ DQ_INIT( &(_head)->waiters); \ (_head)->lockSet = (_lockSet); \ (_head)->mode = (_mode); \ (_head)->state = LK_IDLE; \ (_head)->waitForever = (_waitForever); \ } #define HAS_BYTE_RANGE_LOCKS(_beast) \ (((NamedBeast_s *)(_beast))->startLocks != NULL) /* * Function prototypes */ struct UserXaction_s *COMN_FindDefaultXaction ( struct GeneralMsg_s *genMsg); void COMN_ConnectionUnlockByteRange( struct NSSConnection_s *nssConn); void COMN_TaskUnlockByteRange( struct GeneralMsg_s *genMsg); void COMN_BeastUnlockByteRange( struct GeneralMsg_s *genMsg, struct NamedBeast_s *beast, struct FileHandle_s *fileHandle); STATUS COMN_LockByteRange( struct GeneralMsg_s *genMsg, struct LockByteRangeMsg_s *lockMsg); STATUS COMN_LockByteRangeSet( struct GeneralMsg_s *genMsg, struct LockSetMsg_s *setMsg); STATUS COMN_UnlockByteRange( struct GeneralMsg_s *genMsg, struct UnlockByteRangeMsg_s *unlockMsg); ByteRangeLock_s *COMN_FindByteRangeLock( struct GeneralMsg_s *genMsg, struct LockByteRangeMsg_s *lockMsg); STATUS COMN_UnlockByteRangeSet( struct GeneralMsg_s *genMsg, BOOL clear); BOOL LOCK_IsSharedByteRange ( struct FileHandle_s *fh, Xid_t userXid, QUAD start, QUAD length); BOOL LOCK_IsExclusiveByteRange ( struct FileHandle_s *fh, Xid_t userXid, QUAD start, QUAD length); BOOL LOCK_IsExclusiveByteRangeMandatory ( NamedBeast_s *beast, QUAD start, QUAD length); ByteRangeLock_s *findByteRangeLock( struct UnlockByteRangeMsg_s *unlockMsg); void unlockByteRangeSet( struct LockSet_s *lockSet, BOOL clear); ByteRangeLock_s *testLock( NamedBeast_s *beast, QUAD start, QUAD end, NINT mode, LockSet_s *lockSet, NINT semanticAgentID); void lockChangeStart(ByteRangeLock_s *lock, QUAD start); void lockChangeEnd(ByteRangeLock_s *lock, QUAD end); void lockForceLock(ByteRangeLock_s *lock); void unlockByteRange ( ByteRangeLock_s *lock, BOOL clear); void unlockXaction(struct UserXaction_s *userXaction); void initLockSet(struct LockSet_s *lockSet); void wakeupLockRequests(ByteRangeLock_s *lock); ByteRangeLock_s *allocByteRangeLock ( GeneralMsg_s *genMsg, LockSet_s *lockSet, struct LockByteRangeMsg_s *msg); BOOL checkDeadLockByFH( FileHandle_s *waiter, FileHandle_s *holder, BOOL setWaitFor); void clearXactionWaitForByFH( FileHandle_s *fh); /*************************************************************************** * Logical lock definitions ***************************************************************************/ #define LOCK_HASH_SIZE 128 #define LOCK_MODE_EXCLUSIVE 1 #define LOCK_MODE_SHARED 2 #define LOCKED TRUE #define NOT_LOCKED FALSE #define MAX_KEY_LEN_BYTES 128 typedef struct Lock_s { BYTE key[MAX_KEY_LEN_BYTES]; BYTE keyLen; BYTE pad[3]; Latch_s latch; OneShot_s alarm; DQlink_t hashLink; } Lock_s; extern STATUS LOCK_Startup(void); extern void LOCK_Shutdown(void); extern Lock_s *COMN_LookupLock( BYTE *key, NINT keyBytes, BOOL allocIfNotThere); extern BOOL COMN_LockFunc( BYTE *key, NINT keyBytes, NINT mode, SLONG msecs); extern void COMN_UnLockFunc( BYTE *key, NINT keyBytes); #ifdef __cplusplus } #endif #endif