0611 nwnss: import COMN oplock runtime

This commit is contained in:
Mario Fetka
2026-06-16 12:50:53 +00:00
parent 0922cb1673
commit d9fd616fda
4 changed files with 1018 additions and 15 deletions

View 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

View File

@@ -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

View 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);
}
}

View File

@@ -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;