summaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-08-01 11:53:49 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-08-15 11:54:47 -0400
commite824f99adaaf1ed0e03eac8574599af6d992163d (patch)
treec5d2716566d21f023bd278dae6a92a06cbe72816 /fs/nfs/write.c
parentb30d2f04c35d539bf8003b3e014c389abefc249b (diff)
NFSv4: Use a mutex to protect the per-inode commit lists
The commit lists can get very large, so using the inode->i_lock can end up affecting general metadata performance. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 8d8fa6d4cfcc..5ab5ca24b48a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -195,7 +195,7 @@ nfs_page_find_swap_request(struct page *page)
195 struct nfs_page *req = NULL; 195 struct nfs_page *req = NULL;
196 if (!PageSwapCache(page)) 196 if (!PageSwapCache(page))
197 return NULL; 197 return NULL;
198 spin_lock(&inode->i_lock); 198 mutex_lock(&nfsi->commit_mutex);
199 if (PageSwapCache(page)) { 199 if (PageSwapCache(page)) {
200 req = nfs_page_search_commits_for_head_request_locked(nfsi, 200 req = nfs_page_search_commits_for_head_request_locked(nfsi,
201 page); 201 page);
@@ -204,7 +204,7 @@ nfs_page_find_swap_request(struct page *page)
204 kref_get(&req->wb_kref); 204 kref_get(&req->wb_kref);
205 } 205 }
206 } 206 }
207 spin_unlock(&inode->i_lock); 207 mutex_unlock(&nfsi->commit_mutex);
208 return req; 208 return req;
209} 209}
210 210
@@ -856,7 +856,8 @@ nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi,
856 * number of outstanding requests requiring a commit as well as 856 * number of outstanding requests requiring a commit as well as
857 * the MM page stats. 857 * the MM page stats.
858 * 858 *
859 * The caller must hold cinfo->inode->i_lock, and the nfs_page lock. 859 * The caller must hold NFS_I(cinfo->inode)->commit_mutex, and the
860 * nfs_page lock.
860 */ 861 */
861void 862void
862nfs_request_add_commit_list_locked(struct nfs_page *req, struct list_head *dst, 863nfs_request_add_commit_list_locked(struct nfs_page *req, struct list_head *dst,
@@ -884,9 +885,9 @@ EXPORT_SYMBOL_GPL(nfs_request_add_commit_list_locked);
884void 885void
885nfs_request_add_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo) 886nfs_request_add_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo)
886{ 887{
887 spin_lock(&cinfo->inode->i_lock); 888 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
888 nfs_request_add_commit_list_locked(req, &cinfo->mds->list, cinfo); 889 nfs_request_add_commit_list_locked(req, &cinfo->mds->list, cinfo);
889 spin_unlock(&cinfo->inode->i_lock); 890 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
890 if (req->wb_page) 891 if (req->wb_page)
891 nfs_mark_page_unstable(req->wb_page, cinfo); 892 nfs_mark_page_unstable(req->wb_page, cinfo);
892} 893}
@@ -964,11 +965,11 @@ nfs_clear_request_commit(struct nfs_page *req)
964 struct nfs_commit_info cinfo; 965 struct nfs_commit_info cinfo;
965 966
966 nfs_init_cinfo_from_inode(&cinfo, inode); 967 nfs_init_cinfo_from_inode(&cinfo, inode);
967 spin_lock(&inode->i_lock); 968 mutex_lock(&NFS_I(inode)->commit_mutex);
968 if (!pnfs_clear_request_commit(req, &cinfo)) { 969 if (!pnfs_clear_request_commit(req, &cinfo)) {
969 nfs_request_remove_commit_list(req, &cinfo); 970 nfs_request_remove_commit_list(req, &cinfo);
970 } 971 }
971 spin_unlock(&inode->i_lock); 972 mutex_unlock(&NFS_I(inode)->commit_mutex);
972 nfs_clear_page_commit(req->wb_page); 973 nfs_clear_page_commit(req->wb_page);
973 } 974 }
974} 975}
@@ -1027,7 +1028,7 @@ nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
1027 return cinfo->mds->ncommit; 1028 return cinfo->mds->ncommit;
1028} 1029}
1029 1030
1030/* cinfo->inode->i_lock held by caller */ 1031/* NFS_I(cinfo->inode)->commit_mutex held by caller */
1031int 1032int
1032nfs_scan_commit_list(struct list_head *src, struct list_head *dst, 1033nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
1033 struct nfs_commit_info *cinfo, int max) 1034 struct nfs_commit_info *cinfo, int max)
@@ -1039,13 +1040,12 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
1039 if (!nfs_lock_request(req)) 1040 if (!nfs_lock_request(req))
1040 continue; 1041 continue;
1041 kref_get(&req->wb_kref); 1042 kref_get(&req->wb_kref);
1042 if (cond_resched_lock(&cinfo->inode->i_lock))
1043 list_safe_reset_next(req, tmp, wb_list);
1044 nfs_request_remove_commit_list(req, cinfo); 1043 nfs_request_remove_commit_list(req, cinfo);
1045 nfs_list_add_request(req, dst); 1044 nfs_list_add_request(req, dst);
1046 ret++; 1045 ret++;
1047 if ((ret == max) && !cinfo->dreq) 1046 if ((ret == max) && !cinfo->dreq)
1048 break; 1047 break;
1048 cond_resched();
1049 } 1049 }
1050 return ret; 1050 return ret;
1051} 1051}
@@ -1065,7 +1065,7 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst,
1065{ 1065{
1066 int ret = 0; 1066 int ret = 0;
1067 1067
1068 spin_lock(&cinfo->inode->i_lock); 1068 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
1069 if (cinfo->mds->ncommit > 0) { 1069 if (cinfo->mds->ncommit > 0) {
1070 const int max = INT_MAX; 1070 const int max = INT_MAX;
1071 1071
@@ -1073,7 +1073,7 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst,
1073 cinfo, max); 1073 cinfo, max);
1074 ret += pnfs_scan_commit_lists(inode, cinfo, max - ret); 1074 ret += pnfs_scan_commit_lists(inode, cinfo, max - ret);
1075 } 1075 }
1076 spin_unlock(&cinfo->inode->i_lock); 1076 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
1077 return ret; 1077 return ret;
1078} 1078}
1079 1079