diff options
author | Weston Andros Adamson <dros@primarydata.com> | 2014-05-15 11:56:48 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-05-29 11:11:46 -0400 |
commit | d72ddcbab60a70258d0cd5752db3f53824df78d6 (patch) | |
tree | 53bc78daab4fd608559772abaabe908e5250fcdd /fs/nfs/write.c | |
parent | 20633f042fd0907300069714b98aaf607a8b5bf8 (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.c | 74 |
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 | */ | ||
170 | static struct nfs_page * | ||
171 | nfs_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 | */ | ||
197 | static 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 | */ |
160 | static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count) | 222 | static 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 | ||
171 | static int wb_priority(struct writeback_control *wbc) | 231 | static 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; |