Commit c7d73af2 authored by Tom Haynes's avatar Tom Haynes Committed by Anna Schumaker

pnfs: pnfs_update_layout needs to consider if strict iomode checking is on

As flexfiles has FF_FLAGS_NO_READ_IO, there is a need to generically
support enforcing that a IOMODE_RW segment will not allow READ I/O.
Signed-off-by: default avatarTom Haynes <loghyr@primarydata.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 602c4cd4
...@@ -890,6 +890,7 @@ filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, ...@@ -890,6 +890,7 @@ filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_READ, IOMODE_READ,
false,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) { if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_error = PTR_ERR(pgio->pg_lseg);
...@@ -915,6 +916,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -915,6 +916,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_RW, IOMODE_RW,
false,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) { if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_error = PTR_ERR(pgio->pg_lseg);
......
...@@ -820,6 +820,36 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg, ...@@ -820,6 +820,36 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
return NULL; return NULL;
} }
static void
ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req,
bool strict_iomode)
{
retry_strict:
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context,
0,
NFS4_MAX_UINT64,
IOMODE_READ,
strict_iomode,
GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
}
/* If we don't have checking, do get a IOMODE_RW
* segment, and the server wants to avoid READs
* there, then retry!
*/
if (pgio->pg_lseg && !strict_iomode &&
ff_layout_avoid_read_on_rw(pgio->pg_lseg)) {
strict_iomode = true;
goto retry_strict;
}
}
static void static void
ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req) struct nfs_page *req)
...@@ -830,19 +860,10 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, ...@@ -830,19 +860,10 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
int ds_idx; int ds_idx;
/* Use full layout for now */ /* Use full layout for now */
if (!pgio->pg_lseg || ff_layout_avoid_read_on_rw(pgio->pg_lseg)) { if (!pgio->pg_lseg)
pnfs_put_lseg(pgio->pg_lseg); ff_layout_pg_get_read(pgio, req, false);
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, else if (ff_layout_avoid_read_on_rw(pgio->pg_lseg))
req->wb_context, ff_layout_pg_get_read(pgio, req, true);
0,
NFS4_MAX_UINT64,
IOMODE_READ,
GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
}
}
/* If no lseg, fall back to read through mds */ /* If no lseg, fall back to read through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
...@@ -894,6 +915,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -894,6 +915,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_RW, IOMODE_RW,
false,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) { if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_error = PTR_ERR(pgio->pg_lseg);
...@@ -952,6 +974,7 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, ...@@ -952,6 +974,7 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_RW, IOMODE_RW,
false,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) { if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_error = PTR_ERR(pgio->pg_lseg);
......
...@@ -1321,23 +1321,28 @@ pnfs_find_alloc_layout(struct inode *ino, ...@@ -1321,23 +1321,28 @@ pnfs_find_alloc_layout(struct inode *ino,
/* /*
* iomode matching rules: * iomode matching rules:
* iomode lseg match * iomode lseg strict match
* ----- ----- ----- * iomode
* ANY READ true * ----- ----- ------ -----
* ANY RW true * ANY READ N/A true
* RW READ false * ANY RW N/A true
* RW RW true * RW READ N/A false
* READ READ true * RW RW N/A true
* READ RW true * READ READ N/A true
* READ RW true false
* READ RW false true
*/ */
static bool static bool
pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range,
const struct pnfs_layout_range *range) const struct pnfs_layout_range *range,
bool strict_iomode)
{ {
struct pnfs_layout_range range1; struct pnfs_layout_range range1;
if ((range->iomode == IOMODE_RW && if ((range->iomode == IOMODE_RW &&
ls_range->iomode != IOMODE_RW) || ls_range->iomode != IOMODE_RW) ||
(range->iomode != ls_range->iomode &&
strict_iomode == true) ||
!pnfs_lseg_range_intersecting(ls_range, range)) !pnfs_lseg_range_intersecting(ls_range, range))
return 0; return 0;
...@@ -1352,7 +1357,8 @@ pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, ...@@ -1352,7 +1357,8 @@ pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range,
*/ */
static struct pnfs_layout_segment * static struct pnfs_layout_segment *
pnfs_find_lseg(struct pnfs_layout_hdr *lo, pnfs_find_lseg(struct pnfs_layout_hdr *lo,
struct pnfs_layout_range *range) struct pnfs_layout_range *range,
bool strict_iomode)
{ {
struct pnfs_layout_segment *lseg, *ret = NULL; struct pnfs_layout_segment *lseg, *ret = NULL;
...@@ -1361,7 +1367,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, ...@@ -1361,7 +1367,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
list_for_each_entry(lseg, &lo->plh_segs, pls_list) { list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) &&
!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) && !test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) &&
pnfs_lseg_range_match(&lseg->pls_range, range)) { pnfs_lseg_range_match(&lseg->pls_range, range,
strict_iomode)) {
ret = pnfs_get_lseg(lseg); ret = pnfs_get_lseg(lseg);
break; break;
} }
...@@ -1478,6 +1485,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -1478,6 +1485,7 @@ pnfs_update_layout(struct inode *ino,
loff_t pos, loff_t pos,
u64 count, u64 count,
enum pnfs_iomode iomode, enum pnfs_iomode iomode,
bool strict_iomode,
gfp_t gfp_flags) gfp_t gfp_flags)
{ {
struct pnfs_layout_range arg = { struct pnfs_layout_range arg = {
...@@ -1539,7 +1547,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -1539,7 +1547,7 @@ pnfs_update_layout(struct inode *ino,
goto out_unlock; goto out_unlock;
} }
lseg = pnfs_find_lseg(lo, &arg); lseg = pnfs_find_lseg(lo, &arg, strict_iomode);
if (lseg) { if (lseg) {
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
PNFS_UPDATE_LAYOUT_FOUND_CACHED); PNFS_UPDATE_LAYOUT_FOUND_CACHED);
...@@ -1883,6 +1891,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r ...@@ -1883,6 +1891,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
req_offset(req), req_offset(req),
rd_size, rd_size,
IOMODE_READ, IOMODE_READ,
false,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) { if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_error = PTR_ERR(pgio->pg_lseg);
...@@ -1907,6 +1916,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -1907,6 +1916,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
req_offset(req), req_offset(req),
wb_size, wb_size,
IOMODE_RW, IOMODE_RW,
false,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) { if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg); pgio->pg_error = PTR_ERR(pgio->pg_lseg);
......
...@@ -288,6 +288,7 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, ...@@ -288,6 +288,7 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
loff_t pos, loff_t pos,
u64 count, u64 count,
enum pnfs_iomode iomode, enum pnfs_iomode iomode,
bool strict_iomode,
gfp_t gfp_flags); gfp_t gfp_flags);
void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo); void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment