libafs: allocate vattrs in LINUX to reduce stack used
[openafs.git] / src / afs / LINUX / osi_export.c
index 24d5063..b68f6b2 100644 (file)
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID
-    ("$Header$");
 
 #include <linux/module.h> /* early to avoid printf->printk mapping */
 #include <linux/fs.h>
-#ifdef EXPORTFS_H_EXISTS
+#ifdef HAVE_LINUX_EXPORTFS_H
 #include <linux/exportfs.h>
 #endif
 #include "afs/sysincludes.h"
 #include "afsincludes.h"
 #include "afs/afs_dynroot.h"
-#include "h/smp_lock.h"
+
+#if !defined(AFS_NONFSTRANS)
 
 /* #define OSI_EXPORT_DEBUG */
 
 extern struct dentry_operations afs_dentry_operations;
+#if defined(NEW_EXPORT_OPS)
+static struct dentry *afs_export_get_dentry(struct super_block *sb,
+                                           void *inump);
+#endif
 
 struct get_name_data {
     char *name;
@@ -76,11 +79,11 @@ static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
 
 #ifdef OSI_EXPORT_DEBUG
     printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
-          tvc->fid.Cell,      tvc->fid.Fid.Volume,
-          tvc->fid.Fid.Vnode, tvc->fid.Fid.Unique);
+          tvc->f.fid.Cell,      tvc->f.fid.Fid.Volume,
+          tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique);
 #endif
-    if (afs_IsDynrootAnyFid(&tvc->fid)) {
-       vntype = VNUM_TO_VNTYPE(tvc->fid.Fid.Vnode);
+    if (afs_IsDynrootAnyFid(&tvc->f.fid)) {
+       vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode);
        switch (vntype) {
            case 0:
                /* encode as a normal filehandle */
@@ -95,7 +98,7 @@ static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
            case VN_TYPE_CELL:
            case VN_TYPE_ALIAS:
                AFS_GLOCK();
-               tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->fid.Fid.Vnode),
+               tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode),
                                        READ_LOCK);
                if (!tc) {
                    AFS_GUNLOCK();
@@ -105,15 +108,15 @@ static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
                afs_PutCell(tc, READ_LOCK);
                AFS_GUNLOCK();
                if (vntype == VN_TYPE_MOUNT) {
-                   fh[4] = htonl(tvc->fid.Fid.Unique);
+                   fh[4] = htonl(tvc->f.fid.Fid.Unique);
                    *max_len = 5;
                    return AFSFH_DYN_MOUNT;
                }
                *max_len = 4;
                if (vntype == VN_TYPE_CELL) {
-                   return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->fid.Fid.Vnode);
+                   return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
                } else {
-                   return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->fid.Fid.Vnode);
+                   return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
                }
 
            case VN_TYPE_SYMLINK:
@@ -128,16 +131,16 @@ static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
     if (*max_len < 7) {
        /* not big enough for a migratable filehandle */
        /* always encode in network order */
-       fh[0] = htonl(tvc->fid.Cell);
-       fh[1] = htonl(tvc->fid.Fid.Volume);
-       fh[2] = htonl(tvc->fid.Fid.Vnode);
-       fh[3] = htonl(tvc->fid.Fid.Unique);
+       fh[0] = htonl(tvc->f.fid.Cell);
+       fh[1] = htonl(tvc->f.fid.Fid.Volume);
+       fh[2] = htonl(tvc->f.fid.Fid.Vnode);
+       fh[3] = htonl(tvc->f.fid.Fid.Unique);
        *max_len = 4;
        return AFSFH_NET_VENUSFID;
     }
 
     AFS_GLOCK();
