Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* |
2 | * Written by Paul Popelka (paulp@uts.amdahl.com) | |
3 | * | |
4 | * You can do anything you want with this software, | |
5 | * just don't say you wrote it, | |
6 | * and don't remove this notice. | |
7 | * | |
8 | * This software is provided "as is". | |
9 | * | |
10 | * The author supplies this software to be publicly | |
11 | * redistributed on the understanding that the author | |
12 | * is not responsible for the correct functioning of | |
13 | * this software in any circumstances and is not liable | |
14 | * for any damages caused by this software. | |
15 | * | |
16 | * October 1992 | |
17 | * | |
fde1aeb2 | 18 | * $Id: denode.h,v 1.5 1993/11/25 01:37:04 wollman Exp $ |
15637ed4 RG |
19 | */ |
20 | ||
bbc3f849 GW |
21 | #ifndef _PCFS_DENODE_H_ |
22 | #define _PCFS_DENODE_H_ 1 | |
23 | ||
15637ed4 RG |
24 | /* |
25 | * This is the pc filesystem specific portion of the | |
26 | * vnode structure. | |
27 | * To describe a file uniquely the de_dirclust, de_diroffset, | |
28 | * and de_de.deStartCluster fields are used. de_dirclust | |
29 | * contains the cluster number of the directory cluster containing | |
30 | * the entry for a file or directory. de_diroffset is the | |
31 | * index into the cluster for the entry describing a file | |
32 | * or directory. de_de.deStartCluster is the number of the | |
33 | * first cluster of the file or directory. Now to describe the | |
34 | * quirks of the pc filesystem. | |
35 | * - Clusters 0 and 1 are reserved. | |
36 | * - The first allocatable cluster is 2. | |
37 | * - The root directory is of fixed size and all blocks that | |
38 | * make it up are contiguous. | |
39 | * - Cluster 0 refers to the root directory when it is found | |
40 | * in the startcluster field of a directory entry that points | |
41 | * to another directory. | |
42 | * - Cluster 0 implies a 0 length file when found in the start | |
43 | * cluster field of a directory entry that points to a file. | |
44 | * - You can't use the cluster number 0 to derive | |
45 | * the address of the root directory. | |
46 | * - Multiple directory entries can point to a directory. | |
47 | * The entry in the parent directory points to a child | |
48 | * directory. Any directories in the child directory contain | |
49 | * a ".." entry that points back to the child. The child | |
50 | * directory itself contains a "." entry that points to | |
51 | * itself. | |
52 | * - The root directory does not contain a "." or ".." entry. | |
53 | * - Directory entries for directories are never changed once | |
54 | * they are created (except when removed). The size stays | |
55 | * 0, and the last modification time is never changed. This | |
56 | * is because so many directory entries can point to the physical | |
57 | * clusters that make up a directory. It would lead to an update | |
58 | * nightmare. | |
59 | * - The length field in a directory entry pointing to a directory | |
60 | * contains 0 (always). The only way to find the end of a directory | |
61 | * is to follow the cluster chain until the "last cluster" | |
62 | * marker is found. | |
63 | * My extensions to make this house of cards work. These apply | |
64 | * only to the in memory copy of the directory entry. | |
65 | * - A reference count for each denode will be kept since dos doesn't | |
66 | * keep such things. | |
67 | */ | |
68 | ||
69 | /* Internal pseudo-offset for (nonexistent) directory entry for the root dir | |
70 | * in the root dir */ | |
71 | #define PCFSROOT_OFS 0x1fffffff | |
72 | ||
73 | /* | |
74 | * The fat cache structure. | |
75 | * fc_fsrcn is the filesystem relative cluster number | |
76 | * that corresponds to the file relative cluster number | |
77 | * in this structure (fc_frcn). | |
78 | */ | |
79 | struct fatcache { | |
80 | u_short fc_frcn; /* file relative cluster number */ | |
81 | u_short fc_fsrcn; /* filesystem relative cluster number */ | |
82 | }; | |
83 | ||
84 | /* | |
85 | * The fat entry cache as it stands helps make extending | |
86 | * files a "quick" operation by avoiding having to scan | |
87 | * the fat to discover the last cluster of the file. | |
88 | * The cache also helps sequential reads by remembering | |
89 | * the last cluster read from the file. This also prevents | |
90 | * us from having to rescan the fat to find the next cluster | |
91 | * to read. This cache is probably pretty worthless if a | |
92 | * file is opened by multiple processes. | |
93 | */ | |
94 | #define FC_SIZE 2 /* number of entries in the cache */ | |
95 | #define FC_LASTMAP 0 /* entry the last call to pcbmap() resolved to */ | |
96 | #define FC_LASTFC 1 /* entry for the last cluster in the file */ | |
97 | ||
98 | #define FCE_EMPTY 0xffff /* doesn't represent an actual cluster # */ | |
99 | ||
100 | /* | |
101 | * Set a slot in the fat cache. | |
102 | */ | |
103 | #define fc_setcache(dep, slot, frcn, fsrcn) \ | |
104 | (dep)->de_fc[slot].fc_frcn = frcn; \ | |
105 | (dep)->de_fc[slot].fc_fsrcn = fsrcn; | |
106 | ||
107 | /* | |
108 | * This is the in memory variant of a dos directory | |
109 | * entry. It is usually contained within a vnode. | |
110 | */ | |
111 | struct denode { | |
112 | struct denode *de_chain[2]; /* hash chain ptrs */ | |
113 | struct vnode *de_vnode; /* addr of vnode we are part of */ | |
114 | struct vnode *de_devvp; /* vnode of blk dev we live on */ | |
115 | u_long de_flag; /* flag bits */ | |
116 | dev_t de_dev; /* device where direntry lives */ | |
117 | u_long de_dirclust; /* cluster of the directory file | |
118 | * containing this entry */ | |
119 | u_long de_diroffset; /* ordinal of this entry in the | |
120 | * directory */ | |
121 | long de_refcnt; /* reference count */ | |
122 | struct pcfsmount *de_pmp; /* addr of our mount struct */ | |
123 | struct lockf *de_lockf; /* byte level lock list */ | |
124 | long de_spare0; /* current lock holder */ | |
125 | long de_spare1; /* lock wanter */ | |
126 | struct direntry de_de; /* the actual directory entry */ | |
127 | struct fatcache de_fc[FC_SIZE]; /* fat cache */ | |
128 | }; | |
129 | ||
130 | /* | |
131 | * Values for the de_flag field of the denode. | |
132 | */ | |
133 | #define DELOCKED 0x0001 /* directory entry is locked */ | |
134 | #define DEWANT 0x0002 /* someone wants this de */ | |
135 | #define DERENAME 0x0004 /* de is being renamed */ | |
136 | #define DEUPD 0x0008 /* file has been modified */ | |
137 | #define DESHLOCK 0x0010 /* file has shared lock */ | |
138 | #define DEEXLOCK 0x0020 /* file has exclusive lock */ | |
139 | #define DELWAIT 0x0040 /* someone waiting on file lock */ | |
140 | #define DEMOD 0x0080 /* denode wants to be written back | |
141 | * to disk */ | |
142 | ||
143 | /* | |
144 | * Shorthand macros used to reference fields in the direntry | |
145 | * contained in the denode structure. | |
146 | */ | |
147 | #define de_Name de_de.deName | |
148 | #define de_Extension de_de.deExtension | |
149 | #define de_Attributes de_de.deAttributes | |
150 | #define de_Reserved de_de.deReserved | |
151 | #define de_Time de_de.deTime | |
152 | #define de_Date de_de.deDate | |
153 | #define de_StartCluster de_de.deStartCluster | |
154 | #define de_FileSize de_de.deFileSize | |
155 | #define de_forw de_chain[0] | |
156 | #define de_back de_chain[1] | |
157 | ||
158 | #if defined(KERNEL) | |
159 | ||
160 | #define VTODE(vp) ((struct denode *)(vp)->v_data) | |
161 | #define DETOV(de) ((de)->de_vnode) | |
162 | ||
163 | #define DELOCK(de) delock(de) | |
fde1aeb2 | 164 | extern void delock(struct denode *); |
15637ed4 | 165 | #define DEUNLOCK(de) deunlock(de) |
fde1aeb2 | 166 | extern void deunlock(struct denode *); |
15637ed4 RG |
167 | |
168 | #define DEUPDAT(dep, t, waitfor) \ | |
169 | if (dep->de_flag & DEUPD) \ | |
170 | (void) deupdat(dep, t, waitfor); | |
171 | ||
172 | #define DETIMES(dep, t) \ | |
173 | if (dep->de_flag & DEUPD) { \ | |
174 | (dep)->de_flag |= DEMOD; \ | |
175 | unix2dostime(t, (union dosdate *)&dep->de_Date, \ | |
176 | (union dostime *)&dep->de_Time); \ | |
177 | (dep)->de_flag &= ~DEUPD; \ | |
178 | } | |
179 | ||
180 | /* | |
181 | * This overlays the fid sturcture (see mount.h) | |
182 | */ | |
183 | struct defid { | |
184 | u_short defid_len; /* length of structure */ | |
185 | u_short defid_pad; /* force long alignment */ | |
186 | ||
187 | u_long defid_dirclust; /* cluster this dir entry came from */ | |
188 | u_long defid_dirofs; /* index of entry within the cluster */ | |
189 | ||
8183b32d | 190 | /* u_long defid_gen;*/ /* generation number */ |
15637ed4 RG |
191 | }; |
192 | ||
193 | /* | |
194 | * Prototypes for PCFS vnode operations | |
195 | */ | |
196 | int pcfs_lookup __P((struct vnode *vp, struct nameidata *ndp, struct proc *p)); | |
197 | int pcfs_create __P((struct nameidata *ndp, struct vattr *vap, struct proc *p)); | |
198 | int pcfs_mknod __P((struct nameidata *ndp, struct vattr *vap, struct ucred *cred, | |
199 | struct proc *p)); | |
200 | int pcfs_open __P((struct vnode *vp, int mode, struct ucred *cred, | |
201 | struct proc *p)); | |
202 | int pcfs_close __P((struct vnode *vp, int fflag, struct ucred *cred, | |
203 | struct proc *p)); | |
204 | int pcfs_access __P((struct vnode *vp, int mode, struct ucred *cred, | |
205 | struct proc *p)); | |
206 | int pcfs_getattr __P((struct vnode *vp, struct vattr *vap, struct ucred *cred, | |
207 | struct proc *p)); | |
208 | int pcfs_setattr __P((struct vnode *vp, struct vattr *vap, struct ucred *cred, | |
209 | struct proc *p)); | |
210 | int pcfs_read __P((struct vnode *vp, struct uio *uio, int ioflag, | |
211 | struct ucred *cred)); | |
212 | int pcfs_write __P((struct vnode *vp, struct uio *uio, int ioflag, | |
213 | struct ucred *cred)); | |
214 | int pcfs_ioctl __P((struct vnode *vp, int command, caddr_t data, int fflag, | |
215 | struct ucred *cred, struct proc *p)); | |
216 | int pcfs_select __P((struct vnode *vp, int which, int fflags, struct ucred *cred, | |
217 | struct proc *p)); | |
218 | int pcfs_mmap __P((struct vnode *vp, int fflags, struct ucred *cred, | |
219 | struct proc *p)); | |
220 | int pcfs_fsync __P((struct vnode *vp, int fflags, struct ucred *cred, | |
221 | int waitfor, struct proc *p)); | |
222 | int pcfs_seek __P((struct vnode *vp, off_t oldoff, off_t newoff, | |
223 | struct ucred *cred)); | |
224 | int pcfs_remove __P((struct nameidata *ndp, struct proc *p)); | |
225 | int pcfs_link __P((struct vnode *vp, struct nameidata *ndp, struct proc *p)); | |
226 | int pcfs_rename __P((struct nameidata *fndp, struct nameidata *tdnp, | |
227 | struct proc *p)); | |
228 | int pcfs_mkdir __P((struct nameidata *ndp, struct vattr *vap, struct proc *p)); | |
229 | int pcfs_rmdir __P((struct nameidata *ndp, struct proc *p)); | |
230 | int pcfs_symlink __P((struct nameidata *ndp, struct vattr *vap, char *target, | |
231 | struct proc *p)); | |
232 | int pcfs_readdir __P((struct vnode *vp, struct uio *uio, struct ucred *cred, | |
233 | int *eofflagp)); | |
234 | int pcfs_readlink __P((struct vnode *vp, struct uio *uio, struct ucred *cred)); | |
235 | int pcfs_abortop __P((struct nameidata *ndp)); | |
236 | int pcfs_inactive __P((struct vnode *vp, struct proc *p)); | |
237 | int pcfs_reclaim __P((struct vnode *vp)); | |
238 | int pcfs_lock __P((struct vnode *vp)); | |
239 | int pcfs_unlock __P((struct vnode *vp)); | |
240 | int pcfs_bmap __P((struct vnode *vp, daddr_t bn, struct vnode **vpp, | |
241 | daddr_t *bnp)); | |
242 | int pcfs_strategy __P((struct buf *bp)); | |
4c45483e | 243 | void pcfs_print __P((struct vnode *vp)); |
15637ed4 RG |
244 | int pcfs_islocked __P((struct vnode *vp)); |
245 | int pcfs_advlock __P((struct vnode *vp, caddr_t id, int op, struct flock *fl, | |
246 | int flags)); | |
247 | ||
248 | /* | |
249 | * Internal service routine prototypes. | |
250 | */ | |
251 | int deget __P((struct pcfsmount *pmp, u_long dirclust, u_long diroffset, | |
252 | struct direntry *direntptr, struct denode **depp)); | |
fde1aeb2 GW |
253 | |
254 | extern int pcbmap(struct denode *, u_long, daddr_t *, u_long *); | |
255 | extern void fc_purge(struct denode *, u_int); | |
256 | extern void updateotherfats(struct pcfsmount *, struct buf *, u_long); | |
257 | extern int clusterfree(struct pcfsmount *, u_long, u_long *); | |
258 | extern int fatentry(int, struct pcfsmount *, u_long, u_long *, u_long); | |
259 | extern int clusteralloc(struct pcfsmount *, u_long *, u_long); | |
260 | extern int freeclusterchain(struct pcfsmount *, u_long); | |
261 | extern int fillinusemap(struct pcfsmount *); | |
262 | extern int extendfile(struct denode *, struct buf **, u_int *); | |
263 | extern int readep(struct pcfsmount *, u_long, u_long, struct buf **, | |
264 | struct direntry **); | |
265 | extern int readde(struct denode *, struct buf **, struct direntry **); | |
266 | extern int doscheckpath(struct denode *, struct denode *); | |
267 | extern int dosdirempty(struct denode *); | |
268 | extern int removede(struct nameidata *); | |
269 | extern int markdeleted(struct pcfsmount *, u_long, u_long); | |
270 | extern int createde(struct denode *, struct nameidata *, struct denode **); | |
271 | extern int pcfs_lookup(struct vnode *, struct nameidata *, struct proc *); | |
272 | ||
273 | extern void pcfs_init(void); | |
274 | extern void deput(struct denode *); | |
275 | extern int deupdat(struct denode *, struct timeval *, int); | |
276 | extern int detrunc(struct denode *, u_long, int); | |
277 | extern void reinsert(struct denode *); | |
278 | extern int pcfs_reclaim(struct vnode *); | |
279 | extern int pcfs_inactive(struct vnode *, struct proc *); | |
280 | ||
281 | ||
15637ed4 | 282 | #endif /* defined(KERNEL) */ |
bbc3f849 | 283 | #endif /* _PCFS_DENODE_H_ */ |