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: Trond Myklebust <trond.myklebust@primarydata.com>
This commit is contained in:
parent
b4019c0e21
commit
40dd4b7aee
@ -2714,45 +2714,10 @@ static const struct rpc_call_ops nfs4_close_ops = {
|
|||||||
.rpc_release = nfs4_free_closedata,
|
.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)
|
static bool nfs4_roc(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct nfs_inode *nfsi = NFS_I(inode);
|
if (!nfs_have_layout(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);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock(&inode->i_lock);
|
|
||||||
|
|
||||||
if (nfs4_check_delegation(inode, FMODE_READ))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return pnfs_roc(inode);
|
return pnfs_roc(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "pnfs.h"
|
#include "pnfs.h"
|
||||||
#include "iostat.h"
|
#include "iostat.h"
|
||||||
#include "nfs4trace.h"
|
#include "nfs4trace.h"
|
||||||
|
#include "delegation.h"
|
||||||
|
|
||||||
#define NFSDBG_FACILITY NFSDBG_PNFS
|
#define NFSDBG_FACILITY NFSDBG_PNFS
|
||||||
#define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ)
|
#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)
|
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_hdr *lo;
|
||||||
struct pnfs_layout_segment *lseg, *tmp;
|
struct pnfs_layout_segment *lseg, *tmp;
|
||||||
LIST_HEAD(tmp_list);
|
LIST_HEAD(tmp_list);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
spin_lock(&ino->i_lock);
|
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) ||
|
if (!lo || !test_and_clear_bit(NFS_LAYOUT_ROC, &lo->plh_flags) ||
|
||||||
test_bit(NFS_LAYOUT_BULK_RECALL, &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)
|
list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list)
|
||||||
if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {
|
if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {
|
||||||
mark_lseg_invalid(lseg, &tmp_list);
|
mark_lseg_invalid(lseg, &tmp_list);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
goto out_nolayout;
|
goto out_noroc;
|
||||||
lo->plh_block_lgets++;
|
lo->plh_block_lgets++;
|
||||||
pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */
|
pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */
|
||||||
spin_unlock(&ino->i_lock);
|
spin_unlock(&ino->i_lock);
|
||||||
pnfs_free_lseg_list(&tmp_list);
|
pnfs_free_lseg_list(&tmp_list);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
out_nolayout:
|
out_noroc:
|
||||||
spin_unlock(&ino->i_lock);
|
spin_unlock(&ino->i_lock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -275,6 +275,11 @@ void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node);
|
|||||||
bool nfs4_test_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 *);
|
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 *
|
static inline struct nfs4_deviceid_node *
|
||||||
nfs4_get_deviceid(struct nfs4_deviceid_node *d)
|
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 */
|
#endif /* NFS_DEBUG */
|
||||||
#else /* CONFIG_NFS_V4_1 */
|
#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)
|
static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user