提交 b20135d0 编写于 作者: T Trond Myklebust

NFSv4.1/pNFS: Don't queue up a new commit if the layout segment is invalid

If the layout segment is invalid, then we should not be adding more
write requests to the commit list. Instead, those writes should be
replayed after requesting a new layout.
Signed-off-by: NTrond Myklebust <trond.myklebust@primarydata.com>
上级 af7cf057
...@@ -233,6 +233,8 @@ static u32 initiate_file_draining(struct nfs_client *clp, ...@@ -233,6 +233,8 @@ static u32 initiate_file_draining(struct nfs_client *clp,
unlock: unlock:
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
pnfs_free_lseg_list(&free_me_list); pnfs_free_lseg_list(&free_me_list);
/* Free all lsegs that are attached to commit buckets */
nfs_commit_inode(ino, 0);
pnfs_put_layout_hdr(lo); pnfs_put_layout_hdr(lo);
trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino, trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
&args->cbl_stateid, -rv); &args->cbl_stateid, -rv);
......
...@@ -721,8 +721,20 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data) ...@@ -721,8 +721,20 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
nfs_direct_write_complete(dreq, data->inode); nfs_direct_write_complete(dreq, data->inode);
} }
static void nfs_direct_resched_write(struct nfs_commit_info *cinfo,
struct nfs_page *req)
{
struct nfs_direct_req *dreq = cinfo->dreq;
spin_lock(&dreq->lock);
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
spin_unlock(&dreq->lock);
nfs_mark_request_commit(req, NULL, cinfo, 0);
}
static const struct nfs_commit_completion_ops nfs_direct_commit_completion_ops = { static const struct nfs_commit_completion_ops nfs_direct_commit_completion_ops = {
.completion = nfs_direct_commit_complete, .completion = nfs_direct_commit_complete,
.resched_write = nfs_direct_resched_write,
}; };
static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
......
...@@ -703,6 +703,8 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list, ...@@ -703,6 +703,8 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
ret = -EAGAIN; ret = -EAGAIN;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
pnfs_free_lseg_list(&lseg_list); pnfs_free_lseg_list(&lseg_list);
/* Free all lsegs that are attached to commit buckets */
nfs_commit_inode(inode, 0);
pnfs_put_layout_hdr(lo); pnfs_put_layout_hdr(lo);
iput(inode); iput(inode);
} }
...@@ -1811,6 +1813,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, ...@@ -1811,6 +1813,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
pnfs_mark_matching_lsegs_return(lo, &free_me, &range); pnfs_mark_matching_lsegs_return(lo, &free_me, &range);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
pnfs_free_lseg_list(&free_me); pnfs_free_lseg_list(&free_me);
nfs_commit_inode(inode, 0);
} }
EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return); EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
......
...@@ -412,6 +412,12 @@ pnfs_get_lseg(struct pnfs_layout_segment *lseg) ...@@ -412,6 +412,12 @@ pnfs_get_lseg(struct pnfs_layout_segment *lseg)
return lseg; return lseg;
} }
static inline bool
pnfs_is_valid_lseg(struct pnfs_layout_segment *lseg)
{
return test_bit(NFS_LSEG_VALID, &lseg->pls_flags) != 0;
}
/* Return true if a layout driver is being used for this mountpoint */ /* Return true if a layout driver is being used for this mountpoint */
static inline int pnfs_enabled_sb(struct nfs_server *nfss) static inline int pnfs_enabled_sb(struct nfs_server *nfss)
{ {
......
...@@ -868,6 +868,11 @@ pnfs_layout_mark_request_commit(struct nfs_page *req, ...@@ -868,6 +868,11 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
buckets = cinfo->ds->buckets; buckets = cinfo->ds->buckets;
list = &buckets[ds_commit_idx].written; list = &buckets[ds_commit_idx].written;
if (list_empty(list)) { if (list_empty(list)) {
if (!pnfs_is_valid_lseg(lseg)) {
spin_unlock(cinfo->lock);
cinfo->completion_ops->resched_write(cinfo, req);
return;
}
/* Non-empty buckets hold a reference on the lseg. That ref /* Non-empty buckets hold a reference on the lseg. That ref
* is normally transferred to the COMMIT call and released * is normally transferred to the COMMIT call and released
* there. It could also be released if the last req is pulled * there. It could also be released if the last req is pulled
......
...@@ -1676,6 +1676,13 @@ void nfs_retry_commit(struct list_head *page_list, ...@@ -1676,6 +1676,13 @@ void nfs_retry_commit(struct list_head *page_list,
} }
EXPORT_SYMBOL_GPL(nfs_retry_commit); EXPORT_SYMBOL_GPL(nfs_retry_commit);
static void
nfs_commit_resched_write(struct nfs_commit_info *cinfo,
struct nfs_page *req)
{
__set_page_dirty_nobuffers(req->wb_page);
}
/* /*
* Commit dirty pages * Commit dirty pages
*/ */
...@@ -1777,6 +1784,7 @@ static const struct rpc_call_ops nfs_commit_ops = { ...@@ -1777,6 +1784,7 @@ static const struct rpc_call_ops nfs_commit_ops = {
static const struct nfs_commit_completion_ops nfs_commit_completion_ops = { static const struct nfs_commit_completion_ops nfs_commit_completion_ops = {
.completion = nfs_commit_release_pages, .completion = nfs_commit_release_pages,
.resched_write = nfs_commit_resched_write,
}; };
int nfs_generic_commit_list(struct inode *inode, struct list_head *head, int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
...@@ -1823,6 +1831,7 @@ int nfs_commit_inode(struct inode *inode, int how) ...@@ -1823,6 +1831,7 @@ int nfs_commit_inode(struct inode *inode, int how)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC); __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
return res; return res;
} }
EXPORT_SYMBOL_GPL(nfs_commit_inode);
int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{ {
......
...@@ -1420,10 +1420,12 @@ struct nfs_mds_commit_info { ...@@ -1420,10 +1420,12 @@ struct nfs_mds_commit_info {
struct list_head list; struct list_head list;
}; };
struct nfs_commit_info;
struct nfs_commit_data; struct nfs_commit_data;
struct nfs_inode; struct nfs_inode;
struct nfs_commit_completion_ops { struct nfs_commit_completion_ops {
void (*completion) (struct nfs_commit_data *data); void (*completion) (struct nfs_commit_data *data);
void (*resched_write) (struct nfs_commit_info *, struct nfs_page *);
}; };
struct nfs_commit_info { struct nfs_commit_info {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册