diff options
author | Fred Isaman <iisaman@netapp.com> | 2012-04-20 14:47:44 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-04-27 14:10:37 -0400 |
commit | cd841605f7a721878d8a2d1362484723d8abf569 (patch) | |
tree | b5c37db575cd545a183577249909e042fe38d646 | |
parent | b5542849764aa56fd3f05c0041195b637b9d2ac2 (diff) |
NFS: create common nfs_pgio_header for both read and write
In order to avoid duplicating all the data in nfs_read_data whenever we
split it up into multiple RPC calls (either due to a short read result
or due to rsize < PAGE_SIZE), we split out the bits that are the same
per RPC call into a separate "header" structure.
The goal this patch moves towards is to have a single header
refcounted by several rpc_data structures. Thus, want to always refer
from rpc_data to the header, and not the other way. This patch comes
close to that ideal, but the directio code currently needs some
special casing, isolated in the nfs_direct_[read_write]hdr_release()
functions. This will be dealt with in a future patch.
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 79 | ||||
-rw-r--r-- | fs/nfs/direct.c | 73 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 14 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 40 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 44 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 16 | ||||
-rw-r--r-- | fs/nfs/objlayout/objlayout.c | 19 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 102 | ||||
-rw-r--r-- | fs/nfs/proc.c | 10 | ||||
-rw-r--r-- | fs/nfs/read.c | 89 | ||||
-rw-r--r-- | fs/nfs/write.c | 104 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 12 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 48 |
14 files changed, 376 insertions, 278 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 7f6a23f0244e..7a482517f4c6 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -187,7 +187,6 @@ static void bl_end_io_read(struct bio *bio, int err) | |||
187 | struct parallel_io *par = bio->bi_private; | 187 | struct parallel_io *par = bio->bi_private; |
188 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 188 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
189 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 189 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
190 | struct nfs_read_data *rdata = (struct nfs_read_data *)par->data; | ||
191 | 190 | ||
192 | do { | 191 | do { |
193 | struct page *page = bvec->bv_page; | 192 | struct page *page = bvec->bv_page; |
@@ -198,9 +197,12 @@ static void bl_end_io_read(struct bio *bio, int err) | |||
198 | SetPageUptodate(page); | 197 | SetPageUptodate(page); |
199 | } while (bvec >= bio->bi_io_vec); | 198 | } while (bvec >= bio->bi_io_vec); |
200 | if (!uptodate) { | 199 | if (!uptodate) { |
201 | if (!rdata->pnfs_error) | 200 | struct nfs_read_data *rdata = par->data; |
202 | rdata->pnfs_error = -EIO; | 201 | struct nfs_pgio_header *header = rdata->header; |
203 | pnfs_set_lo_fail(rdata->lseg); | 202 | |
203 | if (!header->pnfs_error) | ||
204 | header->pnfs_error = -EIO; | ||
205 | pnfs_set_lo_fail(header->lseg); | ||
204 | } | 206 | } |
205 | bio_put(bio); | 207 | bio_put(bio); |
206 | put_parallel(par); | 208 | put_parallel(par); |
@@ -221,7 +223,7 @@ bl_end_par_io_read(void *data, int unused) | |||
221 | { | 223 | { |
222 | struct nfs_read_data *rdata = data; | 224 | struct nfs_read_data *rdata = data; |
223 | 225 | ||
224 | rdata->task.tk_status = rdata->pnfs_error; | 226 | rdata->task.tk_status = rdata->header->pnfs_error; |
225 | INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup); | 227 | INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup); |
226 | schedule_work(&rdata->task.u.tk_work); | 228 | schedule_work(&rdata->task.u.tk_work); |
227 | } | 229 | } |
@@ -229,6 +231,7 @@ bl_end_par_io_read(void *data, int unused) | |||
229 | static enum pnfs_try_status | 231 | static enum pnfs_try_status |
230 | bl_read_pagelist(struct nfs_read_data *rdata) | 232 | bl_read_pagelist(struct nfs_read_data *rdata) |
231 | { | 233 | { |
234 | struct nfs_pgio_header *header = rdata->header; | ||
232 | int i, hole; | 235 | int i, hole; |
233 | struct bio *bio = NULL; | 236 | struct bio *bio = NULL; |
234 | struct pnfs_block_extent *be = NULL, *cow_read = NULL; | 237 | struct pnfs_block_extent *be = NULL, *cow_read = NULL; |
@@ -256,10 +259,10 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
256 | bl_put_extent(cow_read); | 259 | bl_put_extent(cow_read); |
257 | bio = bl_submit_bio(READ, bio); | 260 | bio = bl_submit_bio(READ, bio); |
258 | /* Get the next one */ | 261 | /* Get the next one */ |
259 | be = bl_find_get_extent(BLK_LSEG2EXT(rdata->lseg), | 262 | be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), |
260 | isect, &cow_read); | 263 | isect, &cow_read); |
261 | if (!be) { | 264 | if (!be) { |
262 | rdata->pnfs_error = -EIO; | 265 | header->pnfs_error = -EIO; |
263 | goto out; | 266 | goto out; |
264 | } | 267 | } |
265 | extent_length = be->be_length - | 268 | extent_length = be->be_length - |
@@ -286,7 +289,7 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
286 | isect, pages[i], be_read, | 289 | isect, pages[i], be_read, |
287 | bl_end_io_read, par); | 290 | bl_end_io_read, par); |
288 | if (IS_ERR(bio)) { | 291 | if (IS_ERR(bio)) { |
289 | rdata->pnfs_error = PTR_ERR(bio); | 292 | header->pnfs_error = PTR_ERR(bio); |
290 | bio = NULL; | 293 | bio = NULL; |
291 | goto out; | 294 | goto out; |
292 | } | 295 | } |
@@ -294,9 +297,9 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
294 | isect += PAGE_CACHE_SECTORS; | 297 | isect += PAGE_CACHE_SECTORS; |
295 | extent_length -= PAGE_CACHE_SECTORS; | 298 | extent_length -= PAGE_CACHE_SECTORS; |
296 | } | 299 | } |
297 | if ((isect << SECTOR_SHIFT) >= rdata->inode->i_size) { | 300 | if ((isect << SECTOR_SHIFT) >= header->inode->i_size) { |
298 | rdata->res.eof = 1; | 301 | rdata->res.eof = 1; |
299 | rdata->res.count = rdata->inode->i_size - f_offset; | 302 | rdata->res.count = header->inode->i_size - f_offset; |
300 | } else { | 303 | } else { |
301 | rdata->res.count = (isect << SECTOR_SHIFT) - f_offset; | 304 | rdata->res.count = (isect << SECTOR_SHIFT) - f_offset; |
302 | } | 305 | } |
@@ -345,7 +348,6 @@ static void bl_end_io_write_zero(struct bio *bio, int err) | |||
345 | struct parallel_io *par = bio->bi_private; | 348 | struct parallel_io *par = bio->bi_private; |
346 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 349 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
347 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 350 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
348 | struct nfs_write_data *wdata = (struct nfs_write_data *)par->data; | ||
349 | 351 | ||
350 | do { | 352 | do { |
351 | struct page *page = bvec->bv_page; | 353 | struct page *page = bvec->bv_page; |
@@ -358,9 +360,12 @@ static void bl_end_io_write_zero(struct bio *bio, int err) | |||
358 | } while (bvec >= bio->bi_io_vec); | 360 | } while (bvec >= bio->bi_io_vec); |
359 | 361 | ||
360 | if (unlikely(!uptodate)) { | 362 | if (unlikely(!uptodate)) { |
361 | if (!wdata->pnfs_error) | 363 | struct nfs_write_data *data = par->data; |
362 | wdata->pnfs_error = -EIO; | 364 | struct nfs_pgio_header *header = data->header; |
363 | pnfs_set_lo_fail(wdata->lseg); | 365 | |
366 | if (!header->pnfs_error) | ||
367 | header->pnfs_error = -EIO; | ||
368 | pnfs_set_lo_fail(header->lseg); | ||
364 | } | 369 | } |
365 | bio_put(bio); | 370 | bio_put(bio); |
366 | put_parallel(par); | 371 | put_parallel(par); |
@@ -370,12 +375,13 @@ static void bl_end_io_write(struct bio *bio, int err) | |||
370 | { | 375 | { |
371 | struct parallel_io *par = bio->bi_private; | 376 | struct parallel_io *par = bio->bi_private; |
372 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 377 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
373 | struct nfs_write_data *wdata = (struct nfs_write_data *)par->data; | 378 | struct nfs_write_data *data = par->data; |
379 | struct nfs_pgio_header *header = data->header; | ||
374 | 380 | ||
375 | if (!uptodate) { | 381 | if (!uptodate) { |
376 | if (!wdata->pnfs_error) | 382 | if (!header->pnfs_error) |
377 | wdata->pnfs_error = -EIO; | 383 | header->pnfs_error = -EIO; |
378 | pnfs_set_lo_fail(wdata->lseg); | 384 | pnfs_set_lo_fail(header->lseg); |
379 | } | 385 | } |
380 | bio_put(bio); | 386 | bio_put(bio); |
381 | put_parallel(par); | 387 | put_parallel(par); |
@@ -391,9 +397,9 @@ static void bl_write_cleanup(struct work_struct *work) | |||
391 | dprintk("%s enter\n", __func__); | 397 | dprintk("%s enter\n", __func__); |
392 | task = container_of(work, struct rpc_task, u.tk_work); | 398 | task = container_of(work, struct rpc_task, u.tk_work); |
393 | wdata = container_of(task, struct nfs_write_data, task); | 399 | wdata = container_of(task, struct nfs_write_data, task); |
394 | if (likely(!wdata->pnfs_error)) { | 400 | if (likely(!wdata->header->pnfs_error)) { |
395 | /* Marks for LAYOUTCOMMIT */ | 401 | /* Marks for LAYOUTCOMMIT */ |
396 | mark_extents_written(BLK_LSEG2EXT(wdata->lseg), | 402 | mark_extents_written(BLK_LSEG2EXT(wdata->header->lseg), |
397 | wdata->args.offset, wdata->args.count); | 403 | wdata->args.offset, wdata->args.count); |
398 | } | 404 | } |
399 | pnfs_ld_write_done(wdata); | 405 | pnfs_ld_write_done(wdata); |
@@ -404,12 +410,12 @@ static void bl_end_par_io_write(void *data, int num_se) | |||
404 | { | 410 | { |
405 | struct nfs_write_data *wdata = data; | 411 | struct nfs_write_data *wdata = data; |
406 | 412 | ||
407 | if (unlikely(wdata->pnfs_error)) { | 413 | if (unlikely(wdata->header->pnfs_error)) { |
408 | bl_free_short_extents(&BLK_LSEG2EXT(wdata->lseg)->bl_inval, | 414 | bl_free_short_extents(&BLK_LSEG2EXT(wdata->header->lseg)->bl_inval, |
409 | num_se); | 415 | num_se); |
410 | } | 416 | } |
411 | 417 | ||
412 | wdata->task.tk_status = wdata->pnfs_error; | 418 | wdata->task.tk_status = wdata->header->pnfs_error; |
413 | wdata->verf.committed = NFS_FILE_SYNC; | 419 | wdata->verf.committed = NFS_FILE_SYNC; |
414 | INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup); | 420 | INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup); |
415 | schedule_work(&wdata->task.u.tk_work); | 421 | schedule_work(&wdata->task.u.tk_work); |
@@ -540,6 +546,7 @@ check_page: | |||
540 | static enum pnfs_try_status | 546 | static enum pnfs_try_status |
541 | bl_write_pagelist(struct nfs_write_data *wdata, int sync) | 547 | bl_write_pagelist(struct nfs_write_data *wdata, int sync) |
542 | { | 548 | { |
549 | struct nfs_pgio_header *header = wdata->header; | ||
543 | int i, ret, npg_zero, pg_index, last = 0; | 550 | int i, ret, npg_zero, pg_index, last = 0; |
544 | struct bio *bio = NULL; | 551 | struct bio *bio = NULL; |
545 | struct pnfs_block_extent *be = NULL, *cow_read = NULL; | 552 | struct pnfs_block_extent *be = NULL, *cow_read = NULL; |
@@ -552,7 +559,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) | |||
552 | pgoff_t index; | 559 | pgoff_t index; |
553 | u64 temp; | 560 | u64 temp; |
554 | int npg_per_block = | 561 | int npg_per_block = |
555 | NFS_SERVER(wdata->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; | 562 | NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; |
556 | 563 | ||
557 | dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); | 564 | dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); |
558 | /* At this point, wdata->pages is a (sequential) list of nfs_pages. | 565 | /* At this point, wdata->pages is a (sequential) list of nfs_pages. |
@@ -566,7 +573,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) | |||
566 | /* At this point, have to be more careful with error handling */ | 573 | /* At this point, have to be more careful with error handling */ |
567 | 574 | ||
568 | isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT); | 575 | isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT); |
569 | be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), isect, &cow_read); | 576 | be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), isect, &cow_read); |
570 | if (!be || !is_writable(be, isect)) { | 577 | if (!be || !is_writable(be, isect)) { |
571 | dprintk("%s no matching extents!\n", __func__); | 578 | dprintk("%s no matching extents!\n", __func__); |
572 | goto out_mds; | 579 | goto out_mds; |
@@ -597,10 +604,10 @@ fill_invalid_ext: | |||
597 | dprintk("%s zero %dth page: index %lu isect %llu\n", | 604 | dprintk("%s zero %dth page: index %lu isect %llu\n", |
598 | __func__, npg_zero, index, | 605 | __func__, npg_zero, index, |
599 | (unsigned long long)isect); | 606 | (unsigned long long)isect); |
600 | page = bl_find_get_zeroing_page(wdata->inode, index, | 607 | page = bl_find_get_zeroing_page(header->inode, index, |
601 | cow_read); | 608 | cow_read); |
602 | if (unlikely(IS_ERR(page))) { | 609 | if (unlikely(IS_ERR(page))) { |
603 | wdata->pnfs_error = PTR_ERR(page); | 610 | header->pnfs_error = PTR_ERR(page); |
604 | goto out; | 611 | goto out; |
605 | } else if (page == NULL) | 612 | } else if (page == NULL) |
606 | goto next_page; | 613 | goto next_page; |
@@ -612,7 +619,7 @@ fill_invalid_ext: | |||
612 | __func__, ret); | 619 | __func__, ret); |
613 | end_page_writeback(page); | 620 | end_page_writeback(page); |
614 | page_cache_release(page); | 621 | page_cache_release(page); |
615 | wdata->pnfs_error = ret; | 622 | header->pnfs_error = ret; |
616 | goto out; | 623 | goto out; |
617 | } | 624 | } |
618 | if (likely(!bl_push_one_short_extent(be->be_inval))) | 625 | if (likely(!bl_push_one_short_extent(be->be_inval))) |
@@ -620,11 +627,11 @@ fill_invalid_ext: | |||
620 | else { | 627 | else { |
621 | end_page_writeback(page); | 628 | end_page_writeback(page); |
622 | page_cache_release(page); | 629 | page_cache_release(page); |
623 | wdata->pnfs_error = -ENOMEM; | 630 | header->pnfs_error = -ENOMEM; |
624 | goto out; | 631 | goto out; |
625 | } | 632 | } |
626 | /* FIXME: This should be done in bi_end_io */ | 633 | /* FIXME: This should be done in bi_end_io */ |
627 | mark_extents_written(BLK_LSEG2EXT(wdata->lseg), | 634 | mark_extents_written(BLK_LSEG2EXT(header->lseg), |
628 | page->index << PAGE_CACHE_SHIFT, | 635 | page->index << PAGE_CACHE_SHIFT, |
629 | PAGE_CACHE_SIZE); | 636 | PAGE_CACHE_SIZE); |
630 | 637 | ||
@@ -632,7 +639,7 @@ fill_invalid_ext: | |||
632 | isect, page, be, | 639 | isect, page, be, |
633 | bl_end_io_write_zero, par); | 640 | bl_end_io_write_zero, par); |
634 | if (IS_ERR(bio)) { | 641 | if (IS_ERR(bio)) { |
635 | wdata->pnfs_error = PTR_ERR(bio); | 642 | header->pnfs_error = PTR_ERR(bio); |
636 | bio = NULL; | 643 | bio = NULL; |
637 | goto out; | 644 | goto out; |
638 | } | 645 | } |
@@ -653,10 +660,10 @@ next_page: | |||
653 | bl_put_extent(be); | 660 | bl_put_extent(be); |
654 | bio = bl_submit_bio(WRITE, bio); | 661 | bio = bl_submit_bio(WRITE, bio); |
655 | /* Get the next one */ | 662 | /* Get the next one */ |
656 | be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), | 663 | be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), |
657 | isect, NULL); | 664 | isect, NULL); |
658 | if (!be || !is_writable(be, isect)) { | 665 | if (!be || !is_writable(be, isect)) { |
659 | wdata->pnfs_error = -EINVAL; | 666 | header->pnfs_error = -EINVAL; |
660 | goto out; | 667 | goto out; |
661 | } | 668 | } |
662 | if (be->be_state == PNFS_BLOCK_INVALID_DATA) { | 669 | if (be->be_state == PNFS_BLOCK_INVALID_DATA) { |
@@ -664,7 +671,7 @@ next_page: | |||
664 | be->be_inval))) | 671 | be->be_inval))) |
665 | par->bse_count++; | 672 | par->bse_count++; |
666 | else { | 673 | else { |
667 | wdata->pnfs_error = -ENOMEM; | 674 | header->pnfs_error = -ENOMEM; |
668 | goto out; | 675 | goto out; |
669 | } | 676 | } |
670 | } | 677 | } |
@@ -677,7 +684,7 @@ next_page: | |||
677 | if (unlikely(ret)) { | 684 | if (unlikely(ret)) { |
678 | dprintk("%s bl_mark_sectors_init fail %d\n", | 685 | dprintk("%s bl_mark_sectors_init fail %d\n", |
679 | __func__, ret); | 686 | __func__, ret); |
680 | wdata->pnfs_error = ret; | 687 | header->pnfs_error = ret; |
681 | goto out; | 688 | goto out; |
682 | } | 689 | } |
683 | } | 690 | } |
@@ -685,7 +692,7 @@ next_page: | |||
685 | isect, pages[i], be, | 692 | isect, pages[i], be, |
686 | bl_end_io_write, par); | 693 | bl_end_io_write, par); |
687 | if (IS_ERR(bio)) { | 694 | if (IS_ERR(bio)) { |
688 | wdata->pnfs_error = PTR_ERR(bio); | 695 | header->pnfs_error = PTR_ERR(bio); |
689 | bio = NULL; | 696 | bio = NULL; |
690 | goto out; | 697 | goto out; |
691 | } | 698 | } |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index fb7fbaa79c20..56176af1436f 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -242,7 +242,7 @@ static void nfs_direct_read_release(void *calldata) | |||
242 | { | 242 | { |
243 | 243 | ||
244 | struct nfs_read_data *data = calldata; | 244 | struct nfs_read_data *data = calldata; |
245 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | 245 | struct nfs_direct_req *dreq = (struct nfs_direct_req *)data->header->req; |
246 | int status = data->task.tk_status; | 246 | int status = data->task.tk_status; |
247 | 247 | ||
248 | spin_lock(&dreq->lock); | 248 | spin_lock(&dreq->lock); |
@@ -269,6 +269,15 @@ static const struct rpc_call_ops nfs_read_direct_ops = { | |||
269 | .rpc_release = nfs_direct_read_release, | 269 | .rpc_release = nfs_direct_read_release, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static void nfs_direct_readhdr_release(struct nfs_read_header *rhdr) | ||
273 | { | ||
274 | struct nfs_read_data *data = &rhdr->rpc_data; | ||
275 | |||
276 | if (data->pagevec != data->page_array) | ||
277 | kfree(data->pagevec); | ||
278 | nfs_readhdr_free(&rhdr->header); | ||
279 | } | ||
280 | |||
272 | /* | 281 | /* |
273 | * For each rsize'd chunk of the user's buffer, dispatch an NFS READ | 282 | * For each rsize'd chunk of the user's buffer, dispatch an NFS READ |
274 | * operation. If nfs_readdata_alloc() or get_user_pages() fails, | 283 | * operation. If nfs_readdata_alloc() or get_user_pages() fails, |
@@ -301,6 +310,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
301 | ssize_t started = 0; | 310 | ssize_t started = 0; |
302 | 311 | ||
303 | do { | 312 | do { |
313 | struct nfs_read_header *rhdr; | ||
304 | struct nfs_read_data *data; | 314 | struct nfs_read_data *data; |
305 | size_t bytes; | 315 | size_t bytes; |
306 | 316 | ||
@@ -308,23 +318,24 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
308 | bytes = min(rsize,count); | 318 | bytes = min(rsize,count); |
309 | 319 | ||
310 | result = -ENOMEM; | 320 | result = -ENOMEM; |
311 | data = nfs_readdata_alloc(nfs_page_array_len(pgbase, bytes)); | 321 | rhdr = nfs_readhdr_alloc(nfs_page_array_len(pgbase, bytes)); |
312 | if (unlikely(!data)) | 322 | if (unlikely(!rhdr)) |
313 | break; | 323 | break; |
324 | data = &rhdr->rpc_data; | ||
314 | 325 | ||
315 | down_read(¤t->mm->mmap_sem); | 326 | down_read(¤t->mm->mmap_sem); |
316 | result = get_user_pages(current, current->mm, user_addr, | 327 | result = get_user_pages(current, current->mm, user_addr, |
317 | data->npages, 1, 0, data->pagevec, NULL); | 328 | data->npages, 1, 0, data->pagevec, NULL); |
318 | up_read(¤t->mm->mmap_sem); | 329 | up_read(¤t->mm->mmap_sem); |
319 | if (result < 0) { | 330 | if (result < 0) { |
320 | nfs_readdata_free(data); | 331 | nfs_direct_readhdr_release(rhdr); |
321 | break; | 332 | break; |
322 | } | 333 | } |
323 | if ((unsigned)result < data->npages) { | 334 | if ((unsigned)result < data->npages) { |
324 | bytes = result * PAGE_SIZE; | 335 | bytes = result * PAGE_SIZE; |
325 | if (bytes <= pgbase) { | 336 | if (bytes <= pgbase) { |
326 | nfs_direct_release_pages(data->pagevec, result); | 337 | nfs_direct_release_pages(data->pagevec, result); |
327 | nfs_readdata_free(data); | 338 | nfs_direct_readhdr_release(rhdr); |
328 | break; | 339 | break; |
329 | } | 340 | } |
330 | bytes -= pgbase; | 341 | bytes -= pgbase; |
@@ -333,9 +344,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
333 | 344 | ||
334 | get_dreq(dreq); | 345 | get_dreq(dreq); |
335 | 346 | ||
336 | data->req = (struct nfs_page *) dreq; | 347 | rhdr->header.req = (struct nfs_page *) dreq; |
337 | data->inode = inode; | 348 | rhdr->header.inode = inode; |
338 | data->cred = msg.rpc_cred; | 349 | rhdr->header.cred = msg.rpc_cred; |
339 | data->args.fh = NFS_FH(inode); | 350 | data->args.fh = NFS_FH(inode); |
340 | data->args.context = get_nfs_open_context(ctx); | 351 | data->args.context = get_nfs_open_context(ctx); |
341 | data->args.lock_context = dreq->l_ctx; | 352 | data->args.lock_context = dreq->l_ctx; |
@@ -447,13 +458,23 @@ out: | |||
447 | return result; | 458 | return result; |
448 | } | 459 | } |
449 | 460 | ||
461 | static void nfs_direct_writehdr_release(struct nfs_write_header *whdr) | ||
462 | { | ||
463 | struct nfs_write_data *data = &whdr->rpc_data; | ||
464 | |||
465 | if (data->pagevec != data->page_array) | ||
466 | kfree(data->pagevec); | ||
467 | nfs_writehdr_free(&whdr->header); | ||
468 | } | ||
469 | |||
450 | static void nfs_direct_free_writedata(struct nfs_direct_req *dreq) | 470 | static void nfs_direct_free_writedata(struct nfs_direct_req *dreq) |
451 | { | 471 | { |
452 | while (!list_empty(&dreq->rewrite_list)) { | 472 | while (!list_empty(&dreq->rewrite_list)) { |
453 | struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages); | 473 | struct nfs_pgio_header *hdr = list_entry(dreq->rewrite_list.next, struct nfs_pgio_header, pages); |
454 | list_del(&data->pages); | 474 | struct nfs_write_header *whdr = container_of(hdr, struct nfs_write_header, header); |
455 | nfs_direct_release_pages(data->pagevec, data->npages); | 475 | list_del(&hdr->pages); |
456 | nfs_writedata_free(data); | 476 | nfs_direct_release_pages(whdr->rpc_data.pagevec, whdr->rpc_data.npages); |
477 | nfs_direct_writehdr_release(whdr); | ||
457 | } | 478 | } |
458 | } | 479 | } |
459 | 480 | ||
@@ -463,6 +484,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
463 | struct inode *inode = dreq->inode; | 484 | struct inode *inode = dreq->inode; |
464 | struct list_head *p; | 485 | struct list_head *p; |
465 | struct nfs_write_data *data; | 486 | struct nfs_write_data *data; |
487 | struct nfs_pgio_header *hdr; | ||
466 | struct rpc_task *task; | 488 | struct rpc_task *task; |
467 | struct rpc_message msg = { | 489 | struct rpc_message msg = { |
468 | .rpc_cred = dreq->ctx->cred, | 490 | .rpc_cred = dreq->ctx->cred, |
@@ -479,7 +501,8 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
479 | get_dreq(dreq); | 501 | get_dreq(dreq); |
480 | 502 | ||
481 | list_for_each(p, &dreq->rewrite_list) { | 503 | list_for_each(p, &dreq->rewrite_list) { |
482 | data = list_entry(p, struct nfs_write_data, pages); | 504 | hdr = list_entry(p, struct nfs_pgio_header, pages); |
505 | data = &(container_of(hdr, struct nfs_write_header, header))->rpc_data; | ||
483 | 506 | ||
484 | get_dreq(dreq); | 507 | get_dreq(dreq); |
485 | 508 | ||
@@ -652,7 +675,8 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata) | |||
652 | static void nfs_direct_write_release(void *calldata) | 675 | static void nfs_direct_write_release(void *calldata) |
653 | { | 676 | { |
654 | struct nfs_write_data *data = calldata; | 677 | struct nfs_write_data *data = calldata; |
655 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | 678 | struct nfs_pgio_header *hdr = data->header; |
679 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) hdr->req; | ||
656 | int status = data->task.tk_status; | 680 | int status = data->task.tk_status; |
657 | 681 | ||
658 | spin_lock(&dreq->lock); | 682 | spin_lock(&dreq->lock); |
@@ -684,7 +708,7 @@ out_unlock: | |||
684 | spin_unlock(&dreq->lock); | 708 | spin_unlock(&dreq->lock); |
685 | 709 | ||
686 | if (put_dreq(dreq)) | 710 | if (put_dreq(dreq)) |
687 | nfs_direct_write_complete(dreq, data->inode); | 711 | nfs_direct_write_complete(dreq, hdr->inode); |
688 | } | 712 | } |
689 | 713 | ||
690 | static const struct rpc_call_ops nfs_write_direct_ops = { | 714 | static const struct rpc_call_ops nfs_write_direct_ops = { |
@@ -725,6 +749,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
725 | ssize_t started = 0; | 749 | ssize_t started = 0; |
726 | 750 | ||
727 | do { | 751 | do { |
752 | struct nfs_write_header *whdr; | ||
728 | struct nfs_write_data *data; | 753 | struct nfs_write_data *data; |
729 | size_t bytes; | 754 | size_t bytes; |
730 | 755 | ||
@@ -732,23 +757,25 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
732 | bytes = min(wsize,count); | 757 | bytes = min(wsize,count); |
733 | 758 | ||
734 | result = -ENOMEM; | 759 | result = -ENOMEM; |
735 | data = nfs_writedata_alloc(nfs_page_array_len(pgbase, bytes)); | 760 | whdr = nfs_writehdr_alloc(nfs_page_array_len(pgbase, bytes)); |
736 | if (unlikely(!data)) | 761 | if (unlikely(!whdr)) |
737 | break; | 762 | break; |
738 | 763 | ||
764 | data = &whdr->rpc_data; | ||
765 | |||
739 | down_read(¤t->mm->mmap_sem); | 766 | down_read(¤t->mm->mmap_sem); |
740 | result = get_user_pages(current, current->mm, user_addr, | 767 | result = get_user_pages(current, current->mm, user_addr, |
741 | data->npages, 0, 0, data->pagevec, NULL); | 768 | data->npages, 0, 0, data->pagevec, NULL); |
742 | up_read(¤t->mm->mmap_sem); | 769 | up_read(¤t->mm->mmap_sem); |
743 | if (result < 0) { | 770 | if (result < 0) { |
744 | nfs_writedata_free(data); | 771 | nfs_direct_writehdr_release(whdr); |
745 | break; | 772 | break; |
746 | } | 773 | } |
747 | if ((unsigned)result < data->npages) { | 774 | if ((unsigned)result < data->npages) { |
748 | bytes = result * PAGE_SIZE; | 775 | bytes = result * PAGE_SIZE; |
749 | if (bytes <= pgbase) { | 776 | if (bytes <= pgbase) { |
750 | nfs_direct_release_pages(data->pagevec, result); | 777 | nfs_direct_release_pages(data->pagevec, result); |
751 | nfs_writedata_free(data); | 778 | nfs_direct_writehdr_release(whdr); |
752 | break; | 779 | break; |
753 | } | 780 | } |
754 | bytes -= pgbase; | 781 | bytes -= pgbase; |
@@ -757,11 +784,11 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
757 | 784 | ||
758 | get_dreq(dreq); | 785 | get_dreq(dreq); |
759 | 786 | ||
760 | list_move_tail(&data->pages, &dreq->rewrite_list); | 787 | list_move_tail(&whdr->header.pages, &dreq->rewrite_list); |
761 | 788 | ||
762 | data->req = (struct nfs_page *) dreq; | 789 | whdr->header.req = (struct nfs_page *) dreq; |
763 | data->inode = inode; | 790 | whdr->header.inode = inode; |
764 | data->cred = msg.rpc_cred; | 791 | whdr->header.cred = msg.rpc_cred; |
765 | data->args.fh = NFS_FH(inode); | 792 | data->args.fh = NFS_FH(inode); |
766 | data->args.context = ctx; | 793 | data->args.context = ctx; |
767 | data->args.lock_context = dreq->l_ctx; | 794 | data->args.lock_context = dreq->l_ctx; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 650127fd24bb..7dc9be1a6e1a 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -296,6 +296,8 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | |||
296 | 296 | ||
297 | struct nfs_pageio_descriptor; | 297 | struct nfs_pageio_descriptor; |
298 | /* read.c */ | 298 | /* read.c */ |
299 | extern struct nfs_read_header *nfs_readhdr_alloc(unsigned int npages); | ||
300 | extern void nfs_readhdr_free(struct nfs_pgio_header *hdr); | ||
299 | extern int nfs_initiate_read(struct rpc_clnt *clnt, | 301 | extern int nfs_initiate_read(struct rpc_clnt *clnt, |
300 | struct nfs_read_data *data, | 302 | struct nfs_read_data *data, |
301 | const struct rpc_call_ops *call_ops); | 303 | const struct rpc_call_ops *call_ops); |
@@ -309,6 +311,8 @@ extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | |||
309 | extern void nfs_readdata_release(struct nfs_read_data *rdata); | 311 | extern void nfs_readdata_release(struct nfs_read_data *rdata); |
310 | 312 | ||
311 | /* write.c */ | 313 | /* write.c */ |
314 | extern struct nfs_write_header *nfs_writehdr_alloc(unsigned int npages); | ||
315 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); | ||
312 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | 316 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, |
313 | struct list_head *head); | 317 | struct list_head *head); |
314 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 318 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index b1daca7f0f7b..56dcefc2f3f7 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -811,11 +811,13 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
811 | 811 | ||
812 | static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) | 812 | static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) |
813 | { | 813 | { |
814 | if (nfs3_async_handle_jukebox(task, data->inode)) | 814 | struct inode *inode = data->header->inode; |
815 | |||
816 | if (nfs3_async_handle_jukebox(task, inode)) | ||
815 | return -EAGAIN; | 817 | return -EAGAIN; |
816 | 818 | ||
817 | nfs_invalidate_atime(data->inode); | 819 | nfs_invalidate_atime(inode); |
818 | nfs_refresh_inode(data->inode, &data->fattr); | 820 | nfs_refresh_inode(inode, &data->fattr); |
819 | return 0; | 821 | return 0; |
820 | } | 822 | } |
821 | 823 | ||
@@ -831,10 +833,12 @@ static void nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_da | |||
831 | 833 | ||
832 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | 834 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) |
833 | { | 835 | { |
834 | if (nfs3_async_handle_jukebox(task, data->inode)) | 836 | struct inode *inode = data->header->inode; |
837 | |||
838 | if (nfs3_async_handle_jukebox(task, inode)) | ||
835 | return -EAGAIN; | 839 | return -EAGAIN; |
836 | if (task->tk_status >= 0) | 840 | if (task->tk_status >= 0) |
837 | nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); | 841 | nfs_post_op_update_inode_force_wcc(inode, data->res.fattr); |
838 | return 0; | 842 | return 0; |
839 | } | 843 | } |
840 | 844 | ||
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index c536328557cb..ad1d68013a5b 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -148,6 +148,7 @@ wait_on_recovery: | |||
148 | static int filelayout_read_done_cb(struct rpc_task *task, | 148 | static int filelayout_read_done_cb(struct rpc_task *task, |
149 | struct nfs_read_data *data) | 149 | struct nfs_read_data *data) |
150 | { | 150 | { |
151 | struct nfs_pgio_header *hdr = data->header; | ||
151 | int reset = 0; | 152 | int reset = 0; |
152 | 153 | ||
153 | dprintk("%s DS read\n", __func__); | 154 | dprintk("%s DS read\n", __func__); |
@@ -157,7 +158,7 @@ static int filelayout_read_done_cb(struct rpc_task *task, | |||
157 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", | 158 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", |
158 | __func__, data->ds_clp, data->ds_clp->cl_session); | 159 | __func__, data->ds_clp, data->ds_clp->cl_session); |
159 | if (reset) { | 160 | if (reset) { |
160 | pnfs_set_lo_fail(data->lseg); | 161 | pnfs_set_lo_fail(hdr->lseg); |
161 | nfs4_reset_read(task, data); | 162 | nfs4_reset_read(task, data); |
162 | } | 163 | } |
163 | rpc_restart_call_prepare(task); | 164 | rpc_restart_call_prepare(task); |
@@ -175,13 +176,15 @@ static int filelayout_read_done_cb(struct rpc_task *task, | |||
175 | static void | 176 | static void |
176 | filelayout_set_layoutcommit(struct nfs_write_data *wdata) | 177 | filelayout_set_layoutcommit(struct nfs_write_data *wdata) |
177 | { | 178 | { |
178 | if (FILELAYOUT_LSEG(wdata->lseg)->commit_through_mds || | 179 | struct nfs_pgio_header *hdr = wdata->header; |
180 | |||
181 | if (FILELAYOUT_LSEG(hdr->lseg)->commit_through_mds || | ||
179 | wdata->res.verf->committed == NFS_FILE_SYNC) | 182 | wdata->res.verf->committed == NFS_FILE_SYNC) |
180 | return; | 183 | return; |
181 | 184 | ||
182 | pnfs_set_layoutcommit(wdata); | 185 | pnfs_set_layoutcommit(wdata); |
183 | dprintk("%s ionde %lu pls_end_pos %lu\n", __func__, wdata->inode->i_ino, | 186 | dprintk("%s ionde %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, |
184 | (unsigned long) NFS_I(wdata->inode)->layout->plh_lwb); | 187 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); |
185 | } | 188 | } |
186 | 189 | ||
187 | /* | 190 | /* |
@@ -210,27 +213,28 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data) | |||
210 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); | 213 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); |
211 | 214 | ||
212 | /* Note this may cause RPC to be resent */ | 215 | /* Note this may cause RPC to be resent */ |
213 | rdata->mds_ops->rpc_call_done(task, data); | 216 | rdata->header->mds_ops->rpc_call_done(task, data); |
214 | } | 217 | } |
215 | 218 | ||
216 | static void filelayout_read_count_stats(struct rpc_task *task, void *data) | 219 | static void filelayout_read_count_stats(struct rpc_task *task, void *data) |
217 | { | 220 | { |
218 | struct nfs_read_data *rdata = data; | 221 | struct nfs_read_data *rdata = data; |
219 | 222 | ||
220 | rpc_count_iostats(task, NFS_SERVER(rdata->inode)->client->cl_metrics); | 223 | rpc_count_iostats(task, NFS_SERVER(rdata->header->inode)->client->cl_metrics); |
221 | } | 224 | } |
222 | 225 | ||
223 | static void filelayout_read_release(void *data) | 226 | static void filelayout_read_release(void *data) |
224 | { | 227 | { |
225 | struct nfs_read_data *rdata = data; | 228 | struct nfs_read_data *rdata = data; |
226 | 229 | ||
227 | put_lseg(rdata->lseg); | 230 | put_lseg(rdata->header->lseg); |
228 | rdata->mds_ops->rpc_release(data); | 231 | rdata->header->mds_ops->rpc_release(data); |
229 | } | 232 | } |
230 | 233 | ||
231 | static int filelayout_write_done_cb(struct rpc_task *task, | 234 | static int filelayout_write_done_cb(struct rpc_task *task, |
232 | struct nfs_write_data *data) | 235 | struct nfs_write_data *data) |
233 | { | 236 | { |
237 | struct nfs_pgio_header *hdr = data->header; | ||
234 | int reset = 0; | 238 | int reset = 0; |
235 | 239 | ||
236 | if (filelayout_async_handle_error(task, data->args.context->state, | 240 | if (filelayout_async_handle_error(task, data->args.context->state, |
@@ -238,7 +242,7 @@ static int filelayout_write_done_cb(struct rpc_task *task, | |||
238 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", | 242 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", |
239 | __func__, data->ds_clp, data->ds_clp->cl_session); | 243 | __func__, data->ds_clp, data->ds_clp->cl_session); |
240 | if (reset) { | 244 | if (reset) { |
241 | pnfs_set_lo_fail(data->lseg); | 245 | pnfs_set_lo_fail(hdr->lseg); |
242 | nfs4_reset_write(task, data); | 246 | nfs4_reset_write(task, data); |
243 | } | 247 | } |
244 | rpc_restart_call_prepare(task); | 248 | rpc_restart_call_prepare(task); |
@@ -297,22 +301,22 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data) | |||
297 | struct nfs_write_data *wdata = data; | 301 | struct nfs_write_data *wdata = data; |
298 | 302 | ||
299 | /* Note this may cause RPC to be resent */ | 303 | /* Note this may cause RPC to be resent */ |
300 | wdata->mds_ops->rpc_call_done(task, data); | 304 | wdata->header->mds_ops->rpc_call_done(task, data); |
301 | } | 305 | } |
302 | 306 | ||
303 | static void filelayout_write_count_stats(struct rpc_task *task, void *data) | 307 | static void filelayout_write_count_stats(struct rpc_task *task, void *data) |
304 | { | 308 | { |
305 | struct nfs_write_data *wdata = data; | 309 | struct nfs_write_data *wdata = data; |
306 | 310 | ||
307 | rpc_count_iostats(task, NFS_SERVER(wdata->inode)->client->cl_metrics); | 311 | rpc_count_iostats(task, NFS_SERVER(wdata->header->inode)->client->cl_metrics); |
308 | } | 312 | } |
309 | 313 | ||
310 | static void filelayout_write_release(void *data) | 314 | static void filelayout_write_release(void *data) |
311 | { | 315 | { |
312 | struct nfs_write_data *wdata = data; | 316 | struct nfs_write_data *wdata = data; |
313 | 317 | ||
314 | put_lseg(wdata->lseg); | 318 | put_lseg(wdata->header->lseg); |
315 | wdata->mds_ops->rpc_release(data); | 319 | wdata->header->mds_ops->rpc_release(data); |
316 | } | 320 | } |
317 | 321 | ||
318 | static void filelayout_commit_prepare(struct rpc_task *task, void *data) | 322 | static void filelayout_commit_prepare(struct rpc_task *task, void *data) |
@@ -377,7 +381,8 @@ static const struct rpc_call_ops filelayout_commit_call_ops = { | |||
377 | static enum pnfs_try_status | 381 | static enum pnfs_try_status |
378 | filelayout_read_pagelist(struct nfs_read_data *data) | 382 | filelayout_read_pagelist(struct nfs_read_data *data) |
379 | { | 383 | { |
380 | struct pnfs_layout_segment *lseg = data->lseg; | 384 | struct nfs_pgio_header *hdr = data->header; |
385 | struct pnfs_layout_segment *lseg = hdr->lseg; | ||
381 | struct nfs4_pnfs_ds *ds; | 386 | struct nfs4_pnfs_ds *ds; |
382 | loff_t offset = data->args.offset; | 387 | loff_t offset = data->args.offset; |
383 | u32 j, idx; | 388 | u32 j, idx; |
@@ -385,7 +390,7 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
385 | int status; | 390 | int status; |
386 | 391 | ||
387 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", | 392 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", |
388 | __func__, data->inode->i_ino, | 393 | __func__, hdr->inode->i_ino, |
389 | data->args.pgbase, (size_t)data->args.count, offset); | 394 | data->args.pgbase, (size_t)data->args.count, offset); |
390 | 395 | ||
391 | if (test_bit(NFS_DEVICEID_INVALID, &FILELAYOUT_DEVID_NODE(lseg)->flags)) | 396 | if (test_bit(NFS_DEVICEID_INVALID, &FILELAYOUT_DEVID_NODE(lseg)->flags)) |
@@ -423,7 +428,8 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
423 | static enum pnfs_try_status | 428 | static enum pnfs_try_status |
424 | filelayout_write_pagelist(struct nfs_write_data *data, int sync) | 429 | filelayout_write_pagelist(struct nfs_write_data *data, int sync) |
425 | { | 430 | { |
426 | struct pnfs_layout_segment *lseg = data->lseg; | 431 | struct nfs_pgio_header *hdr = data->header; |
432 | struct pnfs_layout_segment *lseg = hdr->lseg; | ||
427 | struct nfs4_pnfs_ds *ds; | 433 | struct nfs4_pnfs_ds *ds; |
428 | loff_t offset = data->args.offset; | 434 | loff_t offset = data->args.offset; |
429 | u32 j, idx; | 435 | u32 j, idx; |
@@ -445,7 +451,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
445 | return PNFS_NOT_ATTEMPTED; | 451 | return PNFS_NOT_ATTEMPTED; |
446 | } | 452 | } |
447 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s\n", __func__, | 453 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s\n", __func__, |
448 | data->inode->i_ino, sync, (size_t) data->args.count, offset, | 454 | hdr->inode->i_ino, sync, (size_t) data->args.count, offset, |
449 | ds->ds_remotestr); | 455 | ds->ds_remotestr); |
450 | 456 | ||
451 | data->write_done_cb = filelayout_write_done_cb; | 457 | data->write_done_cb = filelayout_write_done_cb; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cc04b6e409ed..5375862075de 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3336,12 +3336,12 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3336 | 3336 | ||
3337 | void __nfs4_read_done_cb(struct nfs_read_data *data) | 3337 | void __nfs4_read_done_cb(struct nfs_read_data *data) |
3338 | { | 3338 | { |
3339 | nfs_invalidate_atime(data->inode); | 3339 | nfs_invalidate_atime(data->header->inode); |
3340 | } | 3340 | } |
3341 | 3341 | ||
3342 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) | 3342 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) |
3343 | { | 3343 | { |
3344 | struct nfs_server *server = NFS_SERVER(data->inode); | 3344 | struct nfs_server *server = NFS_SERVER(data->header->inode); |
3345 | 3345 | ||
3346 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3346 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3347 | rpc_restart_call_prepare(task); | 3347 | rpc_restart_call_prepare(task); |
@@ -3376,7 +3376,7 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3376 | 3376 | ||
3377 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 3377 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
3378 | { | 3378 | { |
3379 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | 3379 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3380 | &data->args.seq_args, | 3380 | &data->args.seq_args, |
3381 | &data->res.seq_res, | 3381 | &data->res.seq_res, |
3382 | task)) | 3382 | task)) |
@@ -3387,22 +3387,25 @@ static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_da | |||
3387 | /* Reset the the nfs_read_data to send the read to the MDS. */ | 3387 | /* Reset the the nfs_read_data to send the read to the MDS. */ |
3388 | void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data) | 3388 | void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data) |
3389 | { | 3389 | { |
3390 | struct nfs_pgio_header *hdr = data->header; | ||
3391 | struct inode *inode = hdr->inode; | ||
3392 | |||
3390 | dprintk("%s Reset task for i/o through\n", __func__); | 3393 | dprintk("%s Reset task for i/o through\n", __func__); |
3391 | put_lseg(data->lseg); | 3394 | put_lseg(hdr->lseg); |
3392 | data->lseg = NULL; | 3395 | hdr->lseg = NULL; |
3396 | data->ds_clp = NULL; | ||
3393 | /* offsets will differ in the dense stripe case */ | 3397 | /* offsets will differ in the dense stripe case */ |
3394 | data->args.offset = data->mds_offset; | 3398 | data->args.offset = data->mds_offset; |
3395 | data->ds_clp = NULL; | 3399 | data->args.fh = NFS_FH(inode); |
3396 | data->args.fh = NFS_FH(data->inode); | ||
3397 | data->read_done_cb = nfs4_read_done_cb; | 3400 | data->read_done_cb = nfs4_read_done_cb; |
3398 | task->tk_ops = data->mds_ops; | 3401 | task->tk_ops = hdr->mds_ops; |
3399 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | 3402 | rpc_task_reset_client(task, NFS_CLIENT(inode)); |
3400 | } | 3403 | } |
3401 | EXPORT_SYMBOL_GPL(nfs4_reset_read); | 3404 | EXPORT_SYMBOL_GPL(nfs4_reset_read); |
3402 | 3405 | ||
3403 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 3406 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
3404 | { | 3407 | { |
3405 | struct inode *inode = data->inode; | 3408 | struct inode *inode = data->header->inode; |
3406 | 3409 | ||
3407 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 3410 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3408 | rpc_restart_call_prepare(task); | 3411 | rpc_restart_call_prepare(task); |
@@ -3426,25 +3429,28 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3426 | /* Reset the the nfs_write_data to send the write to the MDS. */ | 3429 | /* Reset the the nfs_write_data to send the write to the MDS. */ |
3427 | void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data) | 3430 | void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data) |
3428 | { | 3431 | { |
3432 | struct nfs_pgio_header *hdr = data->header; | ||
3433 | struct inode *inode = hdr->inode; | ||
3434 | |||
3429 | dprintk("%s Reset task for i/o through\n", __func__); | 3435 | dprintk("%s Reset task for i/o through\n", __func__); |
3430 | put_lseg(data->lseg); | 3436 | put_lseg(hdr->lseg); |
3431 | data->lseg = NULL; | 3437 | hdr->lseg = NULL; |
3432 | data->ds_clp = NULL; | 3438 | data->ds_clp = NULL; |
3433 | data->write_done_cb = nfs4_write_done_cb; | 3439 | data->write_done_cb = nfs4_write_done_cb; |
3434 | data->args.fh = NFS_FH(data->inode); | 3440 | data->args.fh = NFS_FH(inode); |
3435 | data->args.bitmask = data->res.server->cache_consistency_bitmask; | 3441 | data->args.bitmask = data->res.server->cache_consistency_bitmask; |
3436 | data->args.offset = data->mds_offset; | 3442 | data->args.offset = data->mds_offset; |
3437 | data->res.fattr = &data->fattr; | 3443 | data->res.fattr = &data->fattr; |
3438 | task->tk_ops = data->mds_ops; | 3444 | task->tk_ops = hdr->mds_ops; |
3439 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | 3445 | rpc_task_reset_client(task, NFS_CLIENT(inode)); |
3440 | } | 3446 | } |
3441 | EXPORT_SYMBOL_GPL(nfs4_reset_write); | 3447 | EXPORT_SYMBOL_GPL(nfs4_reset_write); |
3442 | 3448 | ||
3443 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3449 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
3444 | { | 3450 | { |
3445 | struct nfs_server *server = NFS_SERVER(data->inode); | 3451 | struct nfs_server *server = NFS_SERVER(data->header->inode); |
3446 | 3452 | ||
3447 | if (data->lseg) { | 3453 | if (data->header->lseg) { |
3448 | data->args.bitmask = NULL; | 3454 | data->args.bitmask = NULL; |
3449 | data->res.fattr = NULL; | 3455 | data->res.fattr = NULL; |
3450 | } else | 3456 | } else |
@@ -3460,7 +3466,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3460 | 3466 | ||
3461 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 3467 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
3462 | { | 3468 | { |
3463 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | 3469 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3464 | &data->args.seq_args, | 3470 | &data->args.seq_args, |
3465 | &data->res.seq_res, | 3471 | &data->res.seq_res, |
3466 | task)) | 3472 | task)) |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 4bff4a3dab46..fbf4874ec252 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -440,11 +440,12 @@ static void _read_done(struct ore_io_state *ios, void *private) | |||
440 | 440 | ||
441 | int objio_read_pagelist(struct nfs_read_data *rdata) | 441 | int objio_read_pagelist(struct nfs_read_data *rdata) |
442 | { | 442 | { |
443 | struct nfs_pgio_header *hdr = rdata->header; | ||
443 | struct objio_state *objios; | 444 | struct objio_state *objios; |
444 | int ret; | 445 | int ret; |
445 | 446 | ||
446 | ret = objio_alloc_io_state(NFS_I(rdata->inode)->layout, true, | 447 | ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, true, |
447 | rdata->lseg, rdata->args.pages, rdata->args.pgbase, | 448 | hdr->lseg, rdata->args.pages, rdata->args.pgbase, |
448 | rdata->args.offset, rdata->args.count, rdata, | 449 | rdata->args.offset, rdata->args.count, rdata, |
449 | GFP_KERNEL, &objios); | 450 | GFP_KERNEL, &objios); |
450 | if (unlikely(ret)) | 451 | if (unlikely(ret)) |
@@ -483,12 +484,12 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) | |||
483 | { | 484 | { |
484 | struct objio_state *objios = priv; | 485 | struct objio_state *objios = priv; |
485 | struct nfs_write_data *wdata = objios->oir.rpcdata; | 486 | struct nfs_write_data *wdata = objios->oir.rpcdata; |
487 | struct address_space *mapping = wdata->header->inode->i_mapping; | ||
486 | pgoff_t index = offset / PAGE_SIZE; | 488 | pgoff_t index = offset / PAGE_SIZE; |
487 | struct page *page = find_get_page(wdata->inode->i_mapping, index); | 489 | struct page *page = find_get_page(mapping, index); |
488 | 490 | ||
489 | if (!page) { | 491 | if (!page) { |
490 | page = find_or_create_page(wdata->inode->i_mapping, | 492 | page = find_or_create_page(mapping, index, GFP_NOFS); |
491 | index, GFP_NOFS); | ||
492 | if (unlikely(!page)) { | 493 | if (unlikely(!page)) { |
493 | dprintk("%s: grab_cache_page Failed index=0x%lx\n", | 494 | dprintk("%s: grab_cache_page Failed index=0x%lx\n", |
494 | __func__, index); | 495 | __func__, index); |
@@ -518,11 +519,12 @@ static const struct _ore_r4w_op _r4w_op = { | |||
518 | 519 | ||
519 | int objio_write_pagelist(struct nfs_write_data *wdata, int how) | 520 | int objio_write_pagelist(struct nfs_write_data *wdata, int how) |
520 | { | 521 | { |
522 | struct nfs_pgio_header *hdr = wdata->header; | ||
521 | struct objio_state *objios; | 523 | struct objio_state *objios; |
522 | int ret; | 524 | int ret; |
523 | 525 | ||
524 | ret = objio_alloc_io_state(NFS_I(wdata->inode)->layout, false, | 526 | ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, false, |
525 | wdata->lseg, wdata->args.pages, wdata->args.pgbase, | 527 | hdr->lseg, wdata->args.pages, wdata->args.pgbase, |
526 | wdata->args.offset, wdata->args.count, wdata, GFP_NOFS, | 528 | wdata->args.offset, wdata->args.count, wdata, GFP_NOFS, |
527 | &objios); | 529 | &objios); |
528 | if (unlikely(ret)) | 530 | if (unlikely(ret)) |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index 595c5fc21a19..874613545301 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -258,7 +258,7 @@ objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync) | |||
258 | if (status >= 0) | 258 | if (status >= 0) |
259 | rdata->res.count = status; | 259 | rdata->res.count = status; |
260 | else | 260 | else |
261 | rdata->pnfs_error = status; | 261 | rdata->header->pnfs_error = status; |
262 | objlayout_iodone(oir); | 262 | objlayout_iodone(oir); |
263 | /* must not use oir after this point */ | 263 | /* must not use oir after this point */ |
264 | 264 | ||
@@ -279,12 +279,14 @@ objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync) | |||
279 | enum pnfs_try_status | 279 | enum pnfs_try_status |
280 | objlayout_read_pagelist(struct nfs_read_data *rdata) | 280 | objlayout_read_pagelist(struct nfs_read_data *rdata) |
281 | { | 281 | { |
282 | struct nfs_pgio_header *hdr = rdata->header; | ||
283 | struct inode *inode = hdr->inode; | ||
282 | loff_t offset = rdata->args.offset; | 284 | loff_t offset = rdata->args.offset; |
283 | size_t count = rdata->args.count; | 285 | size_t count = rdata->args.count; |
284 | int err; | 286 | int err; |
285 | loff_t eof; | 287 | loff_t eof; |
286 | 288 | ||
287 | eof = i_size_read(rdata->inode); | 289 | eof = i_size_read(inode); |
288 | if (unlikely(offset + count > eof)) { | 290 | if (unlikely(offset + count > eof)) { |
289 | if (offset >= eof) { | 291 | if (offset >= eof) { |
290 | err = 0; | 292 | err = 0; |
@@ -297,17 +299,17 @@ objlayout_read_pagelist(struct nfs_read_data *rdata) | |||
297 | } | 299 | } |
298 | 300 | ||
299 | rdata->res.eof = (offset + count) >= eof; | 301 | rdata->res.eof = (offset + count) >= eof; |
300 | _fix_verify_io_params(rdata->lseg, &rdata->args.pages, | 302 | _fix_verify_io_params(hdr->lseg, &rdata->args.pages, |
301 | &rdata->args.pgbase, | 303 | &rdata->args.pgbase, |
302 | rdata->args.offset, rdata->args.count); | 304 | rdata->args.offset, rdata->args.count); |
303 | 305 | ||
304 | dprintk("%s: inode(%lx) offset 0x%llx count 0x%Zx eof=%d\n", | 306 | dprintk("%s: inode(%lx) offset 0x%llx count 0x%Zx eof=%d\n", |
305 | __func__, rdata->inode->i_ino, offset, count, rdata->res.eof); | 307 | __func__, inode->i_ino, offset, count, rdata->res.eof); |
306 | 308 | ||
307 | err = objio_read_pagelist(rdata); | 309 | err = objio_read_pagelist(rdata); |
308 | out: | 310 | out: |
309 | if (unlikely(err)) { | 311 | if (unlikely(err)) { |
310 | rdata->pnfs_error = err; | 312 | hdr->pnfs_error = err; |
311 | dprintk("%s: Returned Error %d\n", __func__, err); | 313 | dprintk("%s: Returned Error %d\n", __func__, err); |
312 | return PNFS_NOT_ATTEMPTED; | 314 | return PNFS_NOT_ATTEMPTED; |
313 | } | 315 | } |
@@ -340,7 +342,7 @@ objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync) | |||
340 | wdata->res.count = status; | 342 | wdata->res.count = status; |
341 | wdata->verf.committed = oir->committed; | 343 | wdata->verf.committed = oir->committed; |
342 | } else { | 344 | } else { |
343 | wdata->pnfs_error = status; | 345 | wdata->header->pnfs_error = status; |
344 | } | 346 | } |
345 | objlayout_iodone(oir); | 347 | objlayout_iodone(oir); |
346 | /* must not use oir after this point */ | 348 | /* must not use oir after this point */ |
@@ -363,15 +365,16 @@ enum pnfs_try_status | |||
363 | objlayout_write_pagelist(struct nfs_write_data *wdata, | 365 | objlayout_write_pagelist(struct nfs_write_data *wdata, |
364 | int how) | 366 | int how) |
365 | { | 367 | { |
368 | struct nfs_pgio_header *hdr = wdata->header; | ||
366 | int err; | 369 | int err; |
367 | 370 | ||
368 | _fix_verify_io_params(wdata->lseg, &wdata->args.pages, | 371 | _fix_verify_io_params(hdr->lseg, &wdata->args.pages, |
369 | &wdata->args.pgbase, | 372 | &wdata->args.pgbase, |
370 | wdata->args.offset, wdata->args.count); | 373 | wdata->args.offset, wdata->args.count); |
371 | 374 | ||
372 | err = objio_write_pagelist(wdata, how); | 375 | err = objio_write_pagelist(wdata, how); |
373 | if (unlikely(err)) { | 376 | if (unlikely(err)) { |
374 | wdata->pnfs_error = err; | 377 | hdr->pnfs_error = err; |
375 | dprintk("%s: Returned Error %d\n", __func__, err); | 378 | dprintk("%s: Returned Error %d\n", __func__, err); |
376 | return PNFS_NOT_ATTEMPTED; | 379 | return PNFS_NOT_ATTEMPTED; |
377 | } | 380 | } |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 9c4d14a17d49..d705da427e6d 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1191,13 +1191,15 @@ static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head * | |||
1191 | 1191 | ||
1192 | static void pnfs_ld_handle_write_error(struct nfs_write_data *data) | 1192 | static void pnfs_ld_handle_write_error(struct nfs_write_data *data) |
1193 | { | 1193 | { |
1194 | dprintk("pnfs write error = %d\n", data->pnfs_error); | 1194 | struct nfs_pgio_header *hdr = data->header; |
1195 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | 1195 | |
1196 | dprintk("pnfs write error = %d\n", hdr->pnfs_error); | ||
1197 | if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & | ||
1196 | PNFS_LAYOUTRET_ON_ERROR) { | 1198 | PNFS_LAYOUTRET_ON_ERROR) { |
1197 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags); | 1199 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags); |
1198 | pnfs_return_layout(data->inode); | 1200 | pnfs_return_layout(hdr->inode); |
1199 | } | 1201 | } |
1200 | data->task.tk_status = pnfs_write_done_resend_to_mds(data->inode, &data->pages); | 1202 | data->task.tk_status = pnfs_write_done_resend_to_mds(hdr->inode, &hdr->pages); |
1201 | } | 1203 | } |
1202 | 1204 | ||
1203 | /* | 1205 | /* |
@@ -1205,13 +1207,15 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data) | |||
1205 | */ | 1207 | */ |
1206 | void pnfs_ld_write_done(struct nfs_write_data *data) | 1208 | void pnfs_ld_write_done(struct nfs_write_data *data) |
1207 | { | 1209 | { |
1208 | if (likely(!data->pnfs_error)) { | 1210 | struct nfs_pgio_header *hdr = data->header; |
1211 | |||
1212 | if (!hdr->pnfs_error) { | ||
1209 | pnfs_set_layoutcommit(data); | 1213 | pnfs_set_layoutcommit(data); |
1210 | data->mds_ops->rpc_call_done(&data->task, data); | 1214 | hdr->mds_ops->rpc_call_done(&data->task, data); |
1211 | } else | 1215 | } else |
1212 | pnfs_ld_handle_write_error(data); | 1216 | pnfs_ld_handle_write_error(data); |
1213 | put_lseg(data->lseg); | 1217 | put_lseg(hdr->lseg); |
1214 | data->mds_ops->rpc_release(data); | 1218 | hdr->mds_ops->rpc_release(data); |
1215 | } | 1219 | } |
1216 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); | 1220 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); |
1217 | 1221 | ||
@@ -1219,12 +1223,14 @@ static void | |||
1219 | pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, | 1223 | pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, |
1220 | struct nfs_write_data *data) | 1224 | struct nfs_write_data *data) |
1221 | { | 1225 | { |
1222 | list_splice_tail_init(&data->pages, &desc->pg_list); | 1226 | struct nfs_pgio_header *hdr = data->header; |
1223 | if (data->req && list_empty(&data->req->wb_list)) | 1227 | |
1224 | nfs_list_add_request(data->req, &desc->pg_list); | 1228 | list_splice_tail_init(&hdr->pages, &desc->pg_list); |
1229 | if (hdr->req && list_empty(&hdr->req->wb_list)) | ||
1230 | nfs_list_add_request(hdr->req, &desc->pg_list); | ||
1225 | nfs_pageio_reset_write_mds(desc); | 1231 | nfs_pageio_reset_write_mds(desc); |
1226 | desc->pg_recoalesce = 1; | 1232 | desc->pg_recoalesce = 1; |
1227 | put_lseg(data->lseg); | 1233 | put_lseg(hdr->lseg); |
1228 | nfs_writedata_release(data); | 1234 | nfs_writedata_release(data); |
1229 | } | 1235 | } |
1230 | 1236 | ||
@@ -1234,20 +1240,21 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata, | |||
1234 | struct pnfs_layout_segment *lseg, | 1240 | struct pnfs_layout_segment *lseg, |
1235 | int how) | 1241 | int how) |
1236 | { | 1242 | { |
1237 | struct inode *inode = wdata->inode; | 1243 | struct nfs_pgio_header *hdr = wdata->header; |
1244 | struct inode *inode = hdr->inode; | ||
1238 | enum pnfs_try_status trypnfs; | 1245 | enum pnfs_try_status trypnfs; |
1239 | struct nfs_server *nfss = NFS_SERVER(inode); | 1246 | struct nfs_server *nfss = NFS_SERVER(inode); |
1240 | 1247 | ||
1241 | wdata->mds_ops = call_ops; | 1248 | hdr->mds_ops = call_ops; |
1242 | wdata->lseg = get_lseg(lseg); | 1249 | hdr->lseg = get_lseg(lseg); |
1243 | 1250 | ||
1244 | dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__, | 1251 | dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__, |
1245 | inode->i_ino, wdata->args.count, wdata->args.offset, how); | 1252 | inode->i_ino, wdata->args.count, wdata->args.offset, how); |
1246 | 1253 | ||
1247 | trypnfs = nfss->pnfs_curr_ld->write_pagelist(wdata, how); | 1254 | trypnfs = nfss->pnfs_curr_ld->write_pagelist(wdata, how); |
1248 | if (trypnfs == PNFS_NOT_ATTEMPTED) { | 1255 | if (trypnfs == PNFS_NOT_ATTEMPTED) { |
1249 | put_lseg(wdata->lseg); | 1256 | put_lseg(hdr->lseg); |
1250 | wdata->lseg = NULL; | 1257 | hdr->lseg = NULL; |
1251 | } else | 1258 | } else |
1252 | nfs_inc_stats(inode, NFSIOS_PNFS_WRITE); | 1259 | nfs_inc_stats(inode, NFSIOS_PNFS_WRITE); |
1253 | 1260 | ||
@@ -1318,13 +1325,15 @@ static int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *h | |||
1318 | 1325 | ||
1319 | static void pnfs_ld_handle_read_error(struct nfs_read_data *data) | 1326 | static void pnfs_ld_handle_read_error(struct nfs_read_data *data) |
1320 | { | 1327 | { |
1321 | dprintk("pnfs read error = %d\n", data->pnfs_error); | 1328 | struct nfs_pgio_header *hdr = data->header; |
1322 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | 1329 | |
1330 | dprintk("pnfs read error = %d\n", hdr->pnfs_error); | ||
1331 | if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & | ||
1323 | PNFS_LAYOUTRET_ON_ERROR) { | 1332 | PNFS_LAYOUTRET_ON_ERROR) { |
1324 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags); | 1333 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags); |
1325 | pnfs_return_layout(data->inode); | 1334 | pnfs_return_layout(hdr->inode); |
1326 | } | 1335 | } |
1327 | data->task.tk_status = pnfs_read_done_resend_to_mds(data->inode, &data->pages); | 1336 | data->task.tk_status = pnfs_read_done_resend_to_mds(hdr->inode, &hdr->pages); |
1328 | } | 1337 | } |
1329 | 1338 | ||
1330 | /* | 1339 | /* |
@@ -1332,13 +1341,15 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data) | |||
1332 | */ | 1341 | */ |
1333 | void pnfs_ld_read_done(struct nfs_read_data *data) | 1342 | void pnfs_ld_read_done(struct nfs_read_data *data) |
1334 | { | 1343 | { |
1335 | if (likely(!data->pnfs_error)) { | 1344 | struct nfs_pgio_header *hdr = data->header; |
1345 | |||
1346 | if (likely(!hdr->pnfs_error)) { | ||
1336 | __nfs4_read_done_cb(data); | 1347 | __nfs4_read_done_cb(data); |
1337 | data->mds_ops->rpc_call_done(&data->task, data); | 1348 | hdr->mds_ops->rpc_call_done(&data->task, data); |
1338 | } else | 1349 | } else |
1339 | pnfs_ld_handle_read_error(data); | 1350 | pnfs_ld_handle_read_error(data); |
1340 | put_lseg(data->lseg); | 1351 | put_lseg(hdr->lseg); |
1341 | data->mds_ops->rpc_release(data); | 1352 | hdr->mds_ops->rpc_release(data); |
1342 | } | 1353 | } |
1343 | EXPORT_SYMBOL_GPL(pnfs_ld_read_done); | 1354 | EXPORT_SYMBOL_GPL(pnfs_ld_read_done); |
1344 | 1355 | ||
@@ -1346,9 +1357,11 @@ static void | |||
1346 | pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, | 1357 | pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, |
1347 | struct nfs_read_data *data) | 1358 | struct nfs_read_data *data) |
1348 | { | 1359 | { |
1349 | list_splice_tail_init(&data->pages, &desc->pg_list); | 1360 | struct nfs_pgio_header *hdr = data->header; |
1350 | if (data->req && list_empty(&data->req->wb_list)) | 1361 | |
1351 | nfs_list_add_request(data->req, &desc->pg_list); | 1362 | list_splice_tail_init(&hdr->pages, &desc->pg_list); |
1363 | if (hdr->req && list_empty(&hdr->req->wb_list)) | ||
1364 | nfs_list_add_request(hdr->req, &desc->pg_list); | ||
1352 | nfs_pageio_reset_read_mds(desc); | 1365 | nfs_pageio_reset_read_mds(desc); |
1353 | desc->pg_recoalesce = 1; | 1366 | desc->pg_recoalesce = 1; |
1354 | nfs_readdata_release(data); | 1367 | nfs_readdata_release(data); |
@@ -1362,20 +1375,21 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata, | |||
1362 | const struct rpc_call_ops *call_ops, | 1375 | const struct rpc_call_ops *call_ops, |
1363 | struct pnfs_layout_segment *lseg) | 1376 | struct pnfs_layout_segment *lseg) |
1364 | { | 1377 | { |
1365 | struct inode *inode = rdata->inode; | 1378 | struct nfs_pgio_header *hdr = rdata->header; |
1379 | struct inode *inode = hdr->inode; | ||
1366 | struct nfs_server *nfss = NFS_SERVER(inode); | 1380 | struct nfs_server *nfss = NFS_SERVER(inode); |
1367 | enum pnfs_try_status trypnfs; | 1381 | enum pnfs_try_status trypnfs; |
1368 | 1382 | ||
1369 | rdata->mds_ops = call_ops; | 1383 | hdr->mds_ops = call_ops; |
1370 | rdata->lseg = get_lseg(lseg); | 1384 | hdr->lseg = get_lseg(lseg); |
1371 | 1385 | ||
1372 | dprintk("%s: Reading ino:%lu %u@%llu\n", | 1386 | dprintk("%s: Reading ino:%lu %u@%llu\n", |
1373 | __func__, inode->i_ino, rdata->args.count, rdata->args.offset); | 1387 | __func__, inode->i_ino, rdata->args.count, rdata->args.offset); |
1374 | 1388 | ||
1375 | trypnfs = nfss->pnfs_curr_ld->read_pagelist(rdata); | 1389 | trypnfs = nfss->pnfs_curr_ld->read_pagelist(rdata); |
1376 | if (trypnfs == PNFS_NOT_ATTEMPTED) { | 1390 | if (trypnfs == PNFS_NOT_ATTEMPTED) { |
1377 | put_lseg(rdata->lseg); | 1391 | put_lseg(hdr->lseg); |
1378 | rdata->lseg = NULL; | 1392 | hdr->lseg = NULL; |
1379 | } else { | 1393 | } else { |
1380 | nfs_inc_stats(inode, NFSIOS_PNFS_READ); | 1394 | nfs_inc_stats(inode, NFSIOS_PNFS_READ); |
1381 | } | 1395 | } |
@@ -1450,30 +1464,32 @@ EXPORT_SYMBOL_GPL(pnfs_set_lo_fail); | |||
1450 | void | 1464 | void |
1451 | pnfs_set_layoutcommit(struct nfs_write_data *wdata) | 1465 | pnfs_set_layoutcommit(struct nfs_write_data *wdata) |
1452 | { | 1466 | { |
1453 | struct nfs_inode *nfsi = NFS_I(wdata->inode); | 1467 | struct nfs_pgio_header *hdr = wdata->header; |
1468 | struct inode *inode = hdr->inode; | ||
1469 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1454 | loff_t end_pos = wdata->mds_offset + wdata->res.count; | 1470 | loff_t end_pos = wdata->mds_offset + wdata->res.count; |
1455 | bool mark_as_dirty = false; | 1471 | bool mark_as_dirty = false; |
1456 | 1472 | ||
1457 | spin_lock(&nfsi->vfs_inode.i_lock); | 1473 | spin_lock(&inode->i_lock); |
1458 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1474 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
1459 | mark_as_dirty = true; | 1475 | mark_as_dirty = true; |
1460 | dprintk("%s: Set layoutcommit for inode %lu ", | 1476 | dprintk("%s: Set layoutcommit for inode %lu ", |
1461 | __func__, wdata->inode->i_ino); | 1477 | __func__, inode->i_ino); |
1462 | } | 1478 | } |
1463 | if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &wdata->lseg->pls_flags)) { | 1479 | if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &hdr->lseg->pls_flags)) { |
1464 | /* references matched in nfs4_layoutcommit_release */ | 1480 | /* references matched in nfs4_layoutcommit_release */ |
1465 | get_lseg(wdata->lseg); | 1481 | get_lseg(hdr->lseg); |
1466 | } | 1482 | } |
1467 | if (end_pos > nfsi->layout->plh_lwb) | 1483 | if (end_pos > nfsi->layout->plh_lwb) |
1468 | nfsi->layout->plh_lwb = end_pos; | 1484 | nfsi->layout->plh_lwb = end_pos; |
1469 | spin_unlock(&nfsi->vfs_inode.i_lock); | 1485 | spin_unlock(&inode->i_lock); |
1470 | dprintk("%s: lseg %p end_pos %llu\n", | 1486 | dprintk("%s: lseg %p end_pos %llu\n", |
1471 | __func__, wdata->lseg, nfsi->layout->plh_lwb); | 1487 | __func__, hdr->lseg, nfsi->layout->plh_lwb); |
1472 | 1488 | ||
1473 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one | 1489 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one |
1474 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ | 1490 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ |
1475 | if (mark_as_dirty) | 1491 | if (mark_as_dirty) |
1476 | mark_inode_dirty_sync(wdata->inode); | 1492 | mark_inode_dirty_sync(inode); |
1477 | } | 1493 | } |
1478 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | 1494 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); |
1479 | 1495 | ||
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index bf80503200f5..22ee70586875 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -641,12 +641,14 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
641 | 641 | ||
642 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) | 642 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) |
643 | { | 643 | { |
644 | struct inode *inode = data->header->inode; | ||
645 | |||
644 | if (nfs_async_handle_expired_key(task)) | 646 | if (nfs_async_handle_expired_key(task)) |
645 | return -EAGAIN; | 647 | return -EAGAIN; |
646 | 648 | ||
647 | nfs_invalidate_atime(data->inode); | 649 | nfs_invalidate_atime(inode); |
648 | if (task->tk_status >= 0) { | 650 | if (task->tk_status >= 0) { |
649 | nfs_refresh_inode(data->inode, data->res.fattr); | 651 | nfs_refresh_inode(inode, data->res.fattr); |
650 | /* Emulate the eof flag, which isn't normally needed in NFSv2 | 652 | /* Emulate the eof flag, which isn't normally needed in NFSv2 |
651 | * as it is guaranteed to always return the file attributes | 653 | * as it is guaranteed to always return the file attributes |
652 | */ | 654 | */ |
@@ -668,11 +670,13 @@ static void nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_dat | |||
668 | 670 | ||
669 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 671 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) |
670 | { | 672 | { |
673 | struct inode *inode = data->header->inode; | ||
674 | |||
671 | if (nfs_async_handle_expired_key(task)) | 675 | if (nfs_async_handle_expired_key(task)) |
672 | return -EAGAIN; | 676 | return -EAGAIN; |
673 | 677 | ||
674 | if (task->tk_status >= 0) | 678 | if (task->tk_status >= 0) |
675 | nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); | 679 | nfs_post_op_update_inode_force_wcc(inode, data->res.fattr); |
676 | return 0; | 680 | return 0; |
677 | } | 681 | } |
678 | 682 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 4ddba6706347..d6d46823d9e4 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -35,19 +35,24 @@ static const struct rpc_call_ops nfs_read_full_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(unsigned int pagecount) |
39 | { | 39 | { |
40 | struct nfs_read_data *p; | 40 | struct nfs_read_header *p; |
41 | 41 | ||
42 | p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); | 42 | p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); |
43 | if (p) { | 43 | if (p) { |
44 | INIT_LIST_HEAD(&p->pages); | 44 | struct nfs_pgio_header *hdr = &p->header; |
45 | p->npages = pagecount; | 45 | struct nfs_read_data *data = &p->rpc_data; |
46 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 46 | |
47 | p->pagevec = p->page_array; | 47 | INIT_LIST_HEAD(&hdr->pages); |
48 | INIT_LIST_HEAD(&data->list); | ||
49 | data->npages = pagecount; | ||
50 | data->header = hdr; | ||
51 | if (pagecount <= ARRAY_SIZE(data->page_array)) | ||
52 | data->pagevec = data->page_array; | ||
48 | else { | 53 | else { |
49 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); | 54 | data->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); |
50 | if (!p->pagevec) { | 55 | if (!data->pagevec) { |
51 | kmem_cache_free(nfs_rdata_cachep, p); | 56 | kmem_cache_free(nfs_rdata_cachep, p); |
52 | p = NULL; | 57 | p = NULL; |
53 | } | 58 | } |
@@ -56,17 +61,19 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | |||
56 | return p; | 61 | return p; |
57 | } | 62 | } |
58 | 63 | ||
59 | void nfs_readdata_free(struct nfs_read_data *p) | 64 | void nfs_readhdr_free(struct nfs_pgio_header *hdr) |
60 | { | 65 | { |
61 | if (p && (p->pagevec != &p->page_array[0])) | 66 | struct nfs_read_header *rhdr = container_of(hdr, struct nfs_read_header, header); |
62 | kfree(p->pagevec); | 67 | |
63 | kmem_cache_free(nfs_rdata_cachep, p); | 68 | kmem_cache_free(nfs_rdata_cachep, rhdr); |
64 | } | 69 | } |
65 | 70 | ||
66 | void nfs_readdata_release(struct nfs_read_data *rdata) | 71 | void nfs_readdata_release(struct nfs_read_data *rdata) |
67 | { | 72 | { |
68 | put_nfs_open_context(rdata->args.context); | 73 | put_nfs_open_context(rdata->args.context); |
69 | nfs_readdata_free(rdata); | 74 | if (rdata->pagevec != rdata->page_array) |
75 | kfree(rdata->pagevec); | ||
76 | nfs_readhdr_free(rdata->header); | ||
70 | } | 77 | } |
71 | 78 | ||
72 | static | 79 | static |
@@ -173,13 +180,13 @@ int nfs_initiate_read(struct rpc_clnt *clnt, | |||
173 | struct nfs_read_data *data, | 180 | struct nfs_read_data *data, |
174 | const struct rpc_call_ops *call_ops) | 181 | const struct rpc_call_ops *call_ops) |
175 | { | 182 | { |
176 | struct inode *inode = data->inode; | 183 | struct inode *inode = data->header->inode; |
177 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; | 184 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; |
178 | struct rpc_task *task; | 185 | struct rpc_task *task; |
179 | struct rpc_message msg = { | 186 | struct rpc_message msg = { |
180 | .rpc_argp = &data->args, | 187 | .rpc_argp = &data->args, |
181 | .rpc_resp = &data->res, | 188 | .rpc_resp = &data->res, |
182 | .rpc_cred = data->cred, | 189 | .rpc_cred = data->header->cred, |
183 | }; | 190 | }; |
184 | struct rpc_task_setup task_setup_data = { | 191 | struct rpc_task_setup task_setup_data = { |
185 | .task = &data->task, | 192 | .task = &data->task, |
@@ -216,11 +223,11 @@ EXPORT_SYMBOL_GPL(nfs_initiate_read); | |||
216 | static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | 223 | static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, |
217 | unsigned int count, unsigned int offset) | 224 | unsigned int count, unsigned int offset) |
218 | { | 225 | { |
219 | struct inode *inode = req->wb_context->dentry->d_inode; | 226 | struct inode *inode = data->header->inode; |
220 | 227 | ||
221 | data->req = req; | 228 | data->header->req = req; |
222 | data->inode = inode; | 229 | data->header->inode = inode; |
223 | data->cred = req->wb_context->cred; | 230 | data->header->cred = req->wb_context->cred; |
224 | 231 | ||
225 | data->args.fh = NFS_FH(inode); | 232 | data->args.fh = NFS_FH(inode); |
226 | data->args.offset = req_offset(req) + offset; | 233 | data->args.offset = req_offset(req) + offset; |
@@ -239,7 +246,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
239 | static int nfs_do_read(struct nfs_read_data *data, | 246 | static int nfs_do_read(struct nfs_read_data *data, |
240 | const struct rpc_call_ops *call_ops) | 247 | const struct rpc_call_ops *call_ops) |
241 | { | 248 | { |
242 | struct inode *inode = data->args.context->dentry->d_inode; | 249 | struct inode *inode = data->header->inode; |
243 | 250 | ||
244 | return nfs_initiate_read(NFS_CLIENT(inode), data, call_ops); | 251 | return nfs_initiate_read(NFS_CLIENT(inode), data, call_ops); |
245 | } | 252 | } |
@@ -293,6 +300,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, struct list_head | |||
293 | { | 300 | { |
294 | struct nfs_page *req = nfs_list_entry(desc->pg_list.next); | 301 | struct nfs_page *req = nfs_list_entry(desc->pg_list.next); |
295 | struct page *page = req->wb_page; | 302 | struct page *page = req->wb_page; |
303 | struct nfs_read_header *rhdr; | ||
296 | struct nfs_read_data *data; | 304 | struct nfs_read_data *data; |
297 | size_t rsize = desc->pg_bsize, nbytes; | 305 | size_t rsize = desc->pg_bsize, nbytes; |
298 | unsigned int offset; | 306 | unsigned int offset; |
@@ -306,9 +314,10 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, struct list_head | |||
306 | do { | 314 | do { |
307 | size_t len = min(nbytes,rsize); | 315 | size_t len = min(nbytes,rsize); |
308 | 316 | ||
309 | data = nfs_readdata_alloc(1); | 317 | rhdr = nfs_readhdr_alloc(1); |
310 | if (!data) | 318 | if (!rhdr) |
311 | goto out_bad; | 319 | goto out_bad; |
320 | data = &rhdr->rpc_data; | ||
312 | data->pagevec[0] = page; | 321 | data->pagevec[0] = page; |
313 | nfs_read_rpcsetup(req, data, len, offset); | 322 | nfs_read_rpcsetup(req, data, len, offset); |
314 | list_add(&data->list, res); | 323 | list_add(&data->list, res); |
@@ -333,26 +342,28 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, struct list_head * | |||
333 | { | 342 | { |
334 | struct nfs_page *req; | 343 | struct nfs_page *req; |
335 | struct page **pages; | 344 | struct page **pages; |
345 | struct nfs_read_header *rhdr; | ||
336 | struct nfs_read_data *data; | 346 | struct nfs_read_data *data; |
337 | struct list_head *head = &desc->pg_list; | 347 | struct list_head *head = &desc->pg_list; |
338 | int ret = 0; | 348 | int ret = 0; |
339 | 349 | ||
340 | data = nfs_readdata_alloc(nfs_page_array_len(desc->pg_base, | 350 | rhdr = nfs_readhdr_alloc(nfs_page_array_len(desc->pg_base, |
341 | desc->pg_count)); | 351 | desc->pg_count)); |
342 | if (!data) { | 352 | if (!rhdr) { |
343 | nfs_async_read_error(head); | 353 | nfs_async_read_error(head); |
344 | ret = -ENOMEM; | 354 | ret = -ENOMEM; |
345 | goto out; | 355 | goto out; |
346 | } | 356 | } |
347 | 357 | ||
358 | data = &rhdr->rpc_data; | ||
348 | pages = data->pagevec; | 359 | pages = data->pagevec; |
349 | while (!list_empty(head)) { | 360 | while (!list_empty(head)) { |
350 | req = nfs_list_entry(head->next); | 361 | req = nfs_list_entry(head->next); |
351 | nfs_list_remove_request(req); | 362 | nfs_list_remove_request(req); |
352 | nfs_list_add_request(req, &data->pages); | 363 | nfs_list_add_request(req, &rhdr->header.pages); |
353 | *pages++ = req->wb_page; | 364 | *pages++ = req->wb_page; |
354 | } | 365 | } |
355 | req = nfs_list_entry(data->pages.next); | 366 | req = nfs_list_entry(rhdr->header.pages.next); |
356 | 367 | ||
357 | nfs_read_rpcsetup(req, data, desc->pg_count, 0); | 368 | nfs_read_rpcsetup(req, data, desc->pg_count, 0); |
358 | list_add(&data->list, res); | 369 | list_add(&data->list, res); |
@@ -390,20 +401,21 @@ static const struct nfs_pageio_ops nfs_pageio_read_ops = { | |||
390 | */ | 401 | */ |
391 | int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | 402 | int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) |
392 | { | 403 | { |
404 | struct inode *inode = data->header->inode; | ||
393 | int status; | 405 | int status; |
394 | 406 | ||
395 | dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid, | 407 | dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid, |
396 | task->tk_status); | 408 | task->tk_status); |
397 | 409 | ||
398 | status = NFS_PROTO(data->inode)->read_done(task, data); | 410 | status = NFS_PROTO(inode)->read_done(task, data); |
399 | if (status != 0) | 411 | if (status != 0) |
400 | return status; | 412 | return status; |
401 | 413 | ||
402 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); | 414 | nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, data->res.count); |
403 | 415 | ||
404 | if (task->tk_status == -ESTALE) { | 416 | if (task->tk_status == -ESTALE) { |
405 | set_bit(NFS_INO_STALE, &NFS_I(data->inode)->flags); | 417 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
406 | nfs_mark_for_revalidate(data->inode); | 418 | nfs_mark_for_revalidate(inode); |
407 | } | 419 | } |
408 | return 0; | 420 | return 0; |
409 | } | 421 | } |
@@ -417,7 +429,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data | |||
417 | return; | 429 | return; |
418 | 430 | ||
419 | /* This is a short read! */ | 431 | /* This is a short read! */ |
420 | nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); | 432 | nfs_inc_stats(data->header->inode, NFSIOS_SHORTREAD); |
421 | /* Has the server at least made some progress? */ | 433 | /* Has the server at least made some progress? */ |
422 | if (resp->count == 0) | 434 | if (resp->count == 0) |
423 | return; | 435 | return; |
@@ -449,7 +461,7 @@ static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata) | |||
449 | static void nfs_readpage_release_partial(void *calldata) | 461 | static void nfs_readpage_release_partial(void *calldata) |
450 | { | 462 | { |
451 | struct nfs_read_data *data = calldata; | 463 | struct nfs_read_data *data = calldata; |
452 | struct nfs_page *req = data->req; | 464 | struct nfs_page *req = data->header->req; |
453 | struct page *page = req->wb_page; | 465 | struct page *page = req->wb_page; |
454 | int status = data->task.tk_status; | 466 | int status = data->task.tk_status; |
455 | 467 | ||
@@ -461,13 +473,13 @@ static void nfs_readpage_release_partial(void *calldata) | |||
461 | SetPageUptodate(page); | 473 | SetPageUptodate(page); |
462 | nfs_readpage_release(req); | 474 | nfs_readpage_release(req); |
463 | } | 475 | } |
464 | nfs_readdata_release(calldata); | 476 | nfs_readdata_release(data); |
465 | } | 477 | } |
466 | 478 | ||
467 | void nfs_read_prepare(struct rpc_task *task, void *calldata) | 479 | void nfs_read_prepare(struct rpc_task *task, void *calldata) |
468 | { | 480 | { |
469 | struct nfs_read_data *data = calldata; | 481 | struct nfs_read_data *data = calldata; |
470 | NFS_PROTO(data->inode)->read_rpc_prepare(task, data); | 482 | NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data); |
471 | } | 483 | } |
472 | 484 | ||
473 | static const struct rpc_call_ops nfs_read_partial_ops = { | 485 | static const struct rpc_call_ops nfs_read_partial_ops = { |
@@ -524,9 +536,10 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata) | |||
524 | static void nfs_readpage_release_full(void *calldata) | 536 | static void nfs_readpage_release_full(void *calldata) |
525 | { | 537 | { |
526 | struct nfs_read_data *data = calldata; | 538 | struct nfs_read_data *data = calldata; |
539 | struct nfs_pgio_header *hdr = data->header; | ||
527 | 540 | ||
528 | while (!list_empty(&data->pages)) { | 541 | while (!list_empty(&hdr->pages)) { |
529 | struct nfs_page *req = nfs_list_entry(data->pages.next); | 542 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); |
530 | 543 | ||
531 | nfs_list_remove_request(req); | 544 | nfs_list_remove_request(req); |
532 | nfs_readpage_release(req); | 545 | nfs_readpage_release(req); |
@@ -685,7 +698,7 @@ out: | |||
685 | int __init nfs_init_readpagecache(void) | 698 | int __init nfs_init_readpagecache(void) |
686 | { | 699 | { |
687 | nfs_rdata_cachep = kmem_cache_create("nfs_read_data", | 700 | nfs_rdata_cachep = kmem_cache_create("nfs_read_data", |
688 | sizeof(struct nfs_read_data), | 701 | sizeof(struct nfs_read_header), |
689 | 0, SLAB_HWCACHE_ALIGN, | 702 | 0, SLAB_HWCACHE_ALIGN, |
690 | NULL); | 703 | NULL); |
691 | if (nfs_rdata_cachep == NULL) | 704 | if (nfs_rdata_cachep == NULL) |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 76735dd8c9a7..dbb5c0a613b8 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -69,19 +69,24 @@ void nfs_commit_free(struct nfs_commit_data *p) | |||
69 | } | 69 | } |
70 | EXPORT_SYMBOL_GPL(nfs_commit_free); | 70 | EXPORT_SYMBOL_GPL(nfs_commit_free); |
71 | 71 | ||
72 | struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | 72 | struct nfs_write_header *nfs_writehdr_alloc(unsigned int pagecount) |
73 | { | 73 | { |
74 | struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS); | 74 | struct nfs_write_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS); |
75 | 75 | ||
76 | if (p) { | 76 | if (p) { |
77 | struct nfs_pgio_header *hdr = &p->header; | ||
78 | struct nfs_write_data *data = &p->rpc_data; | ||
79 | |||
77 | memset(p, 0, sizeof(*p)); | 80 | memset(p, 0, sizeof(*p)); |
78 | INIT_LIST_HEAD(&p->pages); | 81 | INIT_LIST_HEAD(&hdr->pages); |
79 | p->npages = pagecount; | 82 | INIT_LIST_HEAD(&data->list); |
80 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 83 | data->npages = pagecount; |
81 | p->pagevec = p->page_array; | 84 | data->header = hdr; |
85 | if (pagecount <= ARRAY_SIZE(data->page_array)) | ||
86 | data->pagevec = data->page_array; | ||
82 | else { | 87 | else { |
83 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); | 88 | data->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); |
84 | if (!p->pagevec) { | 89 | if (!data->pagevec) { |
85 | mempool_free(p, nfs_wdata_mempool); | 90 | mempool_free(p, nfs_wdata_mempool); |
86 | p = NULL; | 91 | p = NULL; |
87 | } | 92 | } |
@@ -90,17 +95,18 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | |||
90 | return p; | 95 | return p; |
91 | } | 96 | } |
92 | 97 | ||
93 | void nfs_writedata_free(struct nfs_write_data *p) | 98 | void nfs_writehdr_free(struct nfs_pgio_header *hdr) |
94 | { | 99 | { |
95 | if (p && (p->pagevec != &p->page_array[0])) | 100 | struct nfs_write_header *whdr = container_of(hdr, struct nfs_write_header, header); |
96 | kfree(p->pagevec); | 101 | mempool_free(whdr, nfs_wdata_mempool); |
97 | mempool_free(p, nfs_wdata_mempool); | ||
98 | } | 102 | } |
99 | 103 | ||
100 | void nfs_writedata_release(struct nfs_write_data *wdata) | 104 | void nfs_writedata_release(struct nfs_write_data *wdata) |
101 | { | 105 | { |
102 | put_nfs_open_context(wdata->args.context); | 106 | put_nfs_open_context(wdata->args.context); |
103 | nfs_writedata_free(wdata); | 107 | if (wdata->pagevec != wdata->page_array) |
108 | kfree(wdata->pagevec); | ||
109 | nfs_writehdr_free(wdata->header); | ||
104 | } | 110 | } |
105 | 111 | ||
106 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | 112 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) |
@@ -507,9 +513,8 @@ static inline | |||
507 | int nfs_write_need_commit(struct nfs_write_data *data) | 513 | int nfs_write_need_commit(struct nfs_write_data *data) |
508 | { | 514 | { |
509 | if (data->verf.committed == NFS_DATA_SYNC) | 515 | if (data->verf.committed == NFS_DATA_SYNC) |
510 | return data->lseg == NULL; | 516 | return data->header->lseg == NULL; |
511 | else | 517 | return data->verf.committed != NFS_FILE_SYNC; |
512 | return data->verf.committed != NFS_FILE_SYNC; | ||
513 | } | 518 | } |
514 | 519 | ||
515 | static inline | 520 | static inline |
@@ -517,7 +522,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req, | |||
517 | struct nfs_write_data *data) | 522 | struct nfs_write_data *data) |
518 | { | 523 | { |
519 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 524 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
520 | nfs_mark_request_commit(req, data->lseg); | 525 | nfs_mark_request_commit(req, data->header->lseg); |
521 | return 1; | 526 | return 1; |
522 | } | 527 | } |
523 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { | 528 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
@@ -841,13 +846,13 @@ int nfs_initiate_write(struct rpc_clnt *clnt, | |||
841 | const struct rpc_call_ops *call_ops, | 846 | const struct rpc_call_ops *call_ops, |
842 | int how) | 847 | int how) |
843 | { | 848 | { |
844 | struct inode *inode = data->inode; | 849 | struct inode *inode = data->header->inode; |
845 | int priority = flush_task_priority(how); | 850 | int priority = flush_task_priority(how); |
846 | struct rpc_task *task; | 851 | struct rpc_task *task; |
847 | struct rpc_message msg = { | 852 | struct rpc_message msg = { |
848 | .rpc_argp = &data->args, | 853 | .rpc_argp = &data->args, |
849 | .rpc_resp = &data->res, | 854 | .rpc_resp = &data->res, |
850 | .rpc_cred = data->cred, | 855 | .rpc_cred = data->header->cred, |
851 | }; | 856 | }; |
852 | struct rpc_task_setup task_setup_data = { | 857 | struct rpc_task_setup task_setup_data = { |
853 | .rpc_client = clnt, | 858 | .rpc_client = clnt, |
@@ -896,14 +901,15 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
896 | unsigned int count, unsigned int offset, | 901 | unsigned int count, unsigned int offset, |
897 | int how) | 902 | int how) |
898 | { | 903 | { |
904 | struct nfs_pgio_header *hdr = data->header; | ||
899 | struct inode *inode = req->wb_context->dentry->d_inode; | 905 | struct inode *inode = req->wb_context->dentry->d_inode; |
900 | 906 | ||
901 | /* Set up the RPC argument and reply structs | 907 | /* Set up the RPC argument and reply structs |
902 | * NB: take care not to mess about with data->commit et al. */ | 908 | * NB: take care not to mess about with data->commit et al. */ |
903 | 909 | ||
904 | data->req = req; | 910 | hdr->req = req; |
905 | data->inode = inode = req->wb_context->dentry->d_inode; | 911 | hdr->inode = inode = req->wb_context->dentry->d_inode; |
906 | data->cred = req->wb_context->cred; | 912 | hdr->cred = req->wb_context->cred; |
907 | 913 | ||
908 | data->args.fh = NFS_FH(inode); | 914 | data->args.fh = NFS_FH(inode); |
909 | data->args.offset = req_offset(req) + offset; | 915 | data->args.offset = req_offset(req) + offset; |
@@ -935,7 +941,7 @@ static int nfs_do_write(struct nfs_write_data *data, | |||
935 | const struct rpc_call_ops *call_ops, | 941 | const struct rpc_call_ops *call_ops, |
936 | int how) | 942 | int how) |
937 | { | 943 | { |
938 | struct inode *inode = data->args.context->dentry->d_inode; | 944 | struct inode *inode = data->header->inode; |
939 | 945 | ||
940 | return nfs_initiate_write(NFS_CLIENT(inode), data, call_ops, how); | 946 | return nfs_initiate_write(NFS_CLIENT(inode), data, call_ops, how); |
941 | } | 947 | } |
@@ -981,6 +987,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head | |||
981 | { | 987 | { |
982 | struct nfs_page *req = nfs_list_entry(desc->pg_list.next); | 988 | struct nfs_page *req = nfs_list_entry(desc->pg_list.next); |
983 | struct page *page = req->wb_page; | 989 | struct page *page = req->wb_page; |
990 | struct nfs_write_header *whdr; | ||
984 | struct nfs_write_data *data; | 991 | struct nfs_write_data *data; |
985 | size_t wsize = desc->pg_bsize, nbytes; | 992 | size_t wsize = desc->pg_bsize, nbytes; |
986 | unsigned int offset; | 993 | unsigned int offset; |
@@ -1000,9 +1007,10 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head | |||
1000 | do { | 1007 | do { |
1001 | size_t len = min(nbytes, wsize); | 1008 | size_t len = min(nbytes, wsize); |
1002 | 1009 | ||
1003 | data = nfs_writedata_alloc(1); | 1010 | whdr = nfs_writehdr_alloc(1); |
1004 | if (!data) | 1011 | if (!whdr) |
1005 | goto out_bad; | 1012 | goto out_bad; |
1013 | data = &whdr->rpc_data; | ||
1006 | data->pagevec[0] = page; | 1014 | data->pagevec[0] = page; |
1007 | nfs_write_rpcsetup(req, data, len, offset, desc->pg_ioflags); | 1015 | nfs_write_rpcsetup(req, data, len, offset, desc->pg_ioflags); |
1008 | list_add(&data->list, res); | 1016 | list_add(&data->list, res); |
@@ -1036,13 +1044,14 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *r | |||
1036 | { | 1044 | { |
1037 | struct nfs_page *req; | 1045 | struct nfs_page *req; |
1038 | struct page **pages; | 1046 | struct page **pages; |
1047 | struct nfs_write_header *whdr; | ||
1039 | struct nfs_write_data *data; | 1048 | struct nfs_write_data *data; |
1040 | struct list_head *head = &desc->pg_list; | 1049 | struct list_head *head = &desc->pg_list; |
1041 | int ret = 0; | 1050 | int ret = 0; |
1042 | 1051 | ||
1043 | data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base, | 1052 | whdr = nfs_writehdr_alloc(nfs_page_array_len(desc->pg_base, |
1044 | desc->pg_count)); | 1053 | desc->pg_count)); |
1045 | if (!data) { | 1054 | if (!whdr) { |
1046 | while (!list_empty(head)) { | 1055 | while (!list_empty(head)) { |
1047 | req = nfs_list_entry(head->next); | 1056 | req = nfs_list_entry(head->next); |
1048 | nfs_list_remove_request(req); | 1057 | nfs_list_remove_request(req); |
@@ -1051,14 +1060,15 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *r | |||
1051 | ret = -ENOMEM; | 1060 | ret = -ENOMEM; |
1052 | goto out; | 1061 | goto out; |
1053 | } | 1062 | } |
1063 | data = &whdr->rpc_data; | ||
1054 | pages = data->pagevec; | 1064 | pages = data->pagevec; |
1055 | while (!list_empty(head)) { | 1065 | while (!list_empty(head)) { |
1056 | req = nfs_list_entry(head->next); | 1066 | req = nfs_list_entry(head->next); |
1057 | nfs_list_remove_request(req); | 1067 | nfs_list_remove_request(req); |
1058 | nfs_list_add_request(req, &data->pages); | 1068 | nfs_list_add_request(req, &whdr->header.pages); |
1059 | *pages++ = req->wb_page; | 1069 | *pages++ = req->wb_page; |
1060 | } | 1070 | } |
1061 | req = nfs_list_entry(data->pages.next); | 1071 | req = nfs_list_entry(whdr->header.pages.next); |
1062 | 1072 | ||
1063 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 1073 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
1064 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | 1074 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) |
@@ -1126,10 +1136,11 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
1126 | 1136 | ||
1127 | dprintk("NFS: %5u write(%s/%lld %d@%lld)", | 1137 | dprintk("NFS: %5u write(%s/%lld %d@%lld)", |
1128 | task->tk_pid, | 1138 | task->tk_pid, |
1129 | data->req->wb_context->dentry->d_inode->i_sb->s_id, | 1139 | data->header->inode->i_sb->s_id, |
1130 | (long long) | 1140 | (long long) |
1131 | NFS_FILEID(data->req->wb_context->dentry->d_inode), | 1141 | NFS_FILEID(data->header->inode), |
1132 | data->req->wb_bytes, (long long)req_offset(data->req)); | 1142 | data->header->req->wb_bytes, |
1143 | (long long)req_offset(data->header->req)); | ||
1133 | 1144 | ||
1134 | nfs_writeback_done(task, data); | 1145 | nfs_writeback_done(task, data); |
1135 | } | 1146 | } |
@@ -1137,7 +1148,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
1137 | static void nfs_writeback_release_partial(void *calldata) | 1148 | static void nfs_writeback_release_partial(void *calldata) |
1138 | { | 1149 | { |
1139 | struct nfs_write_data *data = calldata; | 1150 | struct nfs_write_data *data = calldata; |
1140 | struct nfs_page *req = data->req; | 1151 | struct nfs_page *req = data->header->req; |
1141 | struct page *page = req->wb_page; | 1152 | struct page *page = req->wb_page; |
1142 | int status = data->task.tk_status; | 1153 | int status = data->task.tk_status; |
1143 | 1154 | ||
@@ -1169,13 +1180,13 @@ static void nfs_writeback_release_partial(void *calldata) | |||
1169 | out: | 1180 | out: |
1170 | if (atomic_dec_and_test(&req->wb_complete)) | 1181 | if (atomic_dec_and_test(&req->wb_complete)) |
1171 | nfs_writepage_release(req, data); | 1182 | nfs_writepage_release(req, data); |
1172 | nfs_writedata_release(calldata); | 1183 | nfs_writedata_release(data); |
1173 | } | 1184 | } |
1174 | 1185 | ||
1175 | void nfs_write_prepare(struct rpc_task *task, void *calldata) | 1186 | void nfs_write_prepare(struct rpc_task *task, void *calldata) |
1176 | { | 1187 | { |
1177 | struct nfs_write_data *data = calldata; | 1188 | struct nfs_write_data *data = calldata; |
1178 | NFS_PROTO(data->inode)->write_rpc_prepare(task, data); | 1189 | NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data); |
1179 | } | 1190 | } |
1180 | 1191 | ||
1181 | void nfs_commit_prepare(struct rpc_task *task, void *calldata) | 1192 | void nfs_commit_prepare(struct rpc_task *task, void *calldata) |
@@ -1208,11 +1219,12 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
1208 | static void nfs_writeback_release_full(void *calldata) | 1219 | static void nfs_writeback_release_full(void *calldata) |
1209 | { | 1220 | { |
1210 | struct nfs_write_data *data = calldata; | 1221 | struct nfs_write_data *data = calldata; |
1222 | struct nfs_pgio_header *hdr = data->header; | ||
1211 | int status = data->task.tk_status; | 1223 | int status = data->task.tk_status; |
1212 | 1224 | ||
1213 | /* Update attributes as result of writeback. */ | 1225 | /* Update attributes as result of writeback. */ |
1214 | while (!list_empty(&data->pages)) { | 1226 | while (!list_empty(&hdr->pages)) { |
1215 | struct nfs_page *req = nfs_list_entry(data->pages.next); | 1227 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); |
1216 | struct page *page = req->wb_page; | 1228 | struct page *page = req->wb_page; |
1217 | 1229 | ||
1218 | nfs_list_remove_request(req); | 1230 | nfs_list_remove_request(req); |
@@ -1233,7 +1245,7 @@ static void nfs_writeback_release_full(void *calldata) | |||
1233 | 1245 | ||
1234 | if (nfs_write_need_commit(data)) { | 1246 | if (nfs_write_need_commit(data)) { |
1235 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1247 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1236 | nfs_mark_request_commit(req, data->lseg); | 1248 | nfs_mark_request_commit(req, hdr->lseg); |
1237 | dprintk(" marked for commit\n"); | 1249 | dprintk(" marked for commit\n"); |
1238 | goto next; | 1250 | goto next; |
1239 | } | 1251 | } |
@@ -1244,7 +1256,7 @@ remove_request: | |||
1244 | nfs_unlock_request(req); | 1256 | nfs_unlock_request(req); |
1245 | nfs_end_page_writeback(page); | 1257 | nfs_end_page_writeback(page); |
1246 | } | 1258 | } |
1247 | nfs_writedata_release(calldata); | 1259 | nfs_writedata_release(data); |
1248 | } | 1260 | } |
1249 | 1261 | ||
1250 | static const struct rpc_call_ops nfs_write_full_ops = { | 1262 | static const struct rpc_call_ops nfs_write_full_ops = { |
@@ -1261,6 +1273,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1261 | { | 1273 | { |
1262 | struct nfs_writeargs *argp = &data->args; | 1274 | struct nfs_writeargs *argp = &data->args; |
1263 | struct nfs_writeres *resp = &data->res; | 1275 | struct nfs_writeres *resp = &data->res; |
1276 | struct inode *inode = data->header->inode; | ||
1264 | int status; | 1277 | int status; |
1265 | 1278 | ||
1266 | dprintk("NFS: %5u nfs_writeback_done (status %d)\n", | 1279 | dprintk("NFS: %5u nfs_writeback_done (status %d)\n", |
@@ -1273,10 +1286,10 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1273 | * another writer had changed the file, but some applications | 1286 | * another writer had changed the file, but some applications |
1274 | * depend on tighter cache coherency when writing. | 1287 | * depend on tighter cache coherency when writing. |
1275 | */ | 1288 | */ |
1276 | status = NFS_PROTO(data->inode)->write_done(task, data); | 1289 | status = NFS_PROTO(inode)->write_done(task, data); |
1277 | if (status != 0) | 1290 | if (status != 0) |
1278 | return; | 1291 | return; |
1279 | nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); | 1292 | nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, resp->count); |
1280 | 1293 | ||
1281 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1294 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1282 | if (resp->verf->committed < argp->stable && task->tk_status >= 0) { | 1295 | if (resp->verf->committed < argp->stable && task->tk_status >= 0) { |
@@ -1294,7 +1307,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1294 | if (time_before(complain, jiffies)) { | 1307 | if (time_before(complain, jiffies)) { |
1295 | dprintk("NFS: faulty NFS server %s:" | 1308 | dprintk("NFS: faulty NFS server %s:" |
1296 | " (committed = %d) != (stable = %d)\n", | 1309 | " (committed = %d) != (stable = %d)\n", |
1297 | NFS_SERVER(data->inode)->nfs_client->cl_hostname, | 1310 | NFS_SERVER(inode)->nfs_client->cl_hostname, |
1298 | resp->verf->committed, argp->stable); | 1311 | resp->verf->committed, argp->stable); |
1299 | complain = jiffies + 300 * HZ; | 1312 | complain = jiffies + 300 * HZ; |
1300 | } | 1313 | } |
@@ -1304,7 +1317,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1304 | if (task->tk_status >= 0 && resp->count < argp->count) { | 1317 | if (task->tk_status >= 0 && resp->count < argp->count) { |
1305 | static unsigned long complain; | 1318 | static unsigned long complain; |
1306 | 1319 | ||
1307 | nfs_inc_stats(data->inode, NFSIOS_SHORTWRITE); | 1320 | nfs_inc_stats(inode, NFSIOS_SHORTWRITE); |
1308 | 1321 | ||
1309 | /* Has the server at least made some progress? */ | 1322 | /* Has the server at least made some progress? */ |
1310 | if (resp->count != 0) { | 1323 | if (resp->count != 0) { |
@@ -1333,7 +1346,6 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1333 | /* Can't do anything about it except throw an error. */ | 1346 | /* Can't do anything about it except throw an error. */ |
1334 | task->tk_status = -EIO; | 1347 | task->tk_status = -EIO; |
1335 | } | 1348 | } |
1336 | return; | ||
1337 | } | 1349 | } |
1338 | 1350 | ||
1339 | 1351 | ||
@@ -1745,7 +1757,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | |||
1745 | int __init nfs_init_writepagecache(void) | 1757 | int __init nfs_init_writepagecache(void) |
1746 | { | 1758 | { |
1747 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", | 1759 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", |
1748 | sizeof(struct nfs_write_data), | 1760 | sizeof(struct nfs_write_header), |
1749 | 0, SLAB_HWCACHE_ALIGN, | 1761 | 0, SLAB_HWCACHE_ALIGN, |
1750 | NULL); | 1762 | NULL); |
1751 | if (nfs_wdata_cachep == NULL) | 1763 | if (nfs_wdata_cachep == NULL) |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index d5d68f322bf0..8d3a2b804201 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -569,12 +569,6 @@ nfs_have_writebacks(struct inode *inode) | |||
569 | } | 569 | } |
570 | 570 | ||
571 | /* | 571 | /* |
572 | * Allocate nfs_write_data structures | ||
573 | */ | ||
574 | extern struct nfs_write_data *nfs_writedata_alloc(unsigned int npages); | ||
575 | extern void nfs_writedata_free(struct nfs_write_data *); | ||
576 | |||
577 | /* | ||
578 | * linux/fs/nfs/read.c | 572 | * linux/fs/nfs/read.c |
579 | */ | 573 | */ |
580 | extern int nfs_readpage(struct file *, struct page *); | 574 | extern int nfs_readpage(struct file *, struct page *); |
@@ -585,12 +579,6 @@ extern int nfs_readpage_async(struct nfs_open_context *, struct inode *, | |||
585 | struct page *); | 579 | struct page *); |
586 | 580 | ||
587 | /* | 581 | /* |
588 | * Allocate nfs_read_data structures | ||
589 | */ | ||
590 | extern struct nfs_read_data *nfs_readdata_alloc(unsigned int npages); | ||
591 | extern void nfs_readdata_free(struct nfs_read_data *); | ||
592 | |||
593 | /* | ||
594 | * linux/fs/nfs3proc.c | 582 | * linux/fs/nfs3proc.c |
595 | */ | 583 | */ |
596 | #ifdef CONFIG_NFS_V3_ACL | 584 | #ifdef CONFIG_NFS_V3_ACL |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 8fb036a0d489..fee324175391 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1168,52 +1168,58 @@ struct nfs_page; | |||
1168 | #define NFS_PAGEVEC_SIZE (8U) | 1168 | #define NFS_PAGEVEC_SIZE (8U) |
1169 | 1169 | ||
1170 | struct nfs_read_data { | 1170 | struct nfs_read_data { |
1171 | struct nfs_pgio_header *header; | ||
1172 | struct list_head list; | ||
1171 | struct rpc_task task; | 1173 | struct rpc_task task; |
1172 | struct inode *inode; | ||
1173 | struct rpc_cred *cred; | ||
1174 | struct nfs_fattr fattr; /* fattr storage */ | 1174 | struct nfs_fattr fattr; /* fattr storage */ |
1175 | struct list_head pages; /* Coalesced read requests */ | ||
1176 | struct list_head list; /* lists of struct nfs_read_data */ | ||
1177 | struct nfs_page *req; /* multi ops per nfs_page */ | ||
1178 | struct page **pagevec; | 1175 | struct page **pagevec; |
1179 | unsigned int npages; /* Max length of pagevec */ | 1176 | unsigned int npages; /* Max length of pagevec */ |
1180 | struct nfs_readargs args; | 1177 | struct nfs_readargs args; |
1181 | struct nfs_readres res; | 1178 | struct nfs_readres res; |
1182 | unsigned long timestamp; /* For lease renewal */ | 1179 | unsigned long timestamp; /* For lease renewal */ |
1183 | struct pnfs_layout_segment *lseg; | ||
1184 | struct nfs_client *ds_clp; /* pNFS data server */ | ||
1185 | const struct rpc_call_ops *mds_ops; | ||
1186 | int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data); | 1180 | int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data); |
1187 | __u64 mds_offset; | 1181 | __u64 mds_offset; |
1188 | int pnfs_error; | ||
1189 | struct page *page_array[NFS_PAGEVEC_SIZE]; | 1182 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
1183 | struct nfs_client *ds_clp; /* pNFS data server */ | ||
1184 | }; | ||
1185 | |||
1186 | struct nfs_pgio_header { | ||
1187 | struct inode *inode; | ||
1188 | struct rpc_cred *cred; | ||
1189 | struct list_head pages; | ||
1190 | struct nfs_page *req; | ||
1191 | struct pnfs_layout_segment *lseg; | ||
1192 | const struct rpc_call_ops *mds_ops; | ||
1193 | int pnfs_error; | ||
1194 | }; | ||
1195 | |||
1196 | struct nfs_read_header { | ||
1197 | struct nfs_pgio_header header; | ||
1198 | struct nfs_read_data rpc_data; | ||
1190 | }; | 1199 | }; |
1191 | 1200 | ||
1192 | struct nfs_direct_req; | 1201 | struct nfs_direct_req; |
1193 | 1202 | ||
1194 | struct nfs_write_data { | 1203 | struct nfs_write_data { |
1204 | struct nfs_pgio_header *header; | ||
1205 | struct list_head list; | ||
1195 | struct rpc_task task; | 1206 | struct rpc_task task; |
1196 | struct inode *inode; | ||
1197 | struct rpc_cred *cred; | ||
1198 | struct nfs_fattr fattr; | 1207 | struct nfs_fattr fattr; |
1199 | struct nfs_writeverf verf; | 1208 | struct nfs_writeverf verf; |
1200 | struct list_head pages; /* Coalesced requests we wish to flush */ | ||
1201 | struct list_head list; /* lists of struct nfs_write_data */ | ||
1202 | struct nfs_page *req; /* multi ops per nfs_page */ | ||
1203 | struct page **pagevec; | 1209 | struct page **pagevec; |
1204 | unsigned int npages; /* Max length of pagevec */ | 1210 | unsigned int npages; /* Max length of pagevec */ |
1205 | struct nfs_writeargs args; /* argument struct */ | 1211 | struct nfs_writeargs args; /* argument struct */ |
1206 | struct nfs_writeres res; /* result struct */ | 1212 | struct nfs_writeres res; /* result struct */ |
1207 | struct pnfs_layout_segment *lseg; | ||
1208 | struct nfs_client *ds_clp; /* pNFS data server */ | ||
1209 | const struct rpc_call_ops *mds_ops; | ||
1210 | int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data); | ||
1211 | #ifdef CONFIG_NFS_V4 | ||
1212 | unsigned long timestamp; /* For lease renewal */ | 1213 | unsigned long timestamp; /* For lease renewal */ |
1213 | #endif | 1214 | int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data); |
1214 | __u64 mds_offset; /* Filelayout dense stripe */ | 1215 | __u64 mds_offset; /* Filelayout dense stripe */ |
1215 | int pnfs_error; | ||
1216 | struct page *page_array[NFS_PAGEVEC_SIZE]; | 1216 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
1217 | struct nfs_client *ds_clp; /* pNFS data server */ | ||
1218 | }; | ||
1219 | |||
1220 | struct nfs_write_header { | ||
1221 | struct nfs_pgio_header header; | ||
1222 | struct nfs_write_data rpc_data; | ||
1217 | }; | 1223 | }; |
1218 | 1224 | ||
1219 | struct nfs_commit_data { | 1225 | struct nfs_commit_data { |