Commit b3230e80 authored by Trond Myklebust's avatar Trond Myklebust

pNFS: Ensure we check layout segment validity in the pg_init() callback

If we have a layout segment cached in pgio->pg_lseg, we should check it
for validity before reusing it in a new RPC request. Otherwise, if we
recoalesce, we can end up looping forever.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent f30cb757
...@@ -933,6 +933,7 @@ static void ...@@ -933,6 +933,7 @@ static void
filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req) struct nfs_page *req)
{ {
pnfs_generic_pg_check_layout(pgio);
if (!pgio->pg_lseg) { if (!pgio->pg_lseg) {
pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
...@@ -959,6 +960,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -959,6 +960,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_commit_info cinfo; struct nfs_commit_info cinfo;
int status; int status;
pnfs_generic_pg_check_layout(pgio);
if (!pgio->pg_lseg) { if (!pgio->pg_lseg) {
pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
......
...@@ -846,6 +846,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, ...@@ -846,6 +846,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
int ds_idx; int ds_idx;
retry: retry:
pnfs_generic_pg_check_layout(pgio);
/* Use full layout for now */ /* Use full layout for now */
if (!pgio->pg_lseg) if (!pgio->pg_lseg)
ff_layout_pg_get_read(pgio, req, false); ff_layout_pg_get_read(pgio, req, false);
...@@ -894,6 +895,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -894,6 +895,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
int status; int status;
retry: retry:
pnfs_generic_pg_check_layout(pgio);
if (!pgio->pg_lseg) { if (!pgio->pg_lseg) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
......
...@@ -2072,11 +2072,23 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, ...@@ -2072,11 +2072,23 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
} }
EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return); EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
void
pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio)
{
if (pgio->pg_lseg == NULL ||
test_bit(NFS_LSEG_VALID, &pgio->pg_lseg->pls_flags))
return;
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = NULL;
}
EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout);
void void
pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{ {
u64 rd_size = req->wb_bytes; u64 rd_size = req->wb_bytes;
pnfs_generic_pg_check_layout(pgio);
if (pgio->pg_lseg == NULL) { if (pgio->pg_lseg == NULL) {
if (pgio->pg_dreq == NULL) if (pgio->pg_dreq == NULL)
rd_size = i_size_read(pgio->pg_inode) - req_offset(req); rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
...@@ -2107,6 +2119,7 @@ void ...@@ -2107,6 +2119,7 @@ void
pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req, u64 wb_size) struct nfs_page *req, u64 wb_size)
{ {
pnfs_generic_pg_check_layout(pgio);
if (pgio->pg_lseg == NULL) { if (pgio->pg_lseg == NULL) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
......
...@@ -234,6 +234,7 @@ void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg); ...@@ -234,6 +234,7 @@ void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg);
void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, struct nfs_fsinfo *); void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, struct nfs_fsinfo *);
void unset_pnfs_layoutdriver(struct nfs_server *); void unset_pnfs_layoutdriver(struct nfs_server *);
void pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio);
void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
......
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