nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
                                           struct nfsd3_attrstat *resp)
 {
-       int     nfserr;
+       int     err, nfserr;
 
        dprintk("nfsd: GETATTR(3)  %s\n",
-                               SVCFH_fmt(&argp->fh));
+               SVCFH_fmt(&argp->fh));
 
        fh_copy(&resp->fh, &argp->fh);
        nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+       if (nfserr)
+               RETURN_STATUS(nfserr);
+
+       err = vfs_getattr(resp->fh.fh_export->ex_mnt,
+                         resp->fh.fh_dentry, &resp->stat);
+       nfserr = nfserrno(err);
+
        RETURN_STATUS(nfserr);
 }
 
 
 }
 
 static inline u32 *
-encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
+             struct kstat *stat)
 {
-       struct vfsmount *mnt = fhp->fh_export->ex_mnt;
        struct dentry   *dentry = fhp->fh_dentry;
-       struct kstat stat;
        struct timespec time;
 
-       vfs_getattr(mnt, dentry, &stat);
-
-       *p++ = htonl(nfs3_ftypes[(stat.mode & S_IFMT) >> 12]);
-       *p++ = htonl((u32) stat.mode);
-       *p++ = htonl((u32) stat.nlink);
-       *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
-       *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
-       if (S_ISLNK(stat.mode) && stat.size > NFS3_MAXPATHLEN) {
+       *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
+       *p++ = htonl((u32) stat->mode);
+       *p++ = htonl((u32) stat->nlink);
+       *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
+       *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
+       if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
                p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
        } else {
-               p = xdr_encode_hyper(p, (u64) stat.size);
+               p = xdr_encode_hyper(p, (u64) stat->size);
        }
-       p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9);
-       *p++ = htonl((u32) MAJOR(stat.rdev));
-       *p++ = htonl((u32) MINOR(stat.rdev));
+       p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
+       *p++ = htonl((u32) MAJOR(stat->rdev));
+       *p++ = htonl((u32) MINOR(stat->rdev));
        if (is_fsid(fhp, rqstp->rq_reffh))
                p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
        else
-               p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat.dev));
-       p = xdr_encode_hyper(p, (u64) stat.ino);
-       p = encode_time3(p, &stat.atime);
+               p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev));
+       p = xdr_encode_hyper(p, (u64) 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.ctime);
+       p = encode_time3(p, &stat->ctime);
 
        return p;
 }
 {
        struct dentry *dentry = fhp->fh_dentry;
        if (dentry && dentry->d_inode != NULL) {
-               *p++ = xdr_one;         /* attributes follow */
-               return encode_fattr3(rqstp, p, fhp);
+               int err;
+               struct kstat stat;
+
+               err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
+               if (!err) {
+                       *p++ = xdr_one;         /* attributes follow */
+                       return encode_fattr3(rqstp, p, fhp, &stat);
+               }
        }
        *p++ = xdr_zero;
        return p;
                                        struct nfsd3_attrstat *resp)
 {
        if (resp->status == 0)
-               p = encode_fattr3(rqstp, p, &resp->fh);
+               p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
        return xdr_ressize_check(rqstp, p);
 }
 
 
 }
 
 static inline u32 *
-encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
+            struct kstat *stat)
 {
-       struct vfsmount *mnt = fhp->fh_export->ex_mnt;
        struct dentry   *dentry = fhp->fh_dentry;
-       struct kstat stat;
        int type;
        struct timespec time;
 
-       vfs_getattr(mnt, dentry, &stat);
-       type = (stat.mode & S_IFMT);
+       type = (stat->mode & S_IFMT);
 
        *p++ = htonl(nfs_ftypes[type >> 12]);
-       *p++ = htonl((u32) stat.mode);
-       *p++ = htonl((u32) stat.nlink);
-       *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
-       *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
+       *p++ = htonl((u32) stat->mode);
+       *p++ = htonl((u32) stat->nlink);
+       *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
+       *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
 
-       if (S_ISLNK(type) && stat.size > NFS_MAXPATHLEN) {
+       if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
                *p++ = htonl(NFS_MAXPATHLEN);
        } else {
-               *p++ = htonl((u32) stat.size);
+               *p++ = htonl((u32) stat->size);
        }
-       *p++ = htonl((u32) stat.blksize);
+       *p++ = htonl((u32) stat->blksize);
        if (S_ISCHR(type) || S_ISBLK(type))
-               *p++ = htonl(new_encode_dev(stat.rdev));
+               *p++ = htonl(new_encode_dev(stat->rdev));
        else
                *p++ = htonl(0xffffffff);
-       *p++ = htonl((u32) stat.blocks);
+       *p++ = htonl((u32) stat->blocks);
        if (is_fsid(fhp, rqstp->rq_reffh))
                *p++ = htonl((u32) fhp->fh_export->ex_fsid);
        else
-               *p++ = htonl(new_encode_dev(stat.dev));
-       *p++ = htonl((u32) stat.ino);
-       *p++ = htonl((u32) stat.atime.tv_sec);
-       *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0);
+               *p++ = htonl(new_encode_dev(stat->dev));
+       *p++ = htonl((u32) stat->ino);
+       *p++ = htonl((u32) stat->atime.tv_sec);
+       *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
        lease_get_mtime(dentry->d_inode, &time); 
        *p++ = htonl((u32) time.tv_sec);
        *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); 
