2 * vi:set cin noet sw=4 tw=70:
3 * Copyright 2006, International Business Machines Corporation and others.
6 * This software has been released under the terms of the IBM Public
7 * License. For details, see the LICENSE file in the top-level source
8 * directory or online at http://www.openafs.org/dl/license10.html
12 * Filesystem export operations for Linux
14 #include <afsconfig.h>
15 #include "afs/param.h"
20 #include <linux/module.h> /* early to avoid printf->printk mapping */
22 #ifdef EXPORTFS_H_EXISTS
23 #include <linux/exportfs.h>
25 #include "afs/sysincludes.h"
26 #include "afsincludes.h"
27 #include "afs/afs_dynroot.h"
28 #include "h/smp_lock.h"
30 #if !defined(AFS_NONFSTRANS)
32 /* #define OSI_EXPORT_DEBUG */
34 extern struct dentry_operations afs_dentry_operations;
35 #if defined(NEW_EXPORT_OPS)
36 static struct dentry *afs_export_get_dentry(struct super_block *sb,
40 struct get_name_data {
47 * Linux reserved the following filehandle types:
48 * - 0 is always the filesystem root; NFS deals with this for us
49 * - 1,2 are reserved by Linux for inode-number-based filehandles
50 * - 0xff is reserved by linux
52 * We encode filehandles for AFS files using the types defined below.
53 * Internally, our "object ID" is a VenusFid; if we get a filehandle
54 * with a more-stable cell ID, we'll turn it into a cell number in
55 * the decode_fh wrapper.
58 #define AFSFH_VENUSFID 0xa0 /* cell, volume, vnode, uniq */
59 #define AFSFH_CELLFID 0xa1 /* cellhandle, volume, vnode, uniq */
60 #define AFSFH_NET_VENUSFID 0xa2 /* net cell, volume, vnode, uniq */
61 #define AFSFH_NET_CELLFID 0xa3 /* net cellhandle, volume, vnode, uniq */
62 #define AFSFH_DYN_RO_CELL 0xd0 /* cellhandle for RO root.cell mount */
63 #define AFSFH_DYN_RW_CELL 0xd1 /* cellhandle for RW root.cell mount */
64 #define AFSFH_DYN_RO_LINK 0xd2 /* cellhandle for RO root.cell symlink */
65 #define AFSFH_DYN_RW_LINK 0xd3 /* cellhandle for RW root.cell symlink */
66 #define AFSFH_DYN_MOUNT 0xd4 /* cellhandle, volume for mount point */
67 #define AFSFH_DYN_SYMLINK 0xd5 /* hash of dynroot symlink target */
69 static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
76 if (!de->d_inode) /* encode a negative dentry?! */
78 if (*max_len < 4) /* not enough space */
81 tvc = VTOAFS(de->d_inode);
83 #ifdef OSI_EXPORT_DEBUG
84 printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
85 tvc->f.fid.Cell, tvc->f.fid.Fid.Volume,
86 tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique);
88 if (afs_IsDynrootAnyFid(&tvc->f.fid)) {
89 vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode);
92 /* encode as a normal filehandle */
104 tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode),
110 memcpy((void *)fh, tc->cellHandle, 16);
111 afs_PutCell(tc, READ_LOCK);
113 if (vntype == VN_TYPE_MOUNT) {
114 fh[4] = htonl(tvc->f.fid.Fid.Unique);
116 return AFSFH_DYN_MOUNT;
119 if (vntype == VN_TYPE_CELL) {
120 return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
122 return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
125 case VN_TYPE_SYMLINK:
126 /* XXX fill in filehandle for dynroot symlink */
127 /* XXX return AFSFH_DYN_SYMLINK; */
135 /* not big enough for a migratable filehandle */
136 /* always encode in network order */
137 fh[0] = htonl(tvc->f.fid.Cell);
138 fh[1] = htonl(tvc->f.fid.Fid.Volume);
139 fh[2] = htonl(tvc->f.fid.Fid.Vnode);
140 fh[3] = htonl(tvc->f.fid.Fid.Unique);
142 return AFSFH_NET_VENUSFID;
146 tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK);
151 memcpy((void *)fh, tc->cellHandle, 16);
152 afs_PutCell(tc, READ_LOCK);
154 /* always encode in network order */
155 fh[4] = htonl(tvc->f.fid.Fid.Volume);
156 fh[5] = htonl(tvc->f.fid.Fid.Vnode);
157 fh[6] = htonl(tvc->f.fid.Fid.Unique);
160 return AFSFH_NET_CELLFID;
163 #if defined(NEW_EXPORT_OPS)
164 static struct dentry *afs_fh_to_dentry(struct super_block *sb, struct fid *fh_fid,
165 int fh_len, int fh_type)
167 static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
168 int fh_len, int fh_type,
169 int (*acceptable)(void *, struct dentry *),
175 struct dentry *result;
176 #if defined(NEW_EXPORT_OPS)
177 __u32 *fh = (__u32 *)fh_fid->raw;
186 fid.Fid.Volume = fh[1];
187 fid.Fid.Vnode = fh[2];
188 fid.Fid.Unique = fh[3];
195 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
200 fid.Cell = tc->cellNum;
201 fid.Fid.Volume = fh[4];
202 fid.Fid.Vnode = fh[5];
203 fid.Fid.Unique = fh[6];
204 afs_PutCell(tc, READ_LOCK);
208 case AFSFH_NET_VENUSFID:
209 fid.Cell = ntohl(fh[0]);
210 fid.Fid.Volume = ntohl(fh[1]);
211 fid.Fid.Vnode = ntohl(fh[2]);
212 fid.Fid.Unique = ntohl(fh[3]);
215 case AFSFH_NET_CELLFID:
219 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
224 fid.Cell = tc->cellNum;
225 fid.Fid.Volume = ntohl(fh[4]);
226 fid.Fid.Vnode = ntohl(fh[5]);
227 fid.Fid.Unique = ntohl(fh[6]);
228 afs_PutCell(tc, READ_LOCK);
232 case AFSFH_DYN_RO_CELL:
233 case AFSFH_DYN_RW_CELL:
237 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
242 afs_GetDynrootFid(&fid);
243 fid.Fid.Vnode = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
245 afs_PutCell(tc, READ_LOCK);
249 case AFSFH_DYN_RO_LINK:
250 case AFSFH_DYN_RW_LINK:
254 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
259 afs_GetDynrootFid(&fid);
260 fid.Fid.Vnode = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
262 afs_PutCell(tc, READ_LOCK);
266 case AFSFH_DYN_MOUNT:
270 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
275 afs_GetDynrootFid(&fid);
276 fid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
278 fid.Fid.Unique = ntohl(fh[4]);
279 afs_PutCell(tc, READ_LOCK);
283 case AFSFH_DYN_SYMLINK:
284 /* XXX parse dynroot symlink filehandle */
291 #if defined(NEW_EXPORT_OPS)
292 result = afs_export_get_dentry(sb, &fid);
294 result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
295 acceptable, context);
299 #ifdef OSI_EXPORT_DEBUG
301 printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
302 fid.Cell, fid.Fid.Volume,
303 fid.Fid.Vnode, fid.Fid.Unique);
304 } else if (IS_ERR(result)) {
305 printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
306 fid.Cell, fid.Fid.Volume,
307 fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
313 static int update_dir_parent(struct vrequest *areq, struct vcache *adp)
315 struct VenusFid tfid;
317 afs_size_t dirOffset, dirLen;
321 if (!(adp->f.states & CStatd)) {
322 if ((code = afs_VerifyVCache2(adp, areq))) {
323 #ifdef OSI_EXPORT_DEBUG
324 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): VerifyVCache2: %d\n",
325 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
326 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
332 tdc = afs_GetDCache(adp, (afs_size_t) 0, areq, &dirOffset, &dirLen, 1);
334 #ifdef OSI_EXPORT_DEBUG
335 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): no dcache\n",
336 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
337 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
342 /* now we will just call dir package with appropriate inode.
343 * Dirs are always fetched in their entirety for now */
344 ObtainSharedLock(&adp->lock, 801);
345 ObtainReadLock(&tdc->lock);
348 * Make sure that the data in the cache is current. There are two
349 * cases we need to worry about:
350 * 1. The cache data is being fetched by another process.
351 * 2. The cache data is no longer valid
353 while ((adp->f.states & CStatd)
354 && (tdc->dflags & DFFetching)
355 && hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
356 ReleaseReadLock(&tdc->lock);
357 ReleaseSharedLock(&adp->lock);
358 afs_osi_Sleep(&tdc->validPos);
359 ObtainSharedLock(&adp->lock, 802);
360 ObtainReadLock(&tdc->lock);
362 if (!(adp->f.states & CStatd)
363 || !hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
364 ReleaseReadLock(&tdc->lock);
365 ReleaseSharedLock(&adp->lock);
367 #ifdef OSI_EXPORT_DEBUG
368 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): dir changed; retrying\n",
369 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
370 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
375 /* lookup the name in the appropriate dir, and return a cache entry
376 * on the resulting fid */
377 code = afs_dir_Lookup(tdc, "..", &tfid.Fid);
379 ReleaseReadLock(&tdc->lock);
383 UpgradeSToWLock(&adp->lock, 803);
384 adp->f.parent.vnode = tfid.Fid.Vnode;
385 adp->f.parent.unique = tfid.Fid.Unique;
387 #ifdef OSI_EXPORT_DEBUG
389 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): afs_dir_Lookup: %d\n",
390 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
391 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
393 printk("afs: update_dir_parent(0x%08x/%d/%d.%d) => %d.%d\n",
394 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
395 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique,
396 adp->parent.vnode, adp->parent.unique);
399 ReleaseSharedLock(&adp->lock);
404 static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
406 struct VenusFid tfid;
411 if (!afs_fakestat_enable)
414 if (*vcpp == afs_globalVp || vType(*vcpp) != VDIR || (*vcpp)->mvstat != 2)
417 /* Figure out what FID to look for */
418 tvp = afs_GetVolume(&(*vcpp)->f.fid, 0, READ_LOCK);
420 #ifdef OSI_EXPORT_DEBUG
421 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n",
422 (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume,
423 (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique);
428 afs_PutVolume(tvp, READ_LOCK);
430 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
432 #ifdef OSI_EXPORT_DEBUG
433 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
434 (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume,
435 (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique,
436 tfid.Cell, tfid.Fid.Volume,
437 tfid.Fid.Vnode, tfid.Fid.Unique);
442 if (afs_fakestat_enable == 2) {
443 ObtainWriteLock(&tvc->lock, 806);
444 code = afs_HandleLink(tvc, areq);
446 ReleaseWriteLock(&tvc->lock);
450 if (!strchr(tvc->linkData, ':')) {
451 ReleaseWriteLock(&tvc->lock);
455 ReleaseWriteLock(&tvc->lock);
458 afs_PutVCache(*vcpp);
465 * Given a FID, obtain or construct a dentry, or return an error.
466 * This should be called with the BKL and AFS_GLOCK held.
468 static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
470 struct vrequest treq;
477 code = afs_InitReq(&treq, credp);
479 #ifdef OSI_EXPORT_DEBUG
480 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
481 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
484 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
486 vcp = afs_GetVCache(afid, &treq, NULL, NULL);
488 #ifdef OSI_EXPORT_DEBUG
489 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
490 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
496 * Now, it might be that we just caused a directory vnode to
497 * spring into existence, in which case its parent FID is unset.
498 * We need to do something about that, but only because we care
499 * in our own get_parent(), below -- the common code never looks
500 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
501 * So, if this fails, we don't really care very much.
503 if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->f.parent.vnode)
504 update_dir_parent(&treq, vcp);
507 * If this is a volume root directory and fakestat is enabled,
508 * we might need to replace the directory by a mount point.
510 code = UnEvalFakeStat(&treq, &vcp);
512 #ifdef OSI_EXPORT_DEBUG
513 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
514 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
518 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
522 afs_getattr(vcp, &vattr, credp);
523 afs_fill_inode(ip, &vattr);
525 /* d_alloc_anon might block, so we shouldn't hold the glock */
527 dp = d_alloc_anon(ip);
532 #ifdef OSI_EXPORT_DEBUG
533 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
534 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
536 return ERR_PTR(-ENOMEM);
539 dp->d_op = &afs_dentry_operations;
543 static struct dentry *afs_export_get_dentry(struct super_block *sb,
553 dp = get_dentry_from_fid(credp, inump);
563 static int get_name_hook(void *hdata, char *name,
564 afs_int32 vnode, afs_int32 unique)
566 struct get_name_data *data = (struct get_name_data *)hdata;
569 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
571 if (len > NAME_MAX) len = NAME_MAX;
572 memcpy(data->name, name, len);
573 data->name[len] = '\0';
579 static int afs_export_get_name(struct dentry *parent, char *name,
580 struct dentry *child)
582 struct afs_fakestat_state fakestate;
583 struct get_name_data data;
584 struct vrequest treq;
589 afs_size_t dirOffset, dirLen;
592 if (!parent->d_inode) {
593 #ifdef OSI_EXPORT_DEBUG
594 /* can't lookup name in a negative dentry */
595 printk("afs: get_name(%s, %s): no parent inode\n",
596 parent->d_name.name ? (char *)parent->d_name.name : "?",
597 child->d_name.name ? (char *)child->d_name.name : "?");
601 if (!child->d_inode) {
602 #ifdef OSI_EXPORT_DEBUG
603 /* can't find the FID of negative dentry */
604 printk("afs: get_name(%s, %s): no child inode\n",
605 parent->d_name.name ? (char *)parent->d_name.name : "?",
606 child->d_name.name ? (char *)child->d_name.name : "?");
611 afs_InitFakeStat(&fakestate);
617 vcp = VTOAFS(child->d_inode);
619 /* special case dynamic mount directory */
620 if (afs_IsDynrootMount(vcp)) {
621 #ifdef OSI_EXPORT_DEBUG
622 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
623 parent->d_name.name ? (char *)parent->d_name.name : "?",
624 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
625 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
627 data.fid = vcp->f.fid;
628 if (VTOAFS(parent->d_inode) == afs_globalVp)
629 strcpy(name, AFS_DYNROOT_MOUNTNAME);
635 /* Figure out what FID to look for */
636 if (vcp->mvstat == 2) { /* volume root */
637 tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
639 #ifdef OSI_EXPORT_DEBUG
640 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
641 parent->d_name.name ? (char *)parent->d_name.name : "?",
642 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
643 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
648 data.fid = tvp->mtpoint;
649 afs_PutVolume(tvp, READ_LOCK);
651 data.fid = vcp->f.fid;
654 vcp = VTOAFS(parent->d_inode);
655 #ifdef OSI_EXPORT_DEBUG
656 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
657 parent->d_name.name ? (char *)parent->d_name.name : "?",
658 data.fid.Cell, data.fid.Fid.Volume,
659 data.fid.Fid.Vnode, data.fid.Fid.Unique,
660 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
661 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
664 code = afs_InitReq(&treq, credp);
666 #ifdef OSI_EXPORT_DEBUG
667 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n",
668 parent->d_name.name ? (char *)parent->d_name.name : "?",
669 data.fid.Cell, data.fid.Fid.Volume,
670 data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
675 /* a dynamic mount point in the dynamic mount directory */
676 if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
677 && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
678 #ifdef OSI_EXPORT_DEBUG
679 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
680 parent->d_name.name ? (char *)parent->d_name.name : "?",
681 data.fid.Cell, data.fid.Fid.Volume,
682 data.fid.Fid.Vnode, data.fid.Fid.Unique);
684 vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
686 ObtainReadLock(&vcp->lock);
687 if (strlen(vcp->linkData + 1) <= NAME_MAX)
688 strcpy(name, vcp->linkData + 1);
691 ReleaseReadLock(&vcp->lock);
694 #ifdef OSI_EXPORT_DEBUG
695 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
696 parent->d_name.name ? (char *)parent->d_name.name : "?",
697 data.fid.Cell, data.fid.Fid.Volume,
698 data.fid.Fid.Vnode, data.fid.Fid.Unique);
705 code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
709 if (vcp->f.fid.Cell != data.fid.Cell ||
710 vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) {
711 /* parent is not the expected cell and volume; thus it
712 * cannot possibly contain the fid we are looking for */
713 #ifdef OSI_EXPORT_DEBUG
714 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
715 parent->d_name.name ? (char *)parent->d_name.name : "?",
716 data.fid.Cell, data.fid.Fid.Volume,
717 data.fid.Fid.Vnode, data.fid.Fid.Unique,
718 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume);
726 if (!(vcp->f.states & CStatd)) {
727 if ((code = afs_VerifyVCache2(vcp, &treq))) {
728 #ifdef OSI_EXPORT_DEBUG
729 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
730 parent->d_name.name ? (char *)parent->d_name.name : "?",
731 data.fid.Cell, data.fid.Fid.Volume,
732 data.fid.Fid.Vnode, data.fid.Fid.Unique,
733 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
734 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
740 tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
742 #ifdef OSI_EXPORT_DEBUG
743 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
744 parent->d_name.name ? (char *)parent->d_name.name : "?",
745 data.fid.Cell, data.fid.Fid.Volume,
746 data.fid.Fid.Vnode, data.fid.Fid.Unique,
747 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
748 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
754 ObtainReadLock(&vcp->lock);
755 ObtainReadLock(&tdc->lock);
758 * Make sure that the data in the cache is current. There are two
759 * cases we need to worry about:
760 * 1. The cache data is being fetched by another process.
761 * 2. The cache data is no longer valid
763 while ((vcp->f.states & CStatd)
764 && (tdc->dflags & DFFetching)
765 && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
766 ReleaseReadLock(&tdc->lock);
767 ReleaseReadLock(&vcp->lock);
768 afs_osi_Sleep(&tdc->validPos);
769 ObtainReadLock(&vcp->lock);
770 ObtainReadLock(&tdc->lock);
772 if (!(vcp->f.states & CStatd)
773 || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
774 ReleaseReadLock(&tdc->lock);
775 ReleaseReadLock(&vcp->lock);
777 #ifdef OSI_EXPORT_DEBUG
778 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
779 parent->d_name.name ? (char *)parent->d_name.name : "?",
780 data.fid.Cell, data.fid.Fid.Volume,
781 data.fid.Fid.Vnode, data.fid.Fid.Unique,
782 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
783 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
790 code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
791 if (!code && !data.found) {
792 #ifdef OSI_EXPORT_DEBUG
793 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
794 parent->d_name.name ? (char *)parent->d_name.name : "?",
795 data.fid.Cell, data.fid.Fid.Volume,
796 data.fid.Fid.Vnode, data.fid.Fid.Unique);
800 #ifdef OSI_EXPORT_DEBUG
801 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
802 parent->d_name.name ? (char *)parent->d_name.name : "?",
803 data.fid.Cell, data.fid.Fid.Volume,
804 data.fid.Fid.Vnode, data.fid.Fid.Unique,
805 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
806 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
810 ReleaseReadLock(&tdc->lock);
811 ReleaseReadLock(&vcp->lock);
816 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
817 parent->d_name.name ? (char *)parent->d_name.name : "?",
818 data.fid.Cell, data.fid.Fid.Volume,
819 data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
821 afs_PutFakeStat(&fakestate);
825 code = afs_CheckCode(code, &treq, 102);
830 static struct dentry *afs_export_get_parent(struct dentry *child)
832 struct VenusFid tfid;
833 struct vrequest treq;
836 struct dentry *dp = NULL;
841 if (!child->d_inode) {
842 /* can't find the parent of a negative dentry */
843 #ifdef OSI_EXPORT_DEBUG
844 printk("afs: get_parent(%s): no inode\n",
845 child->d_name.name ? (char *)child->d_name.name : "?");
847 return ERR_PTR(-EIO);
854 vcp = VTOAFS(child->d_inode);
856 if (afs_IsDynrootMount(vcp)) {
857 /* the dynmount directory; parent is always the AFS root */
858 tfid = afs_globalVp->f.fid;
860 } else if (afs_IsDynrootAny(vcp) &&
861 VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
862 /* a mount point in the dynmount directory */
863 afs_GetDynrootMountFid(&tfid);
865 } else if (vcp->mvstat == 2) {
867 ObtainReadLock(&vcp->lock);
868 if (vcp->mvid && vcp->mvid->Fid.Volume) {
870 ReleaseReadLock(&vcp->lock);
872 ReleaseReadLock(&vcp->lock);
873 tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
875 #ifdef OSI_EXPORT_DEBUG
876 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
877 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
878 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
880 dp = ERR_PTR(-ENOENT);
884 cellidx = tcell->cellIndex;
885 afs_PutCell(tcell, READ_LOCK);
887 afs_GetDynrootMountFid(&tfid);
888 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
889 tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
893 /* any other vnode */
894 if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) {
895 code = afs_InitReq(&treq, credp);
897 #ifdef OSI_EXPORT_DEBUG
898 printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
899 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
900 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
902 dp = ERR_PTR(-ENOENT);
905 code = update_dir_parent(&treq, vcp);
907 #ifdef OSI_EXPORT_DEBUG
908 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
909 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
910 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
912 dp = ERR_PTR(-ENOENT);
918 tfid.Cell = vcp->f.fid.Cell;
919 tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
920 tfid.Fid.Vnode = vcp->f.parent.vnode;
921 tfid.Fid.Unique = vcp->f.parent.unique;
924 #ifdef OSI_EXPORT_DEBUG
925 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
926 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
927 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
928 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
931 dp = get_dentry_from_fid(credp, &tfid);
933 #ifdef OSI_EXPORT_DEBUG
934 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
935 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
936 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
938 dp = ERR_PTR(-ENOENT);
950 struct export_operations afs_export_ops = {
951 .encode_fh = afs_encode_fh,
952 #if defined(NEW_EXPORT_OPS)
953 .fh_to_dentry = afs_fh_to_dentry,
955 .decode_fh = afs_decode_fh,
956 .get_dentry = afs_export_get_dentry,
958 .get_name = afs_export_get_name,
959 .get_parent = afs_export_get_parent,