0611 nwnss: import COMN oplock runtime
This commit is contained in:
380
include/nwnss/include/pssConfig.h
Normal file
380
include/nwnss/include/pssConfig.h
Normal file
@@ -0,0 +1,380 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| (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: gpachner $
|
||||
| $Date: 2007-06-07 02:25:28 +0530 (Thu, 07 Jun 2007) $
|
||||
|
|
||||
| $RCSfile$
|
||||
| $Revision: 2044 $
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
| This module is used to:
|
||||
| Define configuration values for the Z file system
|
||||
|
|
||||
| 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 _PSSCONFIG_H_
|
||||
#define _PSSCONFIG_H_
|
||||
|
||||
#ifndef _OMNI_H_
|
||||
#include <omni.h>
|
||||
#endif
|
||||
|
||||
#include "hmc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern NINT WorkWaitingCount;
|
||||
extern NINT WorkHighWaitingCount;
|
||||
|
||||
#define CACHE_BALANCE_TIMER_SECS 30
|
||||
#define MIN_OS_FREE_CACHE_BUFS 256
|
||||
#define DEFAULT_NUM_BUFFERS_PER_SESSION 1024
|
||||
|
||||
#define PERCENT_OF_OS_BUFS(_num) (((_num)*Config.cache.percentOfOSFree)/100)
|
||||
#define BALANCE_CACHE_MIN 16
|
||||
|
||||
#define MAX_PERCENT_FOR_USER_PAGES 50
|
||||
|
||||
#if defined(__i386__)
|
||||
#define DEFAULT_HMC_CACHE_TYPE HMC_CT_PRIVATE
|
||||
#endif
|
||||
#if defined(__x86_64__)
|
||||
#define DEFAULT_HMC_CACHE_TYPE HMC_CT_NONE
|
||||
#endif
|
||||
#define DEFAULT_PRIVATE_CACHE_PAGES 1 /* Calculated in HMC_Startup */
|
||||
|
||||
|
||||
|
||||
/** Set Maximum value to zero if there is no Maximum limit for the variable **/
|
||||
/** Set Minimum value to zero if the variable can be set to zero **/
|
||||
|
||||
/* Range definitions*/
|
||||
//#define MIN_NUM_BUFFERS 8 /* See debug area */
|
||||
#define MAX_NUM_BUFFERS 1048576 /* Upto 4 GB of memory */
|
||||
|
||||
#define MIN_NUM_ASYNCIOS 4
|
||||
#define MAX_NUM_ASYNCIOS 65536
|
||||
|
||||
#define MIN_NUM_BONDS (2 * MIN_NUM_BUFFERS)
|
||||
#define MAX_NUM_BONDS (2 * MAX_NUM_BUFFERS)
|
||||
|
||||
//#define MIN_CACHE_HASH_SHIFT 8
|
||||
//#define MAX_CACHE_HASH_SHIFT 20
|
||||
|
||||
#define MIN_NOT_IN_USE_BEASTS 16
|
||||
#define MAX_NOT_IN_USE_BEASTS 1000000
|
||||
#define MIN_BEASTS_TO_RETURN 16 /* Always return at least this many */
|
||||
|
||||
#define MIN_BEAST_HASH_SHIFT 8
|
||||
#define MAX_BEAST_HASH_SHIFT 25
|
||||
|
||||
#define MIN_SIZE_MAILBOX 256
|
||||
#define MAX_SIZE_MAILBOX 65536
|
||||
|
||||
#define MIN_SEC 1
|
||||
#define MAX_SEC 3600
|
||||
|
||||
#define MIN_WORK_LIMIT 5
|
||||
#define MAX_WORK_LIMIT 100
|
||||
|
||||
#define MIN_NUM_XACTIONS 4
|
||||
#define MAX_NUM_XACTIONS 65536
|
||||
|
||||
#define MIN_NUM_XDELETES 4
|
||||
#define MAX_NUM_XDELETES 65536
|
||||
|
||||
#define MIN_STORAGE_ALARM_THRESHOLD 0
|
||||
#define MAX_STORAGE_ALARM_THRESHOLD 1000000
|
||||
|
||||
#define MIN_STORAGE_RESET_THRESHOLD 0
|
||||
#define MAX_STORAGE_RESET_THRESHOLD 1000000
|
||||
|
||||
#define DEFAULT_BEAST_PERCENT_MEM 45
|
||||
|
||||
#define DEFAULT_BEAST_BALANCE_SEC 1
|
||||
|
||||
#define MIN_ALLOC_AHEAD_WRITE 0
|
||||
#define DEFAULT_ALLOC_AHEAD_WRITE 0 // On linux most applications on
|
||||
// server and ncp and probably cifs
|
||||
// do larger writes (not network
|
||||
// packet size writes). So we get
|
||||
// better performance without
|
||||
// allocahead.
|
||||
#define MAX_ALLOC_AHEAD_WRITE 63
|
||||
|
||||
|
||||
#if NSS_DEBUG IS_ENABLED
|
||||
/*
|
||||
* DEBUG values
|
||||
*/
|
||||
#define PERCENT_OS_FREE_CACHE 99
|
||||
#define PRERESERVE_FOR_BEAST_FLUSH 64
|
||||
#define CACHE_HYSTERESIS 16 /* Have to have at least this many OS
|
||||
* buffers that we can take before we
|
||||
* take any.
|
||||
*/
|
||||
#define MIN_NUM_BUFFERS (CACHE_HYSTERESIS + PRERESERVE_FOR_BEAST_FLUSH)
|
||||
|
||||
#define DEFAULT_NUM_BONDS 5000 /*(2 * DEFAULT_NUM_BUFFERS)*/
|
||||
#define DEFAULT_NUM_BUFFERS 512
|
||||
#define DEFAULT_NUM_ASYNCIOS 2048
|
||||
#define DEFAULT_NUM_DELAYED_BEASTS 40
|
||||
//#define DEFAULT_CACHE_HASH_SHIFT 10
|
||||
#define DEFAULT_NOT_IN_USE_BEASTS 100000
|
||||
//#define DEFAULT_BEAST_HASH_SHIFT 12
|
||||
#define DEFAULT_SIZE_MAILBOX 512
|
||||
#define DEFAULT_SEC_BEAST 10
|
||||
#define DEFAULT_SEC_XACTION 20
|
||||
#define DEFAULT_SEC_CHKPT 30
|
||||
#define DEFAULT_SEC_OPLOCKWAIT 30
|
||||
#define DEFAULT_WORK_LIMIT 30
|
||||
#define DEFAULT_NUM_XACTIONS 50
|
||||
#define DEFAULT_NUM_XDELETES 10
|
||||
#define DEFAULT_STORAGE_ALARM_THRESHOLD 1 /* in kbytes */
|
||||
#define DEFAULT_STORAGE_RESET_THRESHOLD 2 /* in kbytes */
|
||||
#define DEFAULT_STORAGE_SEND_ALERT 1 /* boolean */
|
||||
#else
|
||||
/*
|
||||
* PRODUCTION values
|
||||
*/
|
||||
#define PERCENT_OS_FREE_CACHE 85
|
||||
#define PRERESERVE_FOR_BEAST_FLUSH 128
|
||||
#define CACHE_HYSTERESIS 256 /* Have to have at least this many OS
|
||||
* buffers that we can take before we
|
||||
* take any.
|
||||
*/
|
||||
#define MIN_NUM_BUFFERS (CACHE_HYSTERESIS + PRERESERVE_FOR_BEAST_FLUSH)
|
||||
|
||||
#define DEFAULT_NUM_BONDS 5000 /*(2 * DEFAULT_NUM_BUFFERS)*/
|
||||
#define DEFAULT_NUM_BUFFERS 512
|
||||
#define DEFAULT_NUM_ASYNCIOS 2048
|
||||
#define DEFAULT_NUM_DELAYED_BEASTS 40
|
||||
//#define DEFAULT_CACHE_HASH_SHIFT 13
|
||||
#define DEFAULT_NOT_IN_USE_BEASTS 100000
|
||||
//#define DEFAULT_BEAST_HASH_SHIFT 16
|
||||
#define DEFAULT_SIZE_MAILBOX 512
|
||||
#define DEFAULT_SEC_BEAST 10
|
||||
#define DEFAULT_SEC_XACTION 20
|
||||
#define DEFAULT_SEC_CHKPT 30
|
||||
#define DEFAULT_SEC_OPLOCKWAIT 30
|
||||
#define DEFAULT_WORK_LIMIT 50
|
||||
#define DEFAULT_NUM_XACTIONS 5000
|
||||
#define DEFAULT_NUM_XDELETES 1000
|
||||
#define DEFAULT_STORAGE_ALARM_THRESHOLD 10 /* in megabytes */
|
||||
#define DEFAULT_STORAGE_RESET_THRESHOLD 15 /* in megabytes */
|
||||
#define DEFAULT_STORAGE_SEND_ALERT 1 /* boolean */
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SEC_JOURNAL_GROUP_WRITE 1
|
||||
#define DEFAULT_SEC_METADATA_GROUP_WRITE 40
|
||||
#define DEFAULT_SEC_USER_DATA_GROUP_WRITE 3
|
||||
#define DEFAULT_METADATA_GROUP_WRITE_LIMIT 20000 /* Really a limit target */
|
||||
|
||||
#define DEFAULT_CHECKER TRUE
|
||||
#define DEFAULT_FORCE_CHECKER FALSE
|
||||
#define DEFAULT_WORK_DELAY_CNT 100
|
||||
#define DEFAULT_MSEC_WORK_WAIT 100
|
||||
|
||||
#define DEFAULT_MAX_WORK_WAITING 1000
|
||||
#define DEFAULT_MAX_HIGH_WORK_WAITING 50
|
||||
|
||||
#define DEFAULT_LV_PURGE_DELAY_AFTER_DELETE_SECONDS (60 * 60 * 24 * 4) /* 4 days (was 2 days, but increased so to stay around over LONG weekend)*/
|
||||
#define DEFAULT_LV_PURGE_DELAY_AFTER_LOAD_SECONDS (60 * 60 * 2) /* 2 hour */
|
||||
#define DEFAULT_LV_PURGE_DELAY_AFTER_LAST_ENTRY_SECONDS (60 * 15) /* 15 minutes */
|
||||
|
||||
#if zLINUX
|
||||
#define DEFAULT_SECURITY_EQUIV_UPDATER TRUE
|
||||
#define DEFAULT_FORCE_SECURITY_EQUIV_UPDATER FALSE
|
||||
#define DEFAULT_SECURITY_EQUIV_UPDATER_SECONDS (((60 * 60) * 2) + 37) /* 2 hours and 37 seconds */
|
||||
#define DEFAULT_SECURITY_EQUIV_UPDATER_CHANGED FALSE
|
||||
#endif
|
||||
|
||||
/* min/max values for the high/low watermarks used to control purge limits */
|
||||
#define zMAX_HIGHWATERMARK 100
|
||||
#define zMIN_HIGHWATERMARK 2
|
||||
#define zMAX_LOWWATERMARK 98
|
||||
#define zMIN_LOWWATERMARK 0
|
||||
|
||||
typedef struct Config_s
|
||||
{
|
||||
struct Cache_s
|
||||
{
|
||||
NINT numBuffers;
|
||||
NINT numBonds;
|
||||
NINT numAsyncios;
|
||||
// NINT hashShift;
|
||||
NINT hashSize;
|
||||
NINT hashMask;
|
||||
|
||||
BOOL usePercentMemory;
|
||||
NINT percentOfOSFree;
|
||||
NINT balanceTimerSecs;
|
||||
NINT minOSFree;
|
||||
NINT numPagesAllocated;
|
||||
NINT maxNumBuffersToAddPerBalance;
|
||||
NINT userPages; /* number of pages used for user data */
|
||||
NINT percentUserPages; /* percentage of total pages for user */
|
||||
NINT hmcCacheType; /* HMC_CT_LINUX, HMC_CT_NONE, or
|
||||
HMC_CT_PRIVATE. Needed on servers with limited low
|
||||
memory, but lots of high memory. In which case,
|
||||
NSS will use high memory as a secondary cache for
|
||||
its meta-data blocks unless user turns off. */
|
||||
NINT privateHashSize;
|
||||
NINT privateHashMask;
|
||||
NINT privateCachePageBuffers; /* Number of page buffers that are
|
||||
currently in the private cache. */
|
||||
NINT privateCachePages; /* Number of pages that are currently
|
||||
attached to our page buffers. */
|
||||
NINT privateCacheSizeRequest; /* For HMC_CT_PRIVATE. Number of
|
||||
pages buffers to have in the private cache. The
|
||||
actual number of page buffers that we have is
|
||||
in privateCachePageBuffers. */
|
||||
BOOL privateCacheSizeRequestStartup; /* Indicates that user
|
||||
set privateCacheSizeRequest at startup time. */
|
||||
NINT metadataBlocksReadyForGroupWriteLimit; /* Limits the number
|
||||
of metadata blocks that are on the metadata
|
||||
group write list. This limits the amount of
|
||||
time needed to play the journal after a crash. */
|
||||
NINT metadataBlocksReadyForGroupWrite; /* Current count of
|
||||
metadata blocks that are on the metadata group
|
||||
write list. */
|
||||
} cache;
|
||||
struct Os_s
|
||||
{
|
||||
NINT sizeMailbox;
|
||||
NINT workLimit;
|
||||
NINT workDelayCnt;
|
||||
} os;
|
||||
struct Bst_s
|
||||
{
|
||||
NINT notInUseMax; /* Max beasts allowed to be not in use */
|
||||
NINT percentMemory; /* Max % memory to be used by beasts */
|
||||
NINT balanceTimerSecs; /* Balance beasts with memory */
|
||||
// NINT hashShift;
|
||||
NINT hashSize;
|
||||
// NINT hashMask;
|
||||
NINT notInUseLimit; /* Current limit for not in use beasts */
|
||||
NINT total; /* Total number of beasts in memory */
|
||||
NINT notInUse; /* Number of closed beasts not in use */
|
||||
SNINT remainingLimit; /* Remaining limit of beasts */
|
||||
} bst;
|
||||
struct Sec_s
|
||||
{
|
||||
NINT beast;
|
||||
NINT xaction;
|
||||
NINT chkpt;
|
||||
NINT opLockWait;
|
||||
NINT journalGroupWriteTime;
|
||||
NINT metadataGroupWriteTime;
|
||||
NINT userDataGroupWriteTime;
|
||||
} sec;
|
||||
struct Msec_s
|
||||
{
|
||||
NINT workWait;
|
||||
} msec_s;
|
||||
struct Tick_s
|
||||
{
|
||||
NINT beast;
|
||||
NINT xaction;
|
||||
NINT chkpt;
|
||||
NINT opLockWait;
|
||||
} tick;
|
||||
struct NumWork_s
|
||||
{
|
||||
NINT waiting;
|
||||
NINT waitingHigh;
|
||||
} work;
|
||||
struct Xact_s
|
||||
{
|
||||
NINT numDelayed;
|
||||
} xact;
|
||||
struct Zfs_s
|
||||
{
|
||||
NINT numXactions;
|
||||
NINT numXdeletes;
|
||||
} zfs;
|
||||
struct Storage
|
||||
{
|
||||
NINT alarmThreshold;
|
||||
NINT resetThreshold;
|
||||
BOOL sendAlert;
|
||||
NINT allocAhead;
|
||||
BOOL checker; /* TRUE if the background checker is to be run */
|
||||
BOOL forceChecker; /* TRUE if the background checker is to be forced to run */
|
||||
} Storage;
|
||||
struct LV_s
|
||||
{
|
||||
NINT PurgeDelayAfterDeleteSeconds; /* Number of seconds that
|
||||
a volume is non-purgeable. */
|
||||
NINT PurgeDelayAfterLoadSeconds; /* Number of seconds that
|
||||
a volume will not be purged in
|
||||
after NSS loads. Used to give the
|
||||
ADMIN some time to change state of
|
||||
a deleted volume after load. */
|
||||
NINT PurgeDelayAfterLastEntrySeconds; /* Number of seconds that
|
||||
a volume is non-purgeable after
|
||||
its last entry into purgeable state.
|
||||
E.G. if a LV is paused then
|
||||
un-paused after its normal purge
|
||||
time then it will not be purgeable
|
||||
for the number of seconds indicated
|
||||
by this element. */
|
||||
} lv;
|
||||
#if zLINUX
|
||||
struct SecEquiv_s
|
||||
{
|
||||
BOOL updater; /* TRUE if the security equivalence
|
||||
* background updater is to be run */
|
||||
BOOL forceUpdater; /* TRUE if the security equivalence
|
||||
* background updater is to be
|
||||
* forced to be run */
|
||||
NINT updaterInterval; /* Number of seconds that we delay
|
||||
* after finishing a security
|
||||
* equivalence update and before
|
||||
* starting a new one.*/
|
||||
BOOL intervalChanged; /* TRUE if the security equivalence
|
||||
* background interval was changed */
|
||||
} SecEquiv;
|
||||
#endif
|
||||
} Config_s;
|
||||
|
||||
extern Config_s Config;
|
||||
|
||||
void configStartup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -129,6 +129,7 @@ add_library(nwnss SHARED
|
||||
comn/common/fsmsg.c
|
||||
comn/common/fileHandle.c
|
||||
comn/common/csaLease.c
|
||||
comn/common/comnOpLock.c
|
||||
comn/common/nameScan.c
|
||||
comn/namespace/nameSpace.c
|
||||
comn/namespace/dosNSpace.c
|
||||
|
||||
637
src/nwnss/comn/common/comnOpLock.c
Normal file
637
src/nwnss/comn/common/comnOpLock.c
Normal file
@@ -0,0 +1,637 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| (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) module
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| $Author: blarsen $
|
||||
| $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $
|
||||
|
|
||||
| $RCSfile$
|
||||
| $Revision: 1315 $
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
| This module is used to:
|
||||
| Define the Common side of OpLocks.
|
||||
|
|
||||
+-------------------------------------------------------------------------*/
|
||||
|
||||
#include <procdefs.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "msgGen.h"
|
||||
#include "xError.h"
|
||||
#include "pssConfig.h"
|
||||
#include "fileHandle.h"
|
||||
#include "comnBeasts.h"
|
||||
#include "opLock.h"
|
||||
#include "pssStartup.h"
|
||||
#include "comnPublics.h"
|
||||
#include "schedule.h"
|
||||
extern STATUS snoozeSec(DQhead_t *list, NINT seconds);
|
||||
extern void roust(DQhead_t *list, STATUS status);
|
||||
|
||||
#ifndef __linux__ // LINUX_NetWareAlerts
|
||||
extern NetWareAlertStructure OpLockTimeoutAlert;
|
||||
|
||||
GROUP_EVENT evOpLockTimeout =
|
||||
{
|
||||
GEventcbID, VTLong, 0, LocksSubjects + 10, 0, 0,
|
||||
nmOpLockTimeout, &OpLockTimeoutAlert, 0, 0
|
||||
};
|
||||
|
||||
NetWareAlertStructure OpLockTimeoutAlert = {
|
||||
&evOpLockTimeout,
|
||||
QAlert320Mask,
|
||||
0,
|
||||
NOTIFY_ERROR_LOG_BIT | NOTIFY_CONSOLE_BIT,
|
||||
ALERT_ID(ALERT_OS, nmOpLockTimeout),
|
||||
LOCUS_LOCKS,
|
||||
CLASS_STATION_FAILURE,
|
||||
SEVERITY_OPERATION_ABORTED,
|
||||
NULL, NULL, 0,
|
||||
InxMSG("Station %d (task %d) timed out waiting for an op-lock on file %s held by station %d.", 592)
|
||||
};
|
||||
#endif
|
||||
|
||||
BOOL OpLockVerbose = FALSE; // TRUE;
|
||||
OpLockInst_s OpLockInst;
|
||||
|
||||
|
||||
OpLockControl_s *getOpLockControl (File_s *file)
|
||||
{
|
||||
OpLockControl_s *opLockControl;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
ASSERT_XLATCH( &file->FILEbeastLatch);
|
||||
|
||||
opLockControl = file->opLockControl;
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
opLockControl = zalloc(sizeof(OpLockControl_s));
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
file->opLockControl = opLockControl;
|
||||
opLockControl->opFile = file;
|
||||
DQ_INIT( &opLockControl->opLockWaiters);
|
||||
DQ_INIT( &opLockControl->opLocks);
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
opLockControl->opHasPSA = FALSE;
|
||||
}
|
||||
return opLockControl;
|
||||
}
|
||||
|
||||
void OPLOCK_roust (OpLockControl_s *opLockControl)
|
||||
{
|
||||
if (DQ_EMPTY( &opLockControl->opLocks))
|
||||
{
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
roust( &opLockControl->opLockWaiters, zOK);
|
||||
}
|
||||
}
|
||||
|
||||
OpLock_s *OPLOCK_AllocExclusive (
|
||||
FileHandle_s *fh,
|
||||
statusfunc_t opCallback)
|
||||
{
|
||||
File_s *file = fh->file;
|
||||
OpLock_s *opLock;
|
||||
OpLockControl_s *opLockControl;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
zASSERT(fh->opLock == NULL);
|
||||
ASSERT_XLATCH( &file->FILEbeastLatch);
|
||||
|
||||
if (file->FILEopenCount != 1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
opLockControl = getOpLockControl(file);
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
opLock = zalloc(sizeof(OpLock_s));
|
||||
if (opLock == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
switch (opLockControl->opState)
|
||||
{
|
||||
case OPLOCK_IDLE:
|
||||
break;
|
||||
case OPLOCK_EXCLUSIVE:
|
||||
case OPLOCK_BREAKING_EXCLUSIVE:
|
||||
case OPLOCK_SHARED:
|
||||
case OPLOCK_BREAKING_SHARED:
|
||||
free(opLock);
|
||||
return NULL;
|
||||
}
|
||||
opLockControl->opState = OPLOCK_EXCLUSIVE;
|
||||
opLock->opCallback = opCallback;
|
||||
opLock->fileHandle = fh;
|
||||
opLock->control = opLockControl;
|
||||
DQ_ENQ( &opLockControl->opLocks, opLock, opLink);
|
||||
fh->opLock = opLock;
|
||||
|
||||
OPLOCK(allocExclusive);
|
||||
return opLock;
|
||||
}
|
||||
|
||||
OpLock_s *OPLOCK_AllocShared (
|
||||
FileHandle_s *fh,
|
||||
statusfunc_t opCallback)
|
||||
{
|
||||
File_s *file = fh->file;
|
||||
OpLock_s *opLock;
|
||||
OpLockControl_s *opLockControl;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
ASSERT_XLATCH( &file->FILEbeastLatch);
|
||||
|
||||
opLockControl = getOpLockControl(file);
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
opLock = zalloc(sizeof(OpLock_s));
|
||||
if (opLock == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
switch (opLockControl->opState)
|
||||
{
|
||||
case OPLOCK_IDLE:
|
||||
case OPLOCK_SHARED:
|
||||
break;
|
||||
case OPLOCK_EXCLUSIVE:
|
||||
case OPLOCK_BREAKING_EXCLUSIVE:
|
||||
case OPLOCK_BREAKING_SHARED:
|
||||
free(opLock);
|
||||
return NULL;
|
||||
}
|
||||
opLockControl->opState = OPLOCK_SHARED;
|
||||
opLock->opCallback = opCallback;
|
||||
opLock->fileHandle = fh;
|
||||
opLock->control = opLockControl;
|
||||
DQ_ENQ( &opLockControl->opLocks, opLock, opLink);
|
||||
fh->opLock = opLock;
|
||||
if (fh->grantedRights & zRR_PSA_CACHE)
|
||||
{
|
||||
opLockControl->opHasPSA = TRUE;
|
||||
}
|
||||
OPLOCK(allocShared);
|
||||
return opLock;
|
||||
}
|
||||
|
||||
void OPLOCK_Free (OpLock_s *opLock)
|
||||
{
|
||||
FileHandle_s *fh;
|
||||
OpLockControl_s *opLockControl;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
if (opLock == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
OPLOCK(free);
|
||||
|
||||
fh = opLock->fileHandle;
|
||||
ASSERT_XLATCH( &fh->file->FILEbeastLatch);
|
||||
fh->opLock = NULL;
|
||||
|
||||
opLock->opCallback(OPLOCK_CLEAR, NULL, opLock);
|
||||
|
||||
zASSERT(!QMEMBER( &opLock->tickle));
|
||||
|
||||
opLockControl = opLock->control;
|
||||
|
||||
if (QMEMBER( &opLock->opLink))
|
||||
{
|
||||
DQ_RMV(opLock, opLink);
|
||||
}
|
||||
free(opLock);
|
||||
switch (opLockControl->opState)
|
||||
{
|
||||
case OPLOCK_IDLE:
|
||||
break;
|
||||
case OPLOCK_EXCLUSIVE: // No one should be snoozing
|
||||
OPLOCK_roust(opLockControl);
|
||||
break;
|
||||
case OPLOCK_SHARED:
|
||||
break;
|
||||
case OPLOCK_BREAKING_EXCLUSIVE:
|
||||
OPLOCK_roust(opLockControl);
|
||||
break;
|
||||
case OPLOCK_BREAKING_SHARED:
|
||||
break;
|
||||
}
|
||||
if (DQ_EMPTY( &opLockControl->opLocks))
|
||||
{
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void OPLOCK_TimeOutAlert (
|
||||
GeneralMsg_s *genMsg,
|
||||
File_s *file,
|
||||
LONG ownerStation)
|
||||
{
|
||||
typedef struct Stack_s {
|
||||
char name[zMAX_COMPONENT_NAME];
|
||||
unicode_t uniName[zMAX_COMPONENT_NAME];
|
||||
} Stack_s;
|
||||
STATUS status;
|
||||
|
||||
STACK_ALLOC();
|
||||
|
||||
if (COMN_GetNameFromBeast(genMsg, file,// cnt zFNU_FIRST_PARENT,
|
||||
zNSPACE_LONG, zMAX_COMPONENT_NAME,
|
||||
aStack->uniName, NULL) == zOK)
|
||||
{
|
||||
status = LB_UnicodeToByte(NSS_UNI_CONVERSION_RAW, aStack->name,
|
||||
zMAX_COMPONENT_NAME, aStack->uniName, NULL);
|
||||
if (status != zOK)
|
||||
{
|
||||
strcpy(aStack->name, "<Couldn't print name>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearErrno(genMsg);
|
||||
strcpy(aStack->name, "<Unknown File>");
|
||||
}
|
||||
#ifndef __linux__ // LINUX_NetWareAlerts
|
||||
ZOS_NetWareAlert((CMN_ModuleHandle, &OpLockTimeoutAlert, 4,
|
||||
genMsg->pssConn.id, genMsg->taskID,
|
||||
aStack->name, ownerStation));
|
||||
#endif
|
||||
STACK_FREE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Assumptions:
|
||||
* 1. COMN_BreakOpLock or OPLOCK_BreakExclusive
|
||||
* has been called and returned zERR_OPLOCK_MUST_WAIT.
|
||||
* 2. The thread has released all of its latches. (This does
|
||||
* not mean that someone else can't have a latch.)
|
||||
* 3. The thread will reaquire the latches its needs after
|
||||
* this call returns.
|
||||
* 4. If you were trying to also break shared oplocks, you'll have
|
||||
* to call OPLOCK_BreakShared
|
||||
*/
|
||||
STATUS OPLOCK_WaitForBreak (
|
||||
GeneralMsg_s *genMsg,
|
||||
File_s *file)
|
||||
{
|
||||
OpLockControl_s *opLockControl;
|
||||
OpLock_s *opLock;
|
||||
statusfunc_t callback;
|
||||
DQhead_t save;
|
||||
LONG ownerStation;
|
||||
STATUS rc;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
|
||||
opLockControl = file->opLockControl;
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
/*
|
||||
* Need to check state
|
||||
*/
|
||||
switch (opLockControl->opState)
|
||||
{
|
||||
case OPLOCK_IDLE:
|
||||
case OPLOCK_BREAKING_SHARED:
|
||||
case OPLOCK_SHARED:
|
||||
case OPLOCK_EXCLUSIVE:
|
||||
OPLOCK_roust(opLockControl); /* Wake up anybody that might be sleeping */
|
||||
zASSERT("OpLock should be in OPLOCK_BREAKING_EXCLUSIVE"==0);
|
||||
SetErrno(genMsg, zERR_INVALID_STATE);
|
||||
return zFAILURE;
|
||||
case OPLOCK_BREAKING_EXCLUSIVE:
|
||||
break;
|
||||
}
|
||||
/* Notify SA that we are waiting (deadlock detection for nwSA) */
|
||||
DQ_PEEK( &opLockControl->opLocks, opLock, OpLock_s, opLink);
|
||||
if (opLock == NULL)
|
||||
{
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
return zOK;
|
||||
}
|
||||
callback = opLock->opCallback;
|
||||
rc = callback(OPLOCK_WAITING, genMsg, opLock);
|
||||
|
||||
OPLOCK(waitForBreak);
|
||||
rc = snoozeSec( &opLockControl->opLockWaiters, Config.sec.opLockWait);
|
||||
callback(OPLOCK_WAIT_OVER, genMsg, NULL);
|
||||
if (rc == zOK)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
if (rc != zERR_TIMEOUT)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
OPLOCK(timedOut);
|
||||
/*
|
||||
* Give the SA a chance to break the oplock
|
||||
*/
|
||||
rc = zOK;
|
||||
ownerStation = -1;
|
||||
DQ_INIT( &save);
|
||||
for (;;)
|
||||
{
|
||||
DQ_DEQ( &opLockControl->opLocks, opLock, OpLock_s, opLink);
|
||||
if (opLock == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DQ_ENQ( &save, opLock, opLink);
|
||||
if (opLock->fileHandle)
|
||||
{
|
||||
ownerStation = opLock->fileHandle->connID;
|
||||
}
|
||||
rc = opLock->opCallback(OPLOCK_TIMEOUT, genMsg, opLock);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
if (rc != zOK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
DQ_APPEND( &opLockControl->opLocks, &save);
|
||||
if (rc == zOK)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
if (rc == zERR_TIMEOUT)
|
||||
{
|
||||
OPLOCK_TimeOutAlert(genMsg, file, ownerStation);
|
||||
}
|
||||
exit:
|
||||
if (rc == zOK)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
SetErrno(genMsg, zERR_OPLOCK_COLLISION);
|
||||
return zFAILURE;
|
||||
}
|
||||
|
||||
STATUS OPLOCK_BreakExclusive (
|
||||
GeneralMsg_s *genMsg, /* Has the connection ID and task */
|
||||
File_s *file,
|
||||
BOOL wait)
|
||||
{
|
||||
OpLockControl_s *opLockControl = file->opLockControl;
|
||||
statusfunc_t callback;
|
||||
OpLock_s *opLock;
|
||||
STATUS rc;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
ASSERT_XLATCH( &file->FILEbeastLatch);
|
||||
/*
|
||||
* See if we have to break any opLocks
|
||||
*/
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
switch (opLockControl->opState)
|
||||
{
|
||||
case OPLOCK_IDLE:
|
||||
return zOK;
|
||||
|
||||
case OPLOCK_EXCLUSIVE:
|
||||
DQ_PEEK( &opLockControl->opLocks, opLock, OpLock_s, opLink);
|
||||
if (opLock == NULL)
|
||||
{
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
return zOK;
|
||||
}
|
||||
callback = opLock->opCallback;
|
||||
rc = callback(OPLOCK_BREAK, genMsg, opLock);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
if (rc != zOK)
|
||||
{
|
||||
if (GetErrno(genMsg) == zERR_IGNORE_OPLOCK_BREAK)
|
||||
{
|
||||
ClearErrno(genMsg);
|
||||
return zOK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
opLockControl->opState = OPLOCK_BREAKING_EXCLUSIVE;
|
||||
OPLOCK(breakExclusive);
|
||||
if (!wait)
|
||||
{
|
||||
SetErrno(genMsg, zERR_OPLOCK_MUST_WAIT);
|
||||
return zFAILURE;
|
||||
}
|
||||
|
||||
UNX_LATCH( &file->FILEbeastLatch);
|
||||
rc = OPLOCK_WaitForBreak(genMsg, file);
|
||||
X_LATCH( &file->FILEbeastLatch);
|
||||
return rc;
|
||||
|
||||
case OPLOCK_BREAKING_EXCLUSIVE:
|
||||
if (!wait)
|
||||
{
|
||||
SetErrno(genMsg, zERR_OPLOCK_MUST_WAIT);
|
||||
return zFAILURE;
|
||||
}
|
||||
/*
|
||||
* Do we need oplock deadlock detection for this case?
|
||||
*/
|
||||
UNX_LATCH( &file->FILEbeastLatch);
|
||||
rc = OPLOCK_WaitForBreak(genMsg, file);
|
||||
X_LATCH( &file->FILEbeastLatch);
|
||||
return rc;
|
||||
|
||||
case OPLOCK_SHARED:
|
||||
case OPLOCK_BREAKING_SHARED:
|
||||
return zOK;
|
||||
|
||||
default:
|
||||
zASSERT("Bad oplock state" == 0);
|
||||
SetErrno(genMsg, zERR_INVALID_STATE);
|
||||
return zFAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
STATUS OPLOCK_BreakShared (File_s *file)
|
||||
{
|
||||
OpLockControl_s *opLockControl = file->opLockControl;
|
||||
OpLock_s *opLock;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
ASSERT_XLATCH( &file->FILEbeastLatch);
|
||||
/*
|
||||
* See if we have to break any opLocks
|
||||
*/
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
if (opLockControl->opState != OPLOCK_SHARED)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
/*
|
||||
* Break the shared op-locks
|
||||
*/
|
||||
opLockControl->opState = OPLOCK_BREAKING_SHARED;
|
||||
for (;;)
|
||||
{
|
||||
DQ_DEQ( &opLockControl->opLocks, opLock, OpLock_s, opLink);
|
||||
if (opLock == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
OPLOCK(breakShared);
|
||||
opLock->opCallback(OPLOCK_BREAK, NULL, opLock);
|
||||
/*
|
||||
* We are ignoring callbacks that failed. It is
|
||||
* their problem, not ours.
|
||||
*/
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
}
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
return zOK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Break shared oplocks setup by PSA. PSA has to be treated
|
||||
* different because it does not close shared oplocks immediately
|
||||
* after it is done with them.
|
||||
*/
|
||||
STATUS OPLOCK_BreakPSA (File_s *file)
|
||||
{
|
||||
OpLockControl_s *opLockControl = file->opLockControl;
|
||||
OpLock_s *opLock;
|
||||
OpLock_s *psaOpLock;
|
||||
DQhead_t psaHead;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
ASSERT_XLATCH( &file->FILEbeastLatch);
|
||||
/*
|
||||
* See if we have to break any opLocks
|
||||
*/
|
||||
if (opLockControl == NULL)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
if (opLockControl->opState != OPLOCK_SHARED)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
if (!opLockControl->opHasPSA)
|
||||
{
|
||||
return zOK;
|
||||
}
|
||||
/*
|
||||
* Break the PSA shared op-locks
|
||||
*/
|
||||
DQ_INIT( &psaHead);
|
||||
DQ_FOREACH( &opLockControl->opLocks, opLock, OpLock_s, opLink)
|
||||
{
|
||||
if (!(opLock->fileHandle->grantedRights & zRR_PSA_CACHE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
psaOpLock = opLock;
|
||||
opLock = OPREV(psaOpLock, OpLock_s, opLink);
|
||||
DQ_RMV(psaOpLock, opLink);
|
||||
DQ_ENQ( &psaHead, psaOpLock, opLink);
|
||||
}
|
||||
opLockControl->opHasPSA = FALSE;
|
||||
if (DQ_EMPTY( &opLockControl->opLocks))
|
||||
{
|
||||
opLockControl->opState = OPLOCK_IDLE;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
DQ_DEQ( &psaHead, opLock, OpLock_s, opLink);
|
||||
if (opLock == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
OPLOCK(breakShared);
|
||||
opLock->opCallback(OPLOCK_BREAK, NULL, opLock);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
}
|
||||
return zOK;
|
||||
}
|
||||
|
||||
STATUS OPLOCK_Break (
|
||||
GeneralMsg_s *genMsg, /* Brings along the connection ID */
|
||||
File_s *file,
|
||||
BOOL wait)
|
||||
{
|
||||
STATUS rc;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
|
||||
OPLOCK(breakAll);
|
||||
rc = OPLOCK_BreakExclusive(genMsg, file, wait);
|
||||
if (rc != zOK)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
return OPLOCK_BreakShared(file);
|
||||
}
|
||||
|
||||
void OPLOCK_MakeShared (OpLock_s *opLock)
|
||||
{
|
||||
OpLockControl_s *opLockControl = opLock->control;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
|
||||
OPLOCK(makeShared);
|
||||
|
||||
if (opLockControl)
|
||||
{
|
||||
opLockControl->opState = OPLOCK_SHARED;
|
||||
roust( &opLockControl->opLockWaiters, zOK);
|
||||
}
|
||||
}
|
||||
|
||||
void OPLOCK_BreakFailed (OpLock_s *opLock)
|
||||
{
|
||||
OpLockControl_s *opLockControl = opLock->control;
|
||||
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
|
||||
OPLOCK(breakFailed);
|
||||
|
||||
if (opLockControl)
|
||||
{
|
||||
ASSERT_XLATCH( &opLockControl->opFile->FILEbeastLatch);
|
||||
opLockControl->opState = OPLOCK_EXCLUSIVE;
|
||||
roust( &opLockControl->opLockWaiters, zERR_OPLOCK_NOT_BROKEN);
|
||||
}
|
||||
}
|
||||
@@ -490,21 +490,6 @@ STATUS BST_flush(void *beast)
|
||||
return zERR_FAILURE;
|
||||
}
|
||||
|
||||
OpLock_s *OPLOCK_AllocShared(FileHandle_s *fh, statusfunc_t opCallback)
|
||||
{
|
||||
(void)fh;
|
||||
(void)opCallback;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATUS OPLOCK_BreakExclusive(GeneralMsg_s *genMsg, File_s *file, BOOL wait)
|
||||
{
|
||||
(void)genMsg;
|
||||
(void)file;
|
||||
(void)wait;
|
||||
return zERR_FAILURE;
|
||||
}
|
||||
|
||||
void MSG_Notify(FileHandle_s *fileHandle)
|
||||
{
|
||||
(void)fileHandle;
|
||||
|
||||
Reference in New Issue
Block a user