From: Benny Halevy <bhalevy@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> the layout stateid must be updated by layout get only on success upon changing the actual state, otherwise, a parallel layout_recall will send the wrong stateid. Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> --- fs/nfsd/nfs4pnfsd.c | 35 ++++++++++++++++++++++------------- 1 files changed, 22 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/nfs4pnfsd.c b/fs/nfsd/nfs4pnfsd.c index 9ce2bf2..fc7f4e5 100644 --- a/fs/nfsd/nfs4pnfsd.c +++ b/fs/nfsd/nfs4pnfsd.c @@ -302,7 +302,7 @@ nfs4_process_layout_stateid(struct nfs4_client *clp, struct nfs4_file *fp, if (lsp && ((verify_stateid(fp, stateid)) == 0)) { dprintk("%s parallel initial layout state\n", __func__); - goto update; + goto verified; } dprintk("%s ERROR bad opaque in stateid 1\n", __func__); @@ -314,14 +314,9 @@ nfs4_process_layout_stateid(struct nfs4_client *clp, struct nfs4_file *fp, dprintk("%s bad stateid 1\n", __func__); goto out_put; } -update: - update_stateid(&ls->ls_stateid); - dprintk("%s Updated ls_stateid to %d on layoutstate %p\n", - __func__, ls->ls_stateid.si_generation, ls); } +verified: status = 0; - /* Set the stateid to be encoded */ - memcpy(stateid, &ls->ls_stateid, sizeof(stateid_t)); /* Return the layout state if requested */ if (lsp) { @@ -351,13 +346,21 @@ free_layout(struct nfs4_layout *lp) kmem_cache_free(pnfs_layout_slab, lp); } +#define update_layout_stateid(ls, sid) { \ + update_stateid(&(ls)->ls_stateid); \ + dprintk("%s Updated ls_stateid to %d on layoutstate %p\n", \ + __func__, (ls)->ls_stateid.si_generation, (ls)); \ + memcpy((sid), &(ls)->ls_stateid, sizeof(stateid_t)); \ +} + static void init_layout(struct nfs4_layout_state *ls, struct nfs4_layout *lp, struct nfs4_file *fp, struct nfs4_client *clp, struct svc_fh *current_fh, - struct nfsd4_layout_seg *seg) + struct nfsd4_layout_seg *seg, + stateid_t *stateid) { dprintk("pNFS %s: ls %p lp %p clp %p fp %p ino %p\n", __func__, ls, lp, clp, fp, fp->fi_inode); @@ -369,6 +372,7 @@ init_layout(struct nfs4_layout_state *ls, lp->lo_state = ls; memcpy(&lp->lo_seg, seg, sizeof(lp->lo_seg)); spin_lock(&layout_lock); + update_layout_stateid(ls, stateid); list_add_tail(&lp->lo_perstate, &ls->ls_layouts); list_add_tail(&lp->lo_perclnt, &clp->cl_layouts); list_add_tail(&lp->lo_perfile, &fp->fi_layouts); @@ -717,7 +721,7 @@ nfs4_pnfs_get_layout(struct nfsd4_pnfs_layoutget *lgp, goto out_freelayout; /* Can't merge, so let's initialize this new layout */ - init_layout(ls, lp, fp, clp, lgp->lg_fhp, &res.lg_seg); + init_layout(ls, lp, fp, clp, lgp->lg_fhp, &res.lg_seg, &lgp->lg_sid); out_unlock: if (ls) put_layout_state(ls); @@ -773,7 +777,8 @@ out: static int pnfs_return_file_layouts(struct nfs4_client *clp, struct nfs4_file *fp, - struct nfsd4_pnfs_layoutreturn *lrp) + struct nfsd4_pnfs_layoutreturn *lrp, + struct nfs4_layout_state *ls) { int layouts_found = 0; struct nfs4_layout *lp, *nextlp; @@ -799,6 +804,8 @@ pnfs_return_file_layouts(struct nfs4_client *clp, struct nfs4_file *fp, destroy_layout(lp); } } + if (ls && layouts_found && lrp->lrs_present) + update_layout_stateid(ls, &lrp->lr_sid); spin_unlock(&layout_lock); return layouts_found; @@ -838,6 +845,7 @@ int nfs4_pnfs_return_layout(struct super_block *sb, struct svc_fh *current_fh, struct inode *ino = current_fh->fh_dentry->d_inode; struct nfs4_file *fp = NULL; struct nfs4_client *clp; + struct nfs4_layout_state *ls = NULL; u64 ex_fsid = current_fh->fh_export->ex_fsid; void *recall_cookie = NULL; @@ -859,13 +867,12 @@ int nfs4_pnfs_return_layout(struct super_block *sb, struct svc_fh *current_fh, /* Check the stateid */ dprintk("%s PROCESS LO_STATEID inode %p\n", __func__, ino); - status = nfs4_process_layout_stateid(clp, fp, &lrp->lr_sid, - NULL); + status = nfs4_process_layout_stateid(clp, fp, &lrp->lr_sid, &ls); if (status) goto out_put_file; /* update layouts */ - layouts_found = pnfs_return_file_layouts(clp, fp, lrp); + layouts_found = pnfs_return_file_layouts(clp, fp, lrp, ls); /* optimize for the all-empty case */ if (list_empty(&fp->fi_layouts)) recall_cookie = PNFS_LAST_LAYOUT_NO_RECALLS; @@ -884,6 +891,8 @@ int nfs4_pnfs_return_layout(struct super_block *sb, struct svc_fh *current_fh, out_put_file: if (fp) put_nfs4_file(fp); + if (ls) + put_layout_state(ls); out: nfs4_unlock_state(); -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html