-       *p++ = htonl((u32) stat.ctime.tv_sec);
-       *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0);
+       *p++ = htonl((u32) stat->ctime.tv_sec);
+       *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0);
 
        return p;
 }
 /* Helper function for NFSv2 ACL code */
 u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
 {
-       return encode_fattr(rqstp, p, fhp);
+       struct kstat stat;
+       vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat);
+       return encode_fattr(rqstp, p, fhp, &stat);
 }
 
 /*
 nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
                                        struct nfsd_attrstat *resp)
 {
-       p = encode_fattr(rqstp, p, &resp->fh);
+       p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        return xdr_ressize_check(rqstp, p);
 }
 
                                        struct nfsd_diropres *resp)
 {
        p = encode_fh(p, &resp->fh);
-       p = encode_fattr(rqstp, p, &resp->fh);
+       p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        return xdr_ressize_check(rqstp, p);
 }
 
 nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
                                        struct nfsd_readres *resp)
 {
-       p = encode_fattr(rqstp, p, &resp->fh);
+       p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        *p++ = htonl(resp->count);
        xdr_ressize_check(rqstp, p);
 
 
  * As this calls fsync (not fdatasync) there is no need for a write_inode
  * after it.
  */
-static inline void nfsd_dosync(struct file *filp, struct dentry *dp,
-                              struct file_operations *fop)
+static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
+                             struct file_operations *fop)
 {
        struct inode *inode = dp->d_inode;
        int (*fsync) (struct file *, struct dentry *, int);
+       int err = nfs_ok;
 
        filemap_fdatawrite(inode->i_mapping);
        if (fop && (fsync = fop->fsync))
-               fsync(filp, dp, 0);
+               err=fsync(filp, dp, 0);
        filemap_fdatawait(inode->i_mapping);
+
+       return nfserrno(err);
 }
        
 
-static void
+static int
 nfsd_sync(struct file *filp)
 {
+        int err;
        struct inode *inode = filp->f_dentry->d_inode;
        dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
        down(&inode->i_sem);
-       nfsd_dosync(filp, filp->f_dentry, filp->f_op);
+       err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
        up(&inode->i_sem);
+
+       return err;
 }
 
 void
 
                        if (inode->i_state & I_DIRTY) {
                                dprintk("nfsd: write sync %d\n", current->pid);
-                               nfsd_sync(file);
+                               err=nfsd_sync(file);
                        }
 #if 0
                        wake_up(&inode->i_wait);
                return err;
        if (EX_ISSYNC(fhp->fh_export)) {
                if (file->f_op && file->f_op->fsync) {
-                       nfsd_sync(file);
+                       err = nfsd_sync(file);
                } else {
                        err = nfserr_notsupp;
                }
 
 
 struct nfsd_attrstat {
        struct svc_fh           fh;
+       struct kstat            stat;
 };
 
 struct nfsd_diropres  {
        struct svc_fh           fh;
+       struct kstat            stat;
 };
 
 struct nfsd_readlinkres {
 struct nfsd_readres {
        struct svc_fh           fh;
        unsigned long           count;
+       struct kstat            stat;
 };
 
 struct nfsd_readdirres {
 
 struct nfsd3_attrstat {
        __u32                   status;
        struct svc_fh           fh;
+       struct kstat            stat;
 };
 
 /* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */