encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
              struct kstat *stat)
 {
-       struct dentry   *dentry = fhp->fh_dentry;
-       struct timespec time;
-
        *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
        *p++ = htonl((u32) stat->mode);
        *p++ = htonl((u32) stat->nlink);
        *p++ = htonl((u32) MAJOR(stat->rdev));
        *p++ = htonl((u32) MINOR(stat->rdev));
        p = encode_fsid(p, fhp);
-       p = xdr_encode_hyper(p, (u64) stat->ino);
+       p = xdr_encode_hyper(p, stat->ino);
        p = encode_time3(p, &stat->atime);
-       lease_get_mtime(dentry->d_inode, &time); 
-       p = encode_time3(p, &time);
+       p = encode_time3(p, &stat->mtime);
        p = encode_time3(p, &stat->ctime);
 
        return p;
 static __be32 *
 encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
-       struct inode    *inode = fhp->fh_dentry->d_inode;
-
        /* Attributes to follow */
        *p++ = xdr_one;
-
-       *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
-       *p++ = htonl((u32) fhp->fh_post_mode);
-       *p++ = htonl((u32) fhp->fh_post_nlink);
-       *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
-       *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
-       if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
-               p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
-       } else {
-               p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
-       }
-       p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
-       *p++ = fhp->fh_post_rdev[0];
-       *p++ = fhp->fh_post_rdev[1];
-       p = encode_fsid(p, fhp);
-       p = xdr_encode_hyper(p, (u64) inode->i_ino);
-       p = encode_time3(p, &fhp->fh_post_atime);
-       p = encode_time3(p, &fhp->fh_post_mtime);
-       p = encode_time3(p, &fhp->fh_post_ctime);
-
-       return p;
+       return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr);
 }
 
 /*
                err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
                if (!err) {
                        *p++ = xdr_one;         /* attributes follow */
+                       lease_get_mtime(dentry->d_inode, &stat.mtime);
                        return encode_fattr3(rqstp, p, fhp, &stat);
                }
        }
        return encode_post_op_attr(rqstp, p, fhp);
 }
 
+/*
+ * Fill in the post_op attr for the wcc data
+ */
+void fill_post_wcc(struct svc_fh *fhp)
+{
+       int err;
+
+       if (fhp->fh_post_saved)
+               printk("nfsd: inode locked twice during operation.\n");
+
+       err = vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry,
+                       &fhp->fh_post_attr);
+       if (err)
+               fhp->fh_post_saved = 0;
+       else
+               fhp->fh_post_saved = 1;
+}
 
 /*
  * XDR decode functions
 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_attrstat *resp)
 {
-       if (resp->status == 0)
+       if (resp->status == 0) {
+               lease_get_mtime(resp->fh.fh_dentry->d_inode,
+                               &resp->stat.mtime);
                p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
+       }
        return xdr_ressize_check(rqstp, p);
 }
 
 
 static __be32 *
 encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
-            int namlen, ino_t ino)
+            int namlen, u64 ino)
 {
        *p++ = xdr_one;                          /* mark entry present */
        p    = xdr_encode_hyper(p, ino);         /* file id */
 #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
 static int
 encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
-            loff_t offset, ino_t ino, unsigned int d_type, int plus)
+            loff_t offset, u64 ino, unsigned int d_type, int plus)
 {
        struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
                                                        common);
 
        if (bmval0 & FATTR4_WORD0_FILEID) {
                if ((buflen -= 8) < 0)
                        goto out_resource;
-               WRITE64((u64) stat.ino);
+               WRITE64(stat.ino);
        }
        if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
                if ((buflen -= 8) < 0)
                WRITE32(stat.mtime.tv_nsec);
        }
        if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
-               struct dentry *mnt_pnt, *mnt_root;
-
                if ((buflen -= 8) < 0)
                        goto out_resource;
-               mnt_root = exp->ex_mnt->mnt_root;
-               if (mnt_root->d_inode == dentry->d_inode) {
-                       mnt_pnt = exp->ex_mnt->mnt_mountpoint;
-                       WRITE64((u64) mnt_pnt->d_inode->i_ino);
-               } else
-                       WRITE64((u64) stat.ino);
+               if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) {
+                       err = vfs_getattr(exp->ex_mnt->mnt_parent,
+                               exp->ex_mnt->mnt_mountpoint, &stat);
+                       if (err)
+                               goto out_nfserr;
+               }
+               WRITE64(stat.ino);
        }
        *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
        *countp = p - buffer;
 
        struct timespec         fh_pre_ctime;   /* ctime before oper */
 
        /* Post-op attributes saved in fh_unlock */
-       umode_t                 fh_post_mode;   /* i_mode */
-       nlink_t                 fh_post_nlink;  /* i_nlink */
-       uid_t                   fh_post_uid;    /* i_uid */
-       gid_t                   fh_post_gid;    /* i_gid */
-       __u64                   fh_post_size;   /* i_size */
-       unsigned long           fh_post_blocks; /* i_blocks */
-       unsigned long           fh_post_blksize;/* i_blksize */
-       __be32                  fh_post_rdev[2];/* i_rdev */
-       struct timespec         fh_post_atime;  /* i_atime */
-       struct timespec         fh_post_mtime;  /* i_mtime */
-       struct timespec         fh_post_ctime;  /* i_ctime */
+       struct kstat            fh_post_attr;   /* full attrs after operation */
 #endif /* CONFIG_NFSD_V3 */
 
 } svc_fh;
        if (!fhp->fh_pre_saved) {
                fhp->fh_pre_mtime = inode->i_mtime;
                fhp->fh_pre_ctime = inode->i_ctime;
-                       fhp->fh_pre_size  = inode->i_size;
-                       fhp->fh_pre_saved = 1;
+               fhp->fh_pre_size  = inode->i_size;
+               fhp->fh_pre_saved = 1;
        }
 }
 
-/*
- * Fill in the post_op attr for the wcc data
- */
-static inline void
-fill_post_wcc(struct svc_fh *fhp)
-{
-       struct inode    *inode = fhp->fh_dentry->d_inode;
-
-       if (fhp->fh_post_saved)
-               printk("nfsd: inode locked twice during operation.\n");
-
-       fhp->fh_post_mode       = inode->i_mode;
-       fhp->fh_post_nlink      = inode->i_nlink;
-       fhp->fh_post_uid        = inode->i_uid;
-       fhp->fh_post_gid        = inode->i_gid;
-       fhp->fh_post_size       = inode->i_size;
-       fhp->fh_post_blksize    = BLOCK_SIZE;
-       fhp->fh_post_blocks     = inode->i_blocks;
-       fhp->fh_post_rdev[0]    = htonl((u32)imajor(inode));
-       fhp->fh_post_rdev[1]    = htonl((u32)iminor(inode));
-       fhp->fh_post_atime      = inode->i_atime;
-       fhp->fh_post_mtime      = inode->i_mtime;
-       fhp->fh_post_ctime      = inode->i_ctime;
-       fhp->fh_post_saved      = 1;
-}
+extern void fill_post_wcc(struct svc_fh *);
 #else
 #define        fill_pre_wcc(ignored)
 #define fill_post_wcc(notused)