Commit e71708d4 authored by Trond Myklebust's avatar Trond Myklebust

pNFS: Return RW layouts on OPEN_DOWNGRADE

If the client holds no more writeable open state, and does not hold a
write delegation, then send a layoutreturn as part of the OPEN_DOWNGRADE.

We do this only for writes, since some layout drivers may require you to
also hold a read layout if you are doing a R/W workload.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent b6808145
...@@ -1251,6 +1251,7 @@ bool pnfs_roc(struct inode *ino, ...@@ -1251,6 +1251,7 @@ bool pnfs_roc(struct inode *ino,
nfs4_stateid stateid; nfs4_stateid stateid;
enum pnfs_iomode iomode = 0; enum pnfs_iomode iomode = 0;
bool layoutreturn = false, roc = false; bool layoutreturn = false, roc = false;
bool skip_read = false;
if (!nfs_have_layout(ino)) if (!nfs_have_layout(ino))
return false; return false;
...@@ -1270,18 +1271,27 @@ bool pnfs_roc(struct inode *ino, ...@@ -1270,18 +1271,27 @@ bool pnfs_roc(struct inode *ino,
} }
/* no roc if we hold a delegation */ /* no roc if we hold a delegation */
if (nfs4_check_delegation(ino, FMODE_READ)) if (nfs4_check_delegation(ino, FMODE_READ)) {
goto out_noroc; if (nfs4_check_delegation(ino, FMODE_WRITE))
goto out_noroc;
skip_read = true;
}
list_for_each_entry(ctx, &nfsi->open_files, list) { list_for_each_entry(ctx, &nfsi->open_files, list) {
state = ctx->state; state = ctx->state;
if (state == NULL)
continue;
/* Don't return layout if there is open file state */ /* Don't return layout if there is open file state */
if (state != NULL && state->state != 0) if (state->state & FMODE_WRITE)
goto out_noroc; goto out_noroc;
if (state->state & FMODE_READ)
skip_read = true;
} }
list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) { list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) {
if (skip_read && lseg->pls_range.iomode == IOMODE_READ)
continue;
/* If we are sending layoutreturn, invalidate all valid lsegs */ /* If we are sending layoutreturn, invalidate all valid lsegs */
if (!test_and_clear_bit(NFS_LSEG_ROC, &lseg->pls_flags)) if (!test_and_clear_bit(NFS_LSEG_ROC, &lseg->pls_flags))
continue; continue;
......
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