Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / vol / vnode.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 * Portions Copyright (c) 2007-2008 Sine Nomine Associates
10 */
11
12 /*
13 System: VICE-TWO
14 Module: vnode.h
15 Institution: The Information Technology Center, Carnegie-Mellon University
16
17 */
18
19 #ifndef _AFS_VOL_VNODE_H
20 #define _AFS_VOL_VNODE_H 1
21
22 #define Date afs_uint32
23
24 struct Volume; /* Potentially forward definition. */
25
26 typedef struct ViceLock {
27 int lockCount;
28 int lockTime;
29 } ViceLock;
30
31 /**
32 * Return non-zero if unlocked.
33 */
34 static_inline int
35 ViceLockCheckLocked(struct ViceLock *vptr)
36 {
37 return (vptr->lockTime == 0);
38 }
39
40 /**
41 * Clear the lock.
42 */
43 static_inline int
44 ViceLockClear(struct ViceLock *vptr)
45 {
46 vptr->lockCount = 0;
47 vptr->lockTime = 0;
48 return 0;
49 }
50
51 #define ROOTVNODE 1
52
53 /*typedef enum {vNull=0, vFile=1, vDirectory=2, vSymlink=3} VnodeType;*/
54 typedef unsigned int VnodeType;
55 #define vNull 0
56 #define vFile 1
57 #define vDirectory 2
58 #define vSymlink 3
59
60 /*typedef enum {vLarge=0,vSmall=1} VnodeClass;*/
61 #define vLarge 0
62 #define vSmall 1
63 typedef int VnodeClass;
64 #define VNODECLASSWIDTH 1
65 #define VNODECLASSMASK ((1<<VNODECLASSWIDTH)-1)
66 #define nVNODECLASSES (VNODECLASSMASK+1)
67
68 struct VnodeClassInfo {
69 struct Vnode *lruHead; /* Head of list of vnodes of this class */
70 int diskSize; /* size of vnode disk object, power of 2 */
71 int logSize; /* log 2 diskSize */
72 int residentSize; /* resident size of vnode */
73 int cacheSize; /* Vnode cache size */
74 bit32 magic; /* Magic number for this type of vnode,
75 * for as long as we're using vnode magic
76 * numbers */
77 int allocs; /* Total number of successful allocation
78 * requests; this is the same as the number
79 * of sanity checks on the vnode index */
80 int gets, reads; /* Number of VGetVnodes and corresponding
81 * reads */
82 int writes; /* Number of vnode writes */
83 };
84
85 extern struct VnodeClassInfo VnodeClassInfo[nVNODECLASSES];
86
87 /**
88 * Return the vnode class (large or small) of this vnode type.
89 */
90 static_inline VnodeClass
91 vnodeTypeToClass(VnodeType vnodeType)
92 {
93 return (vnodeType == vDirectory ? vLarge : vSmall);
94 }
95
96 /**
97 * Return the vnode type of this vnode number.
98 */
99 static_inline VnodeClass
100 vnodeIdToClass(VnodeId vnodeNumber)
101 {
102 return ((vnodeNumber - 1) & VNODECLASSMASK);
103 }
104
105 /**
106 * Return the vnode index of this vnode number.
107 */
108 static_inline afs_uint32
109 vnodeIdToBitNumber(VnodeId vnodeNumber)
110 {
111 return ((vnodeNumber - 1) >> VNODECLASSWIDTH);
112 }
113
114 /**
115 * Return the index file offset of this vnode class and number.
116 *
117 * The following calculation allows for a header record at the beginning of
118 * the index. The header record is the same size as a vnode.
119 */
120 static_inline afs_foff_t
121 vnodeIndexOffset(struct VnodeClassInfo* vcp, VnodeId vnodeNumber)
122 {
123 return (((afs_foff_t)(vnodeIdToBitNumber(vnodeNumber) + 1)) << vcp->logSize);
124 }
125
126 /**
127 * Return the vnode number of this vnode index.
128 */
129 static_inline VnodeId
130 bitNumberToVnodeNumber(afs_uint32 bitNumber, VnodeClass vnodeClass)
131 {
132 return ((((VnodeId)bitNumber) << VNODECLASSWIDTH) + vnodeClass + 1);
133 }
134
135 /**
136 * Return non-zero if this vnode number is a directory.
137 */
138 static_inline int
139 vnodeIsDirectory(VnodeId vnodeNumber)
140 {
141 return (vnodeIdToClass(vnodeNumber) == vLarge);
142 }
143
144
145 typedef struct VnodeDiskObject {
146 unsigned int type:3; /* Vnode is file, directory, symbolic link
147 * or not allocated */
148 unsigned int cloned:1; /* This vnode was cloned--therefore the inode
149 * is copy-on-write; only set for directories */
150 unsigned int modeBits:12; /* Unix mode bits */
151 signed int linkCount:16; /* Number of directory references to vnode
152 * (from single directory only!) */
153 bit32 length; /* Number of bytes in this file */
154 Unique uniquifier; /* Uniquifier for the vnode; assigned
155 * from the volume uniquifier (actually
156 * from nextVnodeUnique in the Volume
157 * structure) */
158 FileVersion dataVersion; /* version number of the data */
159 afs_int32 vn_ino_lo; /* inode number of the data attached to
160 * this vnode - entire ino for standard */
161 Date unixModifyTime; /* set by user */
162 UserId author; /* Userid of the last user storing the file */
163 UserId owner; /* Userid of the user who created the file */
164 VnodeId parent; /* Parent directory vnode */
165 bit32 vnodeMagic; /* Magic number--mainly for file server
166 * paranoia checks */
167 # define SMALLVNODEMAGIC 0xda8c041F
168 # define LARGEVNODEMAGIC 0xad8765fe
169 /* Vnode magic can be removed, someday, if we run need the room. Simply
170 * have to be sure that the thing we replace can be VNODEMAGIC, rather
171 * than 0 (in an old file system). Or go through and zero the fields,
172 * when we notice a version change (the index version number) */
173 ViceLock lock; /* Advisory lock */
174 Date serverModifyTime; /* Used only by the server; for incremental
175 * backup purposes */
176 afs_int32 group; /* unix group */
177 afs_int32 vn_ino_hi; /* high part of 64 bit inode. */
178 bit32 vn_length_hi; /* high part of 64 bit length */
179 /* Missing:
180 * archiving/migration
181 * encryption key
182 */
183 } VnodeDiskObject;
184
185 #define SIZEOF_SMALLDISKVNODE 64
186 #define CHECKSIZE_SMALLVNODE\
187 (sizeof(VnodeDiskObject) == SIZEOF_SMALLDISKVNODE)
188 #define SIZEOF_LARGEDISKVNODE 256
189
190
191
192 #ifdef AFS_DEMAND_ATTACH_FS
193 /**
194 * demand attach vnode state enumeration.
195 *
196 * @note values must be contiguous for VnIsValidState() to work
197 */
198 typedef enum {
199 VN_STATE_INVALID = 0, /**< vnode does not contain valid cache data */
200 VN_STATE_RELEASING = 1, /**< vnode is busy releasing its ihandle ref */
201 VN_STATE_CLOSING = 2, /**< vnode is busy closing its ihandle ref */
202 VN_STATE_ALLOC = 3, /**< vnode is busy allocating disk entry */
203 VN_STATE_ONLINE = 4, /**< vnode is ready for use */
204 VN_STATE_LOAD = 5, /**< vnode is busy being loaded from disk */
205 VN_STATE_EXCLUSIVE = 6, /**< something external to the vnode package
206 * is operating exclusively on this vnode */
207 VN_STATE_STORE = 7, /**< vnode is busy being stored to disk */
208 VN_STATE_READ = 8, /**< a non-zero number of threads are executing
209 * code external to the vnode package which
210 * requires shared access */
211 VN_STATE_ERROR = 10, /**< vnode hard error state */
212 VN_STATE_COUNT
213 } VnState;
214 #endif /* AFS_DEMAND_ATTACH_FS */
215
216 /**
217 * DAFS vnode state flags.
218 */
219 enum VnFlags {
220 VN_ON_HASH = 0x1, /**< vnode is on hash table */
221 VN_ON_LRU = 0x2, /**< vnode is on lru list */
222 VN_ON_VVN = 0x4, /**< vnode is on volume vnode list */
223 VN_FLAGS_END
224 };
225
226
227 typedef struct Vnode {
228 struct rx_queue vid_hash; /* for vnode by volume id hash */
229 struct Vnode *hashNext; /* Next vnode on hash conflict chain */
230 struct Vnode *lruNext; /* Less recently used vnode than this one */
231 struct Vnode *lruPrev; /* More recently used vnode than this one */
232 /* The lruNext, lruPrev fields are not
233 * meaningful if the vnode is in use */
234 bit16 hashIndex; /* Hash table index */
235 #ifdef AFS_AIX_ENV
236 unsigned changed_newTime:1; /* 1 if vnode changed, write time */
237 unsigned changed_oldTime:1; /* 1 changed, don't update time. */
238 unsigned delete:1; /* 1 if the vnode should be deleted; in
239 * this case, changed must also be 1 */
240 #else
241 byte changed_newTime:1; /* 1 if vnode changed, write time */
242 byte changed_oldTime:1; /* 1 changed, don't update time. */
243 byte delete:1; /* 1 if the vnode should be deleted; in
244 * this case, changed must also be 1 */
245 #endif
246 VnodeId vnodeNumber;
247 struct Volume
248 *volumePtr; /* Pointer to the volume containing this file */
249 bit32 nUsers; /* Number of lwp's who have done a VGetVnode */
250 bit32 cacheCheck; /* Must equal the value in the volume Header
251 * for the cache entry to be valid */
252 bit32 vn_state_flags; /**< vnode state flags */
253 #ifdef AFS_DEMAND_ATTACH_FS
254 bit32 nReaders; /**< number of read locks held */
255 VnState vn_state; /**< vnode state */
256 pthread_cond_t vn_state_cv; /**< state change notification cv */
257 #else /* !AFS_DEMAND_ATTACH_FS */
258 struct Lock lock; /* Internal lock */
259 #endif /* !AFS_DEMAND_ATTACH_FS */
260 #ifdef AFS_PTHREAD_ENV
261 pthread_t writer; /* thread holding write lock */
262 #else /* AFS_PTHREAD_ENV */
263 PROCESS writer; /* Process id having write lock */
264 #endif /* AFS_PTHREAD_ENV */
265 struct VnodeClassInfo * vcp; /**< our vnode class */
266 IHandle_t *handle;
267 VnodeDiskObject disk; /* The actual disk data for the vnode */
268 } Vnode;
269
270 #define SIZEOF_LARGEVNODE \
271 (sizeof(struct Vnode) - sizeof(VnodeDiskObject) + SIZEOF_LARGEDISKVNODE)
272 #define SIZEOF_SMALLVNODE (sizeof (struct Vnode))
273
274
275 /*
276 * struct Vnode accessor abstraction
277 */
278 #define Vn_refcount(vnp) ((vnp)->nUsers)
279 #define Vn_state(vnp) ((vnp)->vn_state)
280 #define Vn_stateFlags(vnp) ((vnp)->vn_state_flags)
281 #define Vn_stateCV(vnp) ((vnp)->vn_state_cv)
282 #define Vn_volume(vnp) ((vnp)->volumePtr)
283 #define Vn_cacheCheck(vnp) ((vnp)->cacheCheck)
284 #define Vn_class(vnp) ((vnp)->vcp)
285 #define Vn_readers(vnp) ((vnp)->nReaders)
286 #define Vn_id(vnp) ((vnp)->vnodeNumber)
287
288
289 #define VN_GET_LEN(N, V) FillInt64(N, (V)->disk.vn_length_hi, (V)->disk.length)
290 #define VNDISK_GET_LEN(N, V) FillInt64(N, (V)->vn_length_hi, (V)->length)
291 #define VN_SET_LEN(V, N) SplitInt64(N, (V)->disk.vn_length_hi, (V)->disk.length)
292 #define VNDISK_SET_LEN(V, N) SplitInt64(N, (V)->vn_length_hi, (V)->length)
293
294 #ifdef AFS_64BIT_IOPS_ENV
295 #define VN_GET_INO(V) ((Inode)((V)->disk.vn_ino_lo | \
296 ((V)->disk.vn_ino_hi ? \
297 (((Inode)(V)->disk.vn_ino_hi)<<32) : 0)))
298
299 #define VN_SET_INO(V, I) ((V)->disk.vn_ino_lo = (int)((I)&0xffffffff), \
300 ((V)->disk.vn_ino_hi = (I) ? \
301 (int)(((I)>>32)&0xffffffff) : 0))
302
303 #define VNDISK_GET_INO(V) ((Inode)((V)->vn_ino_lo | \
304 ((V)->vn_ino_hi ? \
305 (((Inode)(V)->vn_ino_hi)<<32) : 0)))
306
307 #define VNDISK_SET_INO(V, I) ((V)->vn_ino_lo = (int)(I&0xffffffff), \
308 ((V)->vn_ino_hi = (I) ? \
309 (int)(((I)>>32)&0xffffffff) : 0))
310 #else
311 #define VN_GET_INO(V) ((V)->disk.vn_ino_lo)
312 #define VN_SET_INO(V, I) ((V)->disk.vn_ino_lo = (I))
313 #define VNDISK_GET_INO(V) ((V)->vn_ino_lo)
314 #define VNDISK_SET_INO(V, I) ((V)->vn_ino_lo = (I))
315 #endif
316
317 #define VVnodeDiskACL(v) /* Only call this with large (dir) vnode!! */ \
318 ((AL_AccessList *) (((byte *)(v))+SIZEOF_SMALLDISKVNODE))
319 #define VVnodeACL(vnp) (VVnodeDiskACL(&(vnp)->disk))
320 /* VAclSize is defined this way to allow information in the vnode header
321 to grow, in a POSSIBLY upward compatible manner. SIZEOF_SMALLDISKVNODE
322 is the maximum size of the basic vnode. The vnode header of either type
323 can actually grow to this size without conflicting with the ACL on larger
324 vnodes */
325 #define VAclSize(vnp) (SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE)
326 #define VAclDiskSize(v) (SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE)
327 /*extern int VolumeHashOffset(); */
328 extern int VolumeHashOffset_r(void);
329 extern int VInitVnodes(VnodeClass class, int nVnodes);
330 /*extern VInitVnodes_r();*/
331 extern Vnode *VGetVnode(Error * ec, struct Volume *vp, VnodeId vnodeNumber,
332 int locktype);
333 extern Vnode *VGetVnode_r(Error * ec, struct Volume *vp, VnodeId vnodeNumber,
334 int locktype);
335 extern void VPutVnode(Error * ec, Vnode * vnp);
336 extern void VPutVnode_r(Error * ec, Vnode * vnp);
337 extern int VVnodeWriteToRead(Error * ec, Vnode * vnp);
338 extern int VVnodeWriteToRead_r(Error * ec, Vnode * vnp);
339 extern Vnode *VAllocVnode(Error * ec, struct Volume *vp, VnodeType type,
340 VnodeId in_vnode, Unique in_unique);
341 extern Vnode *VAllocVnode_r(Error * ec, struct Volume *vp, VnodeType type,
342 VnodeId in_vnode, Unique in_unique);
343
344 /*extern VFreeVnode();*/
345 extern Vnode *VGetFreeVnode_r(struct VnodeClassInfo *vcp, struct Volume *vp,
346 VnodeId vnodeNumber);
347 extern Vnode *VLookupVnode(struct Volume * vp, VnodeId vnodeId);
348
349 extern void AddToVVnList(struct Volume * vp, Vnode * vnp);
350 extern void DeleteFromVVnList(Vnode * vnp);
351 extern void AddToVnLRU(struct VnodeClassInfo * vcp, Vnode * vnp);
352 extern void DeleteFromVnLRU(struct VnodeClassInfo * vcp, Vnode * vnp);
353 extern void AddToVnHash(Vnode * vnp);
354 extern void DeleteFromVnHash(Vnode * vnp);
355
356 #endif /* _AFS_VOL_VNODE_H */