--- flexfilelayout.h.orig 2018-04-22 22:20:09.000000000 -0400 +++ flexfilelayout.h 2018-08-20 18:21:49.035634324 -0400 @@ -215,6 +215,8 @@ unsigned int ff_layout_fetch_ds_ioerr(st unsigned int maxnum); struct nfs_fh * nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx); +nfs4_stateid * +nfs4_ff_layout_select_ds_stateid(struct pnfs_layout_segment *lseg, u32 mirror_idx); struct nfs4_pnfs_ds * nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, --- flexfilelayout.c.orig 2018-04-22 22:20:09.000000000 -0400 +++ flexfilelayout.c 2018-08-20 17:33:04.020861337 -0400 @@ -1368,9 +1368,11 @@ static void ff_layout_read_prepare_v4(st if (ff_layout_read_prepare_common(task, hdr)) return; - if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, - hdr->args.lock_context, FMODE_READ) == -EIO) - rpc_exit(task, -EIO); /* lost lock, terminate I/O */ + if (hdr->args.stateid.type == NFS4_INVALID_STATEID_TYPE) { + if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, + hdr->args.lock_context, FMODE_READ) == -EIO) + rpc_exit(task, -EIO); /* lost lock, terminate I/O */ + } } static void ff_layout_read_call_done(struct rpc_task *task, void *data) @@ -1542,9 +1544,11 @@ static void ff_layout_write_prepare_v4(s if (ff_layout_write_prepare_common(task, hdr)) return; - if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, - hdr->args.lock_context, FMODE_WRITE) == -EIO) - rpc_exit(task, -EIO); /* lost lock, terminate I/O */ + if (hdr->args.stateid.type == NFS4_INVALID_STATEID_TYPE) { + if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, + hdr->args.lock_context, FMODE_WRITE) == -EIO) + rpc_exit(task, -EIO); /* lost lock, terminate I/O */ + } } static void ff_layout_write_call_done(struct rpc_task *task, void *data) @@ -1705,6 +1709,7 @@ ff_layout_read_pagelist(struct nfs_pgio_ u32 idx = hdr->pgio_mirror_idx; int vers; struct nfs_fh *fh; + nfs4_stateid *stateid; dprintk("--> %s ino %lu pgbase %u req %zu@%llu\n", __func__, hdr->inode->i_ino, @@ -1734,6 +1739,16 @@ ff_layout_read_pagelist(struct nfs_pgio_ fh = nfs4_ff_layout_select_ds_fh(lseg, idx); if (fh) hdr->args.fh = fh; + + /* + * If NFS4_INVALID_STATEID_TYPE when ff_layout_read_prepare_v4() + * is called, it will be filled in then. + */ + hdr->args.stateid.type = NFS4_INVALID_STATEID_TYPE; + stateid = nfs4_ff_layout_select_ds_stateid(lseg, idx); + if (stateid) + nfs4_stateid_copy(&hdr->args.stateid, stateid); + /* * Note that if we ever decide to split across DSes, * then we may need to handle dense-like offsets. @@ -1767,6 +1782,7 @@ ff_layout_write_pagelist(struct nfs_pgio int vers; struct nfs_fh *fh; int idx = hdr->pgio_mirror_idx; + nfs4_stateid *stateid; ds = nfs4_ff_layout_prepare_ds(lseg, idx, true); if (!ds) @@ -1797,6 +1813,15 @@ ff_layout_write_pagelist(struct nfs_pgio hdr->args.fh = fh; /* + * If NFS4_INVALID_STATEID_TYPE when ff_layout_write_prepare_v4() + * is called, it will be filled in then. + */ + hdr->args.stateid.type = NFS4_INVALID_STATEID_TYPE; + stateid = nfs4_ff_layout_select_ds_stateid(lseg, idx); + if (stateid) + nfs4_stateid_copy(&hdr->args.stateid, stateid); + + /* * Note that if we ever decide to split across DSes, * then we may need to handle dense-like offsets. */ --- flexfilelayoutdev.c.orig 2018-04-22 22:20:09.000000000 -0400 +++ flexfilelayoutdev.c 2018-08-20 09:03:16.333050929 -0400 @@ -369,6 +369,23 @@ out: return fh; } +nfs4_stateid * +nfs4_ff_layout_select_ds_stateid(struct pnfs_layout_segment *lseg, u32 mirror_idx) +{ + struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, mirror_idx); + nfs4_stateid *stateid = NULL; + + if (!ff_layout_mirror_valid(lseg, mirror, false)) { + pr_err_ratelimited("NFS: %s: No data server for mirror offset index %d\n", + __func__, mirror_idx); + goto out; + } + + stateid = &mirror->stateid; +out: + return stateid; +} + /** * nfs4_ff_layout_prepare_ds - prepare a DS connection for an RPC call * @lseg: the layout segment we're operating on