Skip to content

Commit e824f99

Browse files
committed
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>
1 parent b30d2f0 commit e824f99

File tree

5 files changed

+23
-22
lines changed

5 files changed

+23
-22
lines changed

fs/nfs/direct.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,13 +616,13 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
616616
struct list_head *list,
617617
struct nfs_commit_info *cinfo)
618618
{
619-
spin_lock(&cinfo->inode->i_lock);
619+
mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
620620
#ifdef CONFIG_NFS_V4_1
621621
if (cinfo->ds != NULL && cinfo->ds->nwritten != 0)
622622
NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo);
623623
#endif
624624
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);
626626
}
627627

628628
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)

fs/nfs/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,6 +2016,7 @@ static void init_once(void *foo)
20162016
nfsi->commit_info.ncommit = 0;
20172017
atomic_set(&nfsi->commit_info.rpcs_out, 0);
20182018
init_rwsem(&nfsi->rmdir_sem);
2019+
mutex_init(&nfsi->commit_mutex);
20192020
nfs4_init_once(nfsi);
20202021
}
20212022

fs/nfs/pnfs_nfs.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,13 @@ pnfs_generic_transfer_commit_list(struct list_head *src, struct list_head *dst,
9898
if (!nfs_lock_request(req))
9999
continue;
100100
kref_get(&req->wb_kref);
101-
if (cond_resched_lock(&cinfo->inode->i_lock))
102-
list_safe_reset_next(req, tmp, wb_list);
103101
nfs_request_remove_commit_list(req, cinfo);
104102
clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
105103
nfs_list_add_request(req, dst);
106104
ret++;
107105
if ((ret == max) && !cinfo->dreq)
108106
break;
107+
cond_resched();
109108
}
110109
return ret;
111110
}
@@ -119,7 +118,7 @@ pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
119118
struct list_head *dst = &bucket->committing;
120119
int ret;
121120

122-
lockdep_assert_held(&cinfo->inode->i_lock);
121+
lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
123122
ret = pnfs_generic_transfer_commit_list(src, dst, cinfo, max);
124123
if (ret) {
125124
cinfo->ds->nwritten -= ret;
@@ -142,7 +141,7 @@ int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo,
142141
{
143142
int i, rv = 0, cnt;
144143

145-
lockdep_assert_held(&cinfo->inode->i_lock);
144+
lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
146145
for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
147146
cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i],
148147
cinfo, max);
@@ -162,7 +161,7 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst,
162161
int nwritten;
163162
int i;
164163

165-
lockdep_assert_held(&cinfo->inode->i_lock);
164+
lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
166165
restart:
167166
for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
168167
nwritten = pnfs_generic_transfer_commit_list(&b->written,
@@ -953,12 +952,12 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
953952
struct list_head *list;
954953
struct pnfs_commit_bucket *buckets;
955954

956-
spin_lock(&cinfo->inode->i_lock);
955+
mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
957956
buckets = cinfo->ds->buckets;
958957
list = &buckets[ds_commit_idx].written;
959958
if (list_empty(list)) {
960959
if (!pnfs_is_valid_lseg(lseg)) {
961-
spin_unlock(&cinfo->inode->i_lock);
960+
mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
962961
cinfo->completion_ops->resched_write(cinfo, req);
963962
return;
964963
}
@@ -975,7 +974,7 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
975974
cinfo->ds->nwritten++;
976975

977976
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);
979978
nfs_mark_page_unstable(req->wb_page, cinfo);
980979
}
981980
EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);

fs/nfs/write.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ nfs_page_find_swap_request(struct page *page)
195195
struct nfs_page *req = NULL;
196196
if (!PageSwapCache(page))
197197
return NULL;
198-
spin_lock(&inode->i_lock);
198+
mutex_lock(&nfsi->commit_mutex);
199199
if (PageSwapCache(page)) {
200200
req = nfs_page_search_commits_for_head_request_locked(nfsi,
201201
page);
@@ -204,7 +204,7 @@ nfs_page_find_swap_request(struct page *page)
204204
kref_get(&req->wb_kref);
205205
}
206206
}
207-
spin_unlock(&inode->i_lock);
207+
mutex_unlock(&nfsi->commit_mutex);
208208
return req;
209209
}
210210

@@ -856,7 +856,8 @@ nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi,
856856
* number of outstanding requests requiring a commit as well as
857857
* the MM page stats.
858858
*
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.
860861
*/
861862
void
862863
nfs_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);
884885
void
885886
nfs_request_add_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo)
886887
{
887-
spin_lock(&cinfo->inode->i_lock);
888+
mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
888889
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);
890891
if (req->wb_page)
891892
nfs_mark_page_unstable(req->wb_page, cinfo);
892893
}
@@ -964,11 +965,11 @@ nfs_clear_request_commit(struct nfs_page *req)
964965
struct nfs_commit_info cinfo;
965966

966967
nfs_init_cinfo_from_inode(&cinfo, inode);
967-
spin_lock(&inode->i_lock);
968+
mutex_lock(&NFS_I(inode)->commit_mutex);
968969
if (!pnfs_clear_request_commit(req, &cinfo)) {
969970
nfs_request_remove_commit_list(req, &cinfo);
970971
}
971-
spin_unlock(&inode->i_lock);
972+
mutex_unlock(&NFS_I(inode)->commit_mutex);
972973
nfs_clear_page_commit(req->wb_page);
973974
}
974975
}
@@ -1027,7 +1028,7 @@ nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
10271028
return cinfo->mds->ncommit;
10281029
}
10291030

1030-
/* cinfo->inode->i_lock held by caller */
1031+
/* NFS_I(cinfo->inode)->commit_mutex held by caller */
10311032
int
10321033
nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
10331034
struct nfs_commit_info *cinfo, int max)
@@ -1039,13 +1040,12 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
10391040
if (!nfs_lock_request(req))
10401041
continue;
10411042
kref_get(&req->wb_kref);
1042-
if (cond_resched_lock(&cinfo->inode->i_lock))
1043-
list_safe_reset_next(req, tmp, wb_list);
10441043
nfs_request_remove_commit_list(req, cinfo);
10451044
nfs_list_add_request(req, dst);
10461045
ret++;
10471046
if ((ret == max) && !cinfo->dreq)
10481047
break;
1048+
cond_resched();
10491049
}
10501050
return ret;
10511051
}
@@ -1065,15 +1065,15 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst,
10651065
{
10661066
int ret = 0;
10671067

1068-
spin_lock(&cinfo->inode->i_lock);
1068+
mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
10691069
if (cinfo->mds->ncommit > 0) {
10701070
const int max = INT_MAX;
10711071

10721072
ret = nfs_scan_commit_list(&cinfo->mds->list, dst,
10731073
cinfo, max);
10741074
ret += pnfs_scan_commit_lists(inode, cinfo, max - ret);
10751075
}
1076-
spin_unlock(&cinfo->inode->i_lock);
1076+
mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
10771077
return ret;
10781078
}
10791079

include/linux/nfs_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ struct nfs_inode {
163163
/* Readers: in-flight sillydelete RPC calls */
164164
/* Writers: rmdir */
165165
struct rw_semaphore rmdir_sem;
166+
struct mutex commit_mutex;
166167

167168
#if IS_ENABLED(CONFIG_NFS_V4)
168169
struct nfs4_cached_acl *nfs4_acl;

0 commit comments

Comments
 (0)