windows-scache-ref-dbg-20061008
[openafs.git] / src / WINNT / afsd / cm_scache.h
index a162bb9..a4c83a2 100644 (file)
@@ -10,9 +10,7 @@
 #ifndef __CM_SCACHE_H_ENV__
 #define __CM_SCACHE_H_ENV__ 1
 
-#ifdef DJGPP
-#include "largeint95.h"
-#endif /* DJGPP */
+#define MOUNTPOINTLEN   1024
 
 typedef struct cm_fid {
        unsigned long cell;
@@ -21,107 +19,184 @@ typedef struct cm_fid {
         unsigned long unique;
 } cm_fid_t;
 
-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;
+/* 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_range {
+    afs_int64 offset;
+    afs_int64 length;
+} cm_range_t;
+
+/* forward dcls */
+struct cm_scache;
+typedef struct cm_scache cm_scache_t;
 
 typedef struct cm_file_lock {
-       osi_queue_t q;                  /* list of all locks */
-       osi_queue_t fileq;              /* per-file list of locks */
-       cm_user_t *userp;
-       LARGE_INTEGER LOffset;
-       LARGE_INTEGER LLength;
-       cm_fid_t fid;
-       unsigned char LockType;
-       unsigned char flags;
+    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]*/
+    
+    cm_user_t *userp;           /* The user to which this lock belongs
+                                   to [immutable; held] */
+    cm_scache_t *scp;           /* The scache to which this lock
+                                   applies to [immutable; held] */
+#ifdef DEBUG
+    cm_fid_t   fid;
+#endif
+
+    cm_range_t range;           /* Range for the lock [immutable] */
+    cm_key_t key;               /* Key for the lock [immutable] */
+    unsigned char lockType;     /* LockRead or LockWrite [immutable] */
+    unsigned char flags;        /* combination of CM_FILELOCK_FLAG__*
+                                 * [protected by cm_scacheLock] */
+    time_t lastUpdate;          /* time of last assertion with
+                                 * server. [protected by
+                                 * cm_scacheLock] */
 } cm_file_lock_t;
 
-#define CM_FILELOCK_FLAG_INVALID       0x1
-#define CM_FILELOCK_FLAG_WAITING       0x2
+#define CM_FILELOCK_FLAG_DELETED         0x01
+#define CM_FILELOCK_FLAG_LOST            0x02
+
+/* the following are mutually exclusive */
+#define CM_FILELOCK_FLAG_WAITLOCK        0x04
+#define CM_FILELOCK_FLAG_WAITUNLOCK      0x0C
+
+/* the following is used to indicate that there are no server side
+   locks associated with this lock.  This is true for locks obtained
+   against files in RO volumes as well as files residing on servers
+   that disable client side byte range locking. */
+#define CM_FILELOCK_FLAG_CLIENTONLY      0x10
+
+#define CM_FLSHARE_OFFSET_HIGH           0x01000000
+#define CM_FLSHARE_OFFSET_LOW            0x00000000
+#define CM_FLSHARE_LENGTH_HIGH           0x00000000
+#define CM_FLSHARE_LENGTH_LOW            0x00000001
 
 typedef struct cm_prefetch {           /* last region scanned for prefetching */
        osi_hyper_t base;               /* start of region */
         osi_hyper_t end;               /* first char past region */
 } cm_prefetch_t;
 
