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 = NULL;
474 code = afs_CreateReq(&treq, credp);
476 #ifdef OSI_EXPORT_DEBUG
477 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
478 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
481 return ERR_PTR(-afs_CheckCode(code, NULL, 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);
489 afs_DestroyReq(treq);
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 code = afs_CheckCode(code, treq, 103);
517 afs_DestroyReq(treq);
518 return ERR_PTR(-code);
522 afs_getattr(vcp, &vattr, credp);
523 afs_fill_inode(ip, &vattr);
525 /* d_alloc_anon might block, so we shouldn't hold the glock */
527 dp = d_alloc_anon(ip);
532 #ifdef OSI_EXPORT_DEBUG
533 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
534 afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
536 afs_DestroyReq(treq);
537 return ERR_PTR(-ENOMEM);
540 dp->d_op = &afs_dentry_operations;
541 afs_DestroyReq(treq);
545 static struct dentry *afs_export_get_dentry(struct super_block *sb,
554 dp = get_dentry_from_fid(credp, inump);
563 static int get_name_hook(void *hdata, char *name,
564 afs_int32 vnode, afs_int32 unique)
566 struct get_name_data *data = (struct get_name_data *)hdata;
569 if (vnode == data->fid.Fid.Vnode && unique == data->fid.Fid.Unique) {
571 if (len > NAME_MAX) len = NAME_MAX;
572 memcpy(data->name, name, len);
573 data->name[len] = '\0';
579 static int afs_export_get_name(struct dentry *parent, char *name,
580 struct dentry *child)
582 struct afs_fakestat_state fakestate;
583 struct get_name_data data;
584 struct vrequest *treq = NULL;
589 afs_size_t dirOffset, dirLen;
592 if (!parent->d_inode) {
593 #ifdef OSI_EXPORT_DEBUG
594 /* can't lookup name in a negative dentry */
595 printk("afs: get_name(%s, %s): no parent inode\n",
596 parent->d_name.name ? (char *)parent->d_name.name : "?",
597 child->d_name.name ? (char *)child->d_name.name : "?");
601 if (!child->d_inode) {
602 #ifdef OSI_EXPORT_DEBUG
603 /* can't find the FID of negative dentry */
604 printk("afs: get_name(%s, %s): no child inode\n",
605 parent->d_name.name ? (char *)parent->d_name.name : "?",
606 child->d_name.name ? (char *)child->d_name.name : "?");
611 afs_InitFakeStat(&fakestate);
616 vcp = VTOAFS(child->d_inode);
618 /* special case dynamic mount directory */
619 if (afs_IsDynrootMount(vcp)) {
620 #ifdef OSI_EXPORT_DEBUG
621 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
622 parent->d_name.name ? (char *)parent->d_name.name : "?",
623 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
624 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
626 data.fid = vcp->f.fid;
627 if (VTOAFS(parent->d_inode) == afs_globalVp)
628 strcpy(name, AFS_DYNROOT_MOUNTNAME);
634 /* Figure out what FID to look for */
635 if (vcp->mvstat == 2) { /* volume root */
636 tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
638 #ifdef OSI_EXPORT_DEBUG
639 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
640 parent->d_name.name ? (char *)parent->d_name.name : "?",
641 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
642 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
647 data.fid = tvp->mtpoint;
648 afs_PutVolume(tvp, READ_LOCK);
650 data.fid = vcp->f.fid;
653 vcp = VTOAFS(parent->d_inode);
654 #ifdef OSI_EXPORT_DEBUG
655 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
656 parent->d_name.name ? (char *)parent->d_name.name : "?",
657 data.fid.Cell, data.fid.Fid.Volume,
658 data.fid.Fid.Vnode, data.fid.Fid.Unique,
659 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
660 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
662 code = afs_CreateReq(&treq, credp);
664 #ifdef OSI_EXPORT_DEBUG
665 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_CreateReq: %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);
820 code = afs_CheckCode(code, treq, 102);
821 afs_DestroyReq(treq);
828 static struct dentry *afs_export_get_parent(struct dentry *child)
830 struct VenusFid tfid;
831 struct vrequest *treq = NULL;
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);
851 vcp = VTOAFS(child->d_inode);
853 if (afs_IsDynrootMount(vcp)) {
854 /* the dynmount directory; parent is always the AFS root */
855 tfid = afs_globalVp->f.fid;
857 } else if (afs_IsDynrootAny(vcp) &&
858 VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
859 /* a mount point in the dynmount directory */
860 afs_GetDynrootMountFid(&tfid);
862 } else if (vcp->mvstat == 2) {
864 ObtainReadLock(&vcp->lock);
865 if (vcp->mvid && vcp->mvid->Fid.Volume) {
867 ReleaseReadLock(&vcp->lock);
869 ReleaseReadLock(&vcp->lock);
870 tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
872 #ifdef OSI_EXPORT_DEBUG
873 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
874 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
875 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
877 dp = ERR_PTR(-ENOENT);
881 cellidx = tcell->cellIndex;
882 afs_PutCell(tcell, READ_LOCK);
884 afs_GetDynrootMountFid(&tfid);
885 tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
886 tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
890 /* any other vnode */
891 if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) {
892 code = afs_CreateReq(&treq, credp);
894 #ifdef OSI_EXPORT_DEBUG
895 printk("afs: get_parent(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
896 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
897 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
899 dp = ERR_PTR(-ENOENT);
902 code = update_dir_parent(treq, vcp);
904 #ifdef OSI_EXPORT_DEBUG
905 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %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);
915 tfid.Cell = vcp->f.fid.Cell;
916 tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
917 tfid.Fid.Vnode = vcp->f.parent.vnode;
918 tfid.Fid.Unique = vcp->f.parent.unique;
921 #ifdef OSI_EXPORT_DEBUG
922 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
923 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
924 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
925 tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
928 dp = get_dentry_from_fid(credp, &tfid);
930 #ifdef OSI_EXPORT_DEBUG
931 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
932 vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
933 vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
935 dp = ERR_PTR(-ENOENT);
939 afs_DestroyReq(treq);
947 struct export_operations afs_export_ops = {
948 .encode_fh = afs_encode_fh,
949 #if defined(NEW_EXPORT_OPS)
950 .fh_to_dentry = afs_fh_to_dentry,
952 .decode_fh = afs_decode_fh,
953 .get_dentry = afs_export_get_dentry,
955 .get_name = afs_export_get_name,
956 .get_parent = afs_export_get_parent,