aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-05-15 11:56:46 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-29 11:11:45 -0400
commit67d0338edd71db9a4f406d8778f7c525d31e9f7f (patch)
treee0fdbb1461b833681f641d3f8263d8499f9d644c
parent2bfc6e566daa8386c9cffef2f7de17fc330d3835 (diff)
nfs: page group syncing in read path
Operations that modify state for a whole page must be syncronized across all requests within a page group. In the read path, this is calling unlock_page and SetPageUptodate. Both of these functions should not be called until all requests in a page group have reached the point where they would call them. This patch should have no effect yet since all page groups currently have one request, but will come into play when pg_test functions are modified to split pages into sub-page regions. Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/read.c22
-rw-r--r--include/linux/nfs_page.h2
3 files changed, 21 insertions, 5 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 015fb7b48dfe..18ee4e99347e 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -395,6 +395,8 @@ static void nfs_free_request(struct nfs_page *req)
395 395
396 /* extra debug: make sure no sync bits are still set */ 396 /* extra debug: make sure no sync bits are still set */
397 WARN_ON_ONCE(test_bit(PG_TEARDOWN, &req->wb_flags)); 397 WARN_ON_ONCE(test_bit(PG_TEARDOWN, &req->wb_flags));
398 WARN_ON_ONCE(test_bit(PG_UNLOCKPAGE, &req->wb_flags));
399 WARN_ON_ONCE(test_bit(PG_UPTODATE, &req->wb_flags));
398 400
399 /* Release struct file and open context */ 401 /* Release struct file and open context */
400 nfs_clear_request(req); 402 nfs_clear_request(req);
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 902ba2c63d05..53d5b83611ce 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -105,10 +105,16 @@ static void nfs_readpage_release(struct nfs_page *req)
105{ 105{
106 struct inode *d_inode = req->wb_context->dentry->d_inode; 106 struct inode *d_inode = req->wb_context->dentry->d_inode;
107 107
108 if (PageUptodate(req->wb_page)) 108 dprintk("NFS: read done (%s/%llu %d@%lld)\n", d_inode->i_sb->s_id,
109 nfs_readpage_to_fscache(d_inode, req->wb_page, 0); 109 (unsigned long long)NFS_FILEID(d_inode), req->wb_bytes,
110 (long long)req_offset(req));
110 111
111 unlock_page(req->wb_page); 112 if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) {
113 if (PageUptodate(req->wb_page))
114 nfs_readpage_to_fscache(d_inode, req->wb_page, 0);
115
116 unlock_page(req->wb_page);
117 }
112 118
113 dprintk("NFS: read done (%s/%Lu %d@%Ld)\n", 119 dprintk("NFS: read done (%s/%Lu %d@%Ld)\n",
114 req->wb_context->dentry->d_inode->i_sb->s_id, 120 req->wb_context->dentry->d_inode->i_sb->s_id,
@@ -118,6 +124,12 @@ static void nfs_readpage_release(struct nfs_page *req)
118 nfs_release_request(req); 124 nfs_release_request(req);
119} 125}
120 126
127static void nfs_page_group_set_uptodate(struct nfs_page *req)
128{
129 if (nfs_page_group_sync_on_bit(req, PG_UPTODATE))
130 SetPageUptodate(req->wb_page);
131}
132
121/* Note io was page aligned */ 133/* Note io was page aligned */
122static void nfs_read_completion(struct nfs_pgio_header *hdr) 134static void nfs_read_completion(struct nfs_pgio_header *hdr)
123{ 135{
@@ -140,9 +152,9 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
140 bytes += req->wb_bytes; 152 bytes += req->wb_bytes;
141 if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) { 153 if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
142 if (bytes <= hdr->good_bytes) 154 if (bytes <= hdr->good_bytes)
143 SetPageUptodate(page); 155 nfs_page_group_set_uptodate(req);
144 } else 156 } else
145 SetPageUptodate(page); 157 nfs_page_group_set_uptodate(req);
146 nfs_list_remove_request(req); 158 nfs_list_remove_request(req);
147 nfs_readpage_release(req); 159 nfs_readpage_release(req);
148 } 160 }
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 986c0c279d0e..6385175a127b 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -29,6 +29,8 @@ enum {
29 PG_INODE_REF, /* extra ref held by inode (head req only) */ 29 PG_INODE_REF, /* extra ref held by inode (head req only) */
30 PG_HEADLOCK, /* page group lock of wb_head */ 30 PG_HEADLOCK, /* page group lock of wb_head */
31 PG_TEARDOWN, /* page group sync for destroy */ 31 PG_TEARDOWN, /* page group sync for destroy */
32 PG_UNLOCKPAGE, /* page group sync bit in read path */
33 PG_UPTODATE, /* page group sync bit in read path */
32}; 34};
33 35
34struct nfs_inode; 36struct nfs_inode;