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 EXPORTFS_H_EXISTS
21 #include <linux/exportfs.h>
23 #include "afs/sysincludes.h"
24 #include "afsincludes.h"
25 #include "afs/afs_dynroot.h"
26 #include <linux/smp_lock.h>
28 #if !defined(AFS_NONFSTRANS)
30 /* #define OSI_EXPORT_DEBUG */
32 extern struct dentry_operations afs_dentry_operations;
33 #if defined(NEW_EXPORT_OPS)
34 static struct dentry *afs_export_get_dentry(struct super_block *sb,
38 struct get_name_data {
45 * Linux reserved the following filehandle types:
46 * - 0 is always the filesystem root; NFS deals with this for us
47 * - 1,2 are reserved by Linux for inode-number-based filehandles
48 * - 0xff is reserved by linux
50 * We encode filehandles for AFS files using the types defined below.
51 * Internally, our "object ID" is a VenusFid; if we get a filehandle
52 * with a more-stable cell ID, we'll turn it into a cell number in
53 * the decode_fh wrapper.
56 #define AFSFH_VENUSFID 0xa0 /* cell, volume, vnode, uniq */
57 #define AFSFH_CELLFID 0xa1 /* cellhandle, volume, vnode, uniq */
58 #define AFSFH_NET_VENUSFID 0xa2 /* net cell, volume, vnode, uniq */
59 #define AFSFH_NET_CELLFID 0xa3 /* net cellhandle, volume, vnode, uniq */
60 #define AFSFH_DYN_RO_CELL 0xd0 /* cellhandle for RO root.cell mount */
61 #define AFSFH_DYN_RW_CELL 0xd1 /* cellhandle for RW root.cell mount */
62 #define AFSFH_DYN_RO_LINK 0xd2 /* cellhandle for RO root.cell symlink */
63 #define AFSFH_DYN_RW_LINK 0xd3 /* cellhandle for RW root.cell symlink */
64 #define AFSFH_DYN_MOUNT 0xd4 /* cellhandle, volume for mount point */
65 #define AFSFH_DYN_SYMLINK 0xd5 /* hash of dynroot symlink target */
67 static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
74 if (!de->d_inode) /* encode a negative dentry?! */
76 if (*max_len < 4) /* not enough space */
79 tvc = VTOAFS(de->d_inode);
81 #ifdef OSI_EXPORT_DEBUG
82 printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
83 tvc->f.fid.Cell, tvc->f.fid.Fid.Volume,
84 tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique);
86 if (afs_IsDynrootAnyFid(&tvc->f.fid)) {
87 vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode);
90 /* encode as a normal filehandle */
102 tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode),
108 memcpy((void *)fh, tc->cellHandle, 16);
109 afs_PutCell(tc, READ_LOCK);
111 if (vntype == VN_TYPE_MOUNT) {
112 fh[4] = htonl(tvc->f.fid.Fid.Unique);
114 return AFSFH_DYN_MOUNT;
117 if (vntype == VN_TYPE_CELL) {
118 return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
120 return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
123 case VN_TYPE_SYMLINK:
124 /* XXX fill in filehandle for dynroot symlink */
125 /* XXX return AFSFH_DYN_SYMLINK; */
133 /* not big enough for a migratable filehandle */
134 /* always encode in network order */
135 fh[0] = htonl(tvc->f.fid.Cell);
136 fh[1] = htonl(tvc->f.fid.Fid.Volume);
137 fh[2] = htonl(tvc->f.fid.Fid.Vnode);
138 fh[3] = htonl(tvc->f.fid.Fid.Unique);
140 return AFSFH_NET_VENUSFID;
144 tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK);
149 memcpy((void *)fh, tc->cellHandle, 16);
150 afs_PutCell(tc, READ_LOCK);
152 /* always encode in network order */
153 fh[4] = htonl(tvc->f.fid.Fid.Volume);
154 fh[5] = htonl(tvc->f.fid.Fid.Vnode);
155 fh[6] = htonl(tvc->f.fid.Fid.Unique);
158 return AFSFH_NET_CELLFID;
161 #if defined(NEW_EXPORT_OPS)
162 static struct dentry *afs_fh_to_dentry(struct super_block *sb, struct fid *fh_fid,
163 int fh_len, int fh_type)
165 static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
166 int fh_len, int fh_type,
167 int (*acceptable)(void *, struct dentry *),
173 struct dentry *result;
174 #if defined(NEW_EXPORT_OPS)
175 __u32 *fh = (__u32 *)fh_fid->raw;
184 fid.Fid.Volume = fh[1];
185 fid.Fid.Vnode = fh[2];
186 fid.Fid.Unique = fh[3];
193 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
198 fid.Cell = tc->cellNum;
199 fid.Fid.Volume = fh[4];
200 fid.Fid.Vnode = fh[5];
201 fid.Fid.Unique = fh[6];
202 afs_PutCell(tc, READ_LOCK);
206 case AFSFH_NET_VENUSFID:
207 fid.Cell = ntohl(fh[0]);
208 fid.Fid.Volume = ntohl(fh[1]);
209 fid.Fid.Vnode = ntohl(fh[2]);
210 fid.Fid.Unique = ntohl(fh[3]);
213 case AFSFH_NET_CELLFID:
217 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
222 fid.Cell = tc->cellNum;
223 fid.Fid.Volume = ntohl(fh[4]);
224 fid.Fid.Vnode = ntohl(fh[5]);
225 fid.Fid.Unique = ntohl(fh[6]);
226 afs_PutCell(tc, READ_LOCK);
230 case AFSFH_DYN_RO_CELL:
231 case AFSFH_DYN_RW_CELL:
235 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
240 afs_GetDynrootFid(&fid);
241 fid.Fid.Vnode = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
243 afs_PutCell(tc, READ_LOCK);
247 case AFSFH_DYN_RO_LINK:
248 case AFSFH_DYN_RW_LINK:
252 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
257 afs_GetDynrootFid(&fid);
258 fid.Fid.Vnode = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
260 afs_PutCell(tc, READ_LOCK);
264 case AFSFH_DYN_MOUNT:
268 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
273 afs_GetDynrootFid(&fid);
274 fid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
276 fid.Fid.Unique = ntohl(fh[4]);
277 afs_PutCell(tc, READ_LOCK);
281 case AFSFH_DYN_SYMLINK:
282 /* XXX parse dynroot symlink filehandle */
289 #if defined(NEW_EXPORT_OPS)
290 result = afs_export_get_dentry(sb, &fid);
292 result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
293 acceptable, context);
297 #ifdef OSI_EXPORT_DEBUG
299 printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
300 fid.Cell, fid.Fid.Volume,
301 fid.Fid.Vnode, fid.Fid.Unique);
302 } else if (IS_ERR(result)) {
303 printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
304 fid.Cell, fid.Fid.Volume,
305 fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
311 static int update_dir_parent(struct vrequest *areq, struct vcache *adp)
313 struct VenusFid tfid;
315 afs_size_t dirOffset, dirLen;
319 if (!(adp->f.states & CStatd)) {
320 if ((code = afs_VerifyVCache2(adp, areq))) {
321 #ifdef OSI_EXPORT_DEBUG
322 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): VerifyVCache2: %d\n",
323 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
324 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
330 tdc = afs_GetDCache(adp, (afs_size_t) 0, areq, &dirOffset, &dirLen, 1);
332 #ifdef OSI_EXPORT_DEBUG
333 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): no dcache\n",
334 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
335 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
340 /* now we will just call dir package with appropriate inode.
341 * Dirs are always fetched in their entirety for now */
342 ObtainSharedLock(&adp->lock, 801);
343 ObtainReadLock(&tdc->lock);
346 * Make sure that the data in the cache is current. There are two
347 * cases we need to worry about:
348 * 1. The cache data is being fetched by another process.
349 * 2. The cache data is no longer valid
351 while ((adp->f.states & CStatd)
352 && (tdc->dflags & DFFetching)
353 && hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
354 ReleaseReadLock(&tdc->lock);
355 ReleaseSharedLock(&adp->lock);
356 afs_osi_Sleep(&tdc->validPos);
357 ObtainSharedLock(&adp->lock, 802);
358 ObtainReadLock(&tdc->lock);
360 if (!(adp->f.states & CStatd)
361 || !hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
362 ReleaseReadLock(&tdc->lock);
363 ReleaseSharedLock(&adp->lock);
365 #ifdef OSI_EXPORT_DEBUG
366 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): dir changed; retrying\n",
367 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
368 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
373 /* lookup the name in the appropriate dir, and return a cache entry
374 * on the resulting fid */
375 code = afs_dir_Lookup(tdc, "..", &tfid.Fid);
377 ReleaseReadLock(&tdc->lock);
381 UpgradeSToWLock(&adp->lock, 803);
382 adp->f.parent.vnode = tfid.Fid.Vnode;
383 adp->f.parent.unique = tfid.Fid.Unique;
385 #ifdef OSI_EXPORT_DEBUG
387 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): afs_dir_Lookup: %d\n",
388 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
389 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
391 printk("afs: update_dir_parent(0x%08x/%d/%d.%d) => %d.%d\n",
392 adp->f.fid.Cell, adp->f.fid.Fid.Volume,
393 adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique,
394 adp->parent.vnode, adp->parent.unique);
397 ReleaseSharedLock(&adp->lock);
402 static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
404 struct VenusFid tfid;
409 if (!afs_fakestat_enable)
412 if (*vcpp == afs_globalVp || vType(*vcpp) != VDIR || (*vcpp)->mvstat != 2)
415 /* Figure out what FID to look for */
416 tvp = afs_GetVolume(&(*vcpp)->f.fid, 0, READ_LOCK);
418 #ifdef OSI_EXPORT_DEBUG
419 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n",
420 (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume,
421 (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique);
426 afs_PutVolume(tvp, READ_LOCK);
428 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
430 #ifdef OSI_EXPORT_DEBUG
431 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
432 (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume,
433 (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique,
434 tfid.Cell, tfid.Fid.Volume,
435 tfid.Fid.Vnode, tfid.Fid.Unique);
440 if (afs_fakestat_enable == 2) {
441 ObtainWriteLock(&tvc->lock, 806);
442 code = afs_HandleLink(tvc, areq);
444 ReleaseWriteLock(&tvc->lock);
448 if (!strchr(tvc->linkData, ':')) {
449 ReleaseWriteLock(&tvc->lock);
453 ReleaseWriteLock(&tvc->lock);
456 afs_PutVCache(*vcpp);
463 * Given a FID, obtain or construct a dentry, or return an error.
464 * This should be called with the BKL and AFS_GLOCK held.
466 static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
468 struct vrequest treq;
475 code = afs_InitReq(&treq, credp);
477 #ifdef OSI_EXPORT_DEBUG
478 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
479 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
482 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
484 vcp = afs_GetVCache(afid, &treq, NULL, NULL);
486 #ifdef OSI_EXPORT_DEBUG
487 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
488 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
494 * Now, it might be that we just caused a directory vnode to
495 * spring into existence, in which case its parent FID is unset.
496 * We need to do something about that, but only because we care
497 * in our own get_parent(), below -- the common code never looks
498 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
499 * So, if this fails, we don't really care very much.
501 if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->f.parent.vnode)
502 update_dir_parent(&treq, vcp);
505 * If this is a volume root directory and fakestat is enabled,
506 * we might need to replace the directory by a mount point.
508 code = UnEvalFakeStat(&treq, &vcp);
510 #ifdef OSI_EXPORT_DEBUG
511 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
512 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
516 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
520 afs_getattr(vcp, &vattr, credp);
521 afs_fill_inode(ip, &vattr);
523 /* d_alloc_anon might block, so we shouldn't hold the glock */
525 dp = d_alloc_anon(ip);
530 #ifdef OSI_EXPORT_DEBUG
531 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
532 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
534 return ERR_PTR(-ENOMEM);
537 dp->d_op = &afs_dentry_operations;
541 static struct dentry *afs_export_get_dentry(struct super_block *sb,
551 dp = get_dentry_from_fid(credp, inump);
561 static int get_name_hook(void *hdata, char *name,
562 afs_int32 vnode, afs_int32 unique)
564 struct get_name_data *data = (struct get_name_data *)hdata;
567 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
569 if (len > NAME_MAX) len = NAME_MAX;
570 memcpy(data->name, name, len);
571 data->name[len] = '\0';
577 static int afs_export_get_name(struct dentry *parent, char *name,
578 struct dentry *child)
580 struct afs_fakestat_state fakestate;
581 struct get_name_data data;
582 struct vrequest treq;
587 afs_size_t dirOffset, dirLen;
590 if (!parent->d_inode) {
591 #ifdef OSI_EXPORT_DEBUG
592 /* can't lookup name in a negative dentry */
593 printk("afs: get_name(%s, %s): no parent inode\n",
594 parent->d_name.name ? (char *)parent->d_name.name : "?",
595 child->d_name.name ? (char *)child->d_name.name : "?");
599 if (!child->d_inode) {
600 #ifdef OSI_EXPORT_DEBUG
601 /* can't find the FID of negative dentry */
602 printk("afs: get_name(%s, %s): no child inode\n",
603 parent->d_name.name ? (char *)parent->d_name.name : "?",
604 child->d_name.name ? (char *)child->d_name.name : "?");
609 afs_InitFakeStat(&fakestate);
615 vcp = VTOAFS(child->d_inode);
617 /* special case dynamic mount directory */
618 if (afs_IsDynrootMount(vcp)) {
619 #ifdef OSI_EXPORT_DEBUG
620 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
621 parent->d_name.name ? (char *)parent->d_name.name : "?",
622 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
623 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
625 data.fid = vcp->f.fid;
626 if (VTOAFS(parent->d_inode) == afs_globalVp)
627 strcpy(name, AFS_DYNROOT_MOUNTNAME);
633 /* Figure out what FID to look for */
634 if (vcp->mvstat == 2) { /* volume root */
635 tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
637 #ifdef OSI_EXPORT_DEBUG
638 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
639 parent->d_name.name ? (char *)parent->d_name.name : "?",
640 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
641 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
646 data.fid = tvp->mtpoint;
647 afs_PutVolume(tvp, READ_LOCK);
649 data.fid = vcp->f.fid;
652 vcp = VTOAFS(parent->d_inode);
653 #ifdef OSI_EXPORT_DEBUG
654 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
655 parent->d_name.name ? (char *)parent->d_name.name : "?",
656 data.fid.Cell, data.fid.Fid.Volume,
657 data.fid.Fid.Vnode, data.fid.Fid.Unique,
658 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
659 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
662 code = afs_InitReq(&treq, credp);
664 #ifdef OSI_EXPORT_DEBUG
665 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %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, code);
673 /* a dynamic mount point in the dynamic mount directory */
674 if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
675 && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
676 #ifdef OSI_EXPORT_DEBUG
677 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
678 parent->d_name.name ? (char *)parent->d_name.name : "?",
679 data.fid.Cell, data.fid.Fid.Volume,
680 data.fid.Fid.Vnode, data.fid.Fid.Unique);
682 vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
684 ObtainReadLock(&vcp->lock);
685 if (strlen(vcp->linkData + 1) <= NAME_MAX)
686 strcpy(name, vcp->linkData + 1);
689 ReleaseReadLock(&vcp->lock);
692 #ifdef OSI_EXPORT_DEBUG
693 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
694 parent->d_name.name ? (char *)parent->d_name.name : "?",
695 data.fid.Cell, data.fid.Fid.Volume,
696 data.fid.Fid.Vnode, data.fid.Fid.Unique);
703 code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
707 if (vcp->f.fid.Cell != data.fid.Cell ||
708 vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) {
709 /* parent is not the expected cell and volume; thus it
710 * cannot possibly contain the fid we are looking for */
711 #ifdef OSI_EXPORT_DEBUG
712 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
713 parent->d_name.name ? (char *)parent->d_name.name : "?",
714 data.fid.Cell, data.fid.Fid.Volume,
715 data.fid.Fid.Vnode, data.fid.Fid.Unique,
716 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume);
724 if (!(vcp->f.states & CStatd)) {
725 if ((code = afs_VerifyVCache2(vcp, &treq))) {
726 #ifdef OSI_EXPORT_DEBUG
727 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
728 parent->d_name.name ? (char *)parent->d_name.name : "?",
729 data.fid.Cell, data.fid.Fid.Volume,
730 data.fid.Fid.Vnode, data.fid.Fid.Unique,
731 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
732 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
738 tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
740 #ifdef OSI_EXPORT_DEBUG
741 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
742 parent->d_name.name ? (char *)parent->d_name.name : "?",
743 data.fid.Cell, data.fid.Fid.Volume,
744 data.fid.Fid.Vnode, data.fid.Fid.Unique,
745 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
746 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
752 ObtainReadLock(&vcp->lock);
753 ObtainReadLock(&tdc->lock);
756 * Make sure that the data in the cache is current. There are two
757 * cases we need to worry about:
758 * 1. The cache data is being fetched by another process.
759 * 2. The cache data is no longer valid
761 while ((vcp->f.states & CStatd)
762 && (tdc->dflags & DFFetching)
763 && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
764 ReleaseReadLock(&tdc->lock);
765 ReleaseReadLock(&vcp->lock);
766 afs_osi_Sleep(&tdc->validPos);
767 ObtainReadLock(&vcp->lock);
768 ObtainReadLock(&tdc->lock);
770 if (!(vcp->f.states & CStatd)
771 || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
772 ReleaseReadLock(&tdc->lock);
773 ReleaseReadLock(&vcp->lock);
775 #ifdef OSI_EXPORT_DEBUG
776 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
777 parent->d_name.name ? (char *)parent->d_name.name : "?",
778 data.fid.Cell, data.fid.Fid.Volume,
779 data.fid.Fid.Vnode, data.fid.Fid.Unique,
780 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
781 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
788 code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
789 if (!code && !data.found) {
790 #ifdef OSI_EXPORT_DEBUG
791 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
792 parent->d_name.name ? (char *)parent->d_name.name : "?",
793 data.fid.Cell, data.fid.Fid.Volume,
794 data.fid.Fid.Vnode, data.fid.Fid.Unique);
798 #ifdef OSI_EXPORT_DEBUG
799 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
800 parent->d_name.name ? (char *)parent->d_name.name : "?",
801 data.fid.Cell, data.fid.Fid.Volume,
802 data.fid.Fid.Vnode, data.fid.Fid.Unique,
803 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
804 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
808 ReleaseReadLock(&tdc->lock);
809 ReleaseReadLock(&vcp->lock);
814 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
815 parent->d_name.name ? (char *)parent->d_name.name : "?",
816 data.fid.Cell, data.fid.Fid.Volume,
817 data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
819 afs_PutFakeStat(&fakestate);
823 code = afs_CheckCode(code, &treq, 102);
828 static struct dentry *afs_export_get_parent(struct dentry *child)
830 struct VenusFid tfid;
831 struct vrequest treq;
834 struct dentry *dp = NULL;
839 if (!child->d_inode) {
840 /* can't find the parent of a negative dentry */
841 #ifdef OSI_EXPORT_DEBUG
842 printk("afs: get_parent(%s): no inode\n",
843 child->d_name.name ? (char *)child->d_name.name : "?");
845 return ERR_PTR(-EIO);
852 vcp = VTOAFS(child->d_inode);
854 if (afs_IsDynrootMount(vcp)) {
855 /* the dynmount directory; parent is always the AFS root */
856 tfid = afs_globalVp->f.fid;
858 } else if (afs_IsDynrootAny(vcp) &&
859 VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
860 /* a mount point in the dynmount directory */
861 afs_GetDynrootMountFid(&tfid);
863 } else if (vcp->mvstat == 2) {
865 ObtainReadLock(&vcp->lock);
866 if (vcp->mvid && vcp->mvid->Fid.Volume) {
868 ReleaseReadLock(&vcp->lock);
870 ReleaseReadLock(&vcp->lock);
871 tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
873 #ifdef OSI_EXPORT_DEBUG
874 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
875 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
876 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
878 dp = ERR_PTR(-ENOENT);
882 cellidx = tcell->cellIndex;
883 afs_PutCell(tcell, READ_LOCK);
885 afs_GetDynrootMountFid(&tfid);
886 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
887 tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
891 /* any other vnode */
892 if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) {
893 code = afs_InitReq(&treq, credp);
895 #ifdef OSI_EXPORT_DEBUG
896 printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
897 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
898 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
900 dp = ERR_PTR(-ENOENT);
903 code = update_dir_parent(&treq, vcp);
905 #ifdef OSI_EXPORT_DEBUG
906 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
907 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
908 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
910 dp = ERR_PTR(-ENOENT);
916 tfid.Cell = vcp->f.fid.Cell;
917 tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
918 tfid.Fid.Vnode = vcp->f.parent.vnode;
919 tfid.Fid.Unique = vcp->f.parent.unique;
922 #ifdef OSI_EXPORT_DEBUG
923 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
924 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
925 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
926 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
929 dp = get_dentry_from_fid(credp, &tfid);
931 #ifdef OSI_EXPORT_DEBUG
932 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
933 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
934 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
936 dp = ERR_PTR(-ENOENT);
948 struct export_operations afs_export_ops = {
949 .encode_fh = afs_encode_fh,
950 #if defined(NEW_EXPORT_OPS)
951 .fh_to_dentry = afs_fh_to_dentry,
953 .decode_fh = afs_decode_fh,
954 .get_dentry = afs_export_get_dentry,
956 .get_name = afs_export_get_name,
957 .get_parent = afs_export_get_parent,