aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-07-17 20:42:17 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-08-03 17:05:25 -0400
commit02d1426c7053da7c5a828ae9cd7b636ea4e46bf7 (patch)
treec241cc5c33ce52da89ecf04486988b21c85d0203 /fs
parentb412ddf0661e11485876a202c48868143e3a01cf (diff)
pnfs: find swapped pages on pnfs commit lists too
nfs_page_find_head_request_locked looks through the regular nfs commit lists when the page is swapped out, but doesn't look through the pnfs commit lists. I'm not sure if anyone has hit any issues caused by this. Suggested-by: Peng Tao <tao.peng@primarydata.com> Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/filelayout/filelayout.c31
-rw-r--r--fs/nfs/pnfs.h20
-rw-r--r--fs/nfs/write.c49
3 files changed, 88 insertions, 12 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index 2576d28bffc0..524e66f6bb9c 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -1237,6 +1237,36 @@ restart:
1237 spin_unlock(cinfo->lock); 1237 spin_unlock(cinfo->lock);
1238} 1238}
1239 1239
1240/* filelayout_search_commit_reqs - Search lists in @cinfo for the head reqest
1241 * for @page
1242 * @cinfo - commit info for current inode
1243 * @page - page to search for matching head request
1244 *
1245 * Returns a the head request if one is found, otherwise returns NULL.
1246 */
1247static struct nfs_page *
1248filelayout_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page)
1249{
1250 struct nfs_page *freq, *t;
1251 struct pnfs_commit_bucket *b;
1252 int i;
1253
1254 /* Linearly search the commit lists for each bucket until a matching
1255 * request is found */
1256 for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
1257 list_for_each_entry_safe(freq, t, &b->written, wb_list) {
1258 if (freq->wb_page == page)
1259 return freq->wb_head;
1260 }
1261 list_for_each_entry_safe(freq, t, &b->committing, wb_list) {
1262 if (freq->wb_page == page)
1263 return freq->wb_head;
1264 }
1265 }
1266
1267 return NULL;
1268}
1269
1240static void filelayout_retry_commit(struct nfs_commit_info *cinfo, int idx) 1270static void filelayout_retry_commit(struct nfs_commit_info *cinfo, int idx)
1241{ 1271{
1242 struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; 1272 struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
@@ -1386,6 +1416,7 @@ static struct pnfs_layoutdriver_type filelayout_type = {
1386 .clear_request_commit = filelayout_clear_request_commit, 1416 .clear_request_commit = filelayout_clear_request_commit,
1387 .scan_commit_lists = filelayout_scan_commit_lists, 1417 .scan_commit_lists = filelayout_scan_commit_lists,
1388 .recover_commit_reqs = filelayout_recover_commit_reqs, 1418 .recover_commit_reqs = filelayout_recover_commit_reqs,
1419 .search_commit_reqs = filelayout_search_commit_reqs,
1389 .commit_pagelist = filelayout_commit_pagelist, 1420 .commit_pagelist = filelayout_commit_pagelist,
1390 .read_pagelist = filelayout_read_pagelist, 1421 .read_pagelist = filelayout_read_pagelist,
1391 .write_pagelist = filelayout_write_pagelist, 1422 .write_pagelist = filelayout_write_pagelist,
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 27ddecd3847f..203b6c9498b0 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -104,6 +104,8 @@ struct pnfs_layoutdriver_type {
104 int max); 104 int max);
105 void (*recover_commit_reqs) (struct list_head *list, 105 void (*recover_commit_reqs) (struct list_head *list,
106 struct nfs_commit_info *cinfo); 106 struct nfs_commit_info *cinfo);
107 struct nfs_page * (*search_commit_reqs)(struct nfs_commit_info *cinfo,
108 struct page *page);
107 int (*commit_pagelist)(struct inode *inode, 109 int (*commit_pagelist)(struct inode *inode,
108 struct list_head *mds_pages, 110 struct list_head *mds_pages,
109 int how, 111 int how,
@@ -341,6 +343,17 @@ pnfs_recover_commit_reqs(struct inode *inode, struct list_head *list,
341 NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo); 343 NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo);
342} 344}
343 345
346static inline struct nfs_page *
347pnfs_search_commit_reqs(struct inode *inode, struct nfs_commit_info *cinfo,
348 struct page *page)
349{
350 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
351
352 if (ld == NULL || ld->search_commit_reqs == NULL)
353 return NULL;
354 return ld->search_commit_reqs(cinfo, page);
355}
356
344/* Should the pNFS client commit and return the layout upon a setattr */ 357/* Should the pNFS client commit and return the layout upon a setattr */
345static inline bool 358static inline bool
346pnfs_ld_layoutret_on_setattr(struct inode *inode) 359pnfs_ld_layoutret_on_setattr(struct inode *inode)
@@ -492,6 +505,13 @@ pnfs_recover_commit_reqs(struct inode *inode, struct list_head *list,
492{ 505{
493} 506}
494 507
508static inline struct nfs_page *
509pnfs_search_commit_reqs(struct inode *inode, struct nfs_commit_info *cinfo,
510 struct page *page)
511{
512 return NULL;
513}
514
495static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) 515static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync)
496{ 516{
497 return 0; 517 return 0;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e6bc5b51f325..ba417692b80d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -47,6 +47,8 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
47static const struct nfs_commit_completion_ops nfs_commit_completion_ops; 47static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
48static const struct nfs_rw_ops nfs_rw_write_ops; 48static const struct nfs_rw_ops nfs_rw_write_ops;
49static void nfs_clear_request_commit(struct nfs_page *req); 49static void nfs_clear_request_commit(struct nfs_page *req);
50static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
51 struct inode *inode);
50 52
51static struct kmem_cache *nfs_wdata_cachep; 53static struct kmem_cache *nfs_wdata_cachep;
52static mempool_t *nfs_wdata_mempool; 54static mempool_t *nfs_wdata_mempool;
@@ -93,6 +95,38 @@ static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
93} 95}
94 96
95/* 97/*
98 * nfs_page_search_commits_for_head_request_locked
99 *
100 * Search through commit lists on @inode for the head request for @page.
101 * Must be called while holding the inode (which is cinfo) lock.
102 *
103 * Returns the head request if found, or NULL if not found.
104 */
105static struct nfs_page *
106nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi,
107 struct page *page)
108{
109 struct nfs_page *freq, *t;
110 struct nfs_commit_info cinfo;
111 struct inode *inode = &nfsi->vfs_inode;
112
113 nfs_init_cinfo_from_inode(&cinfo, inode);
114
115 /* search through pnfs commit lists */
116 freq = pnfs_search_commit_reqs(inode, &cinfo, page);
117 if (freq)
118 return freq->wb_head;
119
120 /* Linearly search the commit list for the correct request */
121 list_for_each_entry_safe(freq, t, &cinfo.mds->list, wb_list) {
122 if (freq->wb_page == page)
123 return freq->wb_head;
124 }
125
126 return NULL;
127}
128
129/*
96 * nfs_page_find_head_request_locked - find head request associated with @page 130 * nfs_page_find_head_request_locked - find head request associated with @page
97 * 131 *
98 * must be called while holding the inode lock. 132 * must be called while holding the inode lock.
@@ -106,21 +140,12 @@ nfs_page_find_head_request_locked(struct nfs_inode *nfsi, struct page *page)
106 140
107 if (PagePrivate(page)) 141 if (PagePrivate(page))
108 req = (struct nfs_page *)page_private(page); 142 req = (struct nfs_page *)page_private(page);
109 else if (unlikely(PageSwapCache(page))) { 143 else if (unlikely(PageSwapCache(page)))
110 struct nfs_page *freq, *t; 144 req = nfs_page_search_commits_for_head_request_locked(nfsi,
111 145 page);
112 /* Linearly search the commit list for the correct req */
113 list_for_each_entry_safe(freq, t, &nfsi->commit_info.list, wb_list) {
114 if (freq->wb_page == page) {
115 req = freq->wb_head;
116 break;
117 }
118 }
119 }
120 146
121 if (req) { 147 if (req) {
122 WARN_ON_ONCE(req->wb_head != req); 148 WARN_ON_ONCE(req->wb_head != req);
123
124 kref_get(&req->wb_kref); 149 kref_get(&req->wb_kref);
125 } 150 }
126 151