-    tc = afs_GetCell(tvc->fid.Cell, READ_LOCK);
+    tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK);
     if (!tc) {
        AFS_GUNLOCK();
        return 255;
@@ -146,22 +149,31 @@ static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
     afs_PutCell(tc, READ_LOCK);
     AFS_GUNLOCK();
     /* always encode in network order */
-    fh[4] = htonl(tvc->fid.Fid.Volume);
-    fh[5] = htonl(tvc->fid.Fid.Vnode);
-    fh[6] = htonl(tvc->fid.Fid.Unique);
+    fh[4] = htonl(tvc->f.fid.Fid.Volume);
+    fh[5] = htonl(tvc->f.fid.Fid.Vnode);
+    fh[6] = htonl(tvc->f.fid.Fid.Unique);
 
     *max_len = 7;
     return AFSFH_NET_CELLFID;
 }
 
+#if defined(NEW_EXPORT_OPS)
+static struct dentry *afs_fh_to_dentry(struct super_block *sb, struct fid *fh_fid,
+                                   int fh_len, int fh_type)
+#else
 static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
                                    int fh_len, int fh_type,
                                    int (*acceptable)(void *, struct dentry *),
                                    void *context)
+#endif
 {
     struct VenusFid fid;
     struct cell *tc;
     struct dentry *result;
+#if defined(NEW_EXPORT_OPS)
+    __u32 *fh = (__u32 *)fh_fid->raw;
+#endif
+
 
     switch (fh_type) {
        case AFSFH_VENUSFID:
@@ -191,8 +203,6 @@ static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
            break;
 
        case AFSFH_NET_VENUSFID:
-           if (fh_len != 4)
-               return NULL;
            fid.Cell       = ntohl(fh[0]);
            fid.Fid.Volume = ntohl(fh[1]);
            fid.Fid.Vnode  = ntohl(fh[2]);
@@ -275,8 +285,14 @@ static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
            return NULL;
     }
 
+#if defined(NEW_EXPORT_OPS)
+    result = afs_export_get_dentry(sb, &fid);
+#else
     result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
                                                   acceptable, context);
