* the write call).
  */
 static inline __be32
-nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, umode_t requested)
+nfsd_mode_check(struct svc_rqst *rqstp, struct dentry *dentry,
+               umode_t requested)
 {
-       mode &= S_IFMT;
+       umode_t mode = d_inode(dentry)->i_mode & S_IFMT;
 
        if (requested == 0) /* the caller doesn't care */
                return nfs_ok;
-       if (mode == requested)
+       if (mode == requested) {
+               if (mode == S_IFDIR && !d_can_lookup(dentry)) {
+                       WARN_ON_ONCE(1);
+                       return nfserr_notdir;
+               }
                return nfs_ok;
+       }
        /*
         * v4 has an error more specific than err_notdir which we should
         * return in preference to err_notdir:
        if (error)
                goto out;
 
-       error = nfsd_mode_check(rqstp, d_inode(dentry)->i_mode, type);
+       error = nfsd_mode_check(rqstp, dentry, type);
        if (error)
                goto out;
 
 
        dentry = fhp->fh_dentry;
        dirp = d_inode(dentry);
 
-       err = nfserr_notdir;
-       if (!dirp->i_op->lookup)
-               goto out;
        /*
         * Check whether the response file handle has been verified yet.
         * If it has, the parent directory should already be locked.
        dentry = fhp->fh_dentry;
        dirp = d_inode(dentry);
 
-       /* Get all the sanity checks out of the way before
-        * we lock the parent. */
-       err = nfserr_notdir;
-       if (!dirp->i_op->lookup)
-               goto out;
-
        host_err = fh_want_write(fhp);
        if (host_err)
                goto out_nfserr;