.need   = may_flags & NFSD_FILE_MAY_MASK,
                .net    = SVC_NET(rqstp),
        };
-       struct nfsd_file *nf, *new;
-       bool retry = true;
+       bool open_retry = true;
+       struct nfsd_file *nf;
        __be32 status;
+       int ret;
 
        status = fh_verify(rqstp, fhp, S_IFREG,
                                may_flags|NFSD_MAY_OWNER_OVERRIDE);
        key.cred = get_current_cred();
 
 retry:
-       /* Avoid allocation if the item is already in cache */
-       nf = rhashtable_lookup_fast(&nfsd_file_rhash_tbl, &key,
-                                   nfsd_file_rhash_params);
+       rcu_read_lock();
+       nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
+                              nfsd_file_rhash_params);
        if (nf)
                nf = nfsd_file_get(nf);
+       rcu_read_unlock();
        if (nf)
                goto wait_for_construction;
 
-       new = nfsd_file_alloc(&key, may_flags);
-       if (!new) {
+       nf = nfsd_file_alloc(&key, may_flags);
+       if (!nf) {
                status = nfserr_jukebox;
                goto out_status;
        }
 
-       nf = rhashtable_lookup_get_insert_key(&nfsd_file_rhash_tbl,
-                                             &key, &new->nf_rhash,
-                                             nfsd_file_rhash_params);
-       if (!nf) {
-               nf = new;
-               goto open_file;
-       }
-       if (IS_ERR(nf))
-               goto insert_err;
-       nf = nfsd_file_get(nf);
-       if (nf == NULL) {
-               nf = new;
+       ret = rhashtable_lookup_insert_key(&nfsd_file_rhash_tbl,
+                                          &key, &nf->nf_rhash,
+                                          nfsd_file_rhash_params);
+       if (likely(ret == 0))
                goto open_file;
-       }
-       nfsd_file_slab_free(&new->nf_rcu);
+
+       nfsd_file_slab_free(&nf->nf_rcu);
+       if (ret == -EEXIST)
+               goto retry;
+       trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, ret);
+       status = nfserr_jukebox;
+       goto out_status;
 
 wait_for_construction:
        wait_on_bit(&nf->nf_flags, NFSD_FILE_PENDING, TASK_UNINTERRUPTIBLE);
        /* Did construction of this file fail? */
        if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
                trace_nfsd_file_cons_err(rqstp, key.inode, may_flags, nf);
-               if (!retry) {
+               if (!open_retry) {
                        status = nfserr_jukebox;
                        goto out;
                }
-               retry = false;
+               open_retry = false;
                nfsd_file_put_noref(nf);
                goto retry;
        }
        smp_mb__after_atomic();
        wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
        goto out;
-
-insert_err:
-       nfsd_file_slab_free(&new->nf_rcu);
-       trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, PTR_ERR(nf));
-       nf = NULL;
-       status = nfserr_jukebox;
-       goto out_status;
 }
 
 /**