+#define CM_SCACHE_MAGIC ('S' | 'C'<<8 | 'A'<<16 | 'C'<<24)
+
 typedef struct cm_scache {
-       osi_queue_t q;                  /* lru queue; cm_scacheLock */
-       struct cm_scache *nextp;        /* next in hash; cm_scacheLock */
-       cm_fid_t fid;
-        unsigned long flags;           /* flags; locked by mx */
-
-       /* 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.
-                                         */
-        long 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 */
-        long parentVnode;              /* parent vnode for ACL callbacks */
-        long parentUnique;             /* for ACL callbacks */
-
-       /* local modification stat */
-        unsigned long mask;            /* for clientModTime, length and
-                                        * truncPos */
-
-       /* file status */
-       unsigned int fileType;                  /* file type */
-       time_t clientModTime;   /* mtime */
-        time_t serverModTime;  /* at server, for concurrent call
-                                        * comparisons */
-        osi_hyper_t length;            /* file length */
-       cm_prefetch_t prefetch;         /* prefetch info structure */
-        unsigned int unixModeBits;     /* unix protection mode bits */
-        int linkCount;                 /* link count */
-        long dataVersion;              /* data version */
-        long owner;                    /* file owner */
-        long group;                    /* file owning group */
-
-       /* pseudo file status */
-       osi_hyper_t serverLength;       /* length known to server */
-
-       /* aux file status */
-        osi_hyper_t truncPos;          /* file size to truncate to before
-                                        * storing data */
-
-       /* symlink and mount point info */
-        char *mountPointStringp;       /* the string stored in a mount point;
-                                        * first char is type, then vol name.
+    osi_queue_t q;                     /* lru queue; cm_scacheLock */
+    afs_uint32      magic;
+    struct cm_scache *nextp;           /* next in hash; cm_scacheLock */
+    cm_fid_t fid;
+    afs_uint32 flags;                  /* flags; locked by mx */
+
+    /* 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_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 */
+
+    /* local modification stat */
+    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 */
+    cm_prefetch_t prefetch;            /* prefetch info structure */
+    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 */
+    cm_user_t *creator;                        /* user, if new file */
+
+    /* pseudo file status */
+    osi_hyper_t serverLength;          /* length known to server */
+
+    /* aux file status */
+    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;
+                                                 * first char is type, then vol name.
                                          * If this is a normal symlink, we store
                                         * the link contents here.
                                          */
-       cm_fid_t *mountRootFidp;        /* mounted on root */
-       time_t    mountRootGen;         /* time to update mountRootFidp? */
-       cm_fid_t *dotdotFidp;           /* parent of volume root */
+    cm_fid_t  mountRootFid;            /* mounted on root */
+    time_t    mountRootGen;            /* time to update mountRootFidp? */
+    cm_fid_t  dotdotFid;               /* parent of volume root */
+
+    /* callback info */
+    struct cm_server *cbServerp;       /* server granting callback */
+    time_t cbExpires;          /* time callback expires */
+
+    /* access cache */
+    long anyAccess;                    /* anonymous user's access */
+    struct cm_aclent *randomACLp;      /* access cache entries */
+
+    /* file locks */
+    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
+                                 * should be replaced by a queue of
+                                 * cm_server_lock_t objects which keep
+                                 * track of lock type, the user for
+                                 * whom the lock was obtained, the
+                                 * dataVersion at the time the lock
+                                 * was asserted last, lastRefreshCycle
+                                 * and lateUpdateTime.
+                                 */
+    unsigned long lastRefreshCycle; /* protected with cm_scacheLock
+                                     * for all scaches. */
+    afs_uint32 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.  This count does not
+                                 * include locks which have
+                                 * CM_FILELOCK_FLAG_CLIENTONLY set. */
+
+    afs_uint32   exclusiveLocks; /* number of exclusive locks on
+                                  * ::fileLocks.  This count does not
+                                  * include locks which have
+                                  * CM_FILELOCK_FLAG_CLIENTONLY set.
+                                  */
+
+    afs_uint32   clientLocks;   /* number of locks on ::fileLocks that
+                                   have CM_FILELOCK_FLAG_CLIENTONLY
+                                   set. */
+       
+    /* volume info */
+    struct cm_volume *volp;            /* volume info; held reference */
 
-       /* callback info */
-        struct cm_server *cbServerp;   /* server granting callback */
-        time_t cbExpires;              /* time callback expires */
+    /* bulk stat progress */
+    osi_hyper_t bulkStatProgress;      /* track bulk stats of large dirs */
 
-       /* access cache */
-        long anyAccess;                        /* anonymous user's access */
-        struct cm_aclent *randomACLp;  /* access cache entries */
+    /* open state */
+    afs_uint16 openReads;              /* open for reading */
+    afs_uint16 openWrites;             /* open for writing */
+    afs_uint16 openShares;             /* open for read excl */
+    afs_uint16 openExcls;              /* open for exclusives */
 
-       /* file locks */
-       osi_queue_t *fileLocks;
-       
-       /* volume info */
-        struct cm_volume *volp;                /* volume info; held reference */
-  
-        /* bulk stat progress */
-        osi_hyper_t bulkStatProgress;  /* track bulk stats of large dirs */
-
-        /* open state */
-        short openReads;               /* open for reading */
-        short openWrites;              /* open for writing */
-        short openShares;              /* open for read excl */
-        short openExcls;               /* open for exclusives */
+    /* syncop state */
+    afs_uint32 waitCount;           /* number of threads waiting */
+    afs_uint32 waitRequests;        /* num of thread wait requests */
 } cm_scache_t;
 
 /* mask field - tell what has been modified */
