diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-01 17:29:29 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-15 11:54:48 -0400 |
commit | 2ce209c42c01ca976ad680fea52a8e8b9a53643b (patch) | |
tree | 1728cf3caf2430e3a4cd944228b31f084f577115 /fs/nfs/write.c | |
parent | 8205b9ce030288e104a3024344f2a0a086231e36 (diff) | |
download | linux-2ce209c42c01ca976ad680fea52a8e8b9a53643b.tar.gz linux-2ce209c42c01ca976ad680fea52a8e8b9a53643b.tar.bz2 linux-2ce209c42c01ca976ad680fea52a8e8b9a53643b.zip |
NFS: Wait for requests that are locked on the commit list
If a request is on the commit list, but is locked, we will currently skip
it, which can lead to livelocking when the commit count doesn't reduce
to zero.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 866702823869..5dd3b212376e 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1030,13 +1030,22 @@ int nfs_scan_commit_list(struct list_head *src, struct list_head *dst, struct nfs_commit_info *cinfo, int max) { - struct nfs_page *req, *tmp; + struct nfs_page *req; int ret = 0; - list_for_each_entry_safe(req, tmp, src, wb_list) { - if (!nfs_lock_request(req)) - continue; + while(!list_empty(src)) { + req = list_first_entry(src, struct nfs_page, wb_list); kref_get(&req->wb_kref); + if (!nfs_lock_request(req)) { + int status; + mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex); + status = nfs_wait_on_request(req); + nfs_release_request(req); + mutex_lock(&NFS_I(cinfo->inode)->commit_mutex); + if (status < 0) + break; + continue; + } nfs_request_remove_commit_list(req, cinfo); nfs_list_add_request(req, dst); ret++; |