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

Commit 40dd4b7a authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4.1: Optimise layout return-on-close



Optimise the layout return on close code by ensuring that

1) Add a check for whether we hold a layout before taking any spinlocks
2) Only take the spin lock once
3) Use nfs_state->state to speed up open file checks

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent b4019c0e
Loading
Loading
Loading
Loading
+1 −36
Original line number Diff line number Diff line
@@ -2714,45 +2714,10 @@ static const struct rpc_call_ops nfs4_close_ops = {
	.rpc_release = nfs4_free_closedata,
};

static bool nfs4_state_has_opener(struct nfs4_state *state)
{
	/* first check existing openers */
	if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0 &&
	    state->n_rdonly != 0)
		return true;

	if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0 &&
	    state->n_wronly != 0)
		return true;

	if (test_bit(NFS_O_RDWR_STATE, &state->flags) != 0 &&
	    state->n_rdwr != 0)
		return true;

	return false;
}

static bool nfs4_roc(struct inode *inode)
{
	struct nfs_inode *nfsi = NFS_I(inode);
	struct nfs_open_context *ctx;
	struct nfs4_state *state;

	spin_lock(&inode->i_lock);
	list_for_each_entry(ctx, &nfsi->open_files, list) {
		state = ctx->state;
		if (state == NULL)
			continue;
		if (nfs4_state_has_opener(state)) {
			spin_unlock(&inode->i_lock);
	if (!nfs_have_layout(inode))
		return false;
		}
	}
	spin_unlock(&inode->i_lock);

	if (nfs4_check_delegation(inode, FMODE_READ))
		return false;

	return pnfs_roc(inode);
}

+20 −4
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include "pnfs.h"
#include "iostat.h"
#include "nfs4trace.h"
#include "delegation.h"

#define NFSDBG_FACILITY		NFSDBG_PNFS
#define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ)
@@ -954,30 +955,45 @@ pnfs_commit_and_return_layout(struct inode *inode)

bool pnfs_roc(struct inode *ino)
{
	struct nfs_inode *nfsi = NFS_I(ino);
	struct nfs_open_context *ctx;
	struct nfs4_state *state;
	struct pnfs_layout_hdr *lo;
	struct pnfs_layout_segment *lseg, *tmp;
	LIST_HEAD(tmp_list);
	bool found = false;

	spin_lock(&ino->i_lock);
	lo = NFS_I(ino)->layout;
	lo = nfsi->layout;
	if (!lo || !test_and_clear_bit(NFS_LAYOUT_ROC, &lo->plh_flags) ||
	    test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags))
		goto out_nolayout;
		goto out_noroc;

	/* Don't return layout if we hold a delegation */
	if (nfs4_check_delegation(ino, FMODE_READ))
		goto out_noroc;

	list_for_each_entry(ctx, &nfsi->open_files, list) {
		state = ctx->state;
		/* Don't return layout if there is open file state */
		if (state != NULL && state->state != 0)
			goto out_noroc;
	}

	list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list)
		if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {
			mark_lseg_invalid(lseg, &tmp_list);
			found = true;
		}
	if (!found)
		goto out_nolayout;
		goto out_noroc;
	lo->plh_block_lgets++;
	pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */
	spin_unlock(&ino->i_lock);
	pnfs_free_lseg_list(&tmp_list);
	return true;

out_nolayout:
out_noroc:
	spin_unlock(&ino->i_lock);
	return false;
}
+10 −0
Original line number Diff line number Diff line
@@ -275,6 +275,11 @@ void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node);
bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node);
void nfs4_deviceid_purge_client(const struct nfs_client *);

static inline bool nfs_have_layout(struct inode *inode)
{
	return NFS_I(inode)->layout != NULL;
}

static inline struct nfs4_deviceid_node *
nfs4_get_deviceid(struct nfs4_deviceid_node *d)
{
@@ -427,6 +432,11 @@ static inline void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id)
#endif /* NFS_DEBUG */
#else  /* CONFIG_NFS_V4_1 */

static inline bool nfs_have_layout(struct inode *inode)
{
	return false;
}

static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
{
}