+
+#endif
+
 #ifdef OSI_EXPORT_DEBUG
     if (!result) {
        printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
@@ -299,12 +315,12 @@ static int update_dir_parent(struct vrequest *areq, struct vcache *adp)
     int code;
 
 redo:
-    if (!(adp->states & CStatd)) {
+    if (!(adp->f.states & CStatd)) {
        if ((code = afs_VerifyVCache2(adp, areq))) {
 #ifdef OSI_EXPORT_DEBUG
            printk("afs: update_dir_parent(0x%08x/%d/%d.%d): VerifyVCache2: %d\n",
-                  adp->fid.Cell,      adp->fid.Fid.Volume,
-                  adp->fid.Fid.Vnode, adp->fid.Fid.Unique, code);
+                  adp->f.fid.Cell,      adp->f.fid.Fid.Volume,
+                  adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
 #endif
            return code;
        }
@@ -314,8 +330,8 @@ redo:
     if (!tdc) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: update_dir_parent(0x%08x/%d/%d.%d): no dcache\n",
-              adp->fid.Cell,      adp->fid.Fid.Volume,
-              adp->fid.Fid.Vnode, adp->fid.Fid.Unique);
+              adp->f.fid.Cell,      adp->f.fid.Fid.Volume,
+              adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
 #endif
        return EIO;
     }
@@ -331,24 +347,24 @@ redo:
      * 1. The cache data is being fetched by another process.
      * 2. The cache data is no longer valid
      */
-    while ((adp->states & CStatd)
+    while ((adp->f.states & CStatd)
           && (tdc->dflags & DFFetching)
-          && hsame(adp->m.DataVersion, tdc->f.versionNo)) {
+          && hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
        ReleaseReadLock(&tdc->lock);
        ReleaseSharedLock(&adp->lock);
        afs_osi_Sleep(&tdc->validPos);
        ObtainSharedLock(&adp->lock, 802);
        ObtainReadLock(&tdc->lock);
     }
-    if (!(adp->states & CStatd)
-       || !hsame(adp->m.DataVersion, tdc->f.versionNo)) {
+    if (!(adp->f.states & CStatd)
+       || !hsame(adp->f.m.DataVersion, tdc->f.versionNo)) {
        ReleaseReadLock(&tdc->lock);
        ReleaseSharedLock(&adp->lock);
        afs_PutDCache(tdc);
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: update_dir_parent(0x%08x/%d/%d.%d): dir changed; retrying\n",
-              adp->fid.Cell,      adp->fid.Fid.Volume,
-              adp->fid.Fid.Vnode, adp->fid.Fid.Unique);
+              adp->f.fid.Cell,      adp->f.fid.Fid.Volume,
+              adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique);
 #endif
        goto redo;
     }
@@ -362,19 +378,19 @@ redo:
 
     if (!code) {
        UpgradeSToWLock(&adp->lock, 803);
-       adp->parentVnode  = tfid.Fid.Vnode;
-       adp->parentUnique = tfid.Fid.Unique;
+       adp->f.parent.vnode  = tfid.Fid.Vnode;
+       adp->f.parent.unique = tfid.Fid.Unique;
     }
 #ifdef OSI_EXPORT_DEBUG
     if (code) {
        printk("afs: update_dir_parent(0x%08x/%d/%d.%d): afs_dir_Lookup: %d\n",
-              adp->fid.Cell,      adp->fid.Fid.Volume,
-              adp->fid.Fid.Vnode, adp->fid.Fid.Unique, code);
+              adp->f.fid.Cell,      adp->f.fid.Fid.Volume,
+              adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique, code);
     } else {
        printk("afs: update_dir_parent(0x%08x/%d/%d.%d) => %d.%d\n",
-              adp->fid.Cell,      adp->fid.Fid.Volume,
-              adp->fid.Fid.Vnode, adp->fid.Fid.Unique,
-              adp->parentVnode,   adp->parentUnique);
+              adp->f.fid.Cell,      adp->f.fid.Fid.Volume,
+              adp->f.fid.Fid.Vnode, adp->f.fid.Fid.Unique,
+              adp->parent.vnode,   adp->parent.unique);
     }
 #endif
     ReleaseSharedLock(&adp->lock);
@@ -396,12 +412,12 @@ static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
        return 0;
 
     /* Figure out what FID to look for */
-    tvp = afs_GetVolume(&(*vcpp)->fid, 0, READ_LOCK);
+    tvp = afs_GetVolume(&(*vcpp)->f.fid, 0, READ_LOCK);
     if (!tvp) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n",
-              (*vcpp)->fid.Cell,      (*vcpp)->fid.Fid.Volume,
-              (*vcpp)->fid.Fid.Vnode, (*vcpp)->fid.Fid.Unique);
+              (*vcpp)->f.fid.Cell,      (*vcpp)->f.fid.Fid.Volume,
+              (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique);
 #endif
        return ENOENT;
     }
@@ -412,8 +428,8 @@ static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
     if (!tvc) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n",
-              (*vcpp)->fid.Cell,      (*vcpp)->fid.Fid.Volume,
-              (*vcpp)->fid.Fid.Vnode, (*vcpp)->fid.Fid.Unique,
+              (*vcpp)->f.fid.Cell,      (*vcpp)->f.fid.Fid.Volume,
+              (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique,
               tfid.Cell,          tfid.Fid.Volume,
               tfid.Fid.Vnode,     tfid.Fid.Unique);
 #endif
@@ -448,28 +464,36 @@ static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp)
  */
 static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
 {
-    struct vrequest treq;
+    struct vrequest *treq = NULL;
     struct vcache *vcp;
-    struct vattr vattr;
+    struct vattr *vattr = NULL;
     struct inode *ip;
     struct dentry *dp;
     afs_int32 code;
 
-    code = afs_InitReq(&treq, credp);
+    code = afs_CreateAttr(&vattr);
+    if (code) {
+       return ERR_PTR(-afs_CheckCode(code, NULL, xxx));
+    }
+
+    code = afs_CreateReq(&treq, credp);
     if (code) {
 #ifdef OSI_EXPORT_DEBUG
-       printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
+       printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
               afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
               code);
 #endif
-       return ERR_PTR(-afs_CheckCode(code, &treq, 101));
+       afs_DestroyAttr(vattr);
+       return ERR_PTR(-afs_CheckCode(code, NULL, 101));
     }
-    vcp = afs_GetVCache(afid, &treq, NULL, NULL);
+    vcp = afs_GetVCache(afid, treq, NULL, NULL);
     if (vcp == NULL) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
               afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
 #endif
+       afs_DestroyReq(treq);
+       afs_DestroyAttr(vattr);
        return NULL;
     }
 
@@ -481,14 +505,14 @@ static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
      * at parentVnode on directories, except for VIOCGETVCXSTATUS.
      * So, if this fails, we don't really care very much.
      */
-    if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->parentVnode)
-       update_dir_parent(&treq, vcp);
+    if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->f.parent.vnode)
+       update_dir_parent(treq, vcp);
 
     /*
      * If this is a volume root directory and fakestat is enabled,
      * we might need to replace the directory by a mount point.
      */
-    code = UnEvalFakeStat(&treq, &vcp);
+    code = UnEvalFakeStat(treq, &vcp);
     if (code) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
@@ -496,12 +520,15 @@ static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
               code);
 #endif
        afs_PutVCache(vcp);
-       return ERR_PTR(-afs_CheckCode(code, &treq, 101));
+       code = afs_CheckCode(code, treq, 103);
+       afs_DestroyReq(treq);
+       afs_DestroyAttr(vattr);
+       return ERR_PTR(-code);
     }
 
     ip = AFSTOV(vcp);
-    afs_getattr(vcp, &vattr, credp);
-    afs_fill_inode(ip, &vattr);
+    afs_getattr(vcp, vattr, credp);
+    afs_fill_inode(ip, vattr);
 
     /* d_alloc_anon might block, so we shouldn't hold the glock */
     AFS_GUNLOCK();
@@ -514,10 +541,14 @@ static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
        printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
               afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
 #endif
+       afs_DestroyReq(treq);
+       afs_DestroyAttr(vattr);
        return ERR_PTR(-ENOMEM);
     }
 
     dp->d_op = &afs_dentry_operations;
+    afs_DestroyReq(treq);
+    afs_DestroyAttr(vattr);
     return dp;
 }
 
