diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-01 12:26:53 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-15 11:54:47 -0400 |
commit | b30d2f04c35d539bf8003b3e014c389abefc249b (patch) | |
tree | d9545ae599d39524d44bc4323f6526df01789d59 /fs/nfs/write.c | |
parent | bd37d6fce184836bd5e7cd90ce40116a4fadaf2a (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.c | 42 |
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 | */ |
172 | static struct nfs_page * | 172 | static struct nfs_page * |
173 | nfs_page_find_head_request_locked(struct nfs_inode *nfsi, struct page *page) | 173 | nfs_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 | ||
190 | static struct nfs_page * | ||
191 | nfs_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 | */ |
195 | static struct nfs_page *nfs_page_find_head_request(struct page *page) | 216 | static 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 | ||