summaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-05-15 11:56:48 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-29 11:11:46 -0400
commitd72ddcbab60a70258d0cd5752db3f53824df78d6 (patch)
tree53bc78daab4fd608559772abaabe908e5250fcdd /fs/nfs/write.c
parent20633f042fd0907300069714b98aaf607a8b5bf8 (diff)
nfs: page group support in nfs_mark_uptodate
Change how nfs_mark_uptodate checks to see if writes cover a whole page. 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>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c74
1 files changed, 67 insertions, 7 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 5d752766139d..17b98952f7bd 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -154,18 +154,78 @@ static void nfs_set_pageerror(struct page *page)
154 nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); 154 nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page));
155} 155}
156 156
157/*
158 * nfs_page_group_search_locked
159 * @head - head request of page group
160 * @page_offset - offset into page
161 *
162 * Search page group with head @head to find a request that contains the
163 * page offset @page_offset.
164 *
165 * Returns a pointer to the first matching nfs request, or NULL if no
166 * match is found.
167 *
168 * Must be called with the page group lock held
169 */
170static struct nfs_page *
171nfs_page_group_search_locked(struct nfs_page *head, unsigned int page_offset)
172{
173 struct nfs_page *req;
174
175 WARN_ON_ONCE(head != head->wb_head);
176 WARN_ON_ONCE(!test_bit(PG_HEADLOCK, &head->wb_head->wb_flags));
177
178 req = head;
179 do {
180 if (page_offset >= req->wb_pgbase &&
181 page_offset < (req->wb_pgbase + req->wb_bytes))
182 return req;
183
184 req = req->wb_this_page;
185 } while (req != head);
186
187 return NULL;
188}
189
190/*
191 * nfs_page_group_covers_page
192 * @head - head request of page group
193 *
194 * Return true if the page group with head @head covers the whole page,
195 * returns false otherwise
196 */
197static bool nfs_page_group_covers_page(struct nfs_page *req)
198{
199 struct nfs_page *tmp;
200 unsigned int pos = 0;
201 unsigned int len = nfs_page_length(req->wb_page);
202
203 nfs_page_group_lock(req);
204
205 do {
206 tmp = nfs_page_group_search_locked(req->wb_head, pos);
207 if (tmp) {
208 /* no way this should happen */
209 WARN_ON_ONCE(tmp->wb_pgbase != pos);
210 pos += tmp->wb_bytes - (pos - tmp->wb_pgbase);
211 }
212 } while (tmp && pos < len);
213
214 nfs_page_group_unlock(req);
215 WARN_ON_ONCE(pos > len);
216 return pos == len;
217}
218
157/* We can set the PG_uptodate flag if we see that a write request 219/* We can set the PG_uptodate flag if we see that a write request
158 * covers the full page. 220 * covers the full page.
159 */ 221 */
160static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count) 222static void nfs_mark_uptodate(struct nfs_page *req)
161{ 223{
162 if (PageUptodate(page)) 224 if (PageUptodate(req->wb_page))
163 return;
164 if (base != 0)
165 return; 225 return;
166 if (count != nfs_page_length(page)) 226 if (!nfs_page_group_covers_page(req))
167 return; 227 return;
168 SetPageUptodate(page); 228 SetPageUptodate(req->wb_page);
169} 229}
170 230
171static int wb_priority(struct writeback_control *wbc) 231static int wb_priority(struct writeback_control *wbc)
@@ -796,7 +856,7 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
796 return PTR_ERR(req); 856 return PTR_ERR(req);
797 /* Update file length */ 857 /* Update file length */
798 nfs_grow_file(page, offset, count); 858 nfs_grow_file(page, offset, count);
799 nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); 859 nfs_mark_uptodate(req);
800 nfs_mark_request_dirty(req); 860 nfs_mark_request_dirty(req);
801 nfs_unlock_and_release_request(req); 861 nfs_unlock_and_release_request(req);
802 return 0; 862 return 0;