diff options
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r-- | fs/nfs/read.c | 437 |
1 files changed, 211 insertions, 226 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 0a4be28c2ea3..86ced7836214 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -30,43 +30,73 @@ | |||
30 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 30 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
31 | 31 | ||
32 | static const struct nfs_pageio_ops nfs_pageio_read_ops; | 32 | static const struct nfs_pageio_ops nfs_pageio_read_ops; |
33 | static const struct rpc_call_ops nfs_read_partial_ops; | 33 | static const struct rpc_call_ops nfs_read_common_ops; |
34 | static const struct rpc_call_ops nfs_read_full_ops; | 34 | static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops; |
35 | 35 | ||
36 | static struct kmem_cache *nfs_rdata_cachep; | 36 | static struct kmem_cache *nfs_rdata_cachep; |
37 | 37 | ||
38 | struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | 38 | struct nfs_read_header *nfs_readhdr_alloc(void) |
39 | { | 39 | { |
40 | struct nfs_read_data *p; | 40 | struct nfs_read_header *rhdr; |
41 | 41 | ||
42 | p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); | 42 | rhdr = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); |
43 | if (p) { | 43 | if (rhdr) { |
44 | INIT_LIST_HEAD(&p->pages); | 44 | struct nfs_pgio_header *hdr = &rhdr->header; |
45 | p->npages = pagecount; | 45 | |
46 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 46 | INIT_LIST_HEAD(&hdr->pages); |
47 | p->pagevec = p->page_array; | 47 | INIT_LIST_HEAD(&hdr->rpc_list); |
48 | else { | 48 | spin_lock_init(&hdr->lock); |
49 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); | 49 | atomic_set(&hdr->refcnt, 0); |
50 | if (!p->pagevec) { | 50 | } |
51 | kmem_cache_free(nfs_rdata_cachep, p); | 51 | return rhdr; |
52 | p = NULL; | 52 | } |
53 | } | 53 | |
54 | } | 54 | static struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr, |
55 | unsigned int pagecount) | ||
56 | { | ||
57 | struct nfs_read_data *data, *prealloc; | ||
58 | |||
59 | prealloc = &container_of(hdr, struct nfs_read_header, header)->rpc_data; | ||
60 | if (prealloc->header == NULL) | ||
61 | data = prealloc; | ||
62 | else | ||
63 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
64 | if (!data) | ||
65 | goto out; | ||
66 | |||
67 | if (nfs_pgarray_set(&data->pages, pagecount)) { | ||
68 | data->header = hdr; | ||
69 | atomic_inc(&hdr->refcnt); | ||
70 | } else { | ||
71 | if (data != prealloc) | ||
72 | kfree(data); | ||
73 | data = NULL; | ||
55 | } | 74 | } |
56 | return p; | 75 | out: |
76 | return data; | ||
57 | } | 77 | } |
58 | 78 | ||
59 | void nfs_readdata_free(struct nfs_read_data *p) | 79 | void nfs_readhdr_free(struct nfs_pgio_header *hdr) |
60 | { | 80 | { |
61 | if (p && (p->pagevec != &p->page_array[0])) | 81 | struct nfs_read_header *rhdr = container_of(hdr, struct nfs_read_header, header); |
62 | kfree(p->pagevec); | 82 | |
63 | kmem_cache_free(nfs_rdata_cachep, p); | 83 | kmem_cache_free(nfs_rdata_cachep, rhdr); |
64 | } | 84 | } |
65 | 85 | ||
66 | void nfs_readdata_release(struct nfs_read_data *rdata) | 86 | void nfs_readdata_release(struct nfs_read_data *rdata) |
67 | { | 87 | { |
88 | struct nfs_pgio_header *hdr = rdata->header; | ||
89 | struct nfs_read_header *read_header = container_of(hdr, struct nfs_read_header, header); | ||
90 | |||
68 | put_nfs_open_context(rdata->args.context); | 91 | put_nfs_open_context(rdata->args.context); |
69 | nfs_readdata_free(rdata); | 92 | if (rdata->pages.pagevec != rdata->pages.page_array) |
93 | kfree(rdata->pages.pagevec); | ||
94 | if (rdata != &read_header->rpc_data) | ||
95 | kfree(rdata); | ||
96 | else | ||
97 | rdata->header = NULL; | ||
98 | if (atomic_dec_and_test(&hdr->refcnt)) | ||
99 | hdr->completion_ops->completion(hdr); | ||
70 | } | 100 | } |
71 | 101 | ||
72 | static | 102 | static |
@@ -78,39 +108,11 @@ int nfs_return_empty_page(struct page *page) | |||
78 | return 0; | 108 | return 0; |
79 | } | 109 | } |
80 | 110 | ||
81 | static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) | ||
82 | { | ||
83 | unsigned int remainder = data->args.count - data->res.count; | ||
84 | unsigned int base = data->args.pgbase + data->res.count; | ||
85 | unsigned int pglen; | ||
86 | struct page **pages; | ||
87 | |||
88 | if (data->res.eof == 0 || remainder == 0) | ||
89 | return; | ||
90 | /* | ||
91 | * Note: "remainder" can never be negative, since we check for | ||
92 | * this in the XDR code. | ||
93 | */ | ||
94 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; | ||
95 | base &= ~PAGE_CACHE_MASK; | ||
96 | pglen = PAGE_CACHE_SIZE - base; | ||
97 | for (;;) { | ||
98 | if (remainder <= pglen) { | ||
99 | zero_user(*pages, base, remainder); | ||
100 | break; | ||
101 | } | ||
102 | zero_user(*pages, base, pglen); | ||
103 | pages++; | ||
104 | remainder -= pglen; | ||
105 | pglen = PAGE_CACHE_SIZE; | ||
106 | base = 0; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 111 | void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, |
111 | struct inode *inode) | 112 | struct inode *inode, |
113 | const struct nfs_pgio_completion_ops *compl_ops) | ||
112 | { | 114 | { |
113 | nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, | 115 | nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, compl_ops, |
114 | NFS_SERVER(inode)->rsize, 0); | 116 | NFS_SERVER(inode)->rsize, 0); |
115 | } | 117 | } |
116 | 118 | ||
@@ -121,11 +123,12 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) | |||
121 | } | 123 | } |
122 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); | 124 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); |
123 | 125 | ||
124 | static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | 126 | void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, |
125 | struct inode *inode) | 127 | struct inode *inode, |
128 | const struct nfs_pgio_completion_ops *compl_ops) | ||
126 | { | 129 | { |
127 | if (!pnfs_pageio_init_read(pgio, inode)) | 130 | if (!pnfs_pageio_init_read(pgio, inode, compl_ops)) |
128 | nfs_pageio_init_read_mds(pgio, inode); | 131 | nfs_pageio_init_read_mds(pgio, inode, compl_ops); |
129 | } | 132 | } |
130 | 133 | ||
131 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | 134 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, |
@@ -146,9 +149,10 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
146 | if (len < PAGE_CACHE_SIZE) | 149 | if (len < PAGE_CACHE_SIZE) |
147 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | 150 | zero_user_segment(page, len, PAGE_CACHE_SIZE); |
148 | 151 | ||
149 | nfs_pageio_init_read(&pgio, inode); | 152 | nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops); |
150 | nfs_pageio_add_request(&pgio, new); | 153 | nfs_pageio_add_request(&pgio, new); |
151 | nfs_pageio_complete(&pgio); | 154 | nfs_pageio_complete(&pgio); |
155 | NFS_I(inode)->read_io += pgio.pg_bytes_written; | ||
152 | return 0; | 156 | return 0; |
153 | } | 157 | } |
154 | 158 | ||
@@ -169,16 +173,49 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
169 | nfs_release_request(req); | 173 | nfs_release_request(req); |
170 | } | 174 | } |
171 | 175 | ||
172 | int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | 176 | /* Note io was page aligned */ |
173 | const struct rpc_call_ops *call_ops) | 177 | static void nfs_read_completion(struct nfs_pgio_header *hdr) |
178 | { | ||
179 | unsigned long bytes = 0; | ||
180 | |||
181 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) | ||
182 | goto out; | ||
183 | while (!list_empty(&hdr->pages)) { | ||
184 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); | ||
185 | struct page *page = req->wb_page; | ||
186 | |||
187 | if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) { | ||
188 | if (bytes > hdr->good_bytes) | ||
189 | zero_user(page, 0, PAGE_SIZE); | ||
190 | else if (hdr->good_bytes - bytes < PAGE_SIZE) | ||
191 | zero_user_segment(page, | ||
192 | hdr->good_bytes & ~PAGE_MASK, | ||
193 | PAGE_SIZE); | ||
194 | } | ||
195 | bytes += req->wb_bytes; | ||
196 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) { | ||
197 | if (bytes <= hdr->good_bytes) | ||
198 | SetPageUptodate(page); | ||
199 | } else | ||
200 | SetPageUptodate(page); | ||
201 | nfs_list_remove_request(req); | ||
202 | nfs_readpage_release(req); | ||
203 | } | ||
204 | out: | ||
205 | hdr->release(hdr); | ||
206 | } | ||
207 | |||
208 | int nfs_initiate_read(struct rpc_clnt *clnt, | ||
209 | struct nfs_read_data *data, | ||
210 | const struct rpc_call_ops *call_ops, int flags) | ||
174 | { | 211 | { |
175 | struct inode *inode = data->inode; | 212 | struct inode *inode = data->header->inode; |
176 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; | 213 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; |
177 | struct rpc_task *task; | 214 | struct rpc_task *task; |
178 | struct rpc_message msg = { | 215 | struct rpc_message msg = { |
179 | .rpc_argp = &data->args, | 216 | .rpc_argp = &data->args, |
180 | .rpc_resp = &data->res, | 217 | .rpc_resp = &data->res, |
181 | .rpc_cred = data->cred, | 218 | .rpc_cred = data->header->cred, |
182 | }; | 219 | }; |
183 | struct rpc_task_setup task_setup_data = { | 220 | struct rpc_task_setup task_setup_data = { |
184 | .task = &data->task, | 221 | .task = &data->task, |
@@ -187,7 +224,7 @@ int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | |||
187 | .callback_ops = call_ops, | 224 | .callback_ops = call_ops, |
188 | .callback_data = data, | 225 | .callback_data = data, |
189 | .workqueue = nfsiod_workqueue, | 226 | .workqueue = nfsiod_workqueue, |
190 | .flags = RPC_TASK_ASYNC | swap_flags, | 227 | .flags = RPC_TASK_ASYNC | swap_flags | flags, |
191 | }; | 228 | }; |
192 | 229 | ||
193 | /* Set up the initial task struct. */ | 230 | /* Set up the initial task struct. */ |
@@ -212,19 +249,15 @@ EXPORT_SYMBOL_GPL(nfs_initiate_read); | |||
212 | /* | 249 | /* |
213 | * Set up the NFS read request struct | 250 | * Set up the NFS read request struct |
214 | */ | 251 | */ |
215 | static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | 252 | static void nfs_read_rpcsetup(struct nfs_read_data *data, |
216 | unsigned int count, unsigned int offset) | 253 | unsigned int count, unsigned int offset) |
217 | { | 254 | { |
218 | struct inode *inode = req->wb_context->dentry->d_inode; | 255 | struct nfs_page *req = data->header->req; |
219 | |||
220 | data->req = req; | ||
221 | data->inode = inode; | ||
222 | data->cred = req->wb_context->cred; | ||
223 | 256 | ||
224 | data->args.fh = NFS_FH(inode); | 257 | data->args.fh = NFS_FH(data->header->inode); |
225 | data->args.offset = req_offset(req) + offset; | 258 | data->args.offset = req_offset(req) + offset; |
226 | data->args.pgbase = req->wb_pgbase + offset; | 259 | data->args.pgbase = req->wb_pgbase + offset; |
227 | data->args.pages = data->pagevec; | 260 | data->args.pages = data->pages.pagevec; |
228 | data->args.count = count; | 261 | data->args.count = count; |
229 | data->args.context = get_nfs_open_context(req->wb_context); | 262 | data->args.context = get_nfs_open_context(req->wb_context); |
230 | data->args.lock_context = req->wb_lock_context; | 263 | data->args.lock_context = req->wb_lock_context; |
@@ -238,9 +271,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
238 | static int nfs_do_read(struct nfs_read_data *data, | 271 | static int nfs_do_read(struct nfs_read_data *data, |
239 | const struct rpc_call_ops *call_ops) | 272 | const struct rpc_call_ops *call_ops) |
240 | { | 273 | { |
241 | struct inode *inode = data->args.context->dentry->d_inode; | 274 | struct inode *inode = data->header->inode; |
242 | 275 | ||
243 | return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops); | 276 | return nfs_initiate_read(NFS_CLIENT(inode), data, call_ops, 0); |
244 | } | 277 | } |
245 | 278 | ||
246 | static int | 279 | static int |
@@ -253,7 +286,7 @@ nfs_do_multiple_reads(struct list_head *head, | |||
253 | while (!list_empty(head)) { | 286 | while (!list_empty(head)) { |
254 | int ret2; | 287 | int ret2; |
255 | 288 | ||
256 | data = list_entry(head->next, struct nfs_read_data, list); | 289 | data = list_first_entry(head, struct nfs_read_data, list); |
257 | list_del_init(&data->list); | 290 | list_del_init(&data->list); |
258 | 291 | ||
259 | ret2 = nfs_do_read(data, call_ops); | 292 | ret2 = nfs_do_read(data, call_ops); |
@@ -275,6 +308,24 @@ nfs_async_read_error(struct list_head *head) | |||
275 | } | 308 | } |
276 | } | 309 | } |
277 | 310 | ||
311 | static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = { | ||
312 | .error_cleanup = nfs_async_read_error, | ||
313 | .completion = nfs_read_completion, | ||
314 | }; | ||
315 | |||
316 | static void nfs_pagein_error(struct nfs_pageio_descriptor *desc, | ||
317 | struct nfs_pgio_header *hdr) | ||
318 | { | ||
319 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | ||
320 | while (!list_empty(&hdr->rpc_list)) { | ||
321 | struct nfs_read_data *data = list_first_entry(&hdr->rpc_list, | ||
322 | struct nfs_read_data, list); | ||
323 | list_del(&data->list); | ||
324 | nfs_readdata_release(data); | ||
325 | } | ||
326 | desc->pg_completion_ops->error_cleanup(&desc->pg_list); | ||
327 | } | ||
328 | |||
278 | /* | 329 | /* |
279 | * Generate multiple requests to fill a single page. | 330 | * Generate multiple requests to fill a single page. |
280 | * | 331 | * |
@@ -288,93 +339,95 @@ nfs_async_read_error(struct list_head *head) | |||
288 | * won't see the new data until our attribute cache is updated. This is more | 339 | * won't see the new data until our attribute cache is updated. This is more |
289 | * or less conventional NFS client behavior. | 340 | * or less conventional NFS client behavior. |
290 | */ | 341 | */ |
291 | static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, struct list_head *res) | 342 | static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, |
343 | struct nfs_pgio_header *hdr) | ||
292 | { | 344 | { |
293 | struct nfs_page *req = nfs_list_entry(desc->pg_list.next); | 345 | struct nfs_page *req = hdr->req; |
294 | struct page *page = req->wb_page; | 346 | struct page *page = req->wb_page; |
295 | struct nfs_read_data *data; | 347 | struct nfs_read_data *data; |
296 | size_t rsize = desc->pg_bsize, nbytes; | 348 | size_t rsize = desc->pg_bsize, nbytes; |
297 | unsigned int offset; | 349 | unsigned int offset; |
298 | int requests = 0; | ||
299 | int ret = 0; | ||
300 | |||
301 | nfs_list_remove_request(req); | ||
302 | 350 | ||
303 | offset = 0; | 351 | offset = 0; |
304 | nbytes = desc->pg_count; | 352 | nbytes = desc->pg_count; |
305 | do { | 353 | do { |
306 | size_t len = min(nbytes,rsize); | 354 | size_t len = min(nbytes,rsize); |
307 | 355 | ||
308 | data = nfs_readdata_alloc(1); | 356 | data = nfs_readdata_alloc(hdr, 1); |
309 | if (!data) | 357 | if (!data) { |
310 | goto out_bad; | 358 | nfs_pagein_error(desc, hdr); |
311 | data->pagevec[0] = page; | 359 | return -ENOMEM; |
312 | nfs_read_rpcsetup(req, data, len, offset); | 360 | } |
313 | list_add(&data->list, res); | 361 | data->pages.pagevec[0] = page; |
314 | requests++; | 362 | nfs_read_rpcsetup(data, len, offset); |
363 | list_add(&data->list, &hdr->rpc_list); | ||
315 | nbytes -= len; | 364 | nbytes -= len; |
316 | offset += len; | 365 | offset += len; |
317 | } while(nbytes != 0); | 366 | } while (nbytes != 0); |
318 | atomic_set(&req->wb_complete, requests); | 367 | |
319 | desc->pg_rpc_callops = &nfs_read_partial_ops; | 368 | nfs_list_remove_request(req); |
320 | return ret; | 369 | nfs_list_add_request(req, &hdr->pages); |
321 | out_bad: | 370 | desc->pg_rpc_callops = &nfs_read_common_ops; |
322 | while (!list_empty(res)) { | 371 | return 0; |
323 | data = list_entry(res->next, struct nfs_read_data, list); | ||
324 | list_del(&data->list); | ||
325 | nfs_readdata_release(data); | ||
326 | } | ||
327 | nfs_readpage_release(req); | ||
328 | return -ENOMEM; | ||
329 | } | 372 | } |
330 | 373 | ||
331 | static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, struct list_head *res) | 374 | static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, |
375 | struct nfs_pgio_header *hdr) | ||
332 | { | 376 | { |
333 | struct nfs_page *req; | 377 | struct nfs_page *req; |
334 | struct page **pages; | 378 | struct page **pages; |
335 | struct nfs_read_data *data; | 379 | struct nfs_read_data *data; |
336 | struct list_head *head = &desc->pg_list; | 380 | struct list_head *head = &desc->pg_list; |
337 | int ret = 0; | ||
338 | 381 | ||
339 | data = nfs_readdata_alloc(nfs_page_array_len(desc->pg_base, | 382 | data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base, |
340 | desc->pg_count)); | 383 | desc->pg_count)); |
341 | if (!data) { | 384 | if (!data) { |
342 | nfs_async_read_error(head); | 385 | nfs_pagein_error(desc, hdr); |
343 | ret = -ENOMEM; | 386 | return -ENOMEM; |
344 | goto out; | ||
345 | } | 387 | } |
346 | 388 | ||
347 | pages = data->pagevec; | 389 | pages = data->pages.pagevec; |
348 | while (!list_empty(head)) { | 390 | while (!list_empty(head)) { |
349 | req = nfs_list_entry(head->next); | 391 | req = nfs_list_entry(head->next); |
350 | nfs_list_remove_request(req); | 392 | nfs_list_remove_request(req); |
351 | nfs_list_add_request(req, &data->pages); | 393 | nfs_list_add_request(req, &hdr->pages); |
352 | *pages++ = req->wb_page; | 394 | *pages++ = req->wb_page; |
353 | } | 395 | } |
354 | req = nfs_list_entry(data->pages.next); | ||
355 | 396 | ||
356 | nfs_read_rpcsetup(req, data, desc->pg_count, 0); | 397 | nfs_read_rpcsetup(data, desc->pg_count, 0); |
357 | list_add(&data->list, res); | 398 | list_add(&data->list, &hdr->rpc_list); |
358 | desc->pg_rpc_callops = &nfs_read_full_ops; | 399 | desc->pg_rpc_callops = &nfs_read_common_ops; |
359 | out: | 400 | return 0; |
360 | return ret; | ||
361 | } | 401 | } |
362 | 402 | ||
363 | int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, struct list_head *head) | 403 | int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, |
404 | struct nfs_pgio_header *hdr) | ||
364 | { | 405 | { |
365 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | 406 | if (desc->pg_bsize < PAGE_CACHE_SIZE) |
366 | return nfs_pagein_multi(desc, head); | 407 | return nfs_pagein_multi(desc, hdr); |
367 | return nfs_pagein_one(desc, head); | 408 | return nfs_pagein_one(desc, hdr); |
368 | } | 409 | } |
369 | 410 | ||
370 | static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | 411 | static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) |
371 | { | 412 | { |
372 | LIST_HEAD(head); | 413 | struct nfs_read_header *rhdr; |
414 | struct nfs_pgio_header *hdr; | ||
373 | int ret; | 415 | int ret; |
374 | 416 | ||
375 | ret = nfs_generic_pagein(desc, &head); | 417 | rhdr = nfs_readhdr_alloc(); |
418 | if (!rhdr) { | ||
419 | desc->pg_completion_ops->error_cleanup(&desc->pg_list); | ||
420 | return -ENOMEM; | ||
421 | } | ||
422 | hdr = &rhdr->header; | ||
423 | nfs_pgheader_init(desc, hdr, nfs_readhdr_free); | ||
424 | atomic_inc(&hdr->refcnt); | ||
425 | ret = nfs_generic_pagein(desc, hdr); | ||
376 | if (ret == 0) | 426 | if (ret == 0) |
377 | ret = nfs_do_multiple_reads(&head, desc->pg_rpc_callops); | 427 | ret = nfs_do_multiple_reads(&hdr->rpc_list, |
428 | desc->pg_rpc_callops); | ||
429 | if (atomic_dec_and_test(&hdr->refcnt)) | ||
430 | hdr->completion_ops->completion(hdr); | ||
378 | return ret; | 431 | return ret; |
379 | } | 432 | } |
380 | 433 | ||
@@ -389,20 +442,21 @@ static const struct nfs_pageio_ops nfs_pageio_read_ops = { | |||
389 | */ | 442 | */ |
390 | int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | 443 | int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) |
391 | { | 444 | { |
445 | struct inode *inode = data->header->inode; | ||
392 | int status; | 446 | int status; |
393 | 447 | ||
394 | dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid, | 448 | dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid, |
395 | task->tk_status); | 449 | task->tk_status); |
396 | 450 | ||
397 | status = NFS_PROTO(data->inode)->read_done(task, data); | 451 | status = NFS_PROTO(inode)->read_done(task, data); |
398 | if (status != 0) | 452 | if (status != 0) |
399 | return status; | 453 | return status; |
400 | 454 | ||
401 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); | 455 | nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, data->res.count); |
402 | 456 | ||
403 | if (task->tk_status == -ESTALE) { | 457 | if (task->tk_status == -ESTALE) { |
404 | set_bit(NFS_INO_STALE, &NFS_I(data->inode)->flags); | 458 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
405 | nfs_mark_for_revalidate(data->inode); | 459 | nfs_mark_for_revalidate(inode); |
406 | } | 460 | } |
407 | return 0; | 461 | return 0; |
408 | } | 462 | } |
@@ -412,15 +466,13 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data | |||
412 | struct nfs_readargs *argp = &data->args; | 466 | struct nfs_readargs *argp = &data->args; |
413 | struct nfs_readres *resp = &data->res; | 467 | struct nfs_readres *resp = &data->res; |
414 | 468 | ||
415 | if (resp->eof || resp->count == argp->count) | ||
416 | return; | ||
417 | |||
418 | /* This is a short read! */ | 469 | /* This is a short read! */ |
419 | nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); | 470 | nfs_inc_stats(data->header->inode, NFSIOS_SHORTREAD); |
420 | /* Has the server at least made some progress? */ | 471 | /* Has the server at least made some progress? */ |
421 | if (resp->count == 0) | 472 | if (resp->count == 0) { |
473 | nfs_set_pgio_error(data->header, -EIO, argp->offset); | ||
422 | return; | 474 | return; |
423 | 475 | } | |
424 | /* Yes, so retry the read at the end of the data */ | 476 | /* Yes, so retry the read at the end of the data */ |
425 | data->mds_offset += resp->count; | 477 | data->mds_offset += resp->count; |
426 | argp->offset += resp->count; | 478 | argp->offset += resp->count; |
@@ -429,114 +481,46 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data | |||
429 | rpc_restart_call_prepare(task); | 481 | rpc_restart_call_prepare(task); |
430 | } | 482 | } |
431 | 483 | ||
432 | /* | 484 | static void nfs_readpage_result_common(struct rpc_task *task, void *calldata) |
433 | * Handle a read reply that fills part of a page. | ||
434 | */ | ||
435 | static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata) | ||
436 | { | 485 | { |
437 | struct nfs_read_data *data = calldata; | 486 | struct nfs_read_data *data = calldata; |
438 | 487 | struct nfs_pgio_header *hdr = data->header; | |
488 | |||
489 | /* Note the only returns of nfs_readpage_result are 0 and -EAGAIN */ | ||
439 | if (nfs_readpage_result(task, data) != 0) | 490 | if (nfs_readpage_result(task, data) != 0) |
440 | return; | 491 | return; |
441 | if (task->tk_status < 0) | 492 | if (task->tk_status < 0) |
442 | return; | 493 | nfs_set_pgio_error(hdr, task->tk_status, data->args.offset); |
443 | 494 | else if (data->res.eof) { | |
444 | nfs_readpage_truncate_uninitialised_page(data); | 495 | loff_t bound; |
445 | nfs_readpage_retry(task, data); | 496 | |
497 | bound = data->args.offset + data->res.count; | ||
498 | spin_lock(&hdr->lock); | ||
499 | if (bound < hdr->io_start + hdr->good_bytes) { | ||
500 | set_bit(NFS_IOHDR_EOF, &hdr->flags); | ||
501 | clear_bit(NFS_IOHDR_ERROR, &hdr->flags); | ||
502 | hdr->good_bytes = bound - hdr->io_start; | ||
503 | } | ||
504 | spin_unlock(&hdr->lock); | ||
505 | } else if (data->res.count != data->args.count) | ||
506 | nfs_readpage_retry(task, data); | ||
446 | } | 507 | } |
447 | 508 | ||
448 | static void nfs_readpage_release_partial(void *calldata) | 509 | static void nfs_readpage_release_common(void *calldata) |
449 | { | 510 | { |
450 | struct nfs_read_data *data = calldata; | ||
451 | struct nfs_page *req = data->req; | ||
452 | struct page *page = req->wb_page; | ||
453 | int status = data->task.tk_status; | ||
454 | |||
455 | if (status < 0) | ||
456 | set_bit(PG_PARTIAL_READ_FAILED, &req->wb_flags); | ||
457 | |||
458 | if (atomic_dec_and_test(&req->wb_complete)) { | ||
459 | if (!test_bit(PG_PARTIAL_READ_FAILED, &req->wb_flags)) | ||
460 | SetPageUptodate(page); | ||
461 | nfs_readpage_release(req); | ||
462 | } | ||
463 | nfs_readdata_release(calldata); | 511 | nfs_readdata_release(calldata); |
464 | } | 512 | } |
465 | 513 | ||
466 | void nfs_read_prepare(struct rpc_task *task, void *calldata) | 514 | void nfs_read_prepare(struct rpc_task *task, void *calldata) |
467 | { | 515 | { |
468 | struct nfs_read_data *data = calldata; | 516 | struct nfs_read_data *data = calldata; |
469 | NFS_PROTO(data->inode)->read_rpc_prepare(task, data); | 517 | NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data); |
470 | } | ||
471 | |||
472 | static const struct rpc_call_ops nfs_read_partial_ops = { | ||
473 | .rpc_call_prepare = nfs_read_prepare, | ||
474 | .rpc_call_done = nfs_readpage_result_partial, | ||
475 | .rpc_release = nfs_readpage_release_partial, | ||
476 | }; | ||
477 | |||
478 | static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) | ||
479 | { | ||
480 | unsigned int count = data->res.count; | ||
481 | unsigned int base = data->args.pgbase; | ||
482 | struct page **pages; | ||
483 | |||
484 | if (data->res.eof) | ||
485 | count = data->args.count; | ||
486 | if (unlikely(count == 0)) | ||
487 | return; | ||
488 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; | ||
489 | base &= ~PAGE_CACHE_MASK; | ||
490 | count += base; | ||
491 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) | ||
492 | SetPageUptodate(*pages); | ||
493 | if (count == 0) | ||
494 | return; | ||
495 | /* Was this a short read? */ | ||
496 | if (data->res.eof || data->res.count == data->args.count) | ||
497 | SetPageUptodate(*pages); | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * This is the callback from RPC telling us whether a reply was | ||
502 | * received or some error occurred (timeout or socket shutdown). | ||
503 | */ | ||
504 | static void nfs_readpage_result_full(struct rpc_task *task, void *calldata) | ||
505 | { | ||
506 | struct nfs_read_data *data = calldata; | ||
507 | |||
508 | if (nfs_readpage_result(task, data) != 0) | ||
509 | return; | ||
510 | if (task->tk_status < 0) | ||
511 | return; | ||
512 | /* | ||
513 | * Note: nfs_readpage_retry may change the values of | ||
514 | * data->args. In the multi-page case, we therefore need | ||
515 | * to ensure that we call nfs_readpage_set_pages_uptodate() | ||
516 | * first. | ||
517 | */ | ||
518 | nfs_readpage_truncate_uninitialised_page(data); | ||
519 | nfs_readpage_set_pages_uptodate(data); | ||
520 | nfs_readpage_retry(task, data); | ||
521 | } | ||
522 | |||
523 | static void nfs_readpage_release_full(void *calldata) | ||
524 | { | ||
525 | struct nfs_read_data *data = calldata; | ||
526 | |||
527 | while (!list_empty(&data->pages)) { | ||
528 | struct nfs_page *req = nfs_list_entry(data->pages.next); | ||
529 | |||
530 | nfs_list_remove_request(req); | ||
531 | nfs_readpage_release(req); | ||
532 | } | ||
533 | nfs_readdata_release(calldata); | ||
534 | } | 518 | } |
535 | 519 | ||
536 | static const struct rpc_call_ops nfs_read_full_ops = { | 520 | static const struct rpc_call_ops nfs_read_common_ops = { |
537 | .rpc_call_prepare = nfs_read_prepare, | 521 | .rpc_call_prepare = nfs_read_prepare, |
538 | .rpc_call_done = nfs_readpage_result_full, | 522 | .rpc_call_done = nfs_readpage_result_common, |
539 | .rpc_release = nfs_readpage_release_full, | 523 | .rpc_release = nfs_readpage_release_common, |
540 | }; | 524 | }; |
541 | 525 | ||
542 | /* | 526 | /* |
@@ -668,11 +652,12 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
668 | if (ret == 0) | 652 | if (ret == 0) |
669 | goto read_complete; /* all pages were read */ | 653 | goto read_complete; /* all pages were read */ |
670 | 654 | ||
671 | nfs_pageio_init_read(&pgio, inode); | 655 | nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops); |
672 | 656 | ||
673 | ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); | 657 | ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); |
674 | 658 | ||
675 | nfs_pageio_complete(&pgio); | 659 | nfs_pageio_complete(&pgio); |
660 | NFS_I(inode)->read_io += pgio.pg_bytes_written; | ||
676 | npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 661 | npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
677 | nfs_add_stats(inode, NFSIOS_READPAGES, npages); | 662 | nfs_add_stats(inode, NFSIOS_READPAGES, npages); |
678 | read_complete: | 663 | read_complete: |
@@ -684,7 +669,7 @@ out: | |||
684 | int __init nfs_init_readpagecache(void) | 669 | int __init nfs_init_readpagecache(void) |
685 | { | 670 | { |
686 | nfs_rdata_cachep = kmem_cache_create("nfs_read_data", | 671 | nfs_rdata_cachep = kmem_cache_create("nfs_read_data", |
687 | sizeof(struct nfs_read_data), | 672 | sizeof(struct nfs_read_header), |
688 | 0, SLAB_HWCACHE_ALIGN, | 673 | 0, SLAB_HWCACHE_ALIGN, |
689 | NULL); | 674 | NULL); |
690 | if (nfs_rdata_cachep == NULL) | 675 | if (nfs_rdata_cachep == NULL) |