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 */
21 #include "afs/sysincludes.h"
22 #include "afsincludes.h"
23 #include "afs/afs_dynroot.h"
24 #include "h/smp_lock.h"
26 /* #define OSI_EXPORT_DEBUG */
28 extern struct dentry_operations afs_dentry_operations;
30 struct get_name_data {
37 * Linux reserved the following filehandle types:
38 * - 0 is always the filesystem root; NFS deals with this for us
39 * - 1,2 are reserved by Linux for inode-number-based filehandles
40 * - 0xff is reserved by linux
42 * We encode filehandles for AFS files using the types defined below.
43 * Internally, our "object ID" is a VenusFid; if we get a filehandle
44 * with a more-stable cell ID, we'll turn it into a cell number in
45 * the decode_fh wrapper.
48 #define AFSFH_VENUSFID 0xa0 /* cell, volume, vnode, uniq */
49 #define AFSFH_CELLFID 0xa1 /* cellhandle, volume, vnode, uniq */
50 #define AFSFH_NET_VENUSFID 0xa2 /* net cell, volume, vnode, uniq */
51 #define AFSFH_NET_CELLFID 0xa3 /* net cellhandle, volume, vnode, uniq */
52 #define AFSFH_DYN_RO_CELL 0xd0 /* cellhandle for RO root.cell mount */
53 #define AFSFH_DYN_RW_CELL 0xd1 /* cellhandle for RW root.cell mount */
54 #define AFSFH_DYN_RO_LINK 0xd2 /* cellhandle for RO root.cell symlink */
55 #define AFSFH_DYN_RW_LINK 0xd3 /* cellhandle for RW root.cell symlink */
56 #define AFSFH_DYN_MOUNT 0xd4 /* cellhandle, volume for mount point */
57 #define AFSFH_DYN_SYMLINK 0xd5 /* hash of dynroot symlink target */
59 static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
66 if (!de->d_inode) /* encode a negative dentry?! */
68 if (*max_len < 4) /* not enough space */
71 tvc = VTOAFS(de->d_inode);
73 #ifdef OSI_EXPORT_DEBUG
74 printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
75 tvc->fid.Cell, tvc->fid.Fid.Volume,
76 tvc->fid.Fid.Vnode, tvc->fid.Fid.Unique);
78 if (afs_IsDynrootAnyFid(&tvc->fid)) {
79 vntype = VNUM_TO_VNTYPE(tvc->fid.Fid.Vnode);
82 /* encode as a normal filehandle */
94 tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->fid.Fid.Vnode),
100 memcpy((void *)fh, tc->cellHandle, 16);
101 afs_PutCell(tc, READ_LOCK);
103 if (vntype == VN_TYPE_MOUNT) {
104 fh[4] = htonl(tvc->fid.Fid.Unique);
106 return AFSFH_DYN_MOUNT;
109 if (vntype == VN_TYPE_CELL) {
110 return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->fid.Fid.Vnode);
112 return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->fid.Fid.Vnode);
115 case VN_TYPE_SYMLINK:
116 /* XXX fill in filehandle for dynroot symlink */
117 /* XXX return AFSFH_DYN_SYMLINK; */
125 /* not big enough for a migratable filehandle */
126 /* always encode in network order */
127 fh[0] = htonl(tvc->fid.Cell);
128 fh[1] = htonl(tvc->fid.Fid.Volume);
129 fh[2] = htonl(tvc->fid.Fid.Vnode);
130 fh[3] = htonl(tvc->fid.Fid.Unique);
132 return AFSFH_NET_VENUSFID;
136 tc = afs_GetCell(tvc->fid.Cell, READ_LOCK);
141 memcpy((void *)fh, tc->cellHandle, 16);
142 afs_PutCell(tc, READ_LOCK);
144 /* always encode in network order */
145 fh[4] = htonl(tvc->fid.Fid.Volume);
146 fh[5] = htonl(tvc->fid.Fid.Vnode);
147 fh[6] = htonl(tvc->fid.Fid.Unique);
150 return AFSFH_NET_CELLFID;
153 static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
154 int fh_len, int fh_type,
155 int (*acceptable)(void *, struct dentry *),
160 struct dentry *result;
167 fid.Fid.Volume = fh[1];
168 fid.Fid.Vnode = fh[2];
169 fid.Fid.Unique = fh[3];
176 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
181 fid.Cell = tc->cellNum;
182 fid.Fid.Volume = fh[4];
183 fid.Fid.Vnode = fh[5];
184 fid.Fid.Unique = fh[6];
185 afs_PutCell(tc, READ_LOCK);
189 case AFSFH_NET_VENUSFID:
192 fid.Cell = ntohl(fh[0]);
193 fid.Fid.Volume = ntohl(fh[1]);
194 fid.Fid.Vnode = ntohl(fh[2]);
195 fid.Fid.Unique = ntohl(fh[3]);
198 case AFSFH_NET_CELLFID:
202 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
207 fid.Cell = tc->cellNum;
208 fid.Fid.Volume = ntohl(fh[4]);
209 fid.Fid.Vnode = ntohl(fh[5]);
210 fid.Fid.Unique = ntohl(fh[6]);
211 afs_PutCell(tc, READ_LOCK);
215 case AFSFH_DYN_RO_CELL:
216 case AFSFH_DYN_RW_CELL:
220 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
225 afs_GetDynrootFid(&fid);
226 fid.Fid.Vnode = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
228 afs_PutCell(tc, READ_LOCK);
232 case AFSFH_DYN_RO_LINK:
233 case AFSFH_DYN_RW_LINK:
237 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
242 afs_GetDynrootFid(&fid);
243 fid.Fid.Vnode = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
245 afs_PutCell(tc, READ_LOCK);
249 case AFSFH_DYN_MOUNT:
253 tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
258 afs_GetDynrootFid(&fid);
259 fid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
261 fid.Fid.Unique = ntohl(fh[4]);
262 afs_PutCell(tc, READ_LOCK);
266 case AFSFH_DYN_SYMLINK:
267 /* XXX parse dynroot symlink filehandle */
274 result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
275 acceptable, context);
276 #ifdef OSI_EXPORT_DEBUG
278 printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
279 fid.Cell, fid.Fid.Volume,
280 fid.Fid.Vnode, fid.Fid.Unique);
281 } else if (IS_ERR(result)) {
282 printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
283 fid.Cell, fid.Fid.Volume,
284 fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
290 static int update_dir_parent(struct vrequest *areq, struct vcache *adp)
292 struct VenusFid tfid;
294 afs_size_t dirOffset, dirLen;
298 if (!(adp->states & CStatd)) {
299 if ((code = afs_VerifyVCache2(adp, areq))) {
300 #ifdef OSI_EXPORT_DEBUG
301 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): VerifyVCache2: %d\n",
302 adp->fid.Cell, adp->fid.Fid.Volume,
303 adp->fid.Fid.Vnode, adp->fid.Fid.Unique, code);
309 tdc = afs_GetDCache(adp, (afs_size_t) 0, areq, &dirOffset, &dirLen, 1);
311 #ifdef OSI_EXPORT_DEBUG
312 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): no dcache\n",
313 adp->fid.Cell, adp->fid.Fid.Volume,
314 adp->fid.Fid.Vnode, adp->fid.Fid.Unique);
319 /* now we will just call dir package with appropriate inode.
320 * Dirs are always fetched in their entirety for now */
321 ObtainSharedLock(&adp->lock, 801);
322 ObtainReadLock(&tdc->lock);
325 * Make sure that the data in the cache is current. There are two
326 * cases we need to worry about:
327 * 1. The cache data is being fetched by another process.
328 * 2. The cache data is no longer valid
330 while ((adp->states & CStatd)
331 && (tdc->dflags & DFFetching)
332 && hsame(adp->m.DataVersion, tdc->f.versionNo)) {
333 ReleaseReadLock(&tdc->lock);
334 ReleaseSharedLock(&adp->lock);
335 afs_osi_Sleep(&tdc->validPos);
336 ObtainSharedLock(&adp->lock, 802);
337 ObtainReadLock(&tdc->lock);
339 if (!(adp->states & CStatd)
340 || !hsame(adp->m.DataVersion, tdc->f.versionNo)) {
341 ReleaseReadLock(&tdc->lock);
342 ReleaseSharedLock(&adp->lock);
344 #ifdef OSI_EXPORT_DEBUG
345 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): dir changed; retrying\n",
346 adp->fid.Cell, adp->fid.Fid.Volume,
347 adp->fid.Fid.Vnode, adp->fid.Fid.Unique);
352 /* lookup the name in the appropriate dir, and return a cache entry
353 * on the resulting fid */
354 code = afs_dir_Lookup(tdc, "..", &tfid.Fid);
356 ReleaseReadLock(&tdc->lock);
360 UpgradeSToWLock(&adp->lock, 803);
361 adp->parentVnode = tfid.Fid.Vnode;
362 adp->parentUnique = tfid.Fid.Unique;
364 #ifdef OSI_EXPORT_DEBUG
366 printk("afs: update_dir_parent(0x%08x/%d/%d.%d): afs_dir_Lookup: %d\n",
367 adp->fid.Cell, adp->fid.Fid.Volume,
368 adp->fid.Fid.Vnode, adp->fid.Fid.Unique, code);
370 printk("afs: update_dir_parent(0x%08x/%d/%d.%d) => %d.%d\n",
371 adp->fid.Cell, adp->fid.Fid.Volume,
372 adp->fid.Fid.Vnode, adp->fid.Fid.Unique,
373 adp->parentVnode, adp->parentUnique);
376 ReleaseSharedLock(&adp->lock);
381 static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
383 struct VenusFid tfid;
388 if (!afs_fakestat_enable)
391 if (*vcpp == afs_globalVp || vType(*vcpp) != VDIR || (*vcpp)->mvstat != 2)
394 /* Figure out what FID to look for */
395 tvp = afs_GetVolume(&(*vcpp)->fid, 0, READ_LOCK);
397 #ifdef OSI_EXPORT_DEBUG
398 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n",
399 (*vcpp)->fid.Cell, (*vcpp)->fid.Fid.Volume,
400 (*vcpp)->fid.Fid.Vnode, (*vcpp)->fid.Fid.Unique);
405 afs_PutVolume(tvp, READ_LOCK);
407 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
409 #ifdef OSI_EXPORT_DEBUG
410 printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
411 (*vcpp)->fid.Cell, (*vcpp)->fid.Fid.Volume,
412 (*vcpp)->fid.Fid.Vnode, (*vcpp)->fid.Fid.Unique,
413 tfid.Cell, tfid.Fid.Volume,
414 tfid.Fid.Vnode, tfid.Fid.Unique);
419 if (afs_fakestat_enable == 2) {
420 ObtainWriteLock(&tvc->lock, 806);
421 code = afs_HandleLink(tvc, areq);
423 ReleaseWriteLock(&tvc->lock);
427 if (!strchr(tvc->linkData, ':')) {
428 ReleaseWriteLock(&tvc->lock);
432 ReleaseWriteLock(&tvc->lock);
435 afs_PutVCache(*vcpp);
442 * Given a FID, obtain or construct a dentry, or return an error.
443 * This should be called with the BKL and AFS_GLOCK held.
445 static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
447 struct vrequest treq;
454 code = afs_InitReq(&treq, credp);
456 #ifdef OSI_EXPORT_DEBUG
457 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
458 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
461 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
463 vcp = afs_GetVCache(afid, &treq, NULL, NULL);
465 #ifdef OSI_EXPORT_DEBUG
466 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
467 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
473 * Now, it might be that we just caused a directory vnode to
474 * spring into existence, in which case its parent FID is unset.
475 * We need to do something about that, but only because we care
476 * in our own get_parent(), below -- the common code never looks
477 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
478 * So, if this fails, we don't really care very much.
480 if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->parentVnode)
481 update_dir_parent(&treq, vcp);
484 * If this is a volume root directory and fakestat is enabled,
485 * we might need to replace the directory by a mount point.
487 code = UnEvalFakeStat(&treq, &vcp);
489 #ifdef OSI_EXPORT_DEBUG
490 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
491 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
495 return ERR_PTR(-afs_CheckCode(code, &treq, 101));
499 afs_getattr(vcp, &vattr, credp);
500 afs_fill_inode(ip, &vattr);
502 /* d_alloc_anon might block, so we shouldn't hold the glock */
504 dp = d_alloc_anon(ip);
509 #ifdef OSI_EXPORT_DEBUG
510 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
511 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
513 return ERR_PTR(-ENOMEM);
516 dp->d_op = &afs_dentry_operations;
520 static struct dentry *afs_export_get_dentry(struct super_block *sb,
530 dp = get_dentry_from_fid(credp, inump);
540 static int get_name_hook(void *hdata, char *name,
541 afs_int32 vnode, afs_int32 unique)
543 struct get_name_data *data = (struct get_name_data *)hdata;
546 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
548 if (len > NAME_MAX) len = NAME_MAX;
549 memcpy(data->name, name, len);
550 data->name[len] = '\0';
556 static int afs_export_get_name(struct dentry *parent, char *name,
557 struct dentry *child)
559 struct afs_fakestat_state fakestate;
560 struct get_name_data data;
561 struct vrequest treq;
566 afs_size_t dirOffset, dirLen;
569 if (!parent->d_inode) {
570 #ifdef OSI_EXPORT_DEBUG
571 /* can't lookup name in a negative dentry */
572 printk("afs: get_name(%s, %s): no parent inode\n",
573 parent->d_name.name ? (char *)parent->d_name.name : "?",
574 child->d_name.name ? (char *)child->d_name.name : "?");
578 if (!child->d_inode) {
579 #ifdef OSI_EXPORT_DEBUG
580 /* can't find the FID of negative dentry */
581 printk("afs: get_name(%s, %s): no child inode\n",
582 parent->d_name.name ? (char *)parent->d_name.name : "?",
583 child->d_name.name ? (char *)child->d_name.name : "?");
588 afs_InitFakeStat(&fakestate);
594 vcp = VTOAFS(child->d_inode);
596 /* special case dynamic mount directory */
597 if (afs_IsDynrootMount(vcp)) {
598 #ifdef OSI_EXPORT_DEBUG
599 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
600 parent->d_name.name ? (char *)parent->d_name.name : "?",
601 vcp->fid.Cell, vcp->fid.Fid.Volume,
602 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
605 if (VTOAFS(parent->d_inode) == afs_globalVp)
606 strcpy(name, AFS_DYNROOT_MOUNTNAME);
612 /* Figure out what FID to look for */
613 if (vcp->mvstat == 2) { /* volume root */
614 tvp = afs_GetVolume(&vcp->fid, 0, READ_LOCK);
616 #ifdef OSI_EXPORT_DEBUG
617 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
618 parent->d_name.name ? (char *)parent->d_name.name : "?",
619 vcp->fid.Cell, vcp->fid.Fid.Volume,
620 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
625 data.fid = tvp->mtpoint;
626 afs_PutVolume(tvp, READ_LOCK);
631 vcp = VTOAFS(parent->d_inode);
632 #ifdef OSI_EXPORT_DEBUG
633 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
634 parent->d_name.name ? (char *)parent->d_name.name : "?",
635 data.fid.Cell, data.fid.Fid.Volume,
636 data.fid.Fid.Vnode, data.fid.Fid.Unique,
637 vcp->fid.Cell, vcp->fid.Fid.Volume,
638 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
641 code = afs_InitReq(&treq, credp);
643 #ifdef OSI_EXPORT_DEBUG
644 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n",
645 parent->d_name.name ? (char *)parent->d_name.name : "?",
646 data.fid.Cell, data.fid.Fid.Volume,
647 data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
652 /* a dynamic mount point in the dynamic mount directory */
653 if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
654 && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
655 #ifdef OSI_EXPORT_DEBUG
656 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\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);
661 vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
663 ObtainReadLock(&vcp->lock);
664 if (strlen(vcp->linkData + 1) <= NAME_MAX)
665 strcpy(name, vcp->linkData + 1);
668 ReleaseReadLock(&vcp->lock);
671 #ifdef OSI_EXPORT_DEBUG
672 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
673 parent->d_name.name ? (char *)parent->d_name.name : "?",
674 data.fid.Cell, data.fid.Fid.Volume,
675 data.fid.Fid.Vnode, data.fid.Fid.Unique);
682 code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
686 if (vcp->fid.Cell != data.fid.Cell ||
687 vcp->fid.Fid.Volume != data.fid.Fid.Volume) {
688 /* parent is not the expected cell and volume; thus it
689 * cannot possibly contain the fid we are looking for */
690 #ifdef OSI_EXPORT_DEBUG
691 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
692 parent->d_name.name ? (char *)parent->d_name.name : "?",
693 data.fid.Cell, data.fid.Fid.Volume,
694 data.fid.Fid.Vnode, data.fid.Fid.Unique,
695 vcp->fid.Cell, vcp->fid.Fid.Volume);
703 if (!(vcp->states & CStatd)) {
704 if ((code = afs_VerifyVCache2(vcp, &treq))) {
705 #ifdef OSI_EXPORT_DEBUG
706 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
707 parent->d_name.name ? (char *)parent->d_name.name : "?",
708 data.fid.Cell, data.fid.Fid.Volume,
709 data.fid.Fid.Vnode, data.fid.Fid.Unique,
710 vcp->fid.Cell, vcp->fid.Fid.Volume,
711 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
717 tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
719 #ifdef OSI_EXPORT_DEBUG
720 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
721 parent->d_name.name ? (char *)parent->d_name.name : "?",
722 data.fid.Cell, data.fid.Fid.Volume,
723 data.fid.Fid.Vnode, data.fid.Fid.Unique,
724 vcp->fid.Cell, vcp->fid.Fid.Volume,
725 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
731 ObtainReadLock(&vcp->lock);
732 ObtainReadLock(&tdc->lock);
735 * Make sure that the data in the cache is current. There are two
736 * cases we need to worry about:
737 * 1. The cache data is being fetched by another process.
738 * 2. The cache data is no longer valid
740 while ((vcp->states & CStatd)
741 && (tdc->dflags & DFFetching)
742 && hsame(vcp->m.DataVersion, tdc->f.versionNo)) {
743 ReleaseReadLock(&tdc->lock);
744 ReleaseReadLock(&vcp->lock);
745 afs_osi_Sleep(&tdc->validPos);
746 ObtainReadLock(&vcp->lock);
747 ObtainReadLock(&tdc->lock);
749 if (!(vcp->states & CStatd)
750 || !hsame(vcp->m.DataVersion, tdc->f.versionNo)) {
751 ReleaseReadLock(&tdc->lock);
752 ReleaseReadLock(&vcp->lock);
754 #ifdef OSI_EXPORT_DEBUG
755 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
756 parent->d_name.name ? (char *)parent->d_name.name : "?",
757 data.fid.Cell, data.fid.Fid.Volume,
758 data.fid.Fid.Vnode, data.fid.Fid.Unique,
759 vcp->fid.Cell, vcp->fid.Fid.Volume,
760 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
767 code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
768 if (!code && !data.found) {
769 #ifdef OSI_EXPORT_DEBUG
770 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
771 parent->d_name.name ? (char *)parent->d_name.name : "?",
772 data.fid.Cell, data.fid.Fid.Volume,
773 data.fid.Fid.Vnode, data.fid.Fid.Unique);
777 #ifdef OSI_EXPORT_DEBUG
778 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\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->fid.Cell, vcp->fid.Fid.Volume,
783 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
787 ReleaseReadLock(&tdc->lock);
788 ReleaseReadLock(&vcp->lock);
793 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\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, name);
798 afs_PutFakeStat(&fakestate);
802 code = afs_CheckCode(code, &treq, 102);
807 static struct dentry *afs_export_get_parent(struct dentry *child)
809 struct VenusFid tfid;
810 struct vrequest treq;
813 struct dentry *dp = NULL;
818 if (!child->d_inode) {
819 /* can't find the parent of a negative dentry */
820 #ifdef OSI_EXPORT_DEBUG
821 printk("afs: get_parent(%s): no inode\n",
822 child->d_name.name ? (char *)child->d_name.name : "?");
824 return ERR_PTR(-EIO);
831 vcp = VTOAFS(child->d_inode);
833 if (afs_IsDynrootMount(vcp)) {
834 /* the dynmount directory; parent is always the AFS root */
835 tfid = afs_globalVp->fid;
837 } else if (afs_IsDynrootAny(vcp) &&
838 VNUM_TO_VNTYPE(vcp->fid.Fid.Vnode) == VN_TYPE_MOUNT) {
839 /* a mount point in the dynmount directory */
840 afs_GetDynrootMountFid(&tfid);
842 } else if (vcp->mvstat == 2) {
844 ObtainReadLock(&vcp->lock);
845 if (vcp->mvid && vcp->mvid->Fid.Volume) {
847 ReleaseReadLock(&vcp->lock);
849 ReleaseReadLock(&vcp->lock);
850 tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
852 #ifdef OSI_EXPORT_DEBUG
853 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
854 vcp->fid.Cell, vcp->fid.Fid.Volume,
855 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
857 dp = ERR_PTR(-ENOENT);
861 cellidx = tcell->cellIndex;
862 afs_PutCell(tcell, READ_LOCK);
864 afs_GetDynrootMountFid(&tfid);
865 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
866 tfid.Fid.Unique = vcp->fid.Fid.Volume;
870 /* any other vnode */
871 if (vType(vcp) == VDIR && !vcp->parentVnode && vcp->mvstat != 1) {
872 code = afs_InitReq(&treq, credp);
874 #ifdef OSI_EXPORT_DEBUG
875 printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
876 vcp->fid.Cell, vcp->fid.Fid.Volume,
877 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
879 dp = ERR_PTR(-ENOENT);
882 code = update_dir_parent(&treq, vcp);
884 #ifdef OSI_EXPORT_DEBUG
885 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
886 vcp->fid.Cell, vcp->fid.Fid.Volume,
887 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
889 dp = ERR_PTR(-ENOENT);
895 tfid.Cell = vcp->fid.Cell;
896 tfid.Fid.Volume = vcp->fid.Fid.Volume;
897 tfid.Fid.Vnode = vcp->parentVnode;
898 tfid.Fid.Unique = vcp->parentUnique;
901 #ifdef OSI_EXPORT_DEBUG
902 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
903 vcp->fid.Cell, vcp->fid.Fid.Volume,
904 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique,
905 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
908 dp = get_dentry_from_fid(credp, &tfid);
910 #ifdef OSI_EXPORT_DEBUG
911 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
912 vcp->fid.Cell, vcp->fid.Fid.Volume,
913 vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
915 dp = ERR_PTR(-ENOENT);
927 struct export_operations afs_export_ops = {
928 .encode_fh = afs_encode_fh,
929 .decode_fh = afs_decode_fh,
930 .get_dentry = afs_export_get_dentry,
931 .get_name = afs_export_get_name,
932 .get_parent = afs_export_get_parent,