Commit 085d1e33 authored by Tom Haynes's avatar Tom Haynes

pnfs: Do not grab the commit_info lock twice when rescheduling writes

Acked-by: default avatarJeff Layton <jlayton@primarydata.com>
Signed-off-by: default avatarTom Haynes <loghyr@primarydata.com>
parent f54bcf2e
...@@ -573,6 +573,20 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter, ...@@ -573,6 +573,20 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
return result; return result;
} }
static void
nfs_direct_write_scan_commit_list(struct inode *inode,
struct list_head *list,
struct nfs_commit_info *cinfo)
{
spin_lock(cinfo->lock);
#ifdef CONFIG_NFS_V4_1
if (cinfo->ds != NULL && cinfo->ds->nwritten != 0)
NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo);
#endif
nfs_scan_commit_list(&cinfo->mds->list, list, cinfo, 0);
spin_unlock(cinfo->lock);
}
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
{ {
struct nfs_pageio_descriptor desc; struct nfs_pageio_descriptor desc;
...@@ -582,10 +596,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) ...@@ -582,10 +596,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
LIST_HEAD(failed); LIST_HEAD(failed);
nfs_init_cinfo_from_dreq(&cinfo, dreq); nfs_init_cinfo_from_dreq(&cinfo, dreq);
pnfs_recover_commit_reqs(dreq->inode, &reqs, &cinfo); nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
spin_lock(cinfo.lock);
nfs_scan_commit_list(&cinfo.mds->list, &reqs, &cinfo, 0);
spin_unlock(cinfo.lock);
dreq->count = 0; dreq->count = 0;
get_dreq(dreq); get_dreq(dreq);
......
...@@ -375,15 +375,6 @@ pnfs_scan_commit_lists(struct inode *inode, struct nfs_commit_info *cinfo, ...@@ -375,15 +375,6 @@ pnfs_scan_commit_lists(struct inode *inode, struct nfs_commit_info *cinfo,
return NFS_SERVER(inode)->pnfs_curr_ld->scan_commit_lists(cinfo, max); return NFS_SERVER(inode)->pnfs_curr_ld->scan_commit_lists(cinfo, max);
} }
static inline void
pnfs_recover_commit_reqs(struct inode *inode, struct list_head *list,
struct nfs_commit_info *cinfo)
{
if (cinfo->ds == NULL || cinfo->ds->nwritten == 0)
return;
NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo);
}
static inline struct nfs_page * static inline struct nfs_page *
pnfs_search_commit_reqs(struct inode *inode, struct nfs_commit_info *cinfo, pnfs_search_commit_reqs(struct inode *inode, struct nfs_commit_info *cinfo,
struct page *page) struct page *page)
...@@ -554,12 +545,6 @@ pnfs_scan_commit_lists(struct inode *inode, struct nfs_commit_info *cinfo, ...@@ -554,12 +545,6 @@ pnfs_scan_commit_lists(struct inode *inode, struct nfs_commit_info *cinfo,
return 0; return 0;
} }
static inline void
pnfs_recover_commit_reqs(struct inode *inode, struct list_head *list,
struct nfs_commit_info *cinfo)
{
}
static inline struct nfs_page * static inline struct nfs_page *
pnfs_search_commit_reqs(struct inode *inode, struct nfs_commit_info *cinfo, pnfs_search_commit_reqs(struct inode *inode, struct nfs_commit_info *cinfo,
struct page *page) struct page *page)
......
...@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_release); ...@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_release);
/* The generic layer is about to remove the req from the commit list. /* The generic layer is about to remove the req from the commit list.
* If this will make the bucket empty, it will need to put the lseg reference. * If this will make the bucket empty, it will need to put the lseg reference.
* Note this is must be called holding the inode (/cinfo) lock * Note this must be called holding the inode (/cinfo) lock
*/ */
void void
pnfs_generic_clear_request_commit(struct nfs_page *req, pnfs_generic_clear_request_commit(struct nfs_page *req,
...@@ -115,7 +115,6 @@ pnfs_generic_transfer_commit_list(struct list_head *src, struct list_head *dst, ...@@ -115,7 +115,6 @@ pnfs_generic_transfer_commit_list(struct list_head *src, struct list_head *dst,
return ret; return ret;
} }
/* Note called with cinfo->lock held. */
static int static int
pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket, pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
struct nfs_commit_info *cinfo, struct nfs_commit_info *cinfo,
...@@ -125,6 +124,7 @@ pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket, ...@@ -125,6 +124,7 @@ pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
struct list_head *dst = &bucket->committing; struct list_head *dst = &bucket->committing;
int ret; int ret;
lockdep_assert_held(cinfo->lock);
ret = pnfs_generic_transfer_commit_list(src, dst, cinfo, max); ret = pnfs_generic_transfer_commit_list(src, dst, cinfo, max);
if (ret) { if (ret) {
cinfo->ds->nwritten -= ret; cinfo->ds->nwritten -= ret;
...@@ -138,14 +138,15 @@ pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket, ...@@ -138,14 +138,15 @@ pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
return ret; return ret;
} }
/* Move reqs from written to committing lists, returning count of number moved. /* Move reqs from written to committing lists, returning count
* Note called with cinfo->lock held. * of number moved.
*/ */
int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo,
int max) int max)
{ {
int i, rv = 0, cnt; int i, rv = 0, cnt;
lockdep_assert_held(cinfo->lock);
for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) { for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i], cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i],
cinfo, max); cinfo, max);
...@@ -156,7 +157,7 @@ int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, ...@@ -156,7 +157,7 @@ int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo,
} }
EXPORT_SYMBOL_GPL(pnfs_generic_scan_commit_lists); EXPORT_SYMBOL_GPL(pnfs_generic_scan_commit_lists);
/* Pull everything off the committing lists and dump into @dst */ /* Pull everything off the committing lists and dump into @dst. */
void pnfs_generic_recover_commit_reqs(struct list_head *dst, void pnfs_generic_recover_commit_reqs(struct list_head *dst,
struct nfs_commit_info *cinfo) struct nfs_commit_info *cinfo)
{ {
...@@ -164,8 +165,8 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst, ...@@ -164,8 +165,8 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst,
struct pnfs_layout_segment *freeme; struct pnfs_layout_segment *freeme;
int i; int i;
lockdep_assert_held(cinfo->lock);
restart: restart:
spin_lock(cinfo->lock);
for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
if (pnfs_generic_transfer_commit_list(&b->written, dst, if (pnfs_generic_transfer_commit_list(&b->written, dst,
cinfo, 0)) { cinfo, 0)) {
...@@ -173,11 +174,11 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst, ...@@ -173,11 +174,11 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst,
b->wlseg = NULL; b->wlseg = NULL;
spin_unlock(cinfo->lock); spin_unlock(cinfo->lock);
pnfs_put_lseg(freeme); pnfs_put_lseg(freeme);
spin_lock(cinfo->lock);
goto restart; goto restart;
} }
} }
cinfo->ds->nwritten = 0; cinfo->ds->nwritten = 0;
spin_unlock(cinfo->lock);
} }
EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs); EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs);
......
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