@@ -134,9 +209,11 @@ typedef struct cm_scache {
 #define CM_SCACHETYPE_DIRECTORY                2       /* a dir */
 #define CM_SCACHETYPE_SYMLINK          3       /* a symbolic link */
 #define CM_SCACHETYPE_MOUNTPOINT       4       /* a mount point */
+#define CM_SCACHETYPE_DFSLINK           5       /* a Microsoft Dfs link */
+#define CM_SCACHETYPE_INVALID           99      /* an invalid link */
 
 /* flag bits */
-#define CM_SCACHEFLAG_STATD                 0x01        /* status info is valid */
+#define CM_SCACHEFLAG_STATD             0x01    /* status info is valid */
 #define CM_SCACHEFLAG_DELETED           0x02    /* file has been deleted */
 #define CM_SCACHEFLAG_CALLBACK          0x04    /* have a valid callback */
 #define CM_SCACHEFLAG_STORING           0x08    /* status being stored back */
@@ -164,6 +241,9 @@ typedef struct cm_scache {
 #define CM_SCACHEFLAG_ANYWATCH \
                        (CM_SCACHEFLAG_WATCHED | CM_SCACHEFLAG_WATCHEDSUBTREE)
 
+#define CM_SCACHEFLAG_EACCESS           0x200000 /* Bulk Stat returned EACCES */
+#define CM_SCACHEFLAG_SMB_FID          0x400000
+
 /* 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
@@ -197,6 +277,11 @@ typedef struct cm_scache {
 #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 */
+
+/* flags for cm_RecycleSCache  */
+#define CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS  0x1
 
 /* flags for cm_MergeStatus */
 #define CM_MERGEFLAG_FORCE             1       /* check mtime before merging;
@@ -212,14 +297,12 @@ typedef struct cm_scache {
                                   ((fidp)->volume +    \
                                    (fidp)->vnode +     \
                                    (fidp)->unique))    \
-                                       % cm_hashTableSize)
+                                       % cm_data.hashTableSize)
 
 #include "cm_conn.h"
 #include "cm_buf.h"
 
-extern cm_scache_t cm_fakeSCache;
-
-extern void cm_InitSCache(long);
+extern void cm_InitSCache(int, long);
 
 extern long cm_GetSCache(cm_fid_t *, cm_scache_t **, struct cm_user *,
        struct cm_req *);
@@ -231,15 +314,29 @@ extern cm_scache_t *cm_GetNewSCache(void);
 extern int cm_FidCmp(cm_fid_t *, cm_fid_t *);
 
 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);
+       struct cm_user *, 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 *);
@@ -247,19 +344,28 @@ 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 long cm_hashTableSize;
+extern cm_scache_t *cm_FindSCacheParent(cm_scache_t *);
 
 extern osi_rwlock_t cm_scacheLock;
 
 extern osi_queue_t *cm_allFileLocks;
 
-extern cm_scache_t **cm_hashTablep;
+extern osi_queue_t *cm_freeFileLocks;
+
+extern unsigned long cm_lockRefreshCycle;
 
 extern void cm_DiscardSCache(cm_scache_t *scp);
 
 extern int cm_FindFileType(cm_fid_t *fidp);
 
+extern long cm_ValidateSCache(void);
+
+extern long cm_ShutdownSCache(void);
+
+extern long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags);
+
+extern void cm_RemoveSCacheFromHashTable(cm_scache_t *scp);
 #endif /*  __CM_SCACHE_H_ENV__ */