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"
18 #include <linux/module.h> /* early to avoid printf->printk mapping */
20 #ifdef HAVE_LINUX_EXPORTFS_H
21 #include <linux/exportfs.h>
23 #include "afs/sysincludes.h"
24 #include "afsincludes.h"
25 #include "afs/afs_dynroot.h"
27 #if !defined(AFS_NONFSTRANS)
29 /* #define OSI_EXPORT_DEBUG */
31 extern struct dentry_operations afs_dentry_operations;
32 #if defined(NEW_EXPORT_OPS)
33 static struct dentry *afs_export_get_dentry(struct super_block *sb,
37 struct get_name_data {
44 * Linux reserved the following filehandle types:
45 * - 0 is always the filesystem root; NFS deals with this for us
46 * - 1,2 are reserved by Linux for inode-number-based filehandles
47 * - 0xff is reserved by linux
49 * We encode filehandles for AFS files using the types defined below.
50 * Internally, our "object ID" is a VenusFid; if we get a filehandle
51 * with a more-stable cell ID, we'll turn it into a cell number in
52 * the decode_fh wrapper.
55 #define AFSFH_VENUSFID 0xa0 /* cell, volume, vnode, uniq */
56 #define AFSFH_CELLFID 0xa1 /* cellhandle, volume, vnode, uniq */
57 #define AFSFH_NET_VENUSFID 0xa2 /* net cell, volume, vnode, uniq */
58 #define AFSFH_NET_CELLFID 0xa3 /* net cellhandle, volume, vnode, uniq */
59 #define AFSFH_DYN_RO_CELL 0xd0 /* cellhandle for RO root.cell mount */
60 #define AFSFH_DYN_RW_CELL 0xd1 /* cellhandle for RW root.cell mount */
61 #define AFSFH_DYN_RO_LINK 0xd2 /* cellhandle for RO root.cell symlink */
62 #define AFSFH_DYN_RW_LINK 0xd3 /* cellhandle for RW root.cell symlink */
63 #define AFSFH_DYN_MOUNT 0xd4 /* cellhandle, volume for mount point */
64 #define AFSFH_DYN_SYMLINK 0xd5 /* hash of dynroot symlink target */
66 static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
73 if (!de->d_inode) /* encode a negative dentry?! */
75 if (*max_len < 4) /* not enough space */
78 tvc = VTOAFS(de->d_inode);
80 #ifdef OSI_EXPORT_DEBUG
81 printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
82 tvc->f.fid.Cell, tvc->f.fid.Fid.Volume,
83 tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique);
85 if (afs_IsDynrootAnyFid(&tvc->f.fid)) {
86 vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode);
89 /* encode as a normal filehandle */
101 tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode),
107 memcpy((void *)fh, tc->cellHandle, 16);
108 afs_PutCell(tc, READ_LOCK);
110 if (vntype == VN_TYPE_MOUNT) {
111 fh[4] = htonl(tvc->f.fid.Fid.Unique);
113 return AFSFH_DYN_MOUNT;
116 if (vntype == VN_TYPE_CELL) {
117 return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
119 return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
122 case VN_TYPE_SYMLINK:
123 /* XXX fill in filehandle for dynroot symlink */
124 /* XXX return AFSFH_DYN_SYMLINK; */
132 /* not big enough for a migratable filehandle */
133 /* always encode in network order */
134 fh[0] = htonl(tvc->f.fid.Cell);
135 fh[1] = htonl(tvc->f.fid.Fid.Volume);
136 fh[2] = htonl(tvc->f.fid.Fid.Vnode);
137 fh[3] = htonl(tvc->f.fid.Fid.Unique);
139 return AFSFH_NET_VENUSFID;
143 tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK);
148 memcpy((void *)fh, tc->cellHandle, 16);
149 afs_PutCell(tc, READ_LOCK);
151 /* always encode in network order */
152 fh[4] = htonl(tvc->f.fid.Fid.Volume);
153 fh[5] = htonl(tvc->f.fid.Fid.Vnode);
154 fh[6] = htonl(tvc->f.fid.Fid.Unique);
157 return AFSFH_NET_CELLFID;
160 #if defined(NEW_EXPORT_OPS)
161 static struct dentry *afs_fh_to_dentry(struct super_block *sb, struct fid *fh_fid,
162 int fh_len, int fh_type)
164 static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
165 int fh_len, int fh_type,
166 int (*acceptable)(void *, struct dentry *),
172 struct dentry *result;
173 #if defined(NEW_EXPORT_OPS)
174 __u32 *fh = (__u32 *)fh_fid->raw;
183 fid.Fid.Volume = fh[1];
184 fid.Fid.Vnode = fh[2];
185 fid.Fid.Unique = fh[3];
192 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
197 fid.Cell = tc->cellNum;
198 fid.Fid.Volume = fh[4];
199 fid.Fid.Vnode = fh[5];
200 fid.Fid.Unique = fh[6];
201 afs_PutCell(tc, READ_LOCK);
205 case AFSFH_NET_VENUSFID:
206 fid.Cell = ntohl(fh[0]);
207 fid.Fid.Volume = ntohl(fh[1]);
208 fid.Fid.Vnode = ntohl(fh[2]);
209 fid.Fid.Unique = ntohl(fh[3]);
212 case AFSFH_NET_CELLFID:
216 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
221 fid.Cell = tc->cellNum;
222 fid.Fid.Volume = ntohl(fh[4]);
223 fid.Fid.Vnode = ntohl(fh[5]);
224 fid.Fid.Unique = ntohl(fh[6]);
225 afs_PutCell(tc, READ_LOCK);
229 case AFSFH_DYN_RO_CELL:
230 case AFSFH_DYN_RW_CELL:
234 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
239 afs_GetDynrootFid(&fid);
240 fid.Fid.Vnode = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
242 afs_PutCell(tc, READ_LOCK);
246 case AFSFH_DYN_RO_LINK:
247 case AFSFH_DYN_RW_LINK:
251 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
256 afs_GetDynrootFid(&fid);
257 fid.Fid.Vnode = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
259 afs_PutCell(tc, READ_LOCK);
263 case AFSFH_DYN_MOUNT:
267 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
272 afs_GetDynrootFid(&fid);
273 fid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
275 fid.Fid.Unique = ntohl(fh[4]);
276 afs_PutCell(tc, READ_LOCK);
280 case AFSFH_DYN_SYMLINK:
281 /* XXX parse dynroot symlink filehandle */
288 #if defined(NEW_EXPORT_OPS)
289 result = afs_export_get_dentry(sb, &fid);
291 result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
292 acceptable, context);
296 #ifdef OSI_EXPORT_DEBUG
298 printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
299 fid.Cell, fid.Fid.Volume,
300 fid.Fid.Vnode, fid.Fid.Unique);
301 } else if (IS_ERR(result)) {
302 printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
303 fid.Cell, fid.Fid.Volume,
304 fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
310 static int update_dir_parent(struct vrequest *areq, struct vcache *adp)
312 struct VenusFid tfid;
314 afs_size_t dirOffset, dirLen;
318 if (!(adp->f.states & CStatd)) {
319 if ((code = afs_VerifyVCache2(adp, areq))) {
320 #ifdef OSI_EXPORT_DEBUG
321 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): VerifyVCache2: %d\n",
322 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
323 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
329 tdc = afs_GetDCache(adp, (afs_size_t) 0, areq, &dirOffset, &dirLen, 1);
331 #ifdef OSI_EXPORT_DEBUG
332 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): no dcache\n",
333 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
334 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
339 /* now we will just call dir package with appropriate inode.
340 * Dirs are always fetched in their entirety for now */
341 ObtainSharedLock(&adp->lock, 801);
342 ObtainReadLock(&tdc->lock);
345 * Make sure that the data in the cache is current. There are two
346 * cases we need to worry about:
347 * 1. The cache data is being fetched by another process.
348 * 2. The cache data is no longer valid
350 while ((adp->f.states & CStatd)
351 && (tdc->dflags & DFFetching)
352 && hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
353 ReleaseReadLock(&tdc->lock);
354 ReleaseSharedLock(&adp->lock);
355 afs_osi_Sleep(&tdc->validPos);
356 ObtainSharedLock(&adp->lock, 802);
357 ObtainReadLock(&tdc->lock);
359 if (!(adp->f.states & CStatd)
360 || !hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
361 ReleaseReadLock(&tdc->lock);
362 ReleaseSharedLock(&adp->lock);
364 #ifdef OSI_EXPORT_DEBUG
365 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): dir changed; retrying\n",
366 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
367 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
372 /* lookup the name in the appropriate dir, and return a cache entry
373 * on the resulting fid */
374 code = afs_dir_Lookup(tdc, "..", &tfid.Fid);
376 ReleaseReadLock(&tdc->lock);
380 UpgradeSToWLock(&adp->lock, 803);
381 adp->f.parent.vnode = tfid.Fid.Vnode;
382 adp->f.parent.unique = tfid.Fid.Unique;
384 #ifdef OSI_EXPORT_DEBUG
386 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): afs_dir_Lookup: %d\n",
387 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
388 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
390 printk("afs: update_dir_parent(0x%08x/%d/%d.%d) => %d.%d\n",
391 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
392 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique,
393 adp->parent.vnode, adp->parent.unique);
396 ReleaseSharedLock(&adp->lock);
401 static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
403 struct VenusFid tfid;
408 if (!afs_fakestat_enable)
411 if (*vcpp == afs_globalVp || vType(*vcpp) != VDIR || (*vcpp)->mvstat != AFS_MVSTAT_ROOT)
414 /* Figure out what FID to look for */
415 tvp = afs_GetVolume(&(*vcpp)->f.fid, 0, READ_LOCK);
417 #ifdef OSI_EXPORT_DEBUG
418 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n",
419 (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume,
420 (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique);
425 afs_PutVolume(tvp, READ_LOCK);
427 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
429 #ifdef OSI_EXPORT_DEBUG
430 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
431 (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume,
432 (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique,
433 tfid.Cell, tfid.Fid.Volume,
434 tfid.Fid.Vnode, tfid.Fid.Unique);
439 if (afs_fakestat_enable == 2) {
440 ObtainWriteLock(&tvc->lock, 806);
441 code = afs_HandleLink(tvc, areq);
443 ReleaseWriteLock(&tvc->lock);
447 if (!strchr(tvc->linkData, ':')) {
448 ReleaseWriteLock(&tvc->lock);
452 ReleaseWriteLock(&tvc->lock);
455 afs_PutVCache(*vcpp);
462 * Given a FID, obtain or construct a dentry, or return an error.
463 * This should be called with the BKL and AFS_GLOCK held.
465 static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
467 struct vrequest *treq = NULL;
469 struct vattr *vattr = NULL;
474 code = afs_CreateAttr(&vattr);
476 return ERR_PTR(-afs_CheckCode(code, NULL, 104));
479 code = afs_CreateReq(&treq, credp);
481 #ifdef OSI_EXPORT_DEBUG
482 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
483 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
486 afs_DestroyAttr(vattr);
487 return ERR_PTR(-afs_CheckCode(code, NULL, 101));
489 vcp = afs_GetVCache(afid, treq, NULL, NULL);
491 #ifdef OSI_EXPORT_DEBUG
492 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
493 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
495 afs_DestroyReq(treq);
496 afs_DestroyAttr(vattr);
501 * Now, it might be that we just caused a directory vnode to
502 * spring into existence, in which case its parent FID is unset.
503 * We need to do something about that, but only because we care
504 * in our own get_parent(), below -- the common code never looks
505 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
506 * So, if this fails, we don't really care very much.
508 if (vType(vcp) == VDIR && vcp->mvstat != AFS_MVSTAT_ROOT && !vcp->f.parent.vnode)
509 update_dir_parent(treq, vcp);
512 * If this is a volume root directory and fakestat is enabled,
513 * we might need to replace the directory by a mount point.
515 code = UnEvalFakeStat(treq, &vcp);
517 #ifdef OSI_EXPORT_DEBUG
518 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
519 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
523 code = afs_CheckCode(code, treq, 103);
524 afs_DestroyReq(treq);
525 afs_DestroyAttr(vattr);
526 return ERR_PTR(-code);
530 afs_getattr(vcp, vattr, credp);
531 afs_fill_inode(ip, vattr);
533 /* d_alloc_anon might block, so we shouldn't hold the glock */
535 dp = d_alloc_anon(ip);
540 #ifdef OSI_EXPORT_DEBUG
541 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
542 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
544 afs_DestroyReq(treq);
545 afs_DestroyAttr(vattr);
546 return ERR_PTR(-ENOMEM);
549 dp->d_op = &afs_dentry_operations;
550 afs_DestroyReq(treq);
551 afs_DestroyAttr(vattr);
555 static struct dentry *afs_export_get_dentry(struct super_block *sb,
564 dp = get_dentry_from_fid(credp, inump);
573 static int get_name_hook(void *hdata, char *name,
574 afs_int32 vnode, afs_int32 unique)
576 struct get_name_data *data = (struct get_name_data *)hdata;
579 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
581 if (len > NAME_MAX) len = NAME_MAX;
582 memcpy(data->name, name, len);
583 data->name[len] = '\0';
589 static int afs_export_get_name(struct dentry *parent, char *name,
590 struct dentry *child)
592 struct afs_fakestat_state fakestate;
593 struct get_name_data data;
594 struct vrequest *treq = NULL;
599 afs_size_t dirOffset, dirLen;
602 if (!parent->d_inode) {
603 #ifdef OSI_EXPORT_DEBUG
604 /* can't lookup name in a negative dentry */
605 printk("afs: get_name(%s, %s): no parent inode\n",
606 parent->d_name.name ? (char *)parent->d_name.name : "?",
607 child->d_name.name ? (char *)child->d_name.name : "?");
611 if (!child->d_inode) {
612 #ifdef OSI_EXPORT_DEBUG
613 /* can't find the FID of negative dentry */
614 printk("afs: get_name(%s, %s): no child inode\n",
615 parent->d_name.name ? (char *)parent->d_name.name : "?",
616 child->d_name.name ? (char *)child->d_name.name : "?");
621 afs_InitFakeStat(&fakestate);
626 vcp = VTOAFS(child->d_inode);
628 /* special case dynamic mount directory */
629 if (afs_IsDynrootMount(vcp)) {
630 #ifdef OSI_EXPORT_DEBUG
631 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
632 parent->d_name.name ? (char *)parent->d_name.name : "?",
633 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
634 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
636 data.fid = vcp->f.fid;
637 if (VTOAFS(parent->d_inode) == afs_globalVp)
638 strcpy(name, AFS_DYNROOT_MOUNTNAME);
644 /* Figure out what FID to look for */
645 if (vcp->mvstat == AFS_MVSTAT_ROOT) { /* volume root */
646 tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
648 #ifdef OSI_EXPORT_DEBUG
649 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
650 parent->d_name.name ? (char *)parent->d_name.name : "?",
651 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
652 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
657 data.fid = tvp->mtpoint;
658 afs_PutVolume(tvp, READ_LOCK);
660 data.fid = vcp->f.fid;
663 vcp = VTOAFS(parent->d_inode);
664 #ifdef OSI_EXPORT_DEBUG
665 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
666 parent->d_name.name ? (char *)parent->d_name.name : "?",
667 data.fid.Cell, data.fid.Fid.Volume,
668 data.fid.Fid.Vnode, data.fid.Fid.Unique,
669 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
670 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
672 code = afs_CreateReq(&treq, credp);
674 #ifdef OSI_EXPORT_DEBUG
675 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
676 parent->d_name.name ? (char *)parent->d_name.name : "?",
677 data.fid.Cell, data.fid.Fid.Volume,
678 data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
683 /* a dynamic mount point in the dynamic mount directory */
684 if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
685 && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
686 #ifdef OSI_EXPORT_DEBUG
687 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
688 parent->d_name.name ? (char *)parent->d_name.name : "?",
689 data.fid.Cell, data.fid.Fid.Volume,
690 data.fid.Fid.Vnode, data.fid.Fid.Unique);
692 vcp = afs_GetVCache(&data.fid, treq, NULL, NULL);
694 ObtainReadLock(&vcp->lock);
695 if (strlen(vcp->linkData + 1) <= NAME_MAX)
696 strcpy(name, vcp->linkData + 1);
699 ReleaseReadLock(&vcp->lock);
702 #ifdef OSI_EXPORT_DEBUG
703 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
704 parent->d_name.name ? (char *)parent->d_name.name : "?",
705 data.fid.Cell, data.fid.Fid.Volume,
706 data.fid.Fid.Vnode, data.fid.Fid.Unique);
713 code = afs_EvalFakeStat(&vcp, &fakestate, treq);
717 if (vcp->f.fid.Cell != data.fid.Cell ||
718 vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) {
719 /* parent is not the expected cell and volume; thus it
720 * cannot possibly contain the fid we are looking for */
721 #ifdef OSI_EXPORT_DEBUG
722 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
723 parent->d_name.name ? (char *)parent->d_name.name : "?",
724 data.fid.Cell, data.fid.Fid.Volume,
725 data.fid.Fid.Vnode, data.fid.Fid.Unique,
726 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume);
734 if (!(vcp->f.states & CStatd)) {
735 if ((code = afs_VerifyVCache2(vcp, treq))) {
736 #ifdef OSI_EXPORT_DEBUG
737 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
738 parent->d_name.name ? (char *)parent->d_name.name : "?",
739 data.fid.Cell, data.fid.Fid.Volume,
740 data.fid.Fid.Vnode, data.fid.Fid.Unique,
741 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
742 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
748 tdc = afs_GetDCache(vcp, (afs_size_t) 0, treq, &dirOffset, &dirLen, 1);
750 #ifdef OSI_EXPORT_DEBUG
751 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
752 parent->d_name.name ? (char *)parent->d_name.name : "?",
753 data.fid.Cell, data.fid.Fid.Volume,
754 data.fid.Fid.Vnode, data.fid.Fid.Unique,
755 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
756 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
762 ObtainReadLock(&vcp->lock);
763 ObtainReadLock(&tdc->lock);
766 * Make sure that the data in the cache is current. There are two
767 * cases we need to worry about:
768 * 1. The cache data is being fetched by another process.
769 * 2. The cache data is no longer valid
771 while ((vcp->f.states & CStatd)
772 && (tdc->dflags & DFFetching)
773 && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
774 ReleaseReadLock(&tdc->lock);
775 ReleaseReadLock(&vcp->lock);
776 afs_osi_Sleep(&tdc->validPos);
777 ObtainReadLock(&vcp->lock);
778 ObtainReadLock(&tdc->lock);
780 if (!(vcp->f.states & CStatd)
781 || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
782 ReleaseReadLock(&tdc->lock);
783 ReleaseReadLock(&vcp->lock);
785 #ifdef OSI_EXPORT_DEBUG
786 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
787 parent->d_name.name ? (char *)parent->d_name.name : "?",
788 data.fid.Cell, data.fid.Fid.Volume,
789 data.fid.Fid.Vnode, data.fid.Fid.Unique,
790 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
791 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
798 code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
799 if (!code && !data.found) {
800 #ifdef OSI_EXPORT_DEBUG
801 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\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);
808 #ifdef OSI_EXPORT_DEBUG
809 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
810 parent->d_name.name ? (char *)parent->d_name.name : "?",
811 data.fid.Cell, data.fid.Fid.Volume,
812 data.fid.Fid.Vnode, data.fid.Fid.Unique,
813 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
814 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
818 ReleaseReadLock(&tdc->lock);
819 ReleaseReadLock(&vcp->lock);
824 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
825 parent->d_name.name ? (char *)parent->d_name.name : "?",
826 data.fid.Cell, data.fid.Fid.Volume,
827 data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
829 afs_PutFakeStat(&fakestate);
830 code = afs_CheckCode(code, treq, 102);
831 afs_DestroyReq(treq);
838 static struct dentry *afs_export_get_parent(struct dentry *child)
840 struct VenusFid tfid;
841 struct vrequest *treq = NULL;
844 struct dentry *dp = NULL;
849 if (!child->d_inode) {
850 /* can't find the parent of a negative dentry */
851 #ifdef OSI_EXPORT_DEBUG
852 printk("afs: get_parent(%s): no inode\n",
853 child->d_name.name ? (char *)child->d_name.name : "?");
855 return ERR_PTR(-EIO);
861 vcp = VTOAFS(child->d_inode);
863 if (afs_IsDynrootMount(vcp)) {
864 /* the dynmount directory; parent is always the AFS root */
865 tfid = afs_globalVp->f.fid;
867 } else if (afs_IsDynrootAny(vcp) &&
868 VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
869 /* a mount point in the dynmount directory */
870 afs_GetDynrootMountFid(&tfid);
872 } else if (vcp->mvstat == AFS_MVSTAT_ROOT) {
874 ObtainReadLock(&vcp->lock);
875 if (vcp->mvid.parent && vcp->mvid.parent->Fid.Volume) {
876 tfid = *vcp->mvid.parent;
877 ReleaseReadLock(&vcp->lock);
879 ReleaseReadLock(&vcp->lock);
880 tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
882 #ifdef OSI_EXPORT_DEBUG
883 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
884 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
885 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
887 dp = ERR_PTR(-ENOENT);
891 cellidx = tcell->cellIndex;
892 afs_PutCell(tcell, READ_LOCK);
894 afs_GetDynrootMountFid(&tfid);
895 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
896 tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
900 /* any other vnode */
901 if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != AFS_MVSTAT_MTPT) {
902 code = afs_CreateReq(&treq, credp);
904 #ifdef OSI_EXPORT_DEBUG
905 printk("afs: get_parent(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
906 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
907 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
909 dp = ERR_PTR(-ENOENT);
912 code = update_dir_parent(treq, vcp);
914 #ifdef OSI_EXPORT_DEBUG
915 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
916 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
917 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
919 dp = ERR_PTR(-ENOENT);
925 tfid.Cell = vcp->f.fid.Cell;
926 tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
927 tfid.Fid.Vnode = vcp->f.parent.vnode;
928 tfid.Fid.Unique = vcp->f.parent.unique;
931 #ifdef OSI_EXPORT_DEBUG
932 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
933 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
934 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
935 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
938 dp = get_dentry_from_fid(credp, &tfid);
940 #ifdef OSI_EXPORT_DEBUG
941 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
942 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
943 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
945 dp = ERR_PTR(-ENOENT);
949 afs_DestroyReq(treq);
957 struct export_operations afs_export_ops = {
958 .encode_fh = afs_encode_fh,
959 #if defined(NEW_EXPORT_OPS)
960 .fh_to_dentry = afs_fh_to_dentry,
962 .decode_fh = afs_decode_fh,
963 .get_dentry = afs_export_get_dentry,
965 .get_name = afs_export_get_name,
966 .get_parent = afs_export_get_parent,