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