@@ -528,13 +559,11 @@ static struct dentry *afs_export_get_dentry(struct super_block *sb,
     cred_t *credp;
 
     credp = crref();
-    lock_kernel();
     AFS_GLOCK();
 
     dp = get_dentry_from_fid(credp, inump);
 
     AFS_GUNLOCK();
-    unlock_kernel();
     crfree(credp);
 
     return dp;
@@ -562,7 +591,7 @@ static int afs_export_get_name(struct dentry *parent, char *name,
 {
     struct afs_fakestat_state fakestate;
     struct get_name_data data;
-    struct vrequest treq;
+    struct vrequest *treq = NULL;
     struct volume *tvp;
     struct vcache *vcp;
     struct dcache *tdc;
@@ -592,7 +621,6 @@ static int afs_export_get_name(struct dentry *parent, char *name,
     afs_InitFakeStat(&fakestate);
 
     credp = crref();
-    lock_kernel();
     AFS_GLOCK();
 
     vcp = VTOAFS(child->d_inode);
@@ -602,10 +630,10 @@ static int afs_export_get_name(struct dentry *parent, char *name,
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
               parent->d_name.name ? (char *)parent->d_name.name : "?",
-              vcp->fid.Cell,      vcp->fid.Fid.Volume,
-              vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
+              vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+              vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
 #endif
-       data.fid = vcp->fid;
+       data.fid = vcp->f.fid;
        if (VTOAFS(parent->d_inode) == afs_globalVp)
            strcpy(name, AFS_DYNROOT_MOUNTNAME);
        else
@@ -615,13 +643,13 @@ static int afs_export_get_name(struct dentry *parent, char *name,
 
     /* Figure out what FID to look for */
     if (vcp->mvstat == 2) { /* volume root */
-       tvp = afs_GetVolume(&vcp->fid, 0, READ_LOCK);
+       tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
        if (!tvp) {
 #ifdef OSI_EXPORT_DEBUG
            printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
                   parent->d_name.name ? (char *)parent->d_name.name : "?",
-                  vcp->fid.Cell,      vcp->fid.Fid.Volume,
-                  vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
+                  vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+                  vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
 #endif
            code = ENOENT;
            goto done;
@@ -629,7 +657,7 @@ static int afs_export_get_name(struct dentry *parent, char *name,
        data.fid = tvp->mtpoint;
        afs_PutVolume(tvp, READ_LOCK);
     } else {
-       data.fid = vcp->fid;
+       data.fid = vcp->f.fid;
     }
 
     vcp = VTOAFS(parent->d_inode);
@@ -638,14 +666,13 @@ static int afs_export_get_name(struct dentry *parent, char *name,
           parent->d_name.name ? (char *)parent->d_name.name : "?",
           data.fid.Cell,      data.fid.Fid.Volume,
           data.fid.Fid.Vnode, data.fid.Fid.Unique,
-          vcp->fid.Cell,      vcp->fid.Fid.Volume,
-          vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
+          vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+          vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
 #endif
-
-    code = afs_InitReq(&treq, credp);
+    code = afs_CreateReq(&treq, credp);
     if (code) {
 #ifdef OSI_EXPORT_DEBUG
-       printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n",
+       printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
               parent->d_name.name ? (char *)parent->d_name.name : "?",
               data.fid.Cell,      data.fid.Fid.Volume,
               data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
@@ -662,7 +689,7 @@ static int afs_export_get_name(struct dentry *parent, char *name,
               data.fid.Cell,      data.fid.Fid.Volume,
               data.fid.Fid.Vnode, data.fid.Fid.Unique);
 #endif
-       vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
+       vcp = afs_GetVCache(&data.fid, treq, NULL, NULL);
        if (vcp) {
            ObtainReadLock(&vcp->lock);
            if (strlen(vcp->linkData + 1) <= NAME_MAX)
@@ -683,12 +710,12 @@ static int afs_export_get_name(struct dentry *parent, char *name,
        goto done;
     }
 
-    code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
+    code = afs_EvalFakeStat(&vcp, &fakestate, treq);
     if (code)
        goto done;
 
-    if (vcp->fid.Cell != data.fid.Cell ||
-       vcp->fid.Fid.Volume != data.fid.Fid.Volume) {
+    if (vcp->f.fid.Cell != data.fid.Cell ||
+       vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) {
        /* parent is not the expected cell and volume; thus it
         * cannot possibly contain the fid we are looking for */
 #ifdef OSI_EXPORT_DEBUG
@@ -696,7 +723,7 @@ static int afs_export_get_name(struct dentry *parent, char *name,
               parent->d_name.name ? (char *)parent->d_name.name : "?",
               data.fid.Cell,      data.fid.Fid.Volume,
               data.fid.Fid.Vnode, data.fid.Fid.Unique,
-              vcp->fid.Cell,      vcp->fid.Fid.Volume);
+              vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume);
 #endif
        code = ENOENT;
        goto done;
@@ -704,29 +731,29 @@ static int afs_export_get_name(struct dentry *parent, char *name,
 
 
 redo:
-    if (!(vcp->states & CStatd)) {
-       if ((code = afs_VerifyVCache2(vcp, &treq))) {
+    if (!(vcp->f.states & CStatd)) {
+       if ((code = afs_VerifyVCache2(vcp, treq))) {
 #ifdef OSI_EXPORT_DEBUG
            printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
                   parent->d_name.name ? (char *)parent->d_name.name : "?",
                   data.fid.Cell,      data.fid.Fid.Volume,
                   data.fid.Fid.Vnode, data.fid.Fid.Unique,
-                  vcp->fid.Cell,      vcp->fid.Fid.Volume,
-                  vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
+                  vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+                  vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
 #endif
            goto done;
        }
     }
 
-    tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
+    tdc = afs_GetDCache(vcp, (afs_size_t) 0, treq, &dirOffset, &dirLen, 1);
     if (!tdc) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
               parent->d_name.name ? (char *)parent->d_name.name : "?",
               data.fid.Cell,      data.fid.Fid.Volume,
               data.fid.Fid.Vnode, data.fid.Fid.Unique,
-              vcp->fid.Cell,      vcp->fid.Fid.Volume,
-              vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
+              vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+              vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
 #endif
        code = EIO;
        goto done;
@@ -741,17 +768,17 @@ redo:
      * 1. The cache data is being fetched by another process.
      * 2. The cache data is no longer valid
      */
-    while ((vcp->states & CStatd)
+    while ((vcp->f.states & CStatd)
           && (tdc->dflags & DFFetching)
-          && hsame(vcp->m.DataVersion, tdc->f.versionNo)) {
+          && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
        ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&vcp->lock);
        afs_osi_Sleep(&tdc->validPos);
        ObtainReadLock(&vcp->lock);
        ObtainReadLock(&tdc->lock);
     }
-    if (!(vcp->states & CStatd)
-       || !hsame(vcp->m.DataVersion, tdc->f.versionNo)) {
+    if (!(vcp->f.states & CStatd)
+       || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
        ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&vcp->lock);
        afs_PutDCache(tdc);
@@ -760,8 +787,8 @@ redo:
               parent->d_name.name ? (char *)parent->d_name.name : "?",
               data.fid.Cell,      data.fid.Fid.Volume,
               data.fid.Fid.Vnode, data.fid.Fid.Unique,
-              vcp->fid.Cell,      vcp->fid.Fid.Volume,
-              vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
+              vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+              vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
 #endif
        goto redo;
     }
@@ -783,8 +810,8 @@ redo:
               parent->d_name.name ? (char *)parent->d_name.name : "?",
               data.fid.Cell,      data.fid.Fid.Volume,
               data.fid.Fid.Vnode, data.fid.Fid.Unique,
-              vcp->fid.Cell,      vcp->fid.Fid.Volume,
-              vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
+              vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
+              vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
 #endif
     }
 
@@ -800,10 +827,10 @@ done:
               data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
     }
     afs_PutFakeStat(&fakestate);
+    code = afs_CheckCode(code, treq, 102);
+    afs_DestroyReq(treq);
     AFS_GUNLOCK();
-    unlock_kernel();
     crfree(credp);
-    code = afs_CheckCode(code, &treq, 102);
     return -code;
 }
 
@@ -811,7 +838,7 @@ done:
 static struct dentry *afs_export_get_parent(struct dentry *child)
 {
     struct VenusFid tfid;
-    struct vrequest treq;
+    struct vrequest *treq = NULL;
     struct cell *tcell;
     struct vcache *vcp;
     struct dentry *dp = NULL;
@@ -829,17 +856,16 @@ static struct dentry *afs_export_get_parent(struct dentry *child)
     }
 
     credp = crref();
-    lock_kernel();
     AFS_GLOCK();
 
     vcp = VTOAFS(child->d_inode);
 
     if (afs_IsDynrootMount(vcp)) {
        /* the dynmount directory; parent is always the AFS root */
-       tfid = afs_globalVp->fid;
+       tfid = afs_globalVp->f.fid;
 
     } else if (afs_IsDynrootAny(vcp) &&
-              VNUM_TO_VNTYPE(vcp->fid.Fid.Vnode) == VN_TYPE_MOUNT) {
+              VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
        /* a mount point in the dynmount directory */
        afs_GetDynrootMountFid(&tfid);
 
@@ -851,12 +877,12 @@ static struct dentry *afs_export_get_parent(struct dentry *child)
            ReleaseReadLock(&vcp->lock);
        } else {
            ReleaseReadLock(&vcp->lock);
-           tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
+           tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
            if (!tcell) {
 #ifdef OSI_EXPORT_DEBUG
                printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
-                      vcp->fid.Cell, vcp->fid.Fid.Volume,
-                      vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
+                      vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
+                      vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
 #endif
                dp = ERR_PTR(-ENOENT);
                goto done;
@@ -867,28 +893,28 @@ static struct dentry *afs_export_get_parent(struct dentry *child)
 
            afs_GetDynrootMountFid(&tfid);
            tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
-           tfid.Fid.Unique = vcp->fid.Fid.Volume;
+           tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
        }
 
     } else {
        /* any other vnode */
-       if (vType(vcp) == VDIR && !vcp->parentVnode && vcp->mvstat != 1) {
-           code = afs_InitReq(&treq, credp);
+       if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) {
+           code = afs_CreateReq(&treq, credp);
            if (code) {
 #ifdef OSI_EXPORT_DEBUG
-               printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
-                      vcp->fid.Cell, vcp->fid.Fid.Volume,
-                      vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
+               printk("afs: get_parent(0x%08x/%d/%d.%d): afs_CreateReq: %d\n",
+                      vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
+                      vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
 #endif
                dp = ERR_PTR(-ENOENT);
                goto done;
            } else {
-               code = update_dir_parent(&treq, vcp);
+               code = update_dir_parent(treq, vcp);
                if (code) {
 #ifdef OSI_EXPORT_DEBUG
                    printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
-                          vcp->fid.Cell, vcp->fid.Fid.Volume,
-                          vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique, code);
+                          vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
+                          vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
 #endif
                    dp = ERR_PTR(-ENOENT);
                    goto done;
@@ -896,16 +922,16 @@ static struct dentry *afs_export_get_parent(struct dentry *child)
            }
        }
 
-       tfid.Cell       = vcp->fid.Cell;
-       tfid.Fid.Volume = vcp->fid.Fid.Volume;
-       tfid.Fid.Vnode  = vcp->parentVnode;
-       tfid.Fid.Unique = vcp->parentUnique;
+       tfid.Cell       = vcp->f.fid.Cell;
+       tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
+       tfid.Fid.Vnode  = vcp->f.parent.vnode;
+       tfid.Fid.Unique = vcp->f.parent.unique;
     }
 
 #ifdef OSI_EXPORT_DEBUG
     printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
-          vcp->fid.Cell, vcp->fid.Fid.Volume,
-          vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique,
+          vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
+          vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
           tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
 #endif
 
@@ -913,15 +939,15 @@ static struct dentry *afs_export_get_parent(struct dentry *child)
     if (!dp) {
 #ifdef OSI_EXPORT_DEBUG
        printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
-              vcp->fid.Cell, vcp->fid.Fid.Volume,
-              vcp->fid.Fid.Vnode, vcp->fid.Fid.Unique);
+              vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
+              vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
 #endif
        dp = ERR_PTR(-ENOENT);
     }
 
 done:
+    afs_DestroyReq(treq);
     AFS_GUNLOCK();
-    unlock_kernel();
     crfree(credp);
 
     return dp;
@@ -930,8 +956,14 @@ done:
 
 struct export_operations afs_export_ops = {
     .encode_fh  = afs_encode_fh,
+#if defined(NEW_EXPORT_OPS)
+    .fh_to_dentry  = afs_fh_to_dentry,
+#else
     .decode_fh  = afs_decode_fh,
     .get_dentry = afs_export_get_dentry,
+#endif
     .get_name   = afs_export_get_name,
     .get_parent = afs_export_get_parent,
 };
+
+#endif