/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
-#ifndef __CM_SCACHE_H_ENV__
-#define __CM_SCACHE_H_ENV__ 1
+#ifndef OPENAFS_WINNT_AFSD_CM_SCACHE_H
+#define OPENAFS_WINNT_AFSD_CM_SCACHE_H 1
-#ifdef DJGPP
-#include "largeint95.h"
-#endif /* DJGPP */
+#include <opr/jhash.h>
-#define MOUNTPOINTLEN 1024
+#define MOUNTPOINTLEN 1024 /* max path length for symlink; same as AFSPATHMAX */
typedef struct cm_fid {
- unsigned long cell;
- unsigned long volume;
- unsigned long vnode;
- unsigned long unique;
+ afs_uint32 cell;
+ afs_uint32 volume;
+ afs_uint32 vnode;
+ afs_uint32 unique;
+ afs_uint32 hash;
} cm_fid_t;
-#if 0
-typedef struct cm_accessCache {
- osi_queue_t q; /* queue header */
- struct cm_user *userp; /* user having access rights */
- unsigned long rights; /* rights */
-} cm_accessCache_t;
-#endif
/* Key used for byte range locking. Each unique key identifies a
unique client per cm_scache_t for the purpose of locking. */
-typedef afs_uint64 cm_key_t;
+typedef struct cm_key {
+ afs_offs_t process_id; /* process IDs can be 64bit on 64bit environments */
+ afs_uint16 session_id;
+ afs_uint64 file_id; /* afs redir uses File Object pointers as file id */
+} cm_key_t;
typedef struct cm_range {
afs_int64 offset;
osi_queue_t q; /* list of all locks [protected by
cm_scacheLock] */
osi_queue_t fileq; /* per-file list of locks [protected
- by scp->mx]*/
-
+ by scp->rw]*/
+
cm_user_t *userp; /* The user to which this lock belongs
to [immutable; held] */
cm_scache_t *scp; /* The scache to which this lock
* cm_scacheLock] */
} cm_file_lock_t;
+#define fileq_to_cm_file_lock_t(q) ((cm_file_lock_t *)((char *) (q) - offsetof(cm_file_lock_t, fileq)))
+
#define CM_FILELOCK_FLAG_DELETED 0x01
#define CM_FILELOCK_FLAG_LOST 0x02
#define CM_SCACHE_MAGIC ('S' | 'C'<<8 | 'A'<<16 | 'C'<<24)
typedef struct cm_scache {
- osi_queue_t q; /* lru queue; cm_scacheLock */
+ osi_queue_t q; /* lru queue; cm_scacheLock */
afs_uint32 magic;
- struct cm_scache *nextp; /* next in hash; cm_scacheLock */
+ struct cm_scache *nextp; /* next in hash; cm_scacheLock */
+ struct cm_scache *allNextp; /* next in all scache list; cm_scacheLock */
cm_fid_t fid;
- afs_uint32 flags; /* flags; locked by mx */
+ afs_uint32 flags; /* flags; locked by rw */
/* synchronization stuff */
- osi_mutex_t mx; /* mutex for this structure */
- osi_rwlock_t bufCreateLock; /* read-locked during buffer creation;
- * write-locked to prevent buffers from
- * being created during a truncate op, etc.
- */
- afs_uint32 refCount; /* reference count; cm_scacheLock */
- osi_queueData_t *bufReadsp; /* queue of buffers being read */
+ osi_rwlock_t rw; /* rwlock for this structure */
+ osi_rwlock_t bufCreateLock; /* read-locked during buffer creation;
+ * write-locked to prevent buffers from
+ * being created during a truncate op, etc.
+ */
+ afs_int32 refCount; /* reference count; cm_scacheLock */
+ osi_queueData_t *bufReadsp; /* queue of buffers being read */
osi_queueData_t *bufWritesp; /* queue of buffers being written */
/* parent info for ACLs */
afs_uint32 parentVnode; /* parent vnode for ACL callbacks */
- afs_uint32 parentUnique; /* for ACL callbacks */
+ afs_uint32 parentUnique; /* for ACL callbacks */
/* local modification stat */
- afs_uint32 mask; /* for clientModTime, length and
- * truncPos */
+ afs_uint32 mask; /* for clientModTime, length and
+ * truncPos */
/* file status */
afs_uint32 fileType; /* file type */
time_t clientModTime; /* mtime */
time_t serverModTime; /* at server, for concurrent call
* comparisons */
- osi_hyper_t length; /* file length */
+ osi_hyper_t length; /* file length */
cm_prefetch_t prefetch; /* prefetch info structure */
- afs_uint32 unixModeBits; /* unix protection mode bits */
+ afs_uint32 unixModeBits; /* unix protection mode bits */
afs_uint32 linkCount; /* link count */
- afs_uint32 dataVersion; /* data version */
- afs_uint32 owner; /* file owner */
- afs_uint32 group; /* file owning group */
+ afs_uint64 dataVersion; /* data version */
+ afs_uint64 bufDataVersionLow; /* range of valid cm_buf_t dataVersions;
+ does not apply to directory buffers */
+ afs_uint32 owner; /* file owner */
+ afs_uint32 group; /* file owning group */
+ cm_user_t *creator; /* user, if new file */
+
+ /* volume status */
+ time_t volumeCreationDate; /* volume creation date from AFSVolSync */
/* pseudo file status */
- osi_hyper_t serverLength; /* length known to server */
+ osi_hyper_t serverLength; /* length known to server */
/* aux file status */
- osi_hyper_t truncPos; /* file size to truncate to before
- * storing data */
+ osi_hyper_t truncPos; /* file size to truncate to before
+ * storing data */
/* symlink and mount point info */
char mountPointStringp[MOUNTPOINTLEN]; /* the string stored in a mount point;
* the link contents here.
*/
cm_fid_t mountRootFid; /* mounted on root */
- time_t mountRootGen; /* time to update mountRootFidp? */
+ time_t mountRootGen; /* time to update mountRootFid? */
cm_fid_t dotdotFid; /* parent of volume root */
/* callback info */
struct cm_server *cbServerp; /* server granting callback */
- time_t cbExpires; /* time callback expires */
+ time_t cbExpires; /* time callback expires */
+ time_t cbIssued; /* time callback was issued */
/* access cache */
long anyAccess; /* anonymous user's access */
afs_int32 serverLock; /* current lock we have acquired on
* this file. One of (-1), LockRead
* or LockWrite. [protected by
- * scp->mx]. In the future, this
+ * scp->rw]. In the future, this
* should be replaced by a queue of
* cm_server_lock_t objects which keep
* track of lock type, the user for
*/
unsigned long lastRefreshCycle; /* protected with cm_scacheLock
* for all scaches. */
- afs_uint32 lockDataVersion; /* dataVersion of the scp at the time
+ afs_uint64 lockDataVersion; /* dataVersion of the scp at the time
the server lock for the scp was
asserted for this lock the last
time. */
osi_queue_t *fileLocksH; /* queue of locks (head) */
osi_queue_t *fileLocksT; /* queue of locks (tail) */
+
afs_uint32 sharedLocks; /* number of shared locks on
- * ::fileLocks */
+ * ::fileLocks. This count does not
+ * include locks which have
+ * CM_FILELOCK_FLAG_CLIENTONLY set. */
+
afs_uint32 exclusiveLocks; /* number of exclusive locks on
- * ::fileLocks
+ * ::fileLocks. This count does not
+ * include locks which have
+ * CM_FILELOCK_FLAG_CLIENTONLY set.
*/
-
- /* volume info */
- struct cm_volume *volp; /* volume info; held reference */
+
+ afs_uint32 clientLocks; /* number of locks on ::fileLocks that
+ have CM_FILELOCK_FLAG_CLIENTONLY
+ set. */
+
+ afs_int32 fsLockCount; /* number of locks held as reported
+ * by the file server in the most
+ * recent fetch status. Updated by
+ * the locks known to have been acquired
+ * or released by this client.
+ */
/* bulk stat progress */
osi_hyper_t bulkStatProgress; /* track bulk stats of large dirs */
+#ifdef USE_BPLUS
+ /* directory B+ tree */ /* only allocated if is directory */
+ osi_rwlock_t dirlock; /* controls access to dirBplus */
+ afs_uint64 dirDataVersion; /* data version represented by dirBplus */
+ struct tree *dirBplus; /* dirBplus */
+#endif
+
/* open state */
afs_uint16 openReads; /* open for reading */
afs_uint16 openWrites; /* open for writing */
/* syncop state */
afs_uint32 waitCount; /* number of threads waiting */
afs_uint32 waitRequests; /* num of thread wait requests */
+ osi_queue_t * waitQueueH; /* Queue of waiting threads.
+ Holds queue of
+ cm_scache_waiter_t
+ objects. Protected by
+ cm_scacheLock. */
+ osi_queue_t * waitQueueT; /* locked by cm_scacheLock */
+
+ /* redirector state - protected by scp->redirMx */
+ osi_queue_t * redirQueueH; /* LRU queue of buffers for this
+ file that are assigned to the
+ afsredir kernel module. */
+ osi_queue_t * redirQueueT;
+ afs_uint32 redirBufCount; /* Number of buffers held by the redirector */
+ time_t redirLastAccess; /* last time redir accessed the vnode */
+ osi_mutex_t redirMx;
+
+ afs_uint32 activeRPCs; /* atomic */
} cm_scache_t;
+/* dataVersion */
+#define CM_SCACHE_VERSION_BAD 0xFFFFFFFFFFFFFFFF
+
/* mask field - tell what has been modified */
#define CM_SCACHEMASK_CLIENTMODTIME 1 /* client mod time */
#define CM_SCACHEMASK_LENGTH 2 /* length */
#define CM_SCACHEMASK_TRUNCPOS 4 /* truncation position */
/* fileType values */
+#define CM_SCACHETYPE_UNKNOWN 0 /* unknown */
#define CM_SCACHETYPE_FILE 1 /* a file */
#define CM_SCACHETYPE_DIRECTORY 2 /* a dir */
#define CM_SCACHETYPE_SYMLINK 3 /* a symbolic link */
* this is a truncate op. */
#define CM_SCACHEFLAG_INHASH 0x40 /* in the hash table */
#define CM_SCACHEFLAG_BULKSTATTING 0x80 /* doing a bulk stat */
+#define CM_SCACHEFLAG_SIZESETTING 0x100 /* Stabilized; Truncate */
#define CM_SCACHEFLAG_WAITING 0x200 /* waiting for fetch/store
* state to change */
#define CM_SCACHEFLAG_PURERO 0x400 /* read-only (not even backup);
#define CM_SCACHEFLAG_ANYWATCH \
(CM_SCACHEFLAG_WATCHED | CM_SCACHEFLAG_WATCHEDSUBTREE)
+#define CM_SCACHEFLAG_SMB_FID 0x400000
+#define CM_SCACHEFLAG_LOCAL 0x800000 /* Locally modified */
+#define CM_SCACHEFLAG_BULKREADING 0x1000000/* Bulk read in progress */
+#define CM_SCACHEFLAG_RDR_IN_USE 0x2000000/* in use by Redirector; advisory */
+
/* sync flags for calls to the server. The CM_SCACHEFLAG_FETCHING,
* CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
* below, except for FETCHDATA and STOREDATA, which correspond to non-null
#define CM_SCACHESYNC_BUFLOCKED 0x80000 /* the buffer is locked */
#define CM_SCACHESYNC_NOWAIT 0x100000/* don't wait for the state,
* just fail */
+#define CM_SCACHESYNC_FORCECB 0x200000/* when calling cm_GetCallback()
+ * set the force flag */
+
+#define CM_SCACHESYNC_BULKREAD 0x400000/* reading many buffers */
+
+/* flags for cm_RecycleSCache */
+#define CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS 0x1
/* flags for cm_MergeStatus */
#define CM_MERGEFLAG_FORCE 1 /* check mtime before merging;
* used to see if we're merging
* in old info.
*/
+#define CM_MERGEFLAG_STOREDATA 2 /* Merge due to storedata op */
+#define CM_MERGEFLAG_DIROP 4 /* Merge due to directory op */
+#define CM_MERGEFLAG_FETCHDATA 8 /* Merge due to fetchdata op */
/* hash define. Must not include the cell, since the callback revocation code
* doesn't necessarily know the cell in the case of a multihomed server
* contacting us from a mystery address.
*/
-#define CM_SCACHE_HASH(fidp) (((unsigned long) \
- ((fidp)->volume + \
- (fidp)->vnode + \
- (fidp)->unique)) \
- % cm_data.hashTableSize)
+
+#define CM_FID_GEN_HASH(fidp) do { \
+ (fidp)->hash = opr_jhash(&(fidp)->volume, 3, 0); \
+} while(0)
+
+#define CM_SCACHE_HASH(fidp) ((fidp)->hash & (cm_data.scacheHashTableSize - 1))
#include "cm_conn.h"
#include "cm_buf.h"
+typedef struct cm_scache_waiter {
+ osi_queue_t q;
+ afs_int32 threadId;
+
+ cm_scache_t *scp;
+ afs_int32 flags;
+ cm_buf_t *bufp;
+} cm_scache_waiter_t;
+
extern void cm_InitSCache(int, long);
-extern long cm_GetSCache(cm_fid_t *, cm_scache_t **, struct cm_user *,
+#ifdef DEBUG_REFCOUNT
+extern long cm_GetSCacheDbg(cm_fid_t *, cm_fid_t *, cm_scache_t **, struct cm_user *,
+ struct cm_req *, char *, long);
+
+#define cm_GetSCache(a,b,c,d,e) cm_GetSCacheDbg(a,b,c,d,e,__FILE__,__LINE__)
+#else
+extern long cm_GetSCache(cm_fid_t *, cm_fid_t *, cm_scache_t **, struct cm_user *,
struct cm_req *);
+#endif
-extern void cm_PutSCache(cm_scache_t *);
+extern cm_scache_t *cm_GetNewSCache(afs_uint32 locked);
-extern cm_scache_t *cm_GetNewSCache(void);
+extern __inline int cm_FidCmp(cm_fid_t *, cm_fid_t *);
-extern int cm_FidCmp(cm_fid_t *, cm_fid_t *);
+extern void cm_SetFid(cm_fid_t *, afs_uint32 cell, afs_uint32 volume, afs_uint32 vnode, afs_uint32 unique);
extern long cm_SyncOp(cm_scache_t *, struct cm_buf *, struct cm_user *,
- struct cm_req *, long, long);
+ struct cm_req *, afs_uint32, afs_uint32);
-extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, long);
+extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, afs_uint32);
-extern void cm_MergeStatus(cm_scache_t *, struct AFSFetchStatus *, struct AFSVolSync *,
- struct cm_user *, int flags);
+extern void cm_MergeStatus(cm_scache_t * dscp, cm_scache_t * scp,
+ struct AFSFetchStatus * statusp,
+ struct AFSVolSync * volsyncp,
+ struct cm_user *userp,
+ cm_req_t *reqp,
+ afs_uint32 flags);
extern void cm_AFSFidFromFid(struct AFSFid *, cm_fid_t *);
+#ifdef DEBUG_REFCOUNT
+extern void cm_HoldSCacheNoLockDbg(cm_scache_t *, char *, long);
+
+extern void cm_HoldSCacheDbg(cm_scache_t *, char *, long);
+
+extern void cm_ReleaseSCacheNoLockDbg(cm_scache_t *, char *, long);
+
+extern void cm_ReleaseSCacheDbg(cm_scache_t *, char *, long);
+
+#define cm_HoldSCacheNoLock(scp) cm_HoldSCacheNoLockDbg(scp, __FILE__, __LINE__)
+#define cm_HoldSCache(scp) cm_HoldSCacheDbg(scp, __FILE__, __LINE__)
+#define cm_ReleaseSCacheNoLock(scp) cm_ReleaseSCacheNoLockDbg(scp, __FILE__, __LINE__)
+#define cm_ReleaseSCache(scp) cm_ReleaseSCacheDbg(scp, __FILE__, __LINE__)
+#else
extern void cm_HoldSCacheNoLock(cm_scache_t *);
extern void cm_HoldSCache(cm_scache_t *);
extern void cm_ReleaseSCacheNoLock(cm_scache_t *);
extern void cm_ReleaseSCache(cm_scache_t *);
-
+#endif
extern cm_scache_t *cm_FindSCache(cm_fid_t *fidp);
extern cm_scache_t *cm_FindSCacheParent(cm_scache_t *);
extern long cm_ShutdownSCache(void);
-#endif /* __CM_SCACHE_H_ENV__ */
+extern void cm_SuspendSCache(void);
+
+extern long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags);
+
+extern void cm_RemoveSCacheFromHashTable(cm_scache_t *scp);
+
+extern void cm_AdjustScacheLRU(cm_scache_t *scp);
+
+extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
+
+extern void cm_ResetSCacheDirectory(cm_scache_t *scp, afs_int32 locked);
+
+extern cm_scache_t * cm_RootSCachep(cm_user_t *userp, cm_req_t *reqp);
+#endif /* OPENAFS_WINNT_AFSD_CM_SCACHE_H */