2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #ifndef OPENAFS_WINNT_AFSD_CM_SCACHE_H
11 #define OPENAFS_WINNT_AFSD_CM_SCACHE_H 1
13 #include <opr/jhash.h>
15 #define MOUNTPOINTLEN 1024 /* max path length for symlink; same as AFSPATHMAX */
17 typedef struct cm_fid {
26 /* Key used for byte range locking. Each unique key identifies a
27 unique client per cm_scache_t for the purpose of locking. */
28 typedef struct cm_key {
29 afs_offs_t process_id; /* process IDs can be 64bit on 64bit environments */
30 afs_uint16 session_id;
31 afs_uint64 file_id; /* afs redir uses File Object pointers as file id */
34 typedef struct cm_range {
41 typedef struct cm_scache cm_scache_t;
43 typedef struct cm_file_lock {
44 osi_queue_t q; /* list of all locks [protected by
46 osi_queue_t fileq; /* per-file list of locks [protected
49 cm_user_t *userp; /* The user to which this lock belongs
50 to [immutable; held] */
51 cm_scache_t *scp; /* The scache to which this lock
52 applies to [immutable; held] */
57 cm_range_t range; /* Range for the lock [immutable] */
58 cm_key_t key; /* Key for the lock [immutable] */
59 unsigned char lockType; /* LockRead or LockWrite [immutable] */
60 unsigned char flags; /* combination of CM_FILELOCK_FLAG__*
61 * [protected by cm_scacheLock] */
62 time_t lastUpdate; /* time of last assertion with
63 * server. [protected by
67 #define fileq_to_cm_file_lock_t(q) ((cm_file_lock_t *)((char *) (q) - offsetof(cm_file_lock_t, fileq)))
69 #define CM_FILELOCK_FLAG_DELETED 0x01
70 #define CM_FILELOCK_FLAG_LOST 0x02
72 /* the following are mutually exclusive */
73 #define CM_FILELOCK_FLAG_WAITLOCK 0x04
74 #define CM_FILELOCK_FLAG_WAITUNLOCK 0x0C
76 /* the following is used to indicate that there are no server side
77 locks associated with this lock. This is true for locks obtained
78 against files in RO volumes as well as files residing on servers
79 that disable client side byte range locking. */
80 #define CM_FILELOCK_FLAG_CLIENTONLY 0x10
82 #define CM_FLSHARE_OFFSET_HIGH 0x01000000
83 #define CM_FLSHARE_OFFSET_LOW 0x00000000
84 #define CM_FLSHARE_LENGTH_HIGH 0x00000000
85 #define CM_FLSHARE_LENGTH_LOW 0x00000001
87 typedef struct cm_prefetch { /* last region scanned for prefetching */
88 osi_hyper_t base; /* start of region */
89 osi_hyper_t end; /* first char past region */
92 #define CM_SCACHE_MAGIC ('S' | 'C'<<8 | 'A'<<16 | 'C'<<24)
94 typedef struct cm_scache {
95 osi_queue_t q; /* lru queue; cm_scacheLock */
97 struct cm_scache *nextp; /* next in hash; cm_scacheLock */
98 struct cm_scache *allNextp; /* next in all scache list; cm_scacheLock */
100 afs_uint32 flags; /* flags; locked by rw */
102 /* synchronization stuff */
103 osi_rwlock_t rw; /* rwlock for this structure */
104 osi_rwlock_t bufCreateLock; /* read-locked during buffer creation;
105 * write-locked to prevent buffers from
106 * being created during a truncate op, etc.
108 afs_int32 refCount; /* reference count; cm_scacheLock */
109 osi_queueData_t *bufReadsp; /* queue of buffers being read */
110 osi_queueData_t *bufWritesp; /* queue of buffers being written */
112 /* parent info for ACLs */
113 afs_uint32 parentVnode; /* parent vnode for ACL callbacks */
114 afs_uint32 parentUnique; /* for ACL callbacks */
116 /* local modification stat */
117 afs_uint32 mask; /* for clientModTime, length and
121 afs_uint32 fileType; /* file type */
122 time_t clientModTime; /* mtime */
123 time_t serverModTime; /* at server, for concurrent call
125 osi_hyper_t length; /* file length */
126 cm_prefetch_t prefetch; /* prefetch info structure */
127 afs_uint32 unixModeBits; /* unix protection mode bits */
128 afs_uint32 linkCount; /* link count */
129 afs_uint64 dataVersion; /* data version */
130 afs_uint64 bufDataVersionLow; /* range of valid cm_buf_t dataVersions;
131 does not apply to directory buffers */
132 afs_uint32 owner; /* file owner */
133 afs_uint32 group; /* file owning group */
134 cm_user_t *creator; /* user, if new file */
137 time_t volumeCreationDate; /* volume creation date from AFSVolSync */
139 /* pseudo file status */
140 osi_hyper_t serverLength; /* length known to server */
142 /* aux file status */
143 osi_hyper_t truncPos; /* file size to truncate to before
146 /* symlink and mount point info */
147 afs_uint64 mpDataVersion; /* data version represented by mountPointStringp */
148 char mountPointStringp[MOUNTPOINTLEN]; /* the string stored in a mount point;
149 * first char is type, then vol name.
150 * If this is a normal symlink, we store
151 * the link contents here.
153 cm_fid_t mountRootFid; /* mounted on root */
154 time_t mountRootGen; /* time to update mountRootFid? */
155 cm_fid_t dotdotFid; /* parent of volume root */
158 struct cm_server *cbServerp; /* server granting callback */
159 time_t cbExpires; /* time callback expires */
160 time_t cbIssued; /* time callback was issued */
163 long anyAccess; /* anonymous user's access */
164 struct cm_aclent *randomACLp; /* access cache entries */
167 afs_int32 serverLock; /* current lock we have acquired on
168 * this file. One of (-1), LockRead
169 * or LockWrite. [protected by
170 * scp->rw]. In the future, this
171 * should be replaced by a queue of
172 * cm_server_lock_t objects which keep
173 * track of lock type, the user for
174 * whom the lock was obtained, the
175 * dataVersion at the time the lock
176 * was asserted last, lastRefreshCycle
177 * and lateUpdateTime.
179 unsigned long lastRefreshCycle; /* protected with cm_scacheLock
180 * for all scaches. */
181 afs_uint64 lockDataVersion; /* dataVersion of the scp at the time
182 the server lock for the scp was
183 asserted for this lock the last
185 osi_queue_t *fileLocksH; /* queue of locks (head) */
186 osi_queue_t *fileLocksT; /* queue of locks (tail) */
188 afs_uint32 sharedLocks; /* number of shared locks on
189 * ::fileLocks. This count does not
190 * include locks which have
191 * CM_FILELOCK_FLAG_CLIENTONLY set. */
193 afs_uint32 exclusiveLocks; /* number of exclusive locks on
194 * ::fileLocks. This count does not
195 * include locks which have
196 * CM_FILELOCK_FLAG_CLIENTONLY set.
199 afs_uint32 clientLocks; /* number of locks on ::fileLocks that
200 have CM_FILELOCK_FLAG_CLIENTONLY
203 afs_int32 fsLockCount; /* number of locks held as reported
204 * by the file server in the most
205 * recent fetch status. Updated by
206 * the locks known to have been acquired
207 * or released by this client.
210 /* bulk stat progress */
211 osi_hyper_t bulkStatProgress; /* track bulk stats of large dirs */
214 /* directory B+ tree */ /* only allocated if is directory */
215 osi_rwlock_t dirlock; /* controls access to dirBplus */
216 afs_uint64 dirDataVersion; /* data version represented by dirBplus */
217 struct tree *dirBplus; /* dirBplus */
221 afs_uint16 openReads; /* open for reading */
222 afs_uint16 openWrites; /* open for writing */
223 afs_uint16 openShares; /* open for read excl */
224 afs_uint16 openExcls; /* open for exclusives */
227 afs_uint32 waitCount; /* number of threads waiting */
228 afs_uint32 waitRequests; /* num of thread wait requests */
229 osi_queue_t * waitQueueH; /* Queue of waiting threads.
232 objects. Protected by
234 osi_queue_t * waitQueueT; /* locked by cm_scacheLock */
236 /* redirector state - protected by scp->redirMx */
237 osi_queue_t * redirQueueH; /* LRU queue of buffers for this
238 file that are assigned to the
239 afsredir kernel module. */
240 osi_queue_t * redirQueueT;
241 afs_uint32 redirBufCount; /* Number of buffers held by the redirector */
242 time_t redirLastAccess; /* last time redir accessed the vnode */
245 afs_uint32 activeRPCs; /* atomic */
249 #define CM_SCACHE_VERSION_BAD 0xFFFFFFFFFFFFFFFF
251 /* mask field - tell what has been modified */
252 #define CM_SCACHEMASK_CLIENTMODTIME 1 /* client mod time */
253 #define CM_SCACHEMASK_LENGTH 2 /* length */
254 #define CM_SCACHEMASK_TRUNCPOS 4 /* truncation position */
256 /* fileType values */
257 #define CM_SCACHETYPE_UNKNOWN 0 /* unknown */
258 #define CM_SCACHETYPE_FILE 1 /* a file */
259 #define CM_SCACHETYPE_DIRECTORY 2 /* a dir */
260 #define CM_SCACHETYPE_SYMLINK 3 /* a symbolic link */
261 #define CM_SCACHETYPE_MOUNTPOINT 4 /* a mount point */
262 #define CM_SCACHETYPE_DFSLINK 5 /* a Microsoft Dfs link */
263 #define CM_SCACHETYPE_INVALID 99 /* an invalid link */
266 #define CM_SCACHEFLAG_DELETED 0x02 /* file has been deleted */
267 #define CM_SCACHEFLAG_STORING 0x08 /* status being stored back */
268 #define CM_SCACHEFLAG_FETCHING 0x10 /* status being fetched */
269 #define CM_SCACHEFLAG_SIZESTORING 0x20 /* status being stored that
270 * changes the data; typically,
271 * this is a truncate op. */
272 #define CM_SCACHEFLAG_INHASH 0x40 /* in the hash table */
273 #define CM_SCACHEFLAG_BULKSTATTING 0x80 /* doing a bulk stat */
274 #define CM_SCACHEFLAG_SIZESETTING 0x100 /* Stabilized; Truncate */
275 #define CM_SCACHEFLAG_WAITING 0x200 /* waiting for fetch/store
277 #define CM_SCACHEFLAG_PURERO 0x400 /* read-only (not even backup);
278 * for mount point eval */
279 #define CM_SCACHEFLAG_RO 0x800 /* read-only
280 * (can't do write ops) */
281 #define CM_SCACHEFLAG_GETCALLBACK 0x1000 /* we're getting a callback */
282 #define CM_SCACHEFLAG_DATASTORING 0x2000 /* data being stored */
283 #define CM_SCACHEFLAG_PREFETCHING 0x4000 /* somebody is prefetching */
284 #define CM_SCACHEFLAG_OVERQUOTA 0x8000 /* over quota */
285 #define CM_SCACHEFLAG_OUTOFSPACE 0x10000 /* out of space */
286 #define CM_SCACHEFLAG_ASYNCSTORING 0x20000 /* scheduled to store back */
287 #define CM_SCACHEFLAG_LOCKING 0x40000 /* setting/clearing file lock */
288 #define CM_SCACHEFLAG_WATCHED 0x80000 /* directory being watched */
289 #define CM_SCACHEFLAG_WATCHEDSUBTREE 0x100000 /* dir subtree being watched */
290 #define CM_SCACHEFLAG_ANYWATCH \
291 (CM_SCACHEFLAG_WATCHED | CM_SCACHEFLAG_WATCHEDSUBTREE)
293 #define CM_SCACHEFLAG_SMB_FID 0x400000
294 #define CM_SCACHEFLAG_LOCAL 0x800000 /* Locally modified */
295 #define CM_SCACHEFLAG_BULKREADING 0x1000000/* Bulk read in progress */
296 #define CM_SCACHEFLAG_RDR_IN_USE 0x2000000/* in use by Redirector; advisory */
298 /* sync flags for calls to the server. The CM_SCACHEFLAG_FETCHING,
299 * CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
300 * below, except for FETCHDATA and STOREDATA, which correspond to non-null
301 * buffers in bufReadsp and bufWritesp.
302 * These flags correspond to individual RPCs that we may be making, and at most
303 * one can be set in any one call to SyncOp.
305 #define CM_SCACHESYNC_FETCHSTATUS 0x01 /* fetching status info */
306 #define CM_SCACHESYNC_STORESTATUS 0x02 /* storing status info */
307 #define CM_SCACHESYNC_FETCHDATA 0x04 /* fetch data */
308 #define CM_SCACHESYNC_STOREDATA 0x08 /* store data */
309 #define CM_SCACHESYNC_STORESIZE 0x10 /* store new file size */
310 #define CM_SCACHESYNC_GETCALLBACK 0x20 /* fetching a callback */
311 #define CM_SCACHESYNC_STOREDATA_EXCL 0x40 /* store data */
312 #define CM_SCACHESYNC_ASYNCSTORE 0x80 /* schedule data store */
313 #define CM_SCACHESYNC_LOCK 0x100 /* set/clear file lock */
315 /* sync flags for calls within the client; there are no corresponding flags
316 * in the scache entry, because we hold the scache entry locked during the
319 #define CM_SCACHESYNC_GETSTATUS 0x1000 /* read the status */
320 #define CM_SCACHESYNC_SETSTATUS 0x2000 /* e.g. utimes */
321 #define CM_SCACHESYNC_READ 0x4000 /* read data from a chunk */
322 #define CM_SCACHESYNC_WRITE 0x8000 /* write data to a chunk */
323 #define CM_SCACHESYNC_SETSIZE 0x10000 /* shrink the size of a file,
325 #define CM_SCACHESYNC_NEEDCALLBACK 0x20000 /* need a callback on the file */
326 #define CM_SCACHESYNC_CHECKRIGHTS 0x40000 /* check that user has desired
328 #define CM_SCACHESYNC_BUFLOCKED 0x80000 /* the buffer is locked */
329 #define CM_SCACHESYNC_NOWAIT 0x100000/* don't wait for the state,
331 #define CM_SCACHESYNC_FORCECB 0x200000/* when calling cm_GetCallback()
332 * set the force flag */
334 #define CM_SCACHESYNC_BULKREAD 0x400000/* reading many buffers */
336 /* flags for cm_RecycleSCache */
337 #define CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS 0x1
339 /* flags for cm_MergeStatus */
340 #define CM_MERGEFLAG_FORCE 1 /* check mtime before merging;
341 * used to see if we're merging
344 #define CM_MERGEFLAG_STOREDATA 2 /* Merge due to storedata op */
345 #define CM_MERGEFLAG_DIROP 4 /* Merge due to directory op */
346 #define CM_MERGEFLAG_FETCHDATA 8 /* Merge due to fetchdata op */
347 #define CM_MERGEFLAG_BULKSTAT 0x10 /* Merge due to bulkstat op */
348 #define CM_MERGEFLAG_CACHE_BYPASS 0x20 /* Data not stored into cache */
350 /* hash define. Must not include the cell, since the callback revocation code
351 * doesn't necessarily know the cell in the case of a multihomed server
352 * contacting us from a mystery address.
355 #define CM_FID_GEN_HASH(fidp) do { \
356 (fidp)->hash = opr_jhash(&(fidp)->volume, 3, 0); \
359 #define CM_SCACHE_HASH(fidp) ((fidp)->hash & (cm_data.scacheHashTableSize - 1))
364 typedef struct cm_scache_waiter {
371 } cm_scache_waiter_t;
373 extern void cm_InitSCache(int, long);
375 #ifdef DEBUG_REFCOUNT
376 extern long cm_GetSCacheDbg(cm_fid_t *, cm_fid_t *, cm_scache_t **, struct cm_user *,
377 struct cm_req *, char *, long);
379 #define cm_GetSCache(a,b,c,d,e) cm_GetSCacheDbg(a,b,c,d,e,__FILE__,__LINE__)
381 extern long cm_GetSCache(cm_fid_t *, cm_fid_t *, cm_scache_t **, struct cm_user *,
385 extern cm_scache_t *cm_GetNewSCache(afs_uint32 locked);
387 extern __inline int cm_FidCmp(cm_fid_t *, cm_fid_t *);
389 extern void cm_SetFid(cm_fid_t *, afs_uint32 cell, afs_uint32 volume, afs_uint32 vnode, afs_uint32 unique);
391 extern long cm_SyncOp(cm_scache_t *, struct cm_buf *, struct cm_user *,
392 struct cm_req *, afs_uint32, afs_uint32);
394 extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, afs_uint32);
396 extern long cm_IsStatusValid(AFSFetchStatus *statusp);
398 extern long cm_MergeStatus(cm_scache_t * dscp, cm_scache_t * scp,
399 struct AFSFetchStatus * statusp,
400 struct AFSVolSync * volsyncp,
401 struct cm_user *userp,
405 extern void cm_AFSFidFromFid(struct AFSFid *, cm_fid_t *);
407 #ifdef DEBUG_REFCOUNT
408 extern void cm_HoldSCacheNoLockDbg(cm_scache_t *, char *, long);
410 extern void cm_HoldSCacheDbg(cm_scache_t *, char *, long);
412 extern void cm_ReleaseSCacheNoLockDbg(cm_scache_t *, char *, long);
414 extern void cm_ReleaseSCacheDbg(cm_scache_t *, char *, long);
416 #define cm_HoldSCacheNoLock(scp) cm_HoldSCacheNoLockDbg(scp, __FILE__, __LINE__)
417 #define cm_HoldSCache(scp) cm_HoldSCacheDbg(scp, __FILE__, __LINE__)
418 #define cm_ReleaseSCacheNoLock(scp) cm_ReleaseSCacheNoLockDbg(scp, __FILE__, __LINE__)
419 #define cm_ReleaseSCache(scp) cm_ReleaseSCacheDbg(scp, __FILE__, __LINE__)
421 extern void cm_HoldSCacheNoLock(cm_scache_t *);
423 extern void cm_HoldSCache(cm_scache_t *);
425 extern void cm_ReleaseSCacheNoLock(cm_scache_t *);
427 extern void cm_ReleaseSCache(cm_scache_t *);
429 extern cm_scache_t *cm_FindSCache(cm_fid_t *fidp);
431 extern cm_scache_t *cm_FindSCacheParent(cm_scache_t *);
433 extern osi_rwlock_t cm_scacheLock;
435 extern osi_queue_t *cm_allFileLocks;
437 extern osi_queue_t *cm_freeFileLocks;
439 extern unsigned long cm_lockRefreshCycle;
441 extern void cm_DiscardSCache(cm_scache_t *scp);
443 extern int cm_FindFileType(cm_fid_t *fidp);
445 extern long cm_ValidateSCache(void);
447 extern long cm_ShutdownSCache(void);
449 extern void cm_SuspendSCache(void);
451 extern long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags);
453 extern void cm_RemoveSCacheFromHashTable(cm_scache_t *scp);
455 extern void cm_AdjustScacheLRU(cm_scache_t *scp);
457 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
459 extern void cm_ResetSCacheDirectory(cm_scache_t *scp, afs_int32 locked);
461 extern cm_scache_t * cm_RootSCachep(cm_user_t *userp, cm_req_t *reqp);
462 #endif /* OPENAFS_WINNT_AFSD_CM_SCACHE_H */