Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -890,6 +890,7 @@ filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
					   0,
					   NFS4_MAX_UINT64,
					   IOMODE_READ,
					   false,
					   GFP_KERNEL);
		if (IS_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,
					   NFS4_MAX_UINT64,
					   IOMODE_RW,
					   false,
					   GFP_NOFS);
		if (IS_ERR(pgio->pg_lseg)) {
			pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+36 −13
Original line number Diff line number Diff line
@@ -821,29 +821,50 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
}

static void
ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
			struct nfs_page *req)
ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
		      struct nfs_page *req,
		      bool strict_iomode)
{
	struct nfs_pgio_mirror *pgm;
	struct nfs4_ff_layout_mirror *mirror;
	struct nfs4_pnfs_ds *ds;
	int ds_idx;

	/* Use full layout for now */
	if (!pgio->pg_lseg || ff_layout_avoid_read_on_rw(pgio->pg_lseg)) {
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
ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
			struct nfs_page *req)
{
	struct nfs_pgio_mirror *pgm;
	struct nfs4_ff_layout_mirror *mirror;
	struct nfs4_pnfs_ds *ds;
	int ds_idx;

	/* Use full layout for now */
	if (!pgio->pg_lseg)
		ff_layout_pg_get_read(pgio, req, false);
	else if (ff_layout_avoid_read_on_rw(pgio->pg_lseg))
		ff_layout_pg_get_read(pgio, req, true);

	/* If no lseg, fall back to read through mds */
	if (pgio->pg_lseg == NULL)
		goto out_mds;
@@ -894,6 +915,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
						   0,
						   NFS4_MAX_UINT64,
						   IOMODE_RW,
						   false,
						   GFP_NOFS);
		if (IS_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,
						   NFS4_MAX_UINT64,
						   IOMODE_RW,
						   false,
						   GFP_NOFS);
		if (IS_ERR(pgio->pg_lseg)) {
			pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+22 −12
Original line number Diff line number Diff line
@@ -1321,23 +1321,28 @@ pnfs_find_alloc_layout(struct inode *ino,

/*
 * iomode matching rules:
 * iomode	lseg	match
 * -----	-----	-----
 * ANY		READ	true
 * ANY		RW	true
 * RW		READ	false
 * RW		RW	true
 * READ		READ	true
 * READ		RW	true
 * iomode	lseg	strict match
 *                      iomode
 * -----	-----	------ -----
 * ANY		READ	N/A    true
 * ANY		RW	N/A    true
 * RW		READ	N/A    false
 * RW		RW	N/A    true
 * READ		READ	N/A    true
 * READ		RW	true   false
 * READ		RW	false  true
 */
static bool
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;

	if ((range->iomode == IOMODE_RW &&
	     ls_range->iomode != IOMODE_RW) ||
	    (range->iomode != ls_range->iomode &&
	     strict_iomode == true) ||
	    !pnfs_lseg_range_intersecting(ls_range, range))
		return 0;

@@ -1352,7 +1357,8 @@ pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range,
 */
static struct pnfs_layout_segment *
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;

@@ -1361,7 +1367,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
	list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
		if (test_bit(NFS_LSEG_VALID, &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);
			break;
		}
@@ -1478,6 +1485,7 @@ pnfs_update_layout(struct inode *ino,
		   loff_t pos,
		   u64 count,
		   enum pnfs_iomode iomode,
		   bool strict_iomode,
		   gfp_t gfp_flags)
{
	struct pnfs_layout_range arg = {
@@ -1539,7 +1547,7 @@ pnfs_update_layout(struct inode *ino,
		goto out_unlock;
	}

	lseg = pnfs_find_lseg(lo, &arg);
	lseg = pnfs_find_lseg(lo, &arg, strict_iomode);
	if (lseg) {
		trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
				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),
						   rd_size,
						   IOMODE_READ,
						   false,
						   GFP_KERNEL);
		if (IS_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),
						   wb_size,
						   IOMODE_RW,
						   false,
						   GFP_NOFS);
		if (IS_ERR(pgio->pg_lseg)) {
			pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+1 −0
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
					       loff_t pos,
					       u64 count,
					       enum pnfs_iomode iomode,
					       bool strict_iomode,
					       gfp_t gfp_flags);
void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo);