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) |
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 | |||
1030 | nfs_scan_commit_list(struct list_head *src, struct list_head *dst, | 1030 | nfs_scan_commit_list(struct list_head *src, struct list_head *dst, |
1031 | struct nfs_commit_info *cinfo, int max) | 1031 | struct nfs_commit_info *cinfo, int max) |
1032 | { | 1032 | { |
1033 | struct nfs_page *req, *tmp; | 1033 | struct nfs_page *req; |
1034 | int ret = 0; | 1034 | int ret = 0; |
1035 | 1035 | ||
1036 | list_for_each_entry_safe(req, tmp, src, wb_list) { | 1036 | while(!list_empty(src)) { |
1037 | if (!nfs_lock_request(req)) | 1037 | req = list_first_entry(src, struct nfs_page, wb_list); |
1038 | continue; | ||
1039 | kref_get(&req->wb_kref); | 1038 | kref_get(&req->wb_kref); |
1039 | if (!nfs_lock_request(req)) { | ||
1040 | int status; | ||
1041 | mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex); | ||
1042 | status = nfs_wait_on_request(req); | ||
1043 | nfs_release_request(req); | ||
1044 | mutex_lock(&NFS_I(cinfo->inode)->commit_mutex); | ||
1045 | if (status < 0) | ||
1046 | break; | ||
1047 | continue; | ||
1048 | } | ||
1040 | nfs_request_remove_commit_list(req, cinfo); | 1049 | nfs_request_remove_commit_list(req, cinfo); |
1041 | nfs_list_add_request(req, dst); | 1050 | nfs_list_add_request(req, dst); |
1042 | ret++; | 1051 | ret++; |