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
!= AFS_MVSTAT_ROOT
)
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
;
469 struct vattr
*vattr
= NULL
;
474 code
= afs_CreateAttr(&vattr
);
476 return ERR_PTR(-afs_CheckCode(code
, NULL
, 104));
479 code
= afs_CreateReq(&treq
, credp
);
481 #ifdef OSI_EXPORT_DEBUG
482 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
483 afid
->Cell
, afid
->Fid
.Volume
, afid
->Fid
.Vnode
, afid
->Fid
.Unique
,
486 afs_DestroyAttr(vattr
);
487 return ERR_PTR(-afs_CheckCode(code
, NULL
, 101));
489 vcp
= afs_GetVCache(afid
, treq
, NULL
, NULL
);
491 #ifdef OSI_EXPORT_DEBUG
492 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
493 afid
->Cell
, afid
->Fid
.Volume
, afid
->Fid
.Vnode
, afid
->Fid
.Unique
);
495 afs_DestroyReq(treq
);
496 afs_DestroyAttr(vattr
);
501 * Now, it might be that we just caused a directory vnode to
502 * spring into existence, in which case its parent FID is unset.
503 * We need to do something about that, but only because we care
504 * in our own get_parent(), below -- the common code never looks
505 * at parentVnode on directories, except for VIOCGETVCXSTATUS.
506 * So, if this fails, we don't really care very much.
508 if (vType(vcp
) == VDIR
&& vcp
->mvstat
!= AFS_MVSTAT_ROOT
&& !vcp
->f
.parent
.vnode
)
509 update_dir_parent(treq
, vcp
);
512 * If this is a volume root directory and fakestat is enabled,
513 * we might need to replace the directory by a mount point.
515 code
= UnEvalFakeStat(treq
, &vcp
);
517 #ifdef OSI_EXPORT_DEBUG
518 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
519 afid
->Cell
, afid
->Fid
.Volume
, afid
->Fid
.Vnode
, afid
->Fid
.Unique
,
523 code
= afs_CheckCode(code
, treq
, 103);
524 afs_DestroyReq(treq
);
525 afs_DestroyAttr(vattr
);
526 return ERR_PTR(-code
);
530 afs_getattr(vcp
, vattr
, credp
);
531 afs_fill_inode(ip
, vattr
);
533 /* d_alloc_anon might block, so we shouldn't hold the glock */
535 dp
= d_alloc_anon(ip
);
540 #ifdef OSI_EXPORT_DEBUG
541 printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
542 afid
->Cell
, afid
->Fid
.Volume
, afid
->Fid
.Vnode
, afid
->Fid
.Unique
);
544 afs_DestroyReq(treq
);
545 afs_DestroyAttr(vattr
);
546 return ERR_PTR(-ENOMEM
);
549 dp
->d_op
= &afs_dentry_operations
;
550 afs_DestroyReq(treq
);
551 afs_DestroyAttr(vattr
);
555 static struct dentry
*afs_export_get_dentry(struct super_block
*sb
,
564 dp
= get_dentry_from_fid(credp
, inump
);
573 static int get_name_hook(void *hdata
, char *name
,
574 afs_int32 vnode
, afs_int32 unique
)
576 struct get_name_data
*data
= (struct get_name_data
*)hdata
;
579 if (vnode
== data
->fid
.Fid
.Vnode
&& unique
== data
->fid
.Fid
.Unique
) {
581 if (len
> NAME_MAX
) len
= NAME_MAX
;
582 memcpy(data
->name
, name
, len
);
583 data
->name
[len
] = '\0';
589 static int afs_export_get_name(struct dentry
*parent
, char *name
,
590 struct dentry
*child
)
592 struct afs_fakestat_state fakestate
;
593 struct get_name_data data
;
594 struct vrequest
*treq
= NULL
;
599 afs_size_t dirOffset
, dirLen
;
602 if (!parent
->d_inode
) {
603 #ifdef OSI_EXPORT_DEBUG
604 /* can't lookup name in a negative dentry */
605 printk("afs: get_name(%s, %s): no parent inode\n",
606 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
607 child
->d_name
.name
? (char *)child
->d_name
.name
: "?");
611 if (!child
->d_inode
) {
612 #ifdef OSI_EXPORT_DEBUG
613 /* can't find the FID of negative dentry */
614 printk("afs: get_name(%s, %s): no child inode\n",
615 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
616 child
->d_name
.name
? (char *)child
->d_name
.name
: "?");
621 afs_InitFakeStat(&fakestate
);
626 vcp
= VTOAFS(child
->d_inode
);
628 /* special case dynamic mount directory */
629 if (afs_IsDynrootMount(vcp
)) {
630 #ifdef OSI_EXPORT_DEBUG
631 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
632 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
633 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
634 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
);
636 data
.fid
= vcp
->f
.fid
;
637 if (VTOAFS(parent
->d_inode
) == afs_globalVp
)
638 strcpy(name
, AFS_DYNROOT_MOUNTNAME
);
644 /* Figure out what FID to look for */
645 if (vcp
->mvstat
== AFS_MVSTAT_ROOT
) { /* volume root */
646 tvp
= afs_GetVolume(&vcp
->f
.fid
, 0, READ_LOCK
);
648 #ifdef OSI_EXPORT_DEBUG
649 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
650 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
651 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
652 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
);
657 data
.fid
= tvp
->mtpoint
;
658 afs_PutVolume(tvp
, READ_LOCK
);
660 data
.fid
= vcp
->f
.fid
;
663 vcp
= VTOAFS(parent
->d_inode
);
664 #ifdef OSI_EXPORT_DEBUG
665 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%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
,
669 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
670 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
);
672 code
= afs_CreateReq(&treq
, credp
);
674 #ifdef OSI_EXPORT_DEBUG
675 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
676 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
677 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
678 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
, code
);
683 /* a dynamic mount point in the dynamic mount directory */
684 if (afs_IsDynrootMount(vcp
) && afs_IsDynrootAnyFid(&data
.fid
)
685 && VNUM_TO_VNTYPE(data
.fid
.Fid
.Vnode
) == VN_TYPE_MOUNT
) {
686 #ifdef OSI_EXPORT_DEBUG
687 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
688 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
689 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
690 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
);
692 vcp
= afs_GetVCache(&data
.fid
, treq
, NULL
, NULL
);
694 ObtainReadLock(&vcp
->lock
);
695 if (strlen(vcp
->linkData
+ 1) <= NAME_MAX
)
696 strcpy(name
, vcp
->linkData
+ 1);
699 ReleaseReadLock(&vcp
->lock
);
702 #ifdef OSI_EXPORT_DEBUG
703 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
704 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
705 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
706 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
);
713 code
= afs_EvalFakeStat(&vcp
, &fakestate
, treq
);
717 if (vcp
->f
.fid
.Cell
!= data
.fid
.Cell
||
718 vcp
->f
.fid
.Fid
.Volume
!= data
.fid
.Fid
.Volume
) {
719 /* parent is not the expected cell and volume; thus it
720 * cannot possibly contain the fid we are looking for */
721 #ifdef OSI_EXPORT_DEBUG
722 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
723 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
724 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
725 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
,
726 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
);
734 if (!(vcp
->f
.states
& CStatd
)) {
735 if ((code
= afs_VerifyVCache2(vcp
, treq
))) {
736 #ifdef OSI_EXPORT_DEBUG
737 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(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 tdc
= afs_GetDCache(vcp
, (afs_size_t
) 0, treq
, &dirOffset
, &dirLen
, 1);
750 #ifdef OSI_EXPORT_DEBUG
751 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
752 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
753 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
754 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
,
755 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
756 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
, code
);
762 ObtainReadLock(&vcp
->lock
);
763 ObtainReadLock(&tdc
->lock
);
766 * Make sure that the data in the cache is current. There are two
767 * cases we need to worry about:
768 * 1. The cache data is being fetched by another process.
769 * 2. The cache data is no longer valid
771 while ((vcp
->f
.states
& CStatd
)
772 && (tdc
->dflags
& DFFetching
)
773 && hsame(vcp
->f
.m
.DataVersion
, tdc
->f
.versionNo
)) {
774 ReleaseReadLock(&tdc
->lock
);
775 ReleaseReadLock(&vcp
->lock
);
776 afs_osi_Sleep(&tdc
->validPos
);
777 ObtainReadLock(&vcp
->lock
);
778 ObtainReadLock(&tdc
->lock
);
780 if (!(vcp
->f
.states
& CStatd
)
781 || !hsame(vcp
->f
.m
.DataVersion
, tdc
->f
.versionNo
)) {
782 ReleaseReadLock(&tdc
->lock
);
783 ReleaseReadLock(&vcp
->lock
);
785 #ifdef OSI_EXPORT_DEBUG
786 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
787 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
788 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
789 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
,
790 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
791 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
);
798 code
= afs_dir_EnumerateDir(tdc
, get_name_hook
, &data
);
799 if (!code
&& !data
.found
) {
800 #ifdef OSI_EXPORT_DEBUG
801 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
802 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
803 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
804 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
);
808 #ifdef OSI_EXPORT_DEBUG
809 printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
810 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
811 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
812 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
,
813 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
814 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
, code
);
818 ReleaseReadLock(&tdc
->lock
);
819 ReleaseReadLock(&vcp
->lock
);
824 printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
825 parent
->d_name
.name
? (char *)parent
->d_name
.name
: "?",
826 data
.fid
.Cell
, data
.fid
.Fid
.Volume
,
827 data
.fid
.Fid
.Vnode
, data
.fid
.Fid
.Unique
, name
);
829 afs_PutFakeStat(&fakestate
);
830 code
= afs_CheckCode(code
, treq
, 102);
831 afs_DestroyReq(treq
);
838 static struct dentry
*afs_export_get_parent(struct dentry
*child
)
840 struct VenusFid tfid
;
841 struct vrequest
*treq
= NULL
;
844 struct dentry
*dp
= NULL
;
849 if (!child
->d_inode
) {
850 /* can't find the parent of a negative dentry */
851 #ifdef OSI_EXPORT_DEBUG
852 printk("afs: get_parent(%s): no inode\n",
853 child
->d_name
.name
? (char *)child
->d_name
.name
: "?");
855 return ERR_PTR(-EIO
);
861 vcp
= VTOAFS(child
->d_inode
);
863 if (afs_IsDynrootMount(vcp
)) {
864 /* the dynmount directory; parent is always the AFS root */
865 tfid
= afs_globalVp
->f
.fid
;
867 } else if (afs_IsDynrootAny(vcp
) &&
868 VNUM_TO_VNTYPE(vcp
->f
.fid
.Fid
.Vnode
) == VN_TYPE_MOUNT
) {
869 /* a mount point in the dynmount directory */
870 afs_GetDynrootMountFid(&tfid
);
872 } else if (vcp
->mvstat
== AFS_MVSTAT_ROOT
) {
874 ObtainReadLock(&vcp
->lock
);
875 if (vcp
->mvid
.parent
&& vcp
->mvid
.parent
->Fid
.Volume
) {
876 tfid
= *vcp
->mvid
.parent
;
877 ReleaseReadLock(&vcp
->lock
);
879 ReleaseReadLock(&vcp
->lock
);
880 tcell
= afs_GetCell(vcp
->f
.fid
.Cell
, READ_LOCK
);
882 #ifdef OSI_EXPORT_DEBUG
883 printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
884 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
885 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
);
887 dp
= ERR_PTR(-ENOENT
);
891 cellidx
= tcell
->cellIndex
;
892 afs_PutCell(tcell
, READ_LOCK
);
894 afs_GetDynrootMountFid(&tfid
);
895 tfid
.Fid
.Vnode
= VNUM_FROM_TYPEID(VN_TYPE_MOUNT
, cellidx
<< 2);
896 tfid
.Fid
.Unique
= vcp
->f
.fid
.Fid
.Volume
;
900 /* any other vnode */
901 if (vType(vcp
) == VDIR
&& !vcp
->f
.parent
.vnode
&& vcp
->mvstat
!= AFS_MVSTAT_MTPT
) {
902 code
= afs_CreateReq(&treq
, credp
);
904 #ifdef OSI_EXPORT_DEBUG
905 printk("afs: get_parent(0x%08x/%d/%d.%d): afs_CreateReq: %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
);
912 code
= update_dir_parent(treq
, vcp
);
914 #ifdef OSI_EXPORT_DEBUG
915 printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
916 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
917 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
, code
);
919 dp
= ERR_PTR(-ENOENT
);
925 tfid
.Cell
= vcp
->f
.fid
.Cell
;
926 tfid
.Fid
.Volume
= vcp
->f
.fid
.Fid
.Volume
;
927 tfid
.Fid
.Vnode
= vcp
->f
.parent
.vnode
;
928 tfid
.Fid
.Unique
= vcp
->f
.parent
.unique
;
931 #ifdef OSI_EXPORT_DEBUG
932 printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
933 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
934 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
,
935 tfid
.Cell
, tfid
.Fid
.Volume
, tfid
.Fid
.Vnode
, tfid
.Fid
.Unique
);
938 dp
= get_dentry_from_fid(credp
, &tfid
);
940 #ifdef OSI_EXPORT_DEBUG
941 printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
942 vcp
->f
.fid
.Cell
, vcp
->f
.fid
.Fid
.Volume
,
943 vcp
->f
.fid
.Fid
.Vnode
, vcp
->f
.fid
.Fid
.Unique
);
945 dp
= ERR_PTR(-ENOENT
);
949 afs_DestroyReq(treq
);
957 struct export_operations afs_export_ops
= {
958 .encode_fh
= afs_encode_fh
,
959 #if defined(NEW_EXPORT_OPS)
960 .fh_to_dentry
= afs_fh_to_dentry
,
962 .decode_fh
= afs_decode_fh
,
963 .get_dentry
= afs_export_get_dentry
,
965 .get_name
= afs_export_get_name
,
966 .get_parent
= afs_export_get_parent
,