Commit | Line | Data |
---|---|---|
ad59feb8 RG |
1 | /* |
2 | * Written by Paul Popelka (paulp@uts.amdahl.com) | |
3 | * | |
4 | * You can do anything you want with this software, just don't say you wrote | |
5 | * it, and don't reoove this notice. | |
6 | * | |
7 | * This software is provided "as is". | |
8 | * | |
9 | * The authop supplies this software to be publicly redistributed on the | |
10 | * understanding that the author is not responsible for the correct | |
11 | * functioning of this software in any circumstances and is not liable for | |
12 | * any damages caused by this software. | |
13 | * | |
14 | * October 1992 | |
15 | * | |
16 | * from NetBSD: msdosfs_denode.c,v 1.2 1993/12/18 00:50:51 mycroft Exp | |
d79b78e0 | 17 | * $Id: msdosfs_denode.c,v 1.1 1994/01/24 06:04:53 rgrimes Exp $ |
ad59feb8 RG |
18 | */ |
19 | ||
20 | #include <sys/param.h> | |
21 | #include <sys/systm.h> | |
22 | #include <sys/mount.h> | |
23 | #include <sys/proc.h> | |
24 | #include <sys/buf.h> | |
25 | #include <sys/vnode.h> | |
26 | #include <sys/kernel.h> /* defines "time" */ | |
27 | ||
d79b78e0 RG |
28 | #include <fs/msdosfs/bpb.h> |
29 | #include <fs/msdosfs/msdosfsmount.h> | |
30 | #include <fs/msdosfs/direntry.h> | |
31 | #include <fs/msdosfs/denode.h> | |
32 | #include <fs/msdosfs/fat.h> | |
ad59feb8 RG |
33 | |
34 | #define DEHSZ 512 | |
35 | #if ((DEHSZ & (DEHSZ-1)) == 0) | |
36 | #define DEHASH(dev, deno) (((dev)+(deno)+((deno)>>16))&(DEHSZ-1)) | |
37 | #else | |
38 | #define DEHASH(dev, deno) (((dev)+(deno)+((deno)>>16))%DEHSZ) | |
39 | #endif /* ((DEHSZ & (DEHSZ-1)) == 0) */ | |
40 | ||
41 | union dehead { | |
42 | union dehead *deh_head[2]; | |
43 | struct denode *deh_chain[2]; | |
44 | } dehead[DEHSZ]; | |
45 | ||
46 | msdosfs_init() | |
47 | { | |
48 | int i; | |
49 | union dehead *deh; | |
50 | ||
51 | if (VN_MAXPRIVATE < sizeof(struct denode)) | |
52 | panic("msdosfs_init: vnode too small"); | |
53 | ||
54 | for (i = DEHSZ, deh = dehead; --i >= 0; deh++) { | |
55 | deh->deh_head[0] = deh; | |
56 | deh->deh_head[1] = deh; | |
57 | } | |
58 | } | |
59 | ||
60 | /* | |
61 | * If deget() succeeds it returns with the gotten denode locked(). | |
62 | * pmp - address of msdosfsmount structure of the filesystem | |
63 | * containing the denode of interest. The pm_dev field and the address | |
64 | * of the msdosfsmount structure are used. | |
65 | * dirclust - which cluster bp contains, if dirclust is 0 (root directory) | |
66 | * diroffset is relative to the beginning of the root directory, otherwise | |
67 | * it is cluster relative. | |
68 | * diroffset - offset past begin of cluster of denode we want | |
69 | * direntptr - address of the direntry structure of interest. direntptr | |
70 | * is NULL, the block is read if necessary. | |
71 | * depp - returns the address of the gotten denode. | |
72 | */ | |
73 | int | |
74 | deget(pmp, dirclust, diroffset, direntptr, depp) | |
75 | struct msdosfsmount *pmp; /* so we know the maj/min number */ | |
76 | u_long dirclust; /* cluster this dir entry came from */ | |
77 | u_long diroffset; /* index of entry within the cluster */ | |
78 | struct direntry *direntptr; | |
79 | struct denode **depp; /* returns the addr of the gotten denode */ | |
80 | { | |
81 | int error; | |
82 | dev_t dev = pmp->pm_dev; | |
83 | union dehead *deh; | |
84 | struct mount *mntp = pmp->pm_mountp; | |
85 | extern struct vnodeops msdosfs_vnodeops; | |
86 | struct denode *ldep; | |
87 | struct vnode *nvp; | |
88 | struct buf *bp; | |
89 | ||
90 | #if defined(MSDOSFSDEBUG) | |
91 | printf("deget(pmp %08x, dirclust %d, diroffset %x, direntptr %x, depp %08x)\n", | |
92 | pmp, dirclust, diroffset, direntptr, depp); | |
93 | #endif /* defined(MSDOSFSDEBUG) */ | |
94 | ||
95 | /* | |
96 | * If dir entry is given and refers to a directory, convert to | |
97 | * canonical form | |
98 | */ | |
99 | if (direntptr && (direntptr->deAttributes & ATTR_DIRECTORY)) { | |
100 | dirclust = direntptr->deStartCluster; | |
101 | if (dirclust == MSDOSFSROOT) | |
102 | diroffset = MSDOSFSROOT_OFS; | |
103 | else | |
104 | diroffset = 0; | |
105 | } | |
106 | ||
107 | /* | |
108 | * See if the denode is in the denode cache. Use the location of | |
109 | * the directory entry to compute the hash value. For subdir use | |
110 | * address of "." entry. for root dir use cluster MSDOSFSROOT, | |
111 | * offset MSDOSFSROOT_OFS | |
112 | * | |
113 | * NOTE: The check for de_refcnt > 0 below insures the denode being | |
114 | * examined does not represent an unlinked but still open file. | |
115 | * These files are not to be accessible even when the directory | |
116 | * entry that represented the file happens to be reused while the | |
117 | * deleted file is still open. | |
118 | */ | |
119 | deh = &dehead[DEHASH(dev, dirclust + diroffset)]; | |
120 | loop: | |
121 | for (ldep = deh->deh_chain[0]; ldep != (struct denode *) deh; | |
122 | ldep = ldep->de_forw) { | |
123 | if (dev != ldep->de_dev || ldep->de_refcnt == 0) | |
124 | continue; | |
125 | if (dirclust != ldep->de_dirclust | |
126 | || diroffset != ldep->de_diroffset) | |
127 | continue; | |
128 | if (ldep->de_flag & DELOCKED) { | |
129 | /* | |
130 | * should we brelse() the passed buf hdr to avoid | |
131 | * some potential deadlock? | |
132 | */ | |
133 | ldep->de_flag |= DEWANT; | |
134 | sleep((caddr_t) ldep, PINOD); | |
135 | goto loop; | |
136 | } | |
137 | if (vget(DETOV(ldep))) | |
138 | goto loop; | |
139 | *depp = ldep; | |
140 | return 0; | |
141 | } | |
142 | ||
143 | ||
144 | /* | |
145 | * Directory entry was not in cache, have to create a vnode and | |
146 | * copy it from the passed disk buffer. | |
147 | */ | |
148 | /* getnewvnode() does a VREF() on the vnode */ | |
149 | if (error = getnewvnode(VT_MSDOSFS, mntp, &msdosfs_vnodeops, &nvp)) { | |
150 | *depp = 0; | |
151 | return error; | |
152 | } | |
153 | ldep = VTODE(nvp); | |
154 | ldep->de_vnode = nvp; | |
155 | ldep->de_flag = 0; | |
156 | ldep->de_devvp = 0; | |
157 | ldep->de_lockf = 0; | |
158 | ldep->de_dev = dev; | |
159 | fc_purge(ldep, 0); /* init the fat cache for this denode */ | |
160 | ||
161 | /* | |
162 | * Insert the denode into the hash queue and lock the denode so it | |
163 | * can't be accessed until we've read it in and have done what we | |
164 | * need to it. | |
165 | */ | |
166 | insque(ldep, deh); | |
167 | DELOCK(ldep); | |
168 | ||
169 | /* | |
170 | * Copy the directory entry into the denode area of the vnode. | |
171 | */ | |
172 | if (dirclust == MSDOSFSROOT && diroffset == MSDOSFSROOT_OFS) { | |
173 | /* | |
174 | * Directory entry for the root directory. There isn't one, | |
175 | * so we manufacture one. We should probably rummage | |
176 | * through the root directory and find a label entry (if it | |
177 | * exists), and then use the time and date from that entry | |
178 | * as the time and date for the root denode. | |
179 | */ | |
180 | ldep->de_Attributes = ATTR_DIRECTORY; | |
181 | ldep->de_StartCluster = MSDOSFSROOT; | |
182 | ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec; | |
183 | /* | |
184 | * fill in time and date so that dos2unixtime() doesn't | |
185 | * spit up when called from msdosfs_getattr() with root | |
186 | * denode | |
187 | */ | |
188 | ldep->de_Time = 0x0000; /* 00:00:00 */ | |
189 | ldep->de_Date = (0 << 9) | (1 << 5) | (1 << 0); | |
190 | /* Jan 1, 1980 */ | |
191 | /* leave the other fields as garbage */ | |
192 | } | |
193 | else { | |
194 | bp = NULL; | |
195 | if (!direntptr) { | |
196 | error = readep(pmp, dirclust, diroffset, &bp, | |
197 | &direntptr); | |
198 | if (error) | |
199 | return error; | |
200 | } | |
201 | ldep->de_de = *direntptr; | |
202 | if (bp) | |
203 | brelse(bp); | |
204 | } | |
205 | ||
206 | /* | |
207 | * Fill in a few fields of the vnode and finish filling in the | |
208 | * denode. Then return the address of the found denode. | |
209 | */ | |
210 | ldep->de_pmp = pmp; | |
211 | ldep->de_devvp = pmp->pm_devvp; | |
212 | ldep->de_refcnt = 1; | |
213 | ldep->de_dirclust = dirclust; | |
214 | ldep->de_diroffset = diroffset; | |
215 | if (ldep->de_Attributes & ATTR_DIRECTORY) { | |
216 | /* | |
217 | * Since DOS directory entries that describe directories | |
218 | * have 0 in the filesize field, we take this opportunity | |
219 | * to find out the length of the directory and plug it into | |
220 | * the denode structure. | |
221 | */ | |
222 | u_long size; | |
223 | ||
224 | nvp->v_type = VDIR; | |
225 | if (ldep->de_StartCluster == MSDOSFSROOT) | |
226 | nvp->v_flag |= VROOT; | |
227 | else { | |
228 | error = pcbmap(ldep, 0xffff, 0, &size); | |
229 | if (error == E2BIG) { | |
230 | ldep->de_FileSize = size << pmp->pm_cnshift; | |
231 | error = 0; | |
232 | } | |
233 | else | |
234 | printf("deget(): pcbmap returned %d\n", error); | |
235 | } | |
236 | } | |
237 | else | |
238 | nvp->v_type = VREG; | |
239 | VREF(ldep->de_devvp); | |
240 | *depp = ldep; | |
241 | return 0; | |
242 | } | |
243 | ||
244 | void | |
245 | deput(dep) | |
246 | struct denode *dep; | |
247 | { | |
248 | if ((dep->de_flag & DELOCKED) == 0) | |
249 | panic("deput: denode not locked"); | |
250 | DEUNLOCK(dep); | |
251 | vrele(DETOV(dep)); | |
252 | } | |
253 | ||
254 | int | |
255 | deupdat(dep, tp, waitfor) | |
256 | struct denode *dep; | |
257 | struct timeval *tp; | |
258 | int waitfor; | |
259 | { | |
260 | int error; | |
261 | daddr_t bn; | |
262 | int diro; | |
263 | struct buf *bp; | |
264 | struct direntry *dirp; | |
265 | struct msdosfsmount *pmp = dep->de_pmp; | |
266 | struct vnode *vp = DETOV(dep); | |
267 | ||
268 | #if defined(MSDOSFSDEBUG) | |
269 | printf("deupdat(): dep %08x\n", dep); | |
270 | #endif /* defined(MSDOSFSDEBUG) */ | |
271 | ||
272 | /* | |
273 | * If the update bit is off, or this denode is from a readonly | |
274 | * filesystem, or this denode is for a directory, or the denode | |
275 | * represents an open but unlinked file then don't do anything. DOS | |
276 | * directory entries that describe a directory do not ever get | |
277 | * updated. This is the way dos treats them. | |
278 | */ | |
279 | if ((dep->de_flag & DEUPD) == 0 || | |
280 | vp->v_mount->mnt_flag & MNT_RDONLY || | |
281 | dep->de_Attributes & ATTR_DIRECTORY || | |
282 | dep->de_refcnt <= 0) | |
283 | return 0; | |
284 | ||
285 | /* | |
286 | * Read in the cluster containing the directory entry we want to | |
287 | * update. | |
288 | */ | |
289 | if (error = readde(dep, &bp, &dirp)) | |
290 | return error; | |
291 | ||
292 | /* | |
293 | * Put the passed in time into the directory entry. | |
294 | */ | |
295 | unix2dostime(&time, (union dosdate *) & dep->de_Date, | |
296 | (union dostime *) & dep->de_Time); | |
297 | dep->de_flag &= ~DEUPD; | |
298 | ||
299 | /* | |
300 | * Copy the directory entry out of the denode into the cluster it | |
301 | * came from. | |
302 | */ | |
303 | *dirp = dep->de_de; /* structure copy */ | |
304 | ||
305 | /* | |
306 | * Write the cluster back to disk. If they asked for us to wait | |
307 | * for the write to complete, then use bwrite() otherwise use | |
308 | * bdwrite(). | |
309 | */ | |
310 | error = 0; /* note that error is 0 from above, but ... */ | |
311 | if (waitfor) | |
312 | error = bwrite(bp); | |
313 | else | |
314 | bdwrite(bp); | |
315 | return error; | |
316 | } | |
317 | ||
318 | /* | |
319 | * Truncate the file described by dep to the length specified by length. | |
320 | */ | |
321 | int | |
322 | detrunc(dep, length, flags) | |
323 | struct denode *dep; | |
324 | u_long length; | |
325 | int flags; | |
326 | { | |
327 | int error; | |
328 | int allerror; | |
329 | u_long eofentry; | |
330 | u_long chaintofree; | |
331 | daddr_t bn; | |
332 | int boff; | |
333 | int isadir = dep->de_Attributes & ATTR_DIRECTORY; | |
334 | struct buf *bp; | |
335 | struct msdosfsmount *pmp = dep->de_pmp; | |
336 | ||
337 | #if defined(MSDOSFSDEBUG) | |
338 | printf("detrunc(): file %s, length %d, flags %d\n", dep->de_Name, length, flags); | |
339 | #endif /* defined(MSDOSFSDEBUG) */ | |
340 | ||
341 | /* | |
342 | * Disallow attempts to truncate the root directory since it is of | |
343 | * fixed size. That's just the way dos filesystems are. We use | |
344 | * the VROOT bit in the vnode because checking for the directory | |
345 | * bit and a startcluster of 0 in the denode is not adequate to | |
346 | * recognize the root directory at this point in a file or | |
347 | * directory's life. | |
348 | */ | |
349 | if (DETOV(dep)->v_flag & VROOT) { | |
350 | printf("detrunc(): can't truncate root directory, clust %d, offset %d\n", | |
351 | dep->de_dirclust, dep->de_diroffset); | |
352 | return EINVAL; | |
353 | } | |
354 | ||
355 | vnode_pager_setsize(DETOV(dep), length); | |
356 | ||
357 | if (dep->de_FileSize <= length) { | |
358 | dep->de_flag |= DEUPD; | |
359 | error = deupdat(dep, &time, 1); | |
360 | #if defined(MSDOSFSDEBUG) | |
361 | printf("detrunc(): file is shorter return point, errno %d\n", error); | |
362 | #endif /* defined(MSDOSFSDEBUG) */ | |
363 | return error; | |
364 | } | |
365 | ||
366 | /* | |
367 | * If the desired length is 0 then remember the starting cluster of | |
368 | * the file and set the StartCluster field in the directory entry | |
369 | * to 0. If the desired length is not zero, then get the number of | |
370 | * the last cluster in the shortened file. Then get the number of | |
371 | * the first cluster in the part of the file that is to be freed. | |
372 | * Then set the next cluster pointer in the last cluster of the | |
373 | * file to CLUST_EOFE. | |
374 | */ | |
375 | if (length == 0) { | |
376 | chaintofree = dep->de_StartCluster; | |
377 | dep->de_StartCluster = 0; | |
378 | eofentry = ~0; | |
379 | } | |
380 | else { | |
381 | error = pcbmap(dep, (length - 1) >> pmp->pm_cnshift, | |
382 | 0, &eofentry); | |
383 | if (error) { | |
384 | #if defined(MSDOSFSDEBUG) | |
385 | printf("detrunc(): pcbmap fails %d\n", error); | |
386 | #endif /* defined(MSDOSFSDEBUG) */ | |
387 | return error; | |
388 | } | |
389 | } | |
390 | ||
391 | fc_purge(dep, (length + pmp->pm_crbomask) >> pmp->pm_cnshift); | |
392 | ||
393 | /* | |
394 | * If the new length is not a multiple of the cluster size then we | |
395 | * must zero the tail end of the new last cluster in case it | |
396 | * becomes part of the file again because of a seek. | |
397 | */ | |
398 | if ((boff = length & pmp->pm_crbomask) != 0) { | |
399 | /* | |
400 | * should read from file vnode or filesystem vnode | |
401 | * depending on if file or dir | |
402 | */ | |
403 | if (isadir) { | |
404 | bn = cntobn(pmp, eofentry); | |
405 | error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, | |
406 | NOCRED, &bp); | |
407 | } | |
408 | else { | |
409 | bn = (length - 1) >> pmp->pm_cnshift; | |
410 | error = bread(DETOV(dep), bn, pmp->pm_bpcluster, | |
411 | NOCRED, &bp); | |
412 | } | |
413 | if (error) { | |
414 | #if defined(MSDOSFSDEBUG) | |
415 | printf("detrunc(): bread fails %d\n", error); | |
416 | #endif /* defined(MSDOSFSDEBUG) */ | |
417 | return error; | |
418 | } | |
419 | vnode_pager_uncache(DETOV(dep)); /* what's this for? */ | |
420 | /* | |
421 | * is this the right place for it? | |
422 | */ | |
423 | bzero(bp->b_un.b_addr + boff, pmp->pm_bpcluster - boff); | |
424 | if (flags & IO_SYNC) | |
425 | bwrite(bp); | |
426 | else | |
427 | bdwrite(bp); | |
428 | } | |
429 | ||
430 | /* | |
431 | * Write out the updated directory entry. Even if the update fails | |
432 | * we free the trailing clusters. | |
433 | */ | |
434 | dep->de_FileSize = length; | |
435 | dep->de_flag |= DEUPD; | |
436 | vinvalbuf(DETOV(dep), length > 0); | |
437 | allerror = deupdat(dep, &time, MNT_WAIT); | |
438 | #if defined(MSDOSFSDEBUG) | |
439 | printf("detrunc(): allerror %d, eofentry %d\n", | |
440 | allerror, eofentry); | |
441 | #endif /* defined(MSDOSFSDEBUG) */ | |
442 | ||
443 | /* | |
444 | * If we need to break the cluster chain for the file then do it | |
445 | * now. | |
446 | */ | |
447 | if (eofentry != ~0) { | |
448 | error = fatentry(FAT_GET_AND_SET, pmp, eofentry, | |
449 | &chaintofree, CLUST_EOFE); | |
450 | if (error) { | |
451 | #if defined(MSDOSFSDEBUG) | |
452 | printf("detrunc(): fatentry errors %d\n", error); | |
453 | #endif /* defined(MSDOSFSDEBUG) */ | |
454 | return error; | |
455 | } | |
456 | fc_setcache(dep, FC_LASTFC, (length - 1) >> pmp->pm_cnshift, | |
457 | eofentry); | |
458 | } | |
459 | ||
460 | /* | |
461 | * Now free the clusters removed from the file because of the | |
462 | * truncation. | |
463 | */ | |
464 | if (chaintofree != 0 && !MSDOSFSEOF(chaintofree)) | |
465 | freeclusterchain(pmp, chaintofree); | |
466 | ||
467 | return allerror; | |
468 | } | |
469 | ||
470 | /* | |
471 | * Move a denode to its correct hash queue after the file it represents has | |
472 | * been moved to a new directory. | |
473 | */ | |
474 | reinsert(dep) | |
475 | struct denode *dep; | |
476 | { | |
477 | struct msdosfsmount *pmp = dep->de_pmp; | |
478 | union dehead *deh; | |
479 | ||
480 | /* | |
481 | * Fix up the denode cache. If the denode is for a directory, | |
482 | * there is nothing to do since the hash is based on the starting | |
483 | * cluster of the directory file and that hasn't changed. If for a | |
484 | * file the hash is based on the location of the directory entry, | |
485 | * so we must remove it from the cache and re-enter it with the | |
486 | * hash based on the new location of the directory entry. | |
487 | */ | |
488 | if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { | |
489 | remque(dep); | |
490 | deh = &dehead[DEHASH(pmp->pm_dev, | |
491 | dep->de_dirclust + dep->de_diroffset)]; | |
492 | insque(dep, deh); | |
493 | } | |
494 | } | |
495 | ||
496 | int msdosfs_prtactive; /* print reclaims of active vnodes */ | |
497 | ||
498 | int | |
499 | msdosfs_reclaim(vp) | |
500 | struct vnode *vp; | |
501 | { | |
502 | struct denode *dep = VTODE(vp); | |
503 | int i; | |
504 | ||
505 | #if defined(MSDOSFSDEBUG) | |
506 | printf("msdosfs_reclaim(): dep %08x, file %s, refcnt %d\n", | |
507 | dep, dep->de_Name, dep->de_refcnt); | |
508 | #endif /* defined(MSDOSFSDEBUG) */ | |
509 | ||
510 | if (msdosfs_prtactive && vp->v_usecount != 0) | |
511 | vprint("msdosfs_reclaim(): pushing active", vp); | |
512 | ||
513 | /* | |
514 | * Remove the denode from the denode hash chain we are in. | |
515 | */ | |
516 | remque(dep); | |
517 | dep->de_forw = dep; | |
518 | dep->de_back = dep; | |
519 | ||
520 | cache_purge(vp); | |
521 | /* | |
522 | * Indicate that one less file on the filesystem is open. | |
523 | */ | |
524 | if (dep->de_devvp) { | |
525 | vrele(dep->de_devvp); | |
526 | dep->de_devvp = 0; | |
527 | } | |
528 | ||
529 | dep->de_flag = 0; | |
530 | return 0; | |
531 | } | |
532 | ||
533 | int | |
534 | msdosfs_inactive(vp, p) | |
535 | struct vnode *vp; | |
536 | struct proc *p; | |
537 | { | |
538 | struct denode *dep = VTODE(vp); | |
539 | int error = 0; | |
540 | ||
541 | #if defined(MSDOSFSDEBUG) | |
542 | printf("msdosfs_inactive(): dep %08x, de_Name[0] %x\n", dep, dep->de_Name[0]); | |
543 | #endif /* defined(MSDOSFSDEBUG) */ | |
544 | ||
545 | if (msdosfs_prtactive && vp->v_usecount != 0) | |
546 | vprint("msdosfs_inactive(): pushing active", vp); | |
547 | ||
548 | /* | |
549 | * Get rid of denodes related to stale file handles. Hmmm, what | |
550 | * does this really do? | |
551 | */ | |
552 | if (dep->de_Name[0] == SLOT_DELETED) { | |
553 | if ((vp->v_flag & VXLOCK) == 0) | |
554 | vgone(vp); | |
555 | return 0; | |
556 | } | |
557 | ||
558 | /* | |
559 | * If the file has been deleted and it is on a read/write | |
560 | * filesystem, then truncate the file, and mark the directory slot | |
561 | * as empty. (This may not be necessary for the dos filesystem. | |
562 | */ | |
563 | #if defined(MSDOSFSDEBUG) | |
564 | printf("msdosfs_inactive(): dep %08x, refcnt %d, mntflag %x, MNT_RDONLY %x\n", | |
565 | dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY); | |
566 | #endif /* defined(MSDOSFSDEBUG) */ | |
567 | DELOCK(dep); | |
568 | if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { | |
569 | error = detrunc(dep, (u_long) 0, 0); | |
570 | dep->de_flag |= DEUPD; | |
571 | dep->de_Name[0] = SLOT_DELETED; | |
572 | } | |
573 | DEUPDAT(dep, &time, 0); | |
574 | DEUNLOCK(dep); | |
575 | dep->de_flag = 0; | |
576 | ||
577 | /* | |
578 | * If we are done with the denode, then reclaim it so that it can | |
579 | * be reused now. | |
580 | */ | |
581 | #if defined(MSDOSFSDEBUG) | |
582 | printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount, | |
583 | dep->de_Name[0]); | |
584 | #endif /* defined(MSDOSFSDEBUG) */ | |
585 | if (vp->v_usecount == 0 && dep->de_Name[0] == SLOT_DELETED) | |
586 | vgone(vp); | |
587 | return error; | |
588 | } | |
589 | ||
590 | int | |
591 | delock(dep) | |
592 | struct denode *dep; | |
593 | { | |
594 | while (dep->de_flag & DELOCKED) { | |
595 | dep->de_flag |= DEWANT; | |
596 | if (dep->de_spare0 == curproc->p_pid) | |
597 | panic("delock: locking against myself"); | |
598 | dep->de_spare1 = curproc->p_pid; | |
599 | (void) sleep((caddr_t) dep, PINOD); | |
600 | } | |
601 | dep->de_spare1 = 0; | |
602 | dep->de_spare0 = curproc->p_pid; | |
603 | dep->de_flag |= DELOCKED; | |
604 | ||
605 | return 0; | |
606 | } | |
607 | ||
608 | int | |
609 | deunlock(dep) | |
610 | struct denode *dep; | |
611 | { | |
612 | if ((dep->de_flag & DELOCKED) == 0) | |
613 | vprint("deunlock: found unlocked denode", DETOV(dep)); | |
614 | dep->de_spare0 = 0; | |
615 | dep->de_flag &= ~DELOCKED; | |
616 | if (dep->de_flag & DEWANT) { | |
617 | dep->de_flag &= ~DEWANT; | |
618 | wakeup((caddr_t) dep); | |
619 | } | |
620 | ||
621 | return 0; | |
622 | } |