summaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-08-01 12:26:53 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-08-15 11:54:47 -0400
commitb30d2f04c35d539bf8003b3e014c389abefc249b (patch)
treed9545ae599d39524d44bc4323f6526df01789d59 /fs/nfs/write.c
parentbd37d6fce184836bd5e7cd90ce40116a4fadaf2a (diff)
NFS: Refactor nfs_page_find_head_request()
Split out the 2 cases so that we can treat the locking differently. The issue is that the locking in the pageswapcache cache is highly linked to the commit list locking. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index a06167e20b72..8d8fa6d4cfcc 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -170,20 +170,41 @@ nfs_page_private_request(struct page *page)
170 * returns matching head request with reference held, or NULL if not found. 170 * returns matching head request with reference held, or NULL if not found.
171 */ 171 */
172static struct nfs_page * 172static struct nfs_page *
173nfs_page_find_head_request_locked(struct nfs_inode *nfsi, struct page *page) 173nfs_page_find_private_request(struct page *page)
174{ 174{
175 struct inode *inode = page_file_mapping(page)->host;
175 struct nfs_page *req; 176 struct nfs_page *req;
176 177
178 if (!PagePrivate(page))
179 return NULL;
180 spin_lock(&inode->i_lock);
177 req = nfs_page_private_request(page); 181 req = nfs_page_private_request(page);
178 if (!req && unlikely(PageSwapCache(page)))
179 req = nfs_page_search_commits_for_head_request_locked(nfsi,
180 page);
181
182 if (req) { 182 if (req) {
183 WARN_ON_ONCE(req->wb_head != req); 183 WARN_ON_ONCE(req->wb_head != req);
184 kref_get(&req->wb_kref); 184 kref_get(&req->wb_kref);
185 } 185 }
186 spin_unlock(&inode->i_lock);
187 return req;
188}
186 189
190static struct nfs_page *
191nfs_page_find_swap_request(struct page *page)
192{
193 struct inode *inode = page_file_mapping(page)->host;
194 struct nfs_inode *nfsi = NFS_I(inode);
195 struct nfs_page *req = NULL;
196 if (!PageSwapCache(page))
197 return NULL;
198 spin_lock(&inode->i_lock);
199 if (PageSwapCache(page)) {
200 req = nfs_page_search_commits_for_head_request_locked(nfsi,
201 page);
202 if (req) {
203 WARN_ON_ONCE(req->wb_head != req);
204 kref_get(&req->wb_kref);
205 }
206 }
207 spin_unlock(&inode->i_lock);
187 return req; 208 return req;
188} 209}
189 210
@@ -194,14 +215,11 @@ nfs_page_find_head_request_locked(struct nfs_inode *nfsi, struct page *page)
194 */ 215 */
195static struct nfs_page *nfs_page_find_head_request(struct page *page) 216static struct nfs_page *nfs_page_find_head_request(struct page *page)
196{ 217{
197 struct inode *inode = page_file_mapping(page)->host; 218 struct nfs_page *req;
198 struct nfs_page *req = NULL;
199 219
200 if (PagePrivate(page) || PageSwapCache(page)) { 220 req = nfs_page_find_private_request(page);
201 spin_lock(&inode->i_lock); 221 if (!req)
202 req = nfs_page_find_head_request_locked(NFS_I(inode), page); 222 req = nfs_page_find_swap_request(page);
203 spin_unlock(&inode->i_lock);
204 }
205 return req; 223 return req;
206} 224}
207 225