diff options
Diffstat (limited to 'fs/nfs/pagelist.c')
-rw-r--r-- | fs/nfs/pagelist.c | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index d21fceaa9f62..aed913c833f4 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -26,6 +26,47 @@ | |||
26 | 26 | ||
27 | static struct kmem_cache *nfs_page_cachep; | 27 | static struct kmem_cache *nfs_page_cachep; |
28 | 28 | ||
29 | bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) | ||
30 | { | ||
31 | p->npages = pagecount; | ||
32 | if (pagecount <= ARRAY_SIZE(p->page_array)) | ||
33 | p->pagevec = p->page_array; | ||
34 | else { | ||
35 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); | ||
36 | if (!p->pagevec) | ||
37 | p->npages = 0; | ||
38 | } | ||
39 | return p->pagevec != NULL; | ||
40 | } | ||
41 | |||
42 | void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, | ||
43 | struct nfs_pgio_header *hdr, | ||
44 | void (*release)(struct nfs_pgio_header *hdr)) | ||
45 | { | ||
46 | hdr->req = nfs_list_entry(desc->pg_list.next); | ||
47 | hdr->inode = desc->pg_inode; | ||
48 | hdr->cred = hdr->req->wb_context->cred; | ||
49 | hdr->io_start = req_offset(hdr->req); | ||
50 | hdr->good_bytes = desc->pg_count; | ||
51 | hdr->dreq = desc->pg_dreq; | ||
52 | hdr->release = release; | ||
53 | hdr->completion_ops = desc->pg_completion_ops; | ||
54 | if (hdr->completion_ops->init_hdr) | ||
55 | hdr->completion_ops->init_hdr(hdr); | ||
56 | } | ||
57 | |||
58 | void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) | ||
59 | { | ||
60 | spin_lock(&hdr->lock); | ||
61 | if (pos < hdr->io_start + hdr->good_bytes) { | ||
62 | set_bit(NFS_IOHDR_ERROR, &hdr->flags); | ||
63 | clear_bit(NFS_IOHDR_EOF, &hdr->flags); | ||
64 | hdr->good_bytes = pos - hdr->io_start; | ||
65 | hdr->error = error; | ||
66 | } | ||
67 | spin_unlock(&hdr->lock); | ||
68 | } | ||
69 | |||
29 | static inline struct nfs_page * | 70 | static inline struct nfs_page * |
30 | nfs_page_alloc(void) | 71 | nfs_page_alloc(void) |
31 | { | 72 | { |
@@ -76,12 +117,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
76 | * long write-back delay. This will be adjusted in | 117 | * long write-back delay. This will be adjusted in |
77 | * update_nfs_request below if the region is not locked. */ | 118 | * update_nfs_request below if the region is not locked. */ |
78 | req->wb_page = page; | 119 | req->wb_page = page; |
79 | atomic_set(&req->wb_complete, 0); | ||
80 | req->wb_index = page->index; | 120 | req->wb_index = page->index; |
81 | page_cache_get(page); | 121 | page_cache_get(page); |
82 | BUG_ON(PagePrivate(page)); | ||
83 | BUG_ON(!PageLocked(page)); | ||
84 | BUG_ON(page->mapping->host != inode); | ||
85 | req->wb_offset = offset; | 122 | req->wb_offset = offset; |
86 | req->wb_pgbase = offset; | 123 | req->wb_pgbase = offset; |
87 | req->wb_bytes = count; | 124 | req->wb_bytes = count; |
@@ -104,6 +141,15 @@ void nfs_unlock_request(struct nfs_page *req) | |||
104 | clear_bit(PG_BUSY, &req->wb_flags); | 141 | clear_bit(PG_BUSY, &req->wb_flags); |
105 | smp_mb__after_clear_bit(); | 142 | smp_mb__after_clear_bit(); |
106 | wake_up_bit(&req->wb_flags, PG_BUSY); | 143 | wake_up_bit(&req->wb_flags, PG_BUSY); |
144 | } | ||
145 | |||
146 | /** | ||
147 | * nfs_unlock_and_release_request - Unlock request and release the nfs_page | ||
148 | * @req: | ||
149 | */ | ||
150 | void nfs_unlock_and_release_request(struct nfs_page *req) | ||
151 | { | ||
152 | nfs_unlock_request(req); | ||
107 | nfs_release_request(req); | 153 | nfs_release_request(req); |
108 | } | 154 | } |
109 | 155 | ||
@@ -203,6 +249,7 @@ EXPORT_SYMBOL_GPL(nfs_generic_pg_test); | |||
203 | void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | 249 | void nfs_pageio_init(struct nfs_pageio_descriptor *desc, |
204 | struct inode *inode, | 250 | struct inode *inode, |
205 | const struct nfs_pageio_ops *pg_ops, | 251 | const struct nfs_pageio_ops *pg_ops, |
252 | const struct nfs_pgio_completion_ops *compl_ops, | ||
206 | size_t bsize, | 253 | size_t bsize, |
207 | int io_flags) | 254 | int io_flags) |
208 | { | 255 | { |
@@ -215,9 +262,11 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
215 | desc->pg_recoalesce = 0; | 262 | desc->pg_recoalesce = 0; |
216 | desc->pg_inode = inode; | 263 | desc->pg_inode = inode; |
217 | desc->pg_ops = pg_ops; | 264 | desc->pg_ops = pg_ops; |
265 | desc->pg_completion_ops = compl_ops; | ||
218 | desc->pg_ioflags = io_flags; | 266 | desc->pg_ioflags = io_flags; |
219 | desc->pg_error = 0; | 267 | desc->pg_error = 0; |
220 | desc->pg_lseg = NULL; | 268 | desc->pg_lseg = NULL; |
269 | desc->pg_dreq = NULL; | ||
221 | } | 270 | } |
222 | 271 | ||
223 | /** | 272 | /** |
@@ -241,12 +290,12 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, | |||
241 | return false; | 290 | return false; |
242 | if (req->wb_context->state != prev->wb_context->state) | 291 | if (req->wb_context->state != prev->wb_context->state) |
243 | return false; | 292 | return false; |
244 | if (req->wb_index != (prev->wb_index + 1)) | ||
245 | return false; | ||
246 | if (req->wb_pgbase != 0) | 293 | if (req->wb_pgbase != 0) |
247 | return false; | 294 | return false; |
248 | if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) | 295 | if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) |
249 | return false; | 296 | return false; |
297 | if (req_offset(req) != req_offset(prev) + prev->wb_bytes) | ||
298 | return false; | ||
250 | return pgio->pg_ops->pg_test(pgio, prev, req); | 299 | return pgio->pg_ops->pg_test(pgio, prev, req); |
251 | } | 300 | } |
252 | 301 | ||