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: Tom Haynes <loghyr@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
602c4cd452
commit
c7d73af2d2
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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 @@ out_existing:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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,
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
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,
|
||||||
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 @@ lookup_again:
|
||||||
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
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue