summaryrefslogtreecommitdiffstats
path: root/fs/nfs
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
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')
-rw-r--r--fs/nfs/direct.c4
-rw-r--r--fs/nfs/inode.c1
-rw-r--r--fs/nfs/pnfs_nfs.c15
-rw-r--r--fs/nfs/write.c24
4 files changed, 22 insertions, 22 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 6fb9fad2d1e6..d2972d537469 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -616,13 +616,13 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
616 struct list_head *list, 616 struct list_head *list,
617 struct nfs_commit_info *cinfo) 617 struct nfs_commit_info *cinfo)
618{ 618{
619 spin_lock(&cinfo->inode->i_lock); 619 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
620#ifdef CONFIG_NFS_V4_1 620#ifdef CONFIG_NFS_V4_1
621 if (cinfo->ds != NULL && cinfo->ds->nwritten != 0) 621 if (cinfo->ds != NULL && cinfo->ds->nwritten != 0)
622 NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo); 622 NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo);
623#endif 623#endif
624 nfs_scan_commit_list(&cinfo->mds->list, list, cinfo, 0); 624 nfs_scan_commit_list(&cinfo->mds->list, list, cinfo, 0);
625 spin_unlock(&cinfo->inode->i_lock); 625 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
626} 626}
627 627
628static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) 628static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 109279d6d91b..34d9ebbc0dfd 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2016,6 +2016,7 @@ static void init_once(void *foo)
2016 nfsi->commit_info.ncommit = 0; 2016 nfsi->commit_info.ncommit = 0;
2017 atomic_set(&nfsi->commit_info.rpcs_out, 0); 2017 atomic_set(&nfsi->commit_info.rpcs_out, 0);
2018 init_rwsem(&nfsi->rmdir_sem); 2018 init_rwsem(&nfsi->rmdir_sem);
2019 mutex_init(&nfsi->commit_mutex);
2019 nfs4_init_once(nfsi); 2020 nfs4_init_once(nfsi);
2020} 2021}
2021 2022
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index 25f28fa64c57..2cdee8ce2094 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -98,14 +98,13 @@ pnfs_generic_transfer_commit_list(struct list_head *src, struct list_head *dst,
98 if (!nfs_lock_request(req)) 98 if (!nfs_lock_request(req))
99 continue; 99 continue;
100 kref_get(&req->wb_kref); 100 kref_get(&req->wb_kref);
101 if (cond_resched_lock(&cinfo->inode->i_lock))
102 list_safe_reset_next(req, tmp, wb_list);
103 nfs_request_remove_commit_list(req, cinfo); 101 nfs_request_remove_commit_list(req, cinfo);
104 clear_bit(PG_COMMIT_TO_DS, &req->wb_flags); 102 clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
105 nfs_list_add_request(req, dst); 103 nfs_list_add_request(req, dst);
106 ret++; 104 ret++;
107 if ((ret == max) && !cinfo->dreq) 105 if ((ret == max) && !cinfo->dreq)
108 break; 106 break;
107 cond_resched();
109 } 108 }
110 return ret; 109 return ret;
111} 110}
@@ -119,7 +118,7 @@ pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
119 struct list_head *dst = &bucket->committing; 118 struct list_head *dst = &bucket->committing;
120 int ret; 119 int ret;
121 120
122 lockdep_assert_held(&cinfo->inode->i_lock); 121 lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
123 ret = pnfs_generic_transfer_commit_list(src, dst, cinfo, max); 122 ret = pnfs_generic_transfer_commit_list(src, dst, cinfo, max);
124 if (ret) { 123 if (ret) {
125 cinfo->ds->nwritten -= ret; 124 cinfo->ds->nwritten -= ret;
@@ -142,7 +141,7 @@ int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo,
142{ 141{
143 int i, rv = 0, cnt; 142 int i, rv = 0, cnt;
144 143
145 lockdep_assert_held(&cinfo->inode->i_lock); 144 lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
146 for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) { 145 for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
147 cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i], 146 cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i],
148 cinfo, max); 147 cinfo, max);
@@ -162,7 +161,7 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst,
162 int nwritten; 161 int nwritten;
163 int i; 162 int i;
164 163
165 lockdep_assert_held(&cinfo->inode->i_lock); 164 lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
166restart: 165restart:
167 for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { 166 for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
168 nwritten = pnfs_generic_transfer_commit_list(&b->written, 167 nwritten = pnfs_generic_transfer_commit_list(&b->written,
@@ -953,12 +952,12 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
953 struct list_head *list; 952 struct list_head *list;
954 struct pnfs_commit_bucket *buckets; 953 struct pnfs_commit_bucket *buckets;
955 954
956 spin_lock(&cinfo->inode->i_lock); 955 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
957 buckets = cinfo->ds->buckets; 956 buckets = cinfo->ds->buckets;
958 list = &buckets[ds_commit_idx].written; 957 list = &buckets[ds_commit_idx].written;
959 if (list_empty(list)) { 958 if (list_empty(list)) {
960 if (!pnfs_is_valid_lseg(lseg)) { 959 if (!pnfs_is_valid_lseg(lseg)) {
961 spin_unlock(&cinfo->inode->i_lock); 960 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
962 cinfo->completion_ops->resched_write(cinfo, req); 961 cinfo->completion_ops->resched_write(cinfo, req);
963 return; 962 return;
964 } 963 }
@@ -975,7 +974,7 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
975 cinfo->ds->nwritten++; 974 cinfo->ds->nwritten++;
976 975
977 nfs_request_add_commit_list_locked(req, list, cinfo); 976 nfs_request_add_commit_list_locked(req, list, cinfo);
978 spin_unlock(&cinfo->inode->i_lock); 977 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
979 nfs_mark_page_unstable(req->wb_page, cinfo); 978 nfs_mark_page_unstable(req->wb_page, cinfo);
980} 979}
981EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit); 980EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
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