vol: convert vnode macros to inline functions
[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 */