diff options
Diffstat (limited to 'fs/nfs/pagelist.c')
-rw-r--r-- | fs/nfs/pagelist.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index c80add6e2213..7913961aff22 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -204,6 +204,21 @@ nfs_wait_on_request(struct nfs_page *req) | |||
204 | TASK_UNINTERRUPTIBLE); | 204 | TASK_UNINTERRUPTIBLE); |
205 | } | 205 | } |
206 | 206 | ||
207 | static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) | ||
208 | { | ||
209 | /* | ||
210 | * FIXME: ideally we should be able to coalesce all requests | ||
211 | * that are not block boundary aligned, but currently this | ||
212 | * is problematic for the case of bsize < PAGE_CACHE_SIZE, | ||
213 | * since nfs_flush_multi and nfs_pagein_multi assume you | ||
214 | * can have only one struct nfs_page. | ||
215 | */ | ||
216 | if (desc->pg_bsize < PAGE_SIZE) | ||
217 | return 0; | ||
218 | |||
219 | return desc->pg_count + req->wb_bytes <= desc->pg_bsize; | ||
220 | } | ||
221 | |||
207 | /** | 222 | /** |
208 | * nfs_pageio_init - initialise a page io descriptor | 223 | * nfs_pageio_init - initialise a page io descriptor |
209 | * @desc: pointer to descriptor | 224 | * @desc: pointer to descriptor |
@@ -229,6 +244,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
229 | desc->pg_ioflags = io_flags; | 244 | desc->pg_ioflags = io_flags; |
230 | desc->pg_error = 0; | 245 | desc->pg_error = 0; |
231 | desc->pg_lseg = NULL; | 246 | desc->pg_lseg = NULL; |
247 | desc->pg_test = nfs_generic_pg_test; | ||
248 | pnfs_pageio_init(desc, inode); | ||
232 | } | 249 | } |
233 | 250 | ||
234 | /** | 251 | /** |
@@ -242,29 +259,23 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
242 | * | 259 | * |
243 | * Return 'true' if this is the case, else return 'false'. | 260 | * Return 'true' if this is the case, else return 'false'. |
244 | */ | 261 | */ |
245 | static int nfs_can_coalesce_requests(struct nfs_page *prev, | 262 | static bool nfs_can_coalesce_requests(struct nfs_page *prev, |
246 | struct nfs_page *req, | 263 | struct nfs_page *req, |
247 | struct nfs_pageio_descriptor *pgio) | 264 | struct nfs_pageio_descriptor *pgio) |
248 | { | 265 | { |
249 | if (req->wb_context->cred != prev->wb_context->cred) | 266 | if (req->wb_context->cred != prev->wb_context->cred) |
250 | return 0; | 267 | return false; |
251 | if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner) | 268 | if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner) |
252 | return 0; | 269 | return false; |
253 | if (req->wb_context->state != prev->wb_context->state) | 270 | if (req->wb_context->state != prev->wb_context->state) |
254 | return 0; | 271 | return false; |
255 | if (req->wb_index != (prev->wb_index + 1)) | 272 | if (req->wb_index != (prev->wb_index + 1)) |
256 | return 0; | 273 | return false; |
257 | if (req->wb_pgbase != 0) | 274 | if (req->wb_pgbase != 0) |
258 | return 0; | 275 | return false; |
259 | if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) | 276 | if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) |
260 | return 0; | 277 | return false; |
261 | /* | 278 | return pgio->pg_test(pgio, prev, req); |
262 | * Non-whole file layouts need to check that req is inside of | ||
263 | * pgio->pg_lseg. | ||
264 | */ | ||
265 | if (pgio->pg_test && !pgio->pg_test(pgio, prev, req)) | ||
266 | return 0; | ||
267 | return 1; | ||
268 | } | 279 | } |
269 | 280 | ||
270 | /** | 281 | /** |
@@ -278,31 +289,18 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev, | |||
278 | static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, | 289 | static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, |
279 | struct nfs_page *req) | 290 | struct nfs_page *req) |
280 | { | 291 | { |
281 | size_t newlen = req->wb_bytes; | ||
282 | |||
283 | if (desc->pg_count != 0) { | 292 | if (desc->pg_count != 0) { |
284 | struct nfs_page *prev; | 293 | struct nfs_page *prev; |
285 | 294 | ||
286 | /* | ||
287 | * FIXME: ideally we should be able to coalesce all requests | ||
288 | * that are not block boundary aligned, but currently this | ||
289 | * is problematic for the case of bsize < PAGE_CACHE_SIZE, | ||
290 | * since nfs_flush_multi and nfs_pagein_multi assume you | ||
291 | * can have only one struct nfs_page. | ||
292 | */ | ||
293 | if (desc->pg_bsize < PAGE_SIZE) | ||
294 | return 0; | ||
295 | newlen += desc->pg_count; | ||
296 | if (newlen > desc->pg_bsize) | ||
297 | return 0; | ||
298 | prev = nfs_list_entry(desc->pg_list.prev); | 295 | prev = nfs_list_entry(desc->pg_list.prev); |
299 | if (!nfs_can_coalesce_requests(prev, req, desc)) | 296 | if (!nfs_can_coalesce_requests(prev, req, desc)) |
300 | return 0; | 297 | return 0; |
301 | } else | 298 | } else { |
302 | desc->pg_base = req->wb_pgbase; | 299 | desc->pg_base = req->wb_pgbase; |
300 | } | ||
303 | nfs_list_remove_request(req); | 301 | nfs_list_remove_request(req); |
304 | nfs_list_add_request(req, &desc->pg_list); | 302 | nfs_list_add_request(req, &desc->pg_list); |
305 | desc->pg_count = newlen; | 303 | desc->pg_count += req->wb_bytes; |
306 | return 1; | 304 | return 1; |
307 | } | 305 | } |
308 | 306 | ||