Windows FindACLCache must hold scp write locked
[openafs.git] / src / WINNT / afsd / cm_scache.h
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #ifndef OPENAFS_WINNT_AFSD_CM_SCACHE_H
11 #define OPENAFS_WINNT_AFSD_CM_SCACHE_H 1
12
13 #include <opr/jhash.h>
14
15 #define MOUNTPOINTLEN   1024    /* max path length for symlink; same as AFSPATHMAX */
16
17 typedef struct cm_fid {
18     afs_uint32 cell;
19     afs_uint32 volume;
20     afs_uint32 vnode;
21     afs_uint32 unique;
22     afs_uint32 hash;
23 } cm_fid_t;
24
25
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 */
32 } cm_key_t;
33
34 typedef struct cm_range {
35     afs_int64 offset;
36     afs_int64 length;
37 } cm_range_t;
38
39 /* forward dcls */
40 struct cm_scache;
41 typedef struct cm_scache cm_scache_t;
42
43 typedef struct cm_file_lock {
44     osi_queue_t q;              /* list of all locks [protected by
45                                    cm_scacheLock] */
46     osi_queue_t fileq;          /* per-file list of locks [protected
47                                    by scp->rw]*/
48
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] */
53 #ifdef DEBUG
54     cm_fid_t   fid;
55 #endif
56
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
64                                  * cm_scacheLock] */
65 } cm_file_lock_t;
66
67 #define fileq_to_cm_file_lock_t(q) ((cm_file_lock_t *)((char *) (q) - offsetof(cm_file_lock_t, fileq)))
68
69 #define CM_FILELOCK_FLAG_DELETED         0x01
70 #define CM_FILELOCK_FLAG_LOST            0x02
71
72 /* the following are mutually exclusive */
73 #define CM_FILELOCK_FLAG_WAITLOCK        0x04
74 #define CM_FILELOCK_FLAG_WAITUNLOCK      0x0C
75
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
81
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
86
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 */
90 } cm_prefetch_t;
91
92 #define CM_SCACHE_MAGIC ('S' | 'C'<<8 | 'A'<<16 | 'C'<<24)
93
94 typedef struct cm_scache {
95     osi_queue_t q;                      /* lru queue; cm_scacheLock */
96     afs_uint32      magic;
97     struct cm_scache *nextp;            /* next in hash; cm_scacheLock */
98     struct cm_scache *allNextp;         /* next in all scache list; cm_scacheLock */
99     cm_fid_t fid;
100     afs_uint32 flags;                   /* flags; locked by rw */
101
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.
107                                          */
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 */
111
112     /* parent info for ACLs */
113     afs_uint32 parentVnode;             /* parent vnode for ACL callbacks */
114     afs_uint32 parentUnique;            /* for ACL callbacks */
115
116     /* local modification stat */
117     afs_uint32 mask;                    /* for clientModTime, length and
118                                          * truncPos */
119
120     /* file status */
121     afs_uint32 fileType;                /* file type */
122     time_t clientModTime;               /* mtime */
123     time_t serverModTime;               /* at server, for concurrent call
124                                          * comparisons */
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 */
135
136     /* volume status */
137     time_t volumeCreationDate;          /* volume creation date from AFSVolSync */
138
139     /* pseudo file status */
140     osi_hyper_t serverLength;           /* length known to server */
141
142     /* aux file status */
143     osi_hyper_t truncPos;               /* file size to truncate to before
144                                          * storing data */
145
146     /* symlink and mount point info */
147     char mountPointStringp[MOUNTPOINTLEN];      /* the string stored in a mount point;
148                                                  * first char is type, then vol name.
149                                          * If this is a normal symlink, we store
150                                          * the link contents here.
151                                          */
152     cm_fid_t  mountRootFid;             /* mounted on root */
153     time_t    mountRootGen;             /* time to update mountRootFid? */
154     cm_fid_t  dotdotFid;                /* parent of volume root */
155
156     /* callback info */
157     struct cm_server *cbServerp;        /* server granting callback */
158     time_t cbExpires;                   /* time callback expires */
159     time_t cbIssued;                    /* time callback was issued */
160
161     /* access cache */
162     long anyAccess;                     /* anonymous user's access */
163     struct cm_aclent *randomACLp;       /* access cache entries */
164
165     /* file locks */
166     afs_int32    serverLock;    /* current lock we have acquired on
167                                  * this file.  One of (-1), LockRead
168                                  * or LockWrite. [protected by
169                                  * scp->rw].  In the future, this
170                                  * should be replaced by a queue of
171                                  * cm_server_lock_t objects which keep
172                                  * track of lock type, the user for
173                                  * whom the lock was obtained, the
174                                  * dataVersion at the time the lock
175                                  * was asserted last, lastRefreshCycle
176                                  * and lateUpdateTime.
177                                  */
178     unsigned long lastRefreshCycle; /* protected with cm_scacheLock
179                                      * for all scaches. */
180     afs_uint64  lockDataVersion; /* dataVersion of the scp at the time
181                                    the server lock for the scp was
182                                    asserted for this lock the last
183                                    time. */
184     osi_queue_t *fileLocksH;    /* queue of locks (head) */
185     osi_queue_t *fileLocksT;    /* queue of locks (tail) */
186
187     afs_uint32   sharedLocks;   /* number of shared locks on
188                                  * ::fileLocks.  This count does not
189                                  * include locks which have
190                                  * CM_FILELOCK_FLAG_CLIENTONLY set. */
191
192     afs_uint32   exclusiveLocks; /* number of exclusive locks on
193                                   * ::fileLocks.  This count does not
194                                   * include locks which have
195                                   * CM_FILELOCK_FLAG_CLIENTONLY set.
196                                   */
197
198     afs_uint32   clientLocks;   /* number of locks on ::fileLocks that
199                                    have CM_FILELOCK_FLAG_CLIENTONLY
200                                    set. */
201
202     afs_int32    fsLockCount;   /* number of locks held as reported
203                                  * by the file server in the most
204                                  * recent fetch status.  Updated by
205                                  * the locks known to have been acquired
206                                  * or released by this client.
207                                  */
208
209     /* bulk stat progress */
210     osi_hyper_t bulkStatProgress;       /* track bulk stats of large dirs */
211
212 #ifdef USE_BPLUS
213     /* directory B+ tree */             /* only allocated if is directory */
214     osi_rwlock_t dirlock;               /* controls access to dirBplus */
215     afs_uint64   dirDataVersion;        /* data version represented by dirBplus */
216     struct tree *dirBplus;              /* dirBplus */
217 #endif
218
219     /* open state */
220     afs_uint16 openReads;               /* open for reading */
221     afs_uint16 openWrites;              /* open for writing */
222     afs_uint16 openShares;              /* open for read excl */
223     afs_uint16 openExcls;               /* open for exclusives */
224
225     /* syncop state */
226     afs_uint32 waitCount;           /* number of threads waiting */
227     afs_uint32 waitRequests;        /* num of thread wait requests */
228     osi_queue_t * waitQueueH;       /* Queue of waiting threads.
229                                        Holds queue of
230                                        cm_scache_waiter_t
231                                        objects. Protected by
232                                        cm_scacheLock. */
233     osi_queue_t * waitQueueT;       /* locked by cm_scacheLock */
234
235     /* redirector state - protected by scp->redirMx */
236     osi_queue_t * redirQueueH;      /* LRU queue of buffers for this
237                                        file that are assigned to the
238                                        afsredir kernel module. */
239     osi_queue_t * redirQueueT;
240     afs_uint32    redirBufCount;    /* Number of buffers held by the redirector */
241     time_t        redirLastAccess;  /* last time redir accessed the vnode */
242     osi_mutex_t   redirMx;
243
244     afs_uint32 activeRPCs;              /* atomic */
245 } cm_scache_t;
246
247 /* dataVersion */
248 #define CM_SCACHE_VERSION_BAD           0xFFFFFFFFFFFFFFFF
249
250 /* mask field - tell what has been modified */
251 #define CM_SCACHEMASK_CLIENTMODTIME     1       /* client mod time */
252 #define CM_SCACHEMASK_LENGTH            2       /* length */
253 #define CM_SCACHEMASK_TRUNCPOS          4       /* truncation position */
254
255 /* fileType values */
256 #define CM_SCACHETYPE_UNKNOWN           0       /* unknown */
257 #define CM_SCACHETYPE_FILE              1       /* a file */
258 #define CM_SCACHETYPE_DIRECTORY         2       /* a dir */
259 #define CM_SCACHETYPE_SYMLINK           3       /* a symbolic link */
260 #define CM_SCACHETYPE_MOUNTPOINT        4       /* a mount point */
261 #define CM_SCACHETYPE_DFSLINK           5       /* a Microsoft Dfs link */
262 #define CM_SCACHETYPE_INVALID           99      /* an invalid link */
263
264 /* flag bits */
265 #define CM_SCACHEFLAG_STATD             0x01    /* status info is valid */
266 #define CM_SCACHEFLAG_DELETED           0x02    /* file has been deleted */
267 #define CM_SCACHEFLAG_CALLBACK          0x04    /* have a valid callback */
268 #define CM_SCACHEFLAG_STORING           0x08    /* status being stored back */
269 #define CM_SCACHEFLAG_FETCHING          0x10    /* status being fetched */
270 #define CM_SCACHEFLAG_SIZESTORING       0x20    /* status being stored that
271                                                  * changes the data; typically,
272                                                  * this is a truncate op. */
273 #define CM_SCACHEFLAG_INHASH            0x40    /* in the hash table */
274 #define CM_SCACHEFLAG_BULKSTATTING      0x80    /* doing a bulk stat */
275 #define CM_SCACHEFLAG_SIZESETTING       0x100   /* Stabilized; Truncate */
276 #define CM_SCACHEFLAG_WAITING           0x200   /* waiting for fetch/store
277                                                  * state to change */
278 #define CM_SCACHEFLAG_PURERO            0x400   /* read-only (not even backup);
279                                                  * for mount point eval */
280 #define CM_SCACHEFLAG_RO                0x800   /* read-only
281                                                  * (can't do write ops) */
282 #define CM_SCACHEFLAG_GETCALLBACK       0x1000  /* we're getting a callback */
283 #define CM_SCACHEFLAG_DATASTORING       0x2000  /* data being stored */
284 #define CM_SCACHEFLAG_PREFETCHING       0x4000  /* somebody is prefetching */
285 #define CM_SCACHEFLAG_OVERQUOTA         0x8000  /* over quota */
286 #define CM_SCACHEFLAG_OUTOFSPACE        0x10000 /* out of space */
287 #define CM_SCACHEFLAG_ASYNCSTORING      0x20000 /* scheduled to store back */
288 #define CM_SCACHEFLAG_LOCKING           0x40000 /* setting/clearing file lock */
289 #define CM_SCACHEFLAG_WATCHED           0x80000 /* directory being watched */
290 #define CM_SCACHEFLAG_WATCHEDSUBTREE    0x100000 /* dir subtree being watched */
291 #define CM_SCACHEFLAG_ANYWATCH \
292                         (CM_SCACHEFLAG_WATCHED | CM_SCACHEFLAG_WATCHEDSUBTREE)
293
294 #define CM_SCACHEFLAG_EACCESS           0x200000 /* Bulk Stat returned EACCES */
295 #define CM_SCACHEFLAG_SMB_FID           0x400000
296 #define CM_SCACHEFLAG_LOCAL             0x800000 /* Locally modified */
297 #define CM_SCACHEFLAG_BULKREADING       0x1000000/* Bulk read in progress */
298 #define CM_SCACHEFLAG_RDR_IN_USE        0x2000000/* in use by Redirector; advisory */
299
300 /* sync flags for calls to the server.  The CM_SCACHEFLAG_FETCHING,
301  * CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
302  * below, except for FETCHDATA and STOREDATA, which correspond to non-null
303  * buffers in bufReadsp and bufWritesp.
304  * These flags correspond to individual RPCs that we may be making, and at most
305  * one can be set in any one call to SyncOp.
306  */
307 #define CM_SCACHESYNC_FETCHSTATUS           0x01        /* fetching status info */
308 #define CM_SCACHESYNC_STORESTATUS           0x02        /* storing status info */
309 #define CM_SCACHESYNC_FETCHDATA             0x04        /* fetch data */
310 #define CM_SCACHESYNC_STOREDATA             0x08        /* store data */
311 #define CM_SCACHESYNC_STORESIZE         0x10    /* store new file size */
312 #define CM_SCACHESYNC_GETCALLBACK       0x20    /* fetching a callback */
313 #define CM_SCACHESYNC_STOREDATA_EXCL    0x40    /* store data */
314 #define CM_SCACHESYNC_ASYNCSTORE        0x80    /* schedule data store */
315 #define CM_SCACHESYNC_LOCK              0x100   /* set/clear file lock */
316
317 /* sync flags for calls within the client; there are no corresponding flags
318  * in the scache entry, because we hold the scache entry locked during the
319  * operations below.
320  */
321 #define CM_SCACHESYNC_GETSTATUS         0x1000  /* read the status */
322 #define CM_SCACHESYNC_SETSTATUS         0x2000  /* e.g. utimes */
323 #define CM_SCACHESYNC_READ              0x4000  /* read data from a chunk */
324 #define CM_SCACHESYNC_WRITE             0x8000  /* write data to a chunk */
325 #define CM_SCACHESYNC_SETSIZE           0x10000 /* shrink the size of a file,
326                                                  * e.g. truncate */
327 #define CM_SCACHESYNC_NEEDCALLBACK      0x20000 /* need a callback on the file */
328 #define CM_SCACHESYNC_CHECKRIGHTS       0x40000 /* check that user has desired
329                                                  * access rights */
330 #define CM_SCACHESYNC_BUFLOCKED         0x80000 /* the buffer is locked */
331 #define CM_SCACHESYNC_NOWAIT            0x100000/* don't wait for the state,
332                                                  * just fail */
333 #define CM_SCACHESYNC_FORCECB           0x200000/* when calling cm_GetCallback()
334                                                  * set the force flag */
335
336 #define CM_SCACHESYNC_BULKREAD          0x400000/* reading many buffers */
337
338 /* flags for cm_RecycleSCache   */
339 #define CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS   0x1
340
341 /* flags for cm_MergeStatus */
342 #define CM_MERGEFLAG_FORCE              1       /* check mtime before merging;
343                                                  * used to see if we're merging
344                                                  * in old info.
345                                                  */
346 #define CM_MERGEFLAG_STOREDATA          2       /* Merge due to storedata op */
347 #define CM_MERGEFLAG_DIROP              4       /* Merge due to directory op */
348 #define CM_MERGEFLAG_FETCHDATA          8       /* Merge due to fetchdata op */
349
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.
353  */
354
355 #define CM_FID_GEN_HASH(fidp) do { \
356     (fidp)->hash = opr_jhash(&(fidp)->volume, 3, 0); \
357 } while(0)
358
359 #define CM_SCACHE_HASH(fidp) ((fidp)->hash & (cm_data.scacheHashTableSize - 1))
360
361 #include "cm_conn.h"
362 #include "cm_buf.h"
363
364 typedef struct cm_scache_waiter {
365     osi_queue_t q;
366     afs_int32   threadId;
367
368     cm_scache_t *scp;
369     afs_int32   flags;
370     cm_buf_t    *bufp;
371 } cm_scache_waiter_t;
372
373 extern void cm_InitSCache(int, long);
374
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);
378
379 #define cm_GetSCache(a,b,c,d)  cm_GetSCacheDbg(a,b,c,d,__FILE__,__LINE__)
380 #else
381 extern long cm_GetSCache(cm_fid_t *, cm_fid_t *, cm_scache_t **, struct cm_user *,
382         struct cm_req *);
383 #endif
384
385 extern cm_scache_t *cm_GetNewSCache(afs_uint32 locked);
386
387 extern __inline int cm_FidCmp(cm_fid_t *, cm_fid_t *);
388
389 extern void cm_SetFid(cm_fid_t *, afs_uint32 cell, afs_uint32 volume, afs_uint32 vnode, afs_uint32 unique);
390
391 extern long cm_SyncOp(cm_scache_t *, struct cm_buf *, struct cm_user *,
392         struct cm_req *, afs_uint32, afs_uint32);
393
394 extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, afs_uint32);
395
396 extern void cm_MergeStatus(cm_scache_t * dscp, cm_scache_t * scp,
397                            struct AFSFetchStatus * statusp,
398                            struct AFSVolSync * volsyncp,
399                            struct cm_user *userp,
400                            cm_req_t *reqp,
401                            afs_uint32 flags);
402
403 extern void cm_AFSFidFromFid(struct AFSFid *, cm_fid_t *);
404
405 #ifdef DEBUG_REFCOUNT
406 extern void cm_HoldSCacheNoLockDbg(cm_scache_t *, char *, long);
407
408 extern void cm_HoldSCacheDbg(cm_scache_t *, char *, long);
409
410 extern void cm_ReleaseSCacheNoLockDbg(cm_scache_t *, char *, long);
411
412 extern void cm_ReleaseSCacheDbg(cm_scache_t *, char *, long);
413
414 #define cm_HoldSCacheNoLock(scp)    cm_HoldSCacheNoLockDbg(scp, __FILE__, __LINE__)
415 #define cm_HoldSCache(scp)          cm_HoldSCacheDbg(scp, __FILE__, __LINE__)
416 #define cm_ReleaseSCacheNoLock(scp) cm_ReleaseSCacheNoLockDbg(scp, __FILE__, __LINE__)
417 #define cm_ReleaseSCache(scp)       cm_ReleaseSCacheDbg(scp, __FILE__, __LINE__)
418 #else
419 extern void cm_HoldSCacheNoLock(cm_scache_t *);
420
421 extern void cm_HoldSCache(cm_scache_t *);
422
423 extern void cm_ReleaseSCacheNoLock(cm_scache_t *);
424
425 extern void cm_ReleaseSCache(cm_scache_t *);
426 #endif
427 extern cm_scache_t *cm_FindSCache(cm_fid_t *fidp);
428
429 extern cm_scache_t *cm_FindSCacheParent(cm_scache_t *);
430
431 extern osi_rwlock_t cm_scacheLock;
432
433 extern osi_queue_t *cm_allFileLocks;
434
435 extern osi_queue_t *cm_freeFileLocks;
436
437 extern unsigned long cm_lockRefreshCycle;
438
439 extern void cm_DiscardSCache(cm_scache_t *scp);
440
441 extern int cm_FindFileType(cm_fid_t *fidp);
442
443 extern long cm_ValidateSCache(void);
444
445 extern long cm_ShutdownSCache(void);
446
447 extern void cm_SuspendSCache(void);
448
449 extern long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags);
450
451 extern void cm_RemoveSCacheFromHashTable(cm_scache_t *scp);
452
453 extern void cm_AdjustScacheLRU(cm_scache_t *scp);
454
455 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
456
457 extern void cm_ResetSCacheDirectory(cm_scache_t *scp, afs_int32 locked);
458
459 extern cm_scache_t * cm_RootSCachep(cm_user_t *userp, cm_req_t *reqp);
460 #endif /*  OPENAFS_WINNT_AFSD_CM_SCACHE_H */