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 != 2)
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;
474 code = afs_InitReq(&treq, credp);
476 #ifdef OSI_EXPORT_DEBUG
477 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
478 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
481 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
483 vcp = afs_GetVCache(afid, &treq, NULL, NULL);
485 #ifdef OSI_EXPORT_DEBUG
486 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
487 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
493 * Now, it might be that we just caused a directory vnode to
494 * spring into existence, in which case its parent FID is unset.
495 * We need to do something about that, but only because we care
496 * in our own get_parent(), below -- the common code never looks
497 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
498 * So, if this fails, we don't really care very much.
500 if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->f.parent.vnode)
501 update_dir_parent(&treq, vcp);
504 * If this is a volume root directory and fakestat is enabled,
505 * we might need to replace the directory by a mount point.
507 code = UnEvalFakeStat(&treq, &vcp);
509 #ifdef OSI_EXPORT_DEBUG
510 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
511 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
515 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
519 afs_getattr(vcp, &vattr, credp);
520 afs_fill_inode(ip, &vattr);
522 /* d_alloc_anon might block, so we shouldn't hold the glock */
524 dp = d_alloc_anon(ip);
529 #ifdef OSI_EXPORT_DEBUG
530 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
531 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
533 return ERR_PTR(-ENOMEM);
536 dp->d_op = &afs_dentry_operations;
540 static struct dentry *afs_export_get_dentry(struct super_block *sb,
549 dp = get_dentry_from_fid(credp, inump);
558 static int get_name_hook(void *hdata, char *name,
559 afs_int32 vnode, afs_int32 unique)
561 struct get_name_data *data = (struct get_name_data *)hdata;
564 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
566 if (len > NAME_MAX) len = NAME_MAX;
567 memcpy(data->name, name, len);
568 data->name[len] = '\0';
574 static int afs_export_get_name(struct dentry *parent, char *name,
575 struct dentry *child)
577 struct afs_fakestat_state fakestate;
578 struct get_name_data data;
579 struct vrequest treq;
584 afs_size_t dirOffset, dirLen;
587 if (!parent->d_inode) {
588 #ifdef OSI_EXPORT_DEBUG
589 /* can't lookup name in a negative dentry */
590 printk("afs: get_name(%s, %s): no parent inode\n",
591 parent->d_name.name ? (char *)parent->d_name.name : "?",
592 child->d_name.name ? (char *)child->d_name.name : "?");
596 if (!child->d_inode) {
597 #ifdef OSI_EXPORT_DEBUG
598 /* can't find the FID of negative dentry */
599 printk("afs: get_name(%s, %s): no child inode\n",
600 parent->d_name.name ? (char *)parent->d_name.name : "?",
601 child->d_name.name ? (char *)child->d_name.name : "?");
606 afs_InitFakeStat(&fakestate);
611 vcp = VTOAFS(child->d_inode);
613 /* special case dynamic mount directory */
614 if (afs_IsDynrootMount(vcp)) {
615 #ifdef OSI_EXPORT_DEBUG
616 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
617 parent->d_name.name ? (char *)parent->d_name.name : "?",
618 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
619 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
621 data.fid = vcp->f.fid;
622 if (VTOAFS(parent->d_inode) == afs_globalVp)
623 strcpy(name, AFS_DYNROOT_MOUNTNAME);
629 /* Figure out what FID to look for */
630 if (vcp->mvstat == 2) { /* volume root */
631 tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
633 #ifdef OSI_EXPORT_DEBUG
634 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
635 parent->d_name.name ? (char *)parent->d_name.name : "?",
636 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
637 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
642 data.fid = tvp->mtpoint;
643 afs_PutVolume(tvp, READ_LOCK);
645 data.fid = vcp->f.fid;
648 vcp = VTOAFS(parent->d_inode);
649 #ifdef OSI_EXPORT_DEBUG
650 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
651 parent->d_name.name ? (char *)parent->d_name.name : "?",
652 data.fid.Cell, data.fid.Fid.Volume,
653 data.fid.Fid.Vnode, data.fid.Fid.Unique,
654 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
655 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
658 code = afs_InitReq(&treq, credp);
660 #ifdef OSI_EXPORT_DEBUG
661 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n",
662 parent->d_name.name ? (char *)parent->d_name.name : "?",
663 data.fid.Cell, data.fid.Fid.Volume,
664 data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
669 /* a dynamic mount point in the dynamic mount directory */
670 if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
671 && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
672 #ifdef OSI_EXPORT_DEBUG
673 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
674 parent->d_name.name ? (char *)parent->d_name.name : "?",
675 data.fid.Cell, data.fid.Fid.Volume,
676 data.fid.Fid.Vnode, data.fid.Fid.Unique);
678 vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
680 ObtainReadLock(&vcp->lock);
681 if (strlen(vcp->linkData + 1) <= NAME_MAX)
682 strcpy(name, vcp->linkData + 1);
685 ReleaseReadLock(&vcp->lock);
688 #ifdef OSI_EXPORT_DEBUG
689 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
690 parent->d_name.name ? (char *)parent->d_name.name : "?",
691 data.fid.Cell, data.fid.Fid.Volume,
692 data.fid.Fid.Vnode, data.fid.Fid.Unique);
699 code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
703 if (vcp->f.fid.Cell != data.fid.Cell ||
704 vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) {
705 /* parent is not the expected cell and volume; thus it
706 * cannot possibly contain the fid we are looking for */
707 #ifdef OSI_EXPORT_DEBUG
708 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
709 parent->d_name.name ? (char *)parent->d_name.name : "?",
710 data.fid.Cell, data.fid.Fid.Volume,
711 data.fid.Fid.Vnode, data.fid.Fid.Unique,
712 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume);
720 if (!(vcp->f.states & CStatd)) {
721 if ((code = afs_VerifyVCache2(vcp, &treq))) {
722 #ifdef OSI_EXPORT_DEBUG
723 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
724 parent->d_name.name ? (char *)parent->d_name.name : "?",
725 data.fid.Cell, data.fid.Fid.Volume,
726 data.fid.Fid.Vnode, data.fid.Fid.Unique,
727 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
728 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
734 tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
736 #ifdef OSI_EXPORT_DEBUG
737 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(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 ObtainReadLock(&vcp->lock);
749 ObtainReadLock(&tdc->lock);
752 * Make sure that the data in the cache is current. There are two
753 * cases we need to worry about:
754 * 1. The cache data is being fetched by another process.
755 * 2. The cache data is no longer valid
757 while ((vcp->f.states & CStatd)
758 && (tdc->dflags & DFFetching)
759 && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
760 ReleaseReadLock(&tdc->lock);
761 ReleaseReadLock(&vcp->lock);
762 afs_osi_Sleep(&tdc->validPos);
763 ObtainReadLock(&vcp->lock);
764 ObtainReadLock(&tdc->lock);
766 if (!(vcp->f.states & CStatd)
767 || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
768 ReleaseReadLock(&tdc->lock);
769 ReleaseReadLock(&vcp->lock);
771 #ifdef OSI_EXPORT_DEBUG
772 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
773 parent->d_name.name ? (char *)parent->d_name.name : "?",
774 data.fid.Cell, data.fid.Fid.Volume,
775 data.fid.Fid.Vnode, data.fid.Fid.Unique,
776 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
777 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
784 code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
785 if (!code && !data.found) {
786 #ifdef OSI_EXPORT_DEBUG
787 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
788 parent->d_name.name ? (char *)parent->d_name.name : "?",
789 data.fid.Cell, data.fid.Fid.Volume,
790 data.fid.Fid.Vnode, data.fid.Fid.Unique);
794 #ifdef OSI_EXPORT_DEBUG
795 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
796 parent->d_name.name ? (char *)parent->d_name.name : "?",
797 data.fid.Cell, data.fid.Fid.Volume,
798 data.fid.Fid.Vnode, data.fid.Fid.Unique,
799 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
800 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
804 ReleaseReadLock(&tdc->lock);
805 ReleaseReadLock(&vcp->lock);
810 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
811 parent->d_name.name ? (char *)parent->d_name.name : "?",
812 data.fid.Cell, data.fid.Fid.Volume,
813 data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
815 afs_PutFakeStat(&fakestate);
818 code = afs_CheckCode(code, &treq, 102);
823 static struct dentry *afs_export_get_parent(struct dentry *child)
825 struct VenusFid tfid;
826 struct vrequest treq;
829 struct dentry *dp = NULL;
834 if (!child->d_inode) {
835 /* can't find the parent of a negative dentry */
836 #ifdef OSI_EXPORT_DEBUG
837 printk("afs: get_parent(%s): no inode\n",
838 child->d_name.name ? (char *)child->d_name.name : "?");
840 return ERR_PTR(-EIO);
846 vcp = VTOAFS(child->d_inode);
848 if (afs_IsDynrootMount(vcp)) {
849 /* the dynmount directory; parent is always the AFS root */
850 tfid = afs_globalVp->f.fid;
852 } else if (afs_IsDynrootAny(vcp) &&
853 VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
854 /* a mount point in the dynmount directory */
855 afs_GetDynrootMountFid(&tfid);
857 } else if (vcp->mvstat == 2) {
859 ObtainReadLock(&vcp->lock);
860 if (vcp->mvid && vcp->mvid->Fid.Volume) {
862 ReleaseReadLock(&vcp->lock);
864 ReleaseReadLock(&vcp->lock);
865 tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
867 #ifdef OSI_EXPORT_DEBUG
868 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
869 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
870 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
872 dp = ERR_PTR(-ENOENT);
876 cellidx = tcell->cellIndex;
877 afs_PutCell(tcell, READ_LOCK);
879 afs_GetDynrootMountFid(&tfid);
880 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
881 tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
885 /* any other vnode */
886 if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) {
887 code = afs_InitReq(&treq, credp);
889 #ifdef OSI_EXPORT_DEBUG
890 printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
891 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
892 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
894 dp = ERR_PTR(-ENOENT);
897 code = update_dir_parent(&treq, vcp);
899 #ifdef OSI_EXPORT_DEBUG
900 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
901 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
902 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
904 dp = ERR_PTR(-ENOENT);
910 tfid.Cell = vcp->f.fid.Cell;
911 tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
912 tfid.Fid.Vnode = vcp->f.parent.vnode;
913 tfid.Fid.Unique = vcp->f.parent.unique;
916 #ifdef OSI_EXPORT_DEBUG
917 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
918 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
919 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
920 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
923 dp = get_dentry_from_fid(credp, &tfid);
925 #ifdef OSI_EXPORT_DEBUG
926 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
927 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
928 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
930 dp = ERR_PTR(-ENOENT);
941 struct export_operations afs_export_ops = {
942 .encode_fh = afs_encode_fh,
943 #if defined(NEW_EXPORT_OPS)
944 .fh_to_dentry = afs_fh_to_dentry,
946 .decode_fh = afs_decode_fh,
947 .get_dentry = afs_export_get_dentry,
949 .get_name = afs_export_get_name,
950 .get_parent = afs_export_get_parent,