diff --git a/fs/nfsd/nfs4pnfsd.c b/fs/nfsd/nfs4pnfsd.c
index 50b5208..d3a0bde 100644
--- a/fs/nfsd/nfs4pnfsd.c
+++ b/fs/nfsd/nfs4pnfsd.c
@@ -133,6 +133,7 @@ struct sbid_tracker {
 	nfsd4_init_stid(&new->ls_stid, clp, NFS4_LAYOUT_STID);
 	INIT_LIST_HEAD(&new->ls_perclnt);
 	INIT_LIST_HEAD(&new->ls_perfile);
+	INIT_LIST_HEAD(&new->ls_layouts);
 	new->ls_client = clp;
 	get_nfs4_file(fp);	/* released on destroy_layout_state */
 	new->ls_file = fp;
@@ -276,13 +277,6 @@ static void update_layout_stateid_locked(struct nfs4_layout_state *ls, stateid_t
 		__func__, sid->si_generation, ls);
 }
 
-static void update_layout_stateid(struct nfs4_layout_state *ls, stateid_t *sid)
-{
-	spin_lock(&layout_lock);
-	update_layout_stateid_locked(ls, sid);
-	spin_unlock(&layout_lock);
-}
-
 static void update_layout_roc(struct nfs4_layout_state *ls, bool roc)
 {
 	if (roc) {
@@ -295,35 +289,28 @@ static void update_layout_roc(struct nfs4_layout_state *ls, bool roc)
 static void
 init_layout(struct nfs4_layout *lp,
 	    struct nfs4_layout_state *ls,
-	    struct nfs4_file *fp,
-	    struct nfs4_client *clp,
 	    struct svc_fh *current_fh,
 	    struct nfsd4_layout_seg *seg,
 	    stateid_t *stateid)
 {
-	dprintk("pNFS %s: lp %p ls %p clp %p fp %p ino %p\n", __func__,
-		lp, ls, clp, fp, fp->fi_inode);
+	dprintk("pNFS %s: lp %p ls %p ino %lu\n", __func__,
+		lp, ls, ls->ls_file->fi_inode->i_ino);
 
-	get_nfs4_file(fp);
-	lp->lo_client = clp;
-	lp->lo_file = fp;
 	memcpy(&lp->lo_seg, seg, sizeof(lp->lo_seg));
 	get_layout_state(ls);		/* put on destroy_layout */
 	lp->lo_state = ls;
-	update_layout_stateid(ls, stateid);
-	list_add_tail(&lp->lo_perclnt, &clp->cl_layouts);
-	list_add_tail(&lp->lo_perfile, &fp->fi_layouts);
+	spin_lock(&layout_lock);
+	update_layout_stateid_locked(ls, stateid);
+	list_add_tail(&lp->lo_perstate, &ls->ls_layouts);
+	spin_unlock(&layout_lock);
 	dprintk("pNFS %s end\n", __func__);
 }
 
-/*
- * Note: always called under the layout_lock
- */
 static void
 dequeue_layout(struct nfs4_layout *lp)
 {
-	list_del(&lp->lo_perclnt);
-	list_del(&lp->lo_perfile);
+	ASSERT_LAYOUT_LOCKED();
+	list_del_init(&lp->lo_perstate);
 }
 
 /*
@@ -332,20 +319,15 @@ static void update_layout_roc(struct nfs4_layout_state *ls, bool roc)
 static void
 destroy_layout(struct nfs4_layout *lp)
 {
-	struct nfs4_client *clp;
-	struct nfs4_file *fp;
 	struct nfs4_layout_state *ls;
 
-	clp = lp->lo_client;
-	fp = lp->lo_file;
 	ls = lp->lo_state;
-	dprintk("pNFS %s: lp %p clp %p fp %p ino %p\n",
-		__func__, lp, clp, fp, fp->fi_inode);
+	dprintk("pNFS %s: lp %p ls %p ino %lu\n",
+		__func__, lp, ls, ls->ls_file->fi_inode->i_ino);
 
 	kmem_cache_free(pnfs_layout_slab, lp);
 	/* release references taken by init_layout */
 	put_layout_state(ls);
-	put_nfs4_file(fp);
 }
 
 static void fs_layout_return(struct inode *ino,
@@ -635,15 +617,13 @@ struct super_block *
 }
 
 static bool
-merge_layout(struct nfs4_file *fp,
-	     struct nfs4_client *clp,
-	     struct nfsd4_layout_seg *seg)
+merge_layout(struct nfs4_layout_state *ls, struct nfsd4_layout_seg *seg)
 {
 	bool ret = false;
 	struct nfs4_layout *lp;
 
 	spin_lock(&layout_lock);
-	list_for_each_entry (lp, &fp->fi_layouts, lo_perfile)
+	list_for_each_entry (lp, &ls->ls_layouts, lo_perstate)
 		if (lp->lo_seg.layout_type == seg->layout_type &&
 		    lp->lo_seg.clientid == seg->clientid &&
 		    lp->lo_seg.iomode == seg->iomode &&
@@ -795,11 +775,11 @@ struct super_block *
 	 * Can the new layout be merged into an existing one?
 	 * If so, free unused layout struct
 	 */
-	if (can_merge && merge_layout(fp, clp, &res.lg_seg))
+	if (can_merge && merge_layout(ls, &res.lg_seg))
 		goto out_freelayout;
 
 	/* Can't merge, so let's initialize this new layout */
-	init_layout(lp, ls, fp, clp, lgp->lg_fhp, &res.lg_seg, &lgp->lg_sid);
+	init_layout(lp, ls, lgp->lg_fhp, &res.lg_seg, &lgp->lg_sid);
 out_unlock:
 	if (ls)
 		put_layout_state(ls);
@@ -883,8 +863,8 @@ struct super_block *
 		return;
 	}
 
-	list_for_each_entry_safe(lo, nextlp, lo_destroy_list, lo_perfile) {
-		struct inode *inode = lo->lo_file->fi_inode;
+	list_for_each_entry_safe(lo, nextlp, lo_destroy_list, lo_perstate) {
+		struct inode *inode = lo->lo_state->ls_file->fi_inode;
 		struct nfsd4_pnfs_layoutreturn lr;
 		bool empty;
 		int lr_flags = flags;
@@ -894,39 +874,39 @@ struct super_block *
 		lr.args.lr_seg = lo->lo_seg;
 
 		spin_lock(&layout_lock);
-		if (list_empty(&lo->lo_file->fi_layouts))
+		if (list_empty(&lo->lo_state->ls_file->fi_lo_states))
 			lr_flags |= LR_FLAG_EMPTY;
 		spin_unlock(&layout_lock);
 
-		list_del(&lo->lo_perfile);
+		list_del(&lo->lo_perstate);
 		empty = list_empty(lo_destroy_list);
 
 		fs_layout_return(inode, &lr, lr_flags, empty ? cb_cookie : NULL);
 
-		destroy_layout(lo); /* this will put the lo_file */
+		destroy_layout(lo);
 	}
 }
 
+/*
+ * Return layouts for RETURN_FILE
+ */
 static int
-pnfs_return_file_layouts(struct nfs4_client *clp, struct nfs4_file *fp,
-			 struct nfsd4_pnfs_layoutreturn *lrp,
+pnfs_return_file_layouts(struct nfsd4_pnfs_layoutreturn *lrp,
 			 struct nfs4_layout_state *ls,
 			 struct list_head *lo_destroy_list)
 {
 	int layouts_found = 0;
 	struct nfs4_layout *lp, *nextlp;
 
-	dprintk("%s: clp %p fp %p\n", __func__, clp, fp);
+	dprintk("%s: ls %p\n", __func__, ls);
 	lrp->lrs_present = 0;
 	spin_lock(&layout_lock);
-	list_for_each_entry_safe (lp, nextlp, &fp->fi_layouts, lo_perfile) {
-		dprintk("%s: lp %p client %p,%p lo_type %x,%x iomode %d,%d\n",
-			__func__, lp,
-			lp->lo_client, clp,
+	list_for_each_entry_safe (lp, nextlp, &ls->ls_layouts, lo_perstate) {
+		dprintk("%s: lp %p ls %p inode %lu lo_type %x,%x iomode %d,%d\n",
+			__func__, lp, lp->lo_state,
+			lp->lo_state->ls_file->fi_inode->i_ino,
 			lp->lo_seg.layout_type, lrp->args.lr_seg.layout_type,
 			lp->lo_seg.iomode, lrp->args.lr_seg.iomode);
-		if (lp->lo_client != clp)
-			continue;
 		if (lp->lo_seg.layout_type != lrp->args.lr_seg.layout_type ||
 		    (lp->lo_seg.iomode != lrp->args.lr_seg.iomode &&
 		     lrp->args.lr_seg.iomode != IOMODE_ANY) ||
@@ -938,7 +918,7 @@ struct super_block *
 		trim_layout(&lp->lo_seg, &lrp->args.lr_seg);
 		if (!lp->lo_seg.length) {
 			dequeue_layout(lp);
-			list_add_tail(&lp->lo_perfile, lo_destroy_list);
+			list_add_tail(&lp->lo_perstate, lo_destroy_list);
 		} else
 			lrp->lrs_present = 1;
 	}
@@ -949,28 +929,36 @@ struct super_block *
 	return layouts_found;
 }
 
+/*
+ * Return layouts for RETURN_FSID or RETURN_ALL
+ */
 static int
 pnfs_return_client_layouts(struct nfs4_client *clp,
 			   struct nfsd4_pnfs_layoutreturn *lrp, u64 ex_fsid,
 			   struct list_head *lo_destroy_list)
 {
 	int layouts_found = 0;
+	struct nfs4_layout_state *ls, *nextls;
 	struct nfs4_layout *lp, *nextlp;
 
 	spin_lock(&layout_lock);
-	list_for_each_entry_safe (lp, nextlp, &clp->cl_layouts, lo_perclnt) {
-		if (lrp->args.lr_seg.layout_type != lp->lo_seg.layout_type ||
-		   (lrp->args.lr_seg.iomode != lp->lo_seg.iomode &&
-		    lrp->args.lr_seg.iomode != IOMODE_ANY))
-			continue;
-
+	list_for_each_entry_safe (ls, nextls, &clp->cl_lo_states, ls_perclnt) {
 		if (lrp->args.lr_return_type == RETURN_FSID &&
-		    !same_fsid_major(&lp->lo_file->fi_fsid, ex_fsid))
+		    !same_fsid_major(&ls->ls_file->fi_fsid, ex_fsid))
 			continue;
 
-		layouts_found++;
-		dequeue_layout(lp);
-		list_add_tail(&lp->lo_perfile, lo_destroy_list);
+		list_for_each_entry_safe (lp, nextlp, &ls->ls_layouts, lo_perstate) {
+			if (lrp->args.lr_seg.layout_type != lp->lo_seg.layout_type)
+				break;
+
+			if (lrp->args.lr_seg.iomode != lp->lo_seg.iomode &&
+			    lrp->args.lr_seg.iomode != IOMODE_ANY)
+				continue;
+
+			layouts_found++;
+			dequeue_layout(lp);
+			list_add_tail(&lp->lo_perstate, lo_destroy_list);
+		}
 	}
 	spin_unlock(&layout_lock);
 
@@ -1071,8 +1059,7 @@ int nfs4_pnfs_return_layout(struct svc_rqst *rqstp,
 			goto out_put_file;
 
 		/* update layouts */
-		layouts_found = pnfs_return_file_layouts(clp, fp, lrp, ls,
-							 &lo_destroy_list);
+		layouts_found = pnfs_return_file_layouts(lrp, ls, &lo_destroy_list);
 		put_layout_state(ls);
 		if (!lrp->lrs_present)
 			lr_flags |= LR_FLAG_CL_EMPTY;
@@ -1202,8 +1189,13 @@ int nfs4_pnfs_return_layout(struct svc_rqst *rqstp,
 		clr->clr_client, clr->clr_file);
 
 	if (clr->cb.cbl_recall_type == RETURN_FILE) {
-		pnfs_return_file_layouts(clr->clr_client, clr->clr_file, &lr,
-					 NULL, &lo_destroy_list);
+		struct nfs4_layout_state *ls;
+
+		list_for_each_entry (ls, &clr->clr_client->cl_lo_states, ls_perclnt)
+			if (ls->ls_file == clr->clr_file) {
+				pnfs_return_file_layouts(&lr, ls, &lo_destroy_list);
+				break;
+			}
 		if (!lr.lrs_present)
 			lr_flags |= LR_FLAG_CL_EMPTY;
 	} else {
@@ -1222,6 +1214,15 @@ int nfs4_pnfs_return_layout(struct svc_rqst *rqstp,
 			     recall_cookie);
 }
 
+void strip_layout_state(struct nfs4_layout_state *ls, struct list_head *lo_destroy_list)
+{
+	unhash_layout_state(ls);
+	if (!list_empty(&ls->ls_layouts)) {
+		list_splice(&ls->ls_layouts, lo_destroy_list);
+		INIT_LIST_HEAD(&ls->ls_layouts);
+	}
+}
+
 /* Return On Close:
  *   Look for all layouts of @fp that belong to @clp, if ROC is set, remove
  *   the layout and simulate a layout_return. Surly the client has forgotten
@@ -1229,30 +1230,27 @@ int nfs4_pnfs_return_layout(struct svc_rqst *rqstp,
  */
 void pnfsd_roc(struct nfs4_client *clp, struct nfs4_file *fp)
 {
-	struct nfs4_layout *lo, *nextlp;
+	struct nfs4_layout_state *ls, *nextls;
 	LIST_HEAD(lo_destroy_list);
 
 	/* TODO: We need to also free layout recalls like pnfs_expire_client */
 	dprintk("%s: fp=%p clp=%p", __func__, fp, clp);
 	spin_lock(&layout_lock);
-	list_for_each_entry_safe (lo, nextlp, &fp->fi_layouts, lo_perfile) {
-		/* Check for a match */
-		if (lo->lo_client != clp)
+	list_for_each_entry_safe (ls, nextls, &fp->fi_lo_states, ls_perfile) {
+		if (ls->ls_client != clp)
 			continue;
 
-		/* Return the layout */
-		list_del_init(&lo->lo_state->ls_perfile);	/* just to be on the safe side */
-		dequeue_layout(lo);
-		list_add_tail(&lo->lo_perfile, &lo_destroy_list);
+		strip_layout_state(ls, &lo_destroy_list);
+		break;
 	}
 	spin_unlock(&layout_lock);
 
-	pnfsd_return_lo_list(&lo_destroy_list, NULL, NULL, LR_FLAG_INTERN, NULL);
+	pnfsd_return_lo_list(&lo_destroy_list, fp->fi_inode, NULL, LR_FLAG_INTERN, NULL);
 }
 
 void pnfs_expire_client(struct nfs4_client *clp)
 {
-	struct nfs4_layout *lo, *nextlo;
+	struct nfs4_layout_state *ls, *nextls;
 	LIST_HEAD(lo_destroy_list);
 
 	for (;;) {
@@ -1275,12 +1273,11 @@ void pnfs_expire_client(struct nfs4_client *clp)
 	}
 
 	spin_lock(&layout_lock);
-	list_for_each_entry_safe (lo, nextlo, &clp->cl_layouts, lo_perclnt) {
-		BUG_ON(lo->lo_client != clp);
-		dequeue_layout(lo);
-		list_add_tail(&lo->lo_perfile, &lo_destroy_list);
-		dprintk("%s: inode %lu lp %p clp %p\n", __func__,
-			lo->lo_file->fi_inode->i_ino, lo, clp);
+	list_for_each_entry_safe (ls, nextls, &clp->cl_lo_states, ls_perclnt) {
+		BUG_ON(ls->ls_client != clp);
+		strip_layout_state(ls, &lo_destroy_list);
+		dprintk("%s: inode %lu ls %p clp %p\n", __func__,
+			ls->ls_file->fi_inode->i_ino, ls, clp);
 	}
 	spin_unlock(&layout_lock);
 
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4f40327..faef919 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1321,7 +1321,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
 	INIT_LIST_HEAD(&clp->cl_openowners);
 	INIT_LIST_HEAD(&clp->cl_delegations);
 #if defined(CONFIG_PNFSD)
-	INIT_LIST_HEAD(&clp->cl_layouts);
 	INIT_LIST_HEAD(&clp->cl_lo_states);
 	INIT_LIST_HEAD(&clp->cl_layoutrecalls);
 #endif /* CONFIG_PNFSD */
@@ -2364,7 +2363,6 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino,
 	memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
 	memset(fp->fi_access, 0, sizeof(fp->fi_access));
 #if defined(CONFIG_PNFSD)
-	INIT_LIST_HEAD(&fp->fi_layouts);
 	INIT_LIST_HEAD(&fp->fi_lo_states);
 	fp->fi_fsid.major = current_fh->fh_export->ex_fsid;
 	fp->fi_fsid.minor = 0;
diff --git a/fs/nfsd/pnfsd.h b/fs/nfsd/pnfsd.h
index 454ef23..453f951 100644
--- a/fs/nfsd/pnfsd.h
+++ b/fs/nfsd/pnfsd.h
@@ -48,15 +48,13 @@ struct nfs4_layout_state {
 	struct nfs4_client	*ls_client;
 	struct list_head	ls_perfile;
 	struct nfs4_file	*ls_file;
+	struct list_head	ls_layouts;
 	bool			ls_roc;
 };
 
 /* outstanding layout */
 struct nfs4_layout {
-	struct list_head		lo_perfile;	/* hash by f_id */
-	struct list_head		lo_perclnt;	/* hash by clientid */
-	struct nfs4_file		*lo_file;	/* backpointer */
-	struct nfs4_client		*lo_client;
+	struct list_head		lo_perstate;
 	struct nfs4_layout_state	*lo_state;
 	struct nfsd4_layout_seg		lo_seg;
 };
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e026e0d..ab4a136 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -282,7 +282,6 @@ struct nfs4_client {
 						/* wait here for slots */
 	struct net		*net;
 #if defined(CONFIG_PNFSD)
-	struct list_head	cl_layouts;	/* outstanding layouts */
 	struct list_head	cl_lo_states;	/* outstanding layout states */
 	struct list_head	cl_layoutrecalls; /* outstanding layoutrecall
 						     callbacks */
@@ -412,7 +411,6 @@ struct nfs4_file {
 	struct inode		*fi_inode;
 	bool			fi_had_conflict;
 #if defined(CONFIG_PNFSD)
-	struct list_head	fi_layouts;
 	struct list_head	fi_lo_states;
 	/* used by layoutget / layoutrecall */
 	struct nfs4_fsid	fi_fsid;
