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 /* #define OSI_EXPORT_DEBUG */
32 extern struct dentry_operations afs_dentry_operations;
34 struct get_name_data {
41 * Linux reserved the following filehandle types:
42 * - 0 is always the filesystem root; NFS deals with this for us
43 * - 1,2 are reserved by Linux for inode-number-based filehandles
44 * - 0xff is reserved by linux
46 * We encode filehandles for AFS files using the types defined below.
47 * Internally, our "object ID" is a VenusFid; if we get a filehandle
48 * with a more-stable cell ID, we'll turn it into a cell number in
49 * the decode_fh wrapper.
52 #define AFSFH_VENUSFID 0xa0 /* cell, volume, vnode, uniq */
53 #define AFSFH_CELLFID 0xa1 /* cellhandle, volume, vnode, uniq */
54 #define AFSFH_NET_VENUSFID 0xa2 /* net cell, volume, vnode, uniq */
55 #define AFSFH_NET_CELLFID 0xa3 /* net cellhandle, volume, vnode, uniq */
56 #define AFSFH_DYN_RO_CELL 0xd0 /* cellhandle for RO root.cell mount */
57 #define AFSFH_DYN_RW_CELL 0xd1 /* cellhandle for RW root.cell mount */
58 #define AFSFH_DYN_RO_LINK 0xd2 /* cellhandle for RO root.cell symlink */
59 #define AFSFH_DYN_RW_LINK 0xd3 /* cellhandle for RW root.cell symlink */
60 #define AFSFH_DYN_MOUNT 0xd4 /* cellhandle, volume for mount point */
61 #define AFSFH_DYN_SYMLINK 0xd5 /* hash of dynroot symlink target */
63 static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
70 if (!de->d_inode) /* encode a negative dentry?! */
72 if (*max_len < 4) /* not enough space */
75 tvc = VTOAFS(de->d_inode);
77 #ifdef OSI_EXPORT_DEBUG
78 printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
79 tvc->fid.Cell, tvc->fid.Fid.Volume,
80 tvc->fid.Fid.Vnode, tvc->fid.Fid.Unique);
82 if (afs_IsDynrootAnyFid(&tvc->fid)) {
83 vntype = VNUM_TO_VNTYPE(tvc->fid.Fid.Vnode);
86 /* encode as a normal filehandle */
98 tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->fid.Fid.Vnode),
104 memcpy((void *)fh, tc->cellHandle, 16);
105 afs_PutCell(tc, READ_LOCK);
107 if (vntype == VN_TYPE_MOUNT) {
108 fh[4] = htonl(tvc->fid.Fid.Unique);
110 return AFSFH_DYN_MOUNT;
113 if (vntype == VN_TYPE_CELL) {
114 return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->fid.Fid.Vnode);
116 return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->fid.Fid.Vnode);
119 case VN_TYPE_SYMLINK:
120 /* XXX fill in filehandle for dynroot symlink */
121 /* XXX return AFSFH_DYN_SYMLINK; */
129 /* not big enough for a migratable filehandle */
130 /* always encode in network order */
131 fh[0] = htonl(tvc->fid.Cell);
132 fh[1] = htonl(tvc->fid.Fid.Volume);
133 fh[2] = htonl(tvc->fid.Fid.Vnode);
134 fh[3] = htonl(tvc->fid.Fid.Unique);
136 return AFSFH_NET_VENUSFID;
140 tc = afs_GetCell(tvc->fid.Cell, READ_LOCK);
145 memcpy((void *)fh, tc->cellHandle, 16);
146 afs_PutCell(tc, READ_LOCK);
148 /* always encode in network order */
149 fh[4] = htonl(tvc->fid.Fid.Volume);
150 fh[5] = htonl(tvc->fid.Fid.Vnode);
151 fh[6] = htonl(tvc->fid.Fid.Unique);
154 return AFSFH_NET_CELLFID;
157 static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
158 int fh_len, int fh_type,
159 int (*acceptable)(void *, struct dentry *),
164 struct dentry *result;
171 fid.Fid.Volume = fh[1];
172 fid.Fid.Vnode = fh[2];
173 fid.Fid.Unique = fh[3];
180 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
185 fid.Cell = tc->cellNum;
186 fid.Fid.Volume = fh[4];
187 fid.Fid.Vnode = fh[5];
188 fid.Fid.Unique = fh[6];
189 afs_PutCell(tc, READ_LOCK);
193 case AFSFH_NET_VENUSFID:
196 fid.Cell = ntohl(fh[0]);
197 fid.Fid.Volume = ntohl(fh[1]);
198 fid.Fid.Vnode = ntohl(fh[2]);
199 fid.Fid.Unique = ntohl(fh[3]);
202 case AFSFH_NET_CELLFID:
206 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
211 fid.Cell = tc->cellNum;
212 fid.Fid.Volume = ntohl(fh[4]);
213 fid.Fid.Vnode = ntohl(fh[5]);
214 fid.Fid.Unique = ntohl(fh[6]);
215 afs_PutCell(tc, READ_LOCK);
219 case AFSFH_DYN_RO_CELL:
220 case AFSFH_DYN_RW_CELL:
224 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
229 afs_GetDynrootFid(&fid);
230 fid.Fid.Vnode = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
232 afs_PutCell(tc, READ_LOCK);
236 case AFSFH_DYN_RO_LINK:
237 case AFSFH_DYN_RW_LINK:
241 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
246 afs_GetDynrootFid(&fid);
247 fid.Fid.Vnode = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
249 afs_PutCell(tc, READ_LOCK);
253 case AFSFH_DYN_MOUNT:
257 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
262 afs_GetDynrootFid(&fid);
263 fid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
265 fid.Fid.Unique = ntohl(fh[4]);
266 afs_PutCell(tc, READ_LOCK);
270 case AFSFH_DYN_SYMLINK:
271 /* XXX parse dynroot symlink filehandle */
278 result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
279 acceptable, context);
280 #ifdef OSI_EXPORT_DEBUG
282 printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
283 fid.Cell, fid.Fid.Volume,
284 fid.Fid.Vnode, fid.Fid.Unique);
285 } else if (IS_ERR(result)) {
286 printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
287 fid.Cell, fid.Fid.Volume,
288 fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
294 static int update_dir_parent(struct vrequest *areq, struct vcache *adp)
296 struct VenusFid tfid;
298 afs_size_t dirOffset, dirLen;
302 if (!(adp->states & CStatd)) {
303 if ((code = afs_VerifyVCache2(adp, areq))) {
304 #ifdef OSI_EXPORT_DEBUG
305 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): VerifyVCache2: %d\n",
306 adp->fid.Cell, adp->fid.Fid.Volume,
307 adp->fid.Fid.Vnode, adp->fid.Fid.Unique, code);
313 tdc = afs_GetDCache(adp, (afs_size_t) 0, areq, &dirOffset, &dirLen, 1);
315 #ifdef OSI_EXPORT_DEBUG
316 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): no dcache\n",
317 adp->fid.Cell, adp->fid.Fid.Volume,
318 adp->fid.Fid.Vnode, adp->fid.Fid.Unique);
323 /* now we will just call dir package with appropriate inode.
324 * Dirs are always fetched in their entirety for now */
325 ObtainSharedLock(&adp->lock, 801);
326 ObtainReadLock(&tdc->lock);
329 * Make sure that the data in the cache is current. There are two
330 * cases we need to worry about:
331 * 1. The cache data is being fetched by another process.
332 * 2. The cache data is no longer valid
334 while ((adp->states & CStatd)
335 && (tdc->dflags & DFFetching)
336 && hsame(adp->m.DataVersion, tdc->f.versionNo)) {
337 ReleaseReadLock(&tdc->lock);
338 ReleaseSharedLock(&adp->lock);
339 afs_osi_Sleep(&tdc->validPos);
340 ObtainSharedLock(&adp->lock, 802);
341 ObtainReadLock(&tdc->lock);
343 if (!(adp->states & CStatd)
344 || !hsame(adp->m.DataVersion, tdc->f.versionNo)) {
345 ReleaseReadLock(&tdc->lock);
346 ReleaseSharedLock(&adp->lock);
348 #ifdef OSI_EXPORT_DEBUG
349 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): dir changed; retrying\n",
350 adp->fid.Cell, adp->fid.Fid.Volume,
351 adp->fid.Fid.Vnode, adp->fid.Fid.Unique);
356 /* lookup the name in the appropriate dir, and return a cache entry
357 * on the resulting fid */
358 code = afs_dir_Lookup(tdc, "..", &tfid.Fid);
360 ReleaseReadLock(&tdc->lock);
364 UpgradeSToWLock(&adp->lock, 803);
365 adp->parentVnode = tfid.Fid.Vnode;
366 adp->parentUnique = tfid.Fid.Unique;
368 #ifdef OSI_EXPORT_DEBUG
370 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): afs_dir_Lookup: %d\n",
371 adp->fid.Cell, adp->fid.Fid.Volume,
372 adp->fid.Fid.Vnode, adp->fid.Fid.Unique, code);
374 printk("afs: update_dir_parent(0x%08x/%d/%d.%d) => %d.%d\n",
375 adp->fid.Cell, adp->fid.Fid.Volume,
376 adp->fid.Fid.Vnode, adp->fid.Fid.Unique,
377 adp->parentVnode, adp->parentUnique);
380 ReleaseSharedLock(&adp->lock);
385 static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
387 struct VenusFid tfid;
392 if (!afs_fakestat_enable)
395 if (*vcpp == afs_globalVp || vType(*vcpp) != VDIR || (*vcpp)->mvstat != 2)
398 /* Figure out what FID to look for */
399 tvp = afs_GetVolume(&(*vcpp)->fid, 0, READ_LOCK);
401 #ifdef OSI_EXPORT_DEBUG
402 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n",
403 (*vcpp)->fid.Cell, (*vcpp)->fid.Fid.Volume,
404 (*vcpp)->fid.Fid.Vnode, (*vcpp)->fid.Fid.Unique);
409 afs_PutVolume(tvp, READ_LOCK);
411 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
413 #ifdef OSI_EXPORT_DEBUG
414 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
415 (*vcpp)->fid.Cell, (*vcpp)->fid.Fid.Volume,
416 (*vcpp)->fid.Fid.Vnode, (*vcpp)->fid.Fid.Unique,
417 tfid.Cell, tfid.Fid.Volume,
418 tfid.Fid.Vnode, tfid.Fid.Unique);
423 if (afs_fakestat_enable == 2) {
424 ObtainWriteLock(&tvc->lock, 806);
425 code = afs_HandleLink(tvc, areq);
427 ReleaseWriteLock(&tvc->lock);
431 if (!strchr(tvc->linkData, ':')) {
432 ReleaseWriteLock(&tvc->lock);
436 ReleaseWriteLock(&tvc->lock);
439 afs_PutVCache(*vcpp);
446 * Given a FID, obtain or construct a dentry, or return an error.
447 * This should be called with the BKL and AFS_GLOCK held.
449 static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
451 struct vrequest treq;
458 code = afs_InitReq(&treq, credp);
460 #ifdef OSI_EXPORT_DEBUG
461 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
462 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
465 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
467 vcp = afs_GetVCache(afid, &treq, NULL, NULL);
469 #ifdef OSI_EXPORT_DEBUG
470 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
471 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
477 * Now, it might be that we just caused a directory vnode to
478 * spring into existence, in which case its parent FID is unset.
479 * We need to do something about that, but only because we care
480 * in our own get_parent(), below -- the common code never looks
481 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
482 * So, if this fails, we don't really care very much.
484 if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->parentVnode)
485 update_dir_parent(&treq, vcp);
488 * If this is a volume root directory and fakestat is enabled,
489 * we might need to replace the directory by a mount point.
491 code = UnEvalFakeStat(&treq, &vcp);
493 #ifdef OSI_EXPORT_DEBUG
494 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
495 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
499 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
503 afs_getattr(vcp, &vattr, credp);
504 afs_fill_inode(ip, &vattr);
506 /* d_alloc_anon might block, so we shouldn't hold the glock */
508 dp = d_alloc_anon(ip);
513 #ifdef OSI_EXPORT_DEBUG
514 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
515 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
517 return ERR_PTR(-ENOMEM);
520 dp->d_op = &afs_dentry_operations;
524 static struct dentry *afs_export_get_dentry(struct super_block *sb,
534 dp = get_dentry_from_fid(credp, inump);
544 static int get_name_hook(void *hdata, char *name,
545 afs_int32 vnode, afs_int32 unique)
547 struct get_name_data *data = (struct get_name_data *)hdata;
550 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
552 if (len > NAME_MAX) len = NAME_MAX;
553 memcpy(data->name, name, len);
554 data->name[len] = '\0';
560 static int afs_export_get_name(struct dentry *parent, char *name,
561 struct dentry *child)
563 struct afs_fakestat_state fakestate;
564 struct get_name_data data;
565 struct vrequest treq;
570 afs_size_t dirOffset, dirLen;
573 if (!parent->d_inode) {
574 #ifdef OSI_EXPORT_DEBUG
575 /* can't lookup name in a negative dentry */
576 printk("afs: get_name(%s, %s): no parent inode\n",
577 parent->d_name.name ? (char *)parent->d_name.name : "?",
578 child->d_name.name ? (char *)child->d_name.name : "?");
582 if (!child->d_inode) {
583 #ifdef OSI_EXPORT_DEBUG
584 /* can't find the FID of negative dentry */
585 printk("afs: get_name(%s, %s): no child inode\n",
586 parent->d_name.name ? (char *)parent->d_name.name : "?",
587 child->d_name.name ? (char *)child->d_name.name : "?");
592 afs_InitFakeStat(&fakestate);
598 vcp = VTOAFS(child->d_inode);
600 /* special case dynamic mount directory */
601 if (afs_IsDynrootMount(vcp)) {
602 #ifdef OSI_EXPORT_DEBUG
603 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
604 parent->d_name.name ? (char *)parent->d_name.name : "?",
605 vcp->fid.Cell, vcp->fid.Fid.Volume,
606 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
609 if (VTOAFS(parent->d_inode) == afs_globalVp)
610 strcpy(name, AFS_DYNROOT_MOUNTNAME);
616 /* Figure out what FID to look for */
617 if (vcp->mvstat == 2) { /* volume root */
618 tvp = afs_GetVolume(&vcp->fid, 0, READ_LOCK);
620 #ifdef OSI_EXPORT_DEBUG
621 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
622 parent->d_name.name ? (char *)parent->d_name.name : "?",
623 vcp->fid.Cell, vcp->fid.Fid.Volume,
624 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
629 data.fid = tvp->mtpoint;
630 afs_PutVolume(tvp, READ_LOCK);
635 vcp = VTOAFS(parent->d_inode);
636 #ifdef OSI_EXPORT_DEBUG
637 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
638 parent->d_name.name ? (char *)parent->d_name.name : "?",
639 data.fid.Cell, data.fid.Fid.Volume,
640 data.fid.Fid.Vnode, data.fid.Fid.Unique,
641 vcp->fid.Cell, vcp->fid.Fid.Volume,
642 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
645 code = afs_InitReq(&treq, credp);
647 #ifdef OSI_EXPORT_DEBUG
648 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n",
649 parent->d_name.name ? (char *)parent->d_name.name : "?",
650 data.fid.Cell, data.fid.Fid.Volume,
651 data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
656 /* a dynamic mount point in the dynamic mount directory */
657 if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
658 && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
659 #ifdef OSI_EXPORT_DEBUG
660 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
661 parent->d_name.name ? (char *)parent->d_name.name : "?",
662 data.fid.Cell, data.fid.Fid.Volume,
663 data.fid.Fid.Vnode, data.fid.Fid.Unique);
665 vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
667 ObtainReadLock(&vcp->lock);
668 if (strlen(vcp->linkData + 1) <= NAME_MAX)
669 strcpy(name, vcp->linkData + 1);
672 ReleaseReadLock(&vcp->lock);
675 #ifdef OSI_EXPORT_DEBUG
676 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
677 parent->d_name.name ? (char *)parent->d_name.name : "?",
678 data.fid.Cell, data.fid.Fid.Volume,
679 data.fid.Fid.Vnode, data.fid.Fid.Unique);
686 code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
690 if (vcp->fid.Cell != data.fid.Cell ||
691 vcp->fid.Fid.Volume != data.fid.Fid.Volume) {
692 /* parent is not the expected cell and volume; thus it
693 * cannot possibly contain the fid we are looking for */
694 #ifdef OSI_EXPORT_DEBUG
695 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\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,
699 vcp->fid.Cell, vcp->fid.Fid.Volume);
707 if (!(vcp->states & CStatd)) {
708 if ((code = afs_VerifyVCache2(vcp, &treq))) {
709 #ifdef OSI_EXPORT_DEBUG
710 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
711 parent->d_name.name ? (char *)parent->d_name.name : "?",
712 data.fid.Cell, data.fid.Fid.Volume,
713 data.fid.Fid.Vnode, data.fid.Fid.Unique,
714 vcp->fid.Cell, vcp->fid.Fid.Volume,
715 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
721 tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
723 #ifdef OSI_EXPORT_DEBUG
724 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
725 parent->d_name.name ? (char *)parent->d_name.name : "?",
726 data.fid.Cell, data.fid.Fid.Volume,
727 data.fid.Fid.Vnode, data.fid.Fid.Unique,
728 vcp->fid.Cell, vcp->fid.Fid.Volume,
729 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
735 ObtainReadLock(&vcp->lock);
736 ObtainReadLock(&tdc->lock);
739 * Make sure that the data in the cache is current. There are two
740 * cases we need to worry about:
741 * 1. The cache data is being fetched by another process.
742 * 2. The cache data is no longer valid
744 while ((vcp->states & CStatd)
745 && (tdc->dflags & DFFetching)
746 && hsame(vcp->m.DataVersion, tdc->f.versionNo)) {
747 ReleaseReadLock(&tdc->lock);
748 ReleaseReadLock(&vcp->lock);
749 afs_osi_Sleep(&tdc->validPos);
750 ObtainReadLock(&vcp->lock);
751 ObtainReadLock(&tdc->lock);
753 if (!(vcp->states & CStatd)
754 || !hsame(vcp->m.DataVersion, tdc->f.versionNo)) {
755 ReleaseReadLock(&tdc->lock);
756 ReleaseReadLock(&vcp->lock);
758 #ifdef OSI_EXPORT_DEBUG
759 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
760 parent->d_name.name ? (char *)parent->d_name.name : "?",
761 data.fid.Cell, data.fid.Fid.Volume,
762 data.fid.Fid.Vnode, data.fid.Fid.Unique,
763 vcp->fid.Cell, vcp->fid.Fid.Volume,
764 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
771 code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
772 if (!code && !data.found) {
773 #ifdef OSI_EXPORT_DEBUG
774 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
775 parent->d_name.name ? (char *)parent->d_name.name : "?",
776 data.fid.Cell, data.fid.Fid.Volume,
777 data.fid.Fid.Vnode, data.fid.Fid.Unique);
781 #ifdef OSI_EXPORT_DEBUG
782 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
783 parent->d_name.name ? (char *)parent->d_name.name : "?",
784 data.fid.Cell, data.fid.Fid.Volume,
785 data.fid.Fid.Vnode, data.fid.Fid.Unique,
786 vcp->fid.Cell, vcp->fid.Fid.Volume,
787 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
791 ReleaseReadLock(&tdc->lock);
792 ReleaseReadLock(&vcp->lock);
797 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
798 parent->d_name.name ? (char *)parent->d_name.name : "?",
799 data.fid.Cell, data.fid.Fid.Volume,
800 data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
802 afs_PutFakeStat(&fakestate);
806 code = afs_CheckCode(code, &treq, 102);
811 static struct dentry *afs_export_get_parent(struct dentry *child)
813 struct VenusFid tfid;
814 struct vrequest treq;
817 struct dentry *dp = NULL;
822 if (!child->d_inode) {
823 /* can't find the parent of a negative dentry */
824 #ifdef OSI_EXPORT_DEBUG
825 printk("afs: get_parent(%s): no inode\n",
826 child->d_name.name ? (char *)child->d_name.name : "?");
828 return ERR_PTR(-EIO);
835 vcp = VTOAFS(child->d_inode);
837 if (afs_IsDynrootMount(vcp)) {
838 /* the dynmount directory; parent is always the AFS root */
839 tfid = afs_globalVp->fid;
841 } else if (afs_IsDynrootAny(vcp) &&
842 VNUM_TO_VNTYPE(vcp->fid.Fid.Vnode) == VN_TYPE_MOUNT) {
843 /* a mount point in the dynmount directory */
844 afs_GetDynrootMountFid(&tfid);
846 } else if (vcp->mvstat == 2) {
848 ObtainReadLock(&vcp->lock);
849 if (vcp->mvid && vcp->mvid->Fid.Volume) {
851 ReleaseReadLock(&vcp->lock);
853 ReleaseReadLock(&vcp->lock);
854 tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
856 #ifdef OSI_EXPORT_DEBUG
857 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
858 vcp->fid.Cell, vcp->fid.Fid.Volume,
859 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
861 dp = ERR_PTR(-ENOENT);
865 cellidx = tcell->cellIndex;
866 afs_PutCell(tcell, READ_LOCK);
868 afs_GetDynrootMountFid(&tfid);
869 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
870 tfid.Fid.Unique = vcp->fid.Fid.Volume;
874 /* any other vnode */
875 if (vType(vcp) == VDIR && !vcp->parentVnode && vcp->mvstat != 1) {
876 code = afs_InitReq(&treq, credp);
878 #ifdef OSI_EXPORT_DEBUG
879 printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
880 vcp->fid.Cell, vcp->fid.Fid.Volume,
881 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
883 dp = ERR_PTR(-ENOENT);
886 code = update_dir_parent(&treq, vcp);
888 #ifdef OSI_EXPORT_DEBUG
889 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
890 vcp->fid.Cell, vcp->fid.Fid.Volume,
891 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
893 dp = ERR_PTR(-ENOENT);
899 tfid.Cell = vcp->fid.Cell;
900 tfid.Fid.Volume = vcp->fid.Fid.Volume;
901 tfid.Fid.Vnode = vcp->parentVnode;
902 tfid.Fid.Unique = vcp->parentUnique;
905 #ifdef OSI_EXPORT_DEBUG
906 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
907 vcp->fid.Cell, vcp->fid.Fid.Volume,
908 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique,
909 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
912 dp = get_dentry_from_fid(credp, &tfid);
914 #ifdef OSI_EXPORT_DEBUG
915 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
916 vcp->fid.Cell, vcp->fid.Fid.Volume,
917 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
919 dp = ERR_PTR(-ENOENT);
931 struct export_operations afs_export_ops = {
932 .encode_fh = afs_encode_fh,
933 .decode_fh = afs_decode_fh,
934 .get_dentry = afs_export_get_dentry,
935 .get_name = afs_export_get_name,
936 .get_parent = afs_export_get_parent,