aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-09-19 10:55:07 -0400
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:45 -0500
commita7d42ddb3099727f58366fa006f850a219cce6c8 (patch)
treec794857eb5c3ca29f77e259ecd3c155f841134d1 /fs/nfs
parentb57ff1303a2d4d1484c7a82bd80a3e014d6cdf5e (diff)
nfs: add mirroring support to pgio layer
This patch adds mirrored write support to the pgio layer. The default is to use one mirror, but pgio callers may define callbacks to change this to any value up to the (arbitrarily selected) limit of 16. The basic idea is to break out members of nfs_pageio_descriptor that cannot be shared between mirrored DSes and put them in a new structure. Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/direct.c17
-rw-r--r--fs/nfs/internal.h1
-rw-r--r--fs/nfs/objlayout/objio_osd.c3
-rw-r--r--fs/nfs/pagelist.c270
-rw-r--r--fs/nfs/pnfs.c26
-rw-r--r--fs/nfs/read.c30
-rw-r--r--fs/nfs/write.c10
7 files changed, 293 insertions, 64 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 1ee41d74c31c..0178d4fe8ab7 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -360,8 +360,14 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
360 spin_lock(&dreq->lock); 360 spin_lock(&dreq->lock);
361 if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0)) 361 if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0))
362 dreq->error = hdr->error; 362 dreq->error = hdr->error;
363 else 363 else {
364 dreq->count += hdr->good_bytes; 364 /*
365 * FIXME: right now this only accounts for bytes written
366 * to the first mirror
367 */
368 if (hdr->pgio_mirror_idx == 0)
369 dreq->count += hdr->good_bytes;
370 }
365 spin_unlock(&dreq->lock); 371 spin_unlock(&dreq->lock);
366 372
367 while (!list_empty(&hdr->pages)) { 373 while (!list_empty(&hdr->pages)) {
@@ -724,7 +730,12 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
724 dreq->error = hdr->error; 730 dreq->error = hdr->error;
725 } 731 }
726 if (dreq->error == 0) { 732 if (dreq->error == 0) {
727 dreq->count += hdr->good_bytes; 733 /*
734 * FIXME: right now this only accounts for bytes written
735 * to the first mirror
736 */
737 if (hdr->pgio_mirror_idx == 0)
738 dreq->count += hdr->good_bytes;
728 if (nfs_write_need_commit(hdr)) { 739 if (nfs_write_need_commit(hdr)) {
729 if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) 740 if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
730 request_commit = true; 741 request_commit = true;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 05f9a87cdab4..ef1c703e487b 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -469,6 +469,7 @@ void nfs_init_cinfo(struct nfs_commit_info *cinfo,
469 struct nfs_direct_req *dreq); 469 struct nfs_direct_req *dreq);
470int nfs_key_timeout_notify(struct file *filp, struct inode *inode); 470int nfs_key_timeout_notify(struct file *filp, struct inode *inode);
471bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx); 471bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx);
472void nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio);
472 473
473#ifdef CONFIG_MIGRATION 474#ifdef CONFIG_MIGRATION
474extern int nfs_migrate_page(struct address_space *, 475extern int nfs_migrate_page(struct address_space *,
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index d00778077df1..9a5f2ee6001f 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -537,11 +537,12 @@ int objio_write_pagelist(struct nfs_pgio_header *hdr, int how)
537static size_t objio_pg_test(struct nfs_pageio_descriptor *pgio, 537static size_t objio_pg_test(struct nfs_pageio_descriptor *pgio,
538 struct nfs_page *prev, struct nfs_page *req) 538 struct nfs_page *prev, struct nfs_page *req)
539{ 539{
540 struct nfs_pgio_mirror *mirror = &pgio->pg_mirrors[pgio->pg_mirror_idx];
540 unsigned int size; 541 unsigned int size;
541 542
542 size = pnfs_generic_pg_test(pgio, prev, req); 543 size = pnfs_generic_pg_test(pgio, prev, req);
543 544
544 if (!size || pgio->pg_count + req->wb_bytes > 545 if (!size || mirror->pg_count + req->wb_bytes >
545 (unsigned long)pgio->pg_layout_private) 546 (unsigned long)pgio->pg_layout_private)
546 return 0; 547 return 0;
547 548
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 1c031878c752..eec12b75c232 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -46,17 +46,22 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
46 struct nfs_pgio_header *hdr, 46 struct nfs_pgio_header *hdr,
47 void (*release)(struct nfs_pgio_header *hdr)) 47 void (*release)(struct nfs_pgio_header *hdr))
48{ 48{
49 hdr->req = nfs_list_entry(desc->pg_list.next); 49 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
50
51
52 hdr->req = nfs_list_entry(mirror->pg_list.next);
50 hdr->inode = desc->pg_inode; 53 hdr->inode = desc->pg_inode;
51 hdr->cred = hdr->req->wb_context->cred; 54 hdr->cred = hdr->req->wb_context->cred;
52 hdr->io_start = req_offset(hdr->req); 55 hdr->io_start = req_offset(hdr->req);
53 hdr->good_bytes = desc->pg_count; 56 hdr->good_bytes = mirror->pg_count;
54 hdr->dreq = desc->pg_dreq; 57 hdr->dreq = desc->pg_dreq;
55 hdr->layout_private = desc->pg_layout_private; 58 hdr->layout_private = desc->pg_layout_private;
56 hdr->release = release; 59 hdr->release = release;
57 hdr->completion_ops = desc->pg_completion_ops; 60 hdr->completion_ops = desc->pg_completion_ops;
58 if (hdr->completion_ops->init_hdr) 61 if (hdr->completion_ops->init_hdr)
59 hdr->completion_ops->init_hdr(hdr); 62 hdr->completion_ops->init_hdr(hdr);
63
64 hdr->pgio_mirror_idx = desc->pg_mirror_idx;
60} 65}
61EXPORT_SYMBOL_GPL(nfs_pgheader_init); 66EXPORT_SYMBOL_GPL(nfs_pgheader_init);
62 67
@@ -480,7 +485,10 @@ nfs_wait_on_request(struct nfs_page *req)
480size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, 485size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
481 struct nfs_page *prev, struct nfs_page *req) 486 struct nfs_page *prev, struct nfs_page *req)
482{ 487{
483 if (desc->pg_count > desc->pg_bsize) { 488 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
489
490
491 if (mirror->pg_count > mirror->pg_bsize) {
484 /* should never happen */ 492 /* should never happen */
485 WARN_ON_ONCE(1); 493 WARN_ON_ONCE(1);
486 return 0; 494 return 0;
@@ -490,11 +498,11 @@ size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
490 * Limit the request size so that we can still allocate a page array 498 * Limit the request size so that we can still allocate a page array
491 * for it without upsetting the slab allocator. 499 * for it without upsetting the slab allocator.
492 */ 500 */
493 if (((desc->pg_count + req->wb_bytes) >> PAGE_SHIFT) * 501 if (((mirror->pg_count + req->wb_bytes) >> PAGE_SHIFT) *
494 sizeof(struct page) > PAGE_SIZE) 502 sizeof(struct page) > PAGE_SIZE)
495 return 0; 503 return 0;
496 504
497 return min(desc->pg_bsize - desc->pg_count, (size_t)req->wb_bytes); 505 return min(mirror->pg_bsize - mirror->pg_count, (size_t)req->wb_bytes);
498} 506}
499EXPORT_SYMBOL_GPL(nfs_generic_pg_test); 507EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
500 508
@@ -651,10 +659,18 @@ EXPORT_SYMBOL_GPL(nfs_initiate_pgio);
651static int nfs_pgio_error(struct nfs_pageio_descriptor *desc, 659static int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
652 struct nfs_pgio_header *hdr) 660 struct nfs_pgio_header *hdr)
653{ 661{
662 struct nfs_pgio_mirror *mirror;
663 u32 midx;
664
654 set_bit(NFS_IOHDR_REDO, &hdr->flags); 665 set_bit(NFS_IOHDR_REDO, &hdr->flags);
655 nfs_pgio_data_destroy(hdr); 666 nfs_pgio_data_destroy(hdr);
656 hdr->completion_ops->completion(hdr); 667 hdr->completion_ops->completion(hdr);
657 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 668 /* TODO: Make sure it's right to clean up all mirrors here
669 * and not just hdr->pgio_mirror_idx */
670 for (midx = 0; midx < desc->pg_mirror_count; midx++) {
671 mirror = &desc->pg_mirrors[midx];
672 desc->pg_completion_ops->error_cleanup(&mirror->pg_list);
673 }
658 return -ENOMEM; 674 return -ENOMEM;
659} 675}
660 676
@@ -671,6 +687,17 @@ static void nfs_pgio_release(void *calldata)
671 hdr->completion_ops->completion(hdr); 687 hdr->completion_ops->completion(hdr);
672} 688}
673 689
690static void nfs_pageio_mirror_init(struct nfs_pgio_mirror *mirror,
691 unsigned int bsize)
692{
693 INIT_LIST_HEAD(&mirror->pg_list);
694 mirror->pg_bytes_written = 0;
695 mirror->pg_count = 0;
696 mirror->pg_bsize = bsize;
697 mirror->pg_base = 0;
698 mirror->pg_recoalesce = 0;
699}
700
674/** 701/**
675 * nfs_pageio_init - initialise a page io descriptor 702 * nfs_pageio_init - initialise a page io descriptor
676 * @desc: pointer to descriptor 703 * @desc: pointer to descriptor
@@ -687,13 +714,10 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
687 size_t bsize, 714 size_t bsize,
688 int io_flags) 715 int io_flags)
689{ 716{
690 INIT_LIST_HEAD(&desc->pg_list); 717 struct nfs_pgio_mirror *new;
691 desc->pg_bytes_written = 0; 718 int i;
692 desc->pg_count = 0; 719
693 desc->pg_bsize = bsize;
694 desc->pg_base = 0;
695 desc->pg_moreio = 0; 720 desc->pg_moreio = 0;
696 desc->pg_recoalesce = 0;
697 desc->pg_inode = inode; 721 desc->pg_inode = inode;
698 desc->pg_ops = pg_ops; 722 desc->pg_ops = pg_ops;
699 desc->pg_completion_ops = compl_ops; 723 desc->pg_completion_ops = compl_ops;
@@ -703,6 +727,26 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
703 desc->pg_lseg = NULL; 727 desc->pg_lseg = NULL;
704 desc->pg_dreq = NULL; 728 desc->pg_dreq = NULL;
705 desc->pg_layout_private = NULL; 729 desc->pg_layout_private = NULL;
730 desc->pg_bsize = bsize;
731
732 desc->pg_mirror_count = 1;
733 desc->pg_mirror_idx = 0;
734
735 if (pg_ops->pg_get_mirror_count) {
736 /* until we have a request, we don't have an lseg and no
737 * idea how many mirrors there will be */
738 new = kcalloc(NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX,
739 sizeof(struct nfs_pgio_mirror), GFP_KERNEL);
740 desc->pg_mirrors_dynamic = new;
741 desc->pg_mirrors = new;
742
743 for (i = 0; i < NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX; i++)
744 nfs_pageio_mirror_init(&desc->pg_mirrors[i], bsize);
745 } else {
746 desc->pg_mirrors_dynamic = NULL;
747 desc->pg_mirrors = desc->pg_mirrors_static;
748 nfs_pageio_mirror_init(&desc->pg_mirrors[0], bsize);
749 }
706} 750}
707EXPORT_SYMBOL_GPL(nfs_pageio_init); 751EXPORT_SYMBOL_GPL(nfs_pageio_init);
708 752
@@ -738,14 +782,16 @@ static void nfs_pgio_result(struct rpc_task *task, void *calldata)
738int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, 782int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
739 struct nfs_pgio_header *hdr) 783 struct nfs_pgio_header *hdr)
740{ 784{
785 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
786
741 struct nfs_page *req; 787 struct nfs_page *req;
742 struct page **pages, 788 struct page **pages,
743 *last_page; 789 *last_page;
744 struct list_head *head = &desc->pg_list; 790 struct list_head *head = &mirror->pg_list;
745 struct nfs_commit_info cinfo; 791 struct nfs_commit_info cinfo;
746 unsigned int pagecount, pageused; 792 unsigned int pagecount, pageused;
747 793
748 pagecount = nfs_page_array_len(desc->pg_base, desc->pg_count); 794 pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count);
749 if (!nfs_pgarray_set(&hdr->page_array, pagecount)) 795 if (!nfs_pgarray_set(&hdr->page_array, pagecount))
750 return nfs_pgio_error(desc, hdr); 796 return nfs_pgio_error(desc, hdr);
751 797
@@ -773,7 +819,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
773 desc->pg_ioflags &= ~FLUSH_COND_STABLE; 819 desc->pg_ioflags &= ~FLUSH_COND_STABLE;
774 820
775 /* Set up the argument struct */ 821 /* Set up the argument struct */
776 nfs_pgio_rpcsetup(hdr, desc->pg_count, 0, desc->pg_ioflags, &cinfo); 822 nfs_pgio_rpcsetup(hdr, mirror->pg_count, 0, desc->pg_ioflags, &cinfo);
777 desc->pg_rpc_callops = &nfs_pgio_common_ops; 823 desc->pg_rpc_callops = &nfs_pgio_common_ops;
778 return 0; 824 return 0;
779} 825}
@@ -781,12 +827,17 @@ EXPORT_SYMBOL_GPL(nfs_generic_pgio);
781 827
782static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc) 828static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
783{ 829{
830 struct nfs_pgio_mirror *mirror;
784 struct nfs_pgio_header *hdr; 831 struct nfs_pgio_header *hdr;
785 int ret; 832 int ret;
786 833
834 mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
835
787 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); 836 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops);
788 if (!hdr) { 837 if (!hdr) {
789 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 838 /* TODO: make sure this is right with mirroring - or
839 * should it back out all mirrors? */
840 desc->pg_completion_ops->error_cleanup(&mirror->pg_list);
790 return -ENOMEM; 841 return -ENOMEM;
791 } 842 }
792 nfs_pgheader_init(desc, hdr, nfs_pgio_header_free); 843 nfs_pgheader_init(desc, hdr, nfs_pgio_header_free);
@@ -801,6 +852,49 @@ static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
801 return ret; 852 return ret;
802} 853}
803 854
855/*
856 * nfs_pageio_setup_mirroring - determine if mirroring is to be used
857 * by calling the pg_get_mirror_count op
858 */
859static int nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio,
860 struct nfs_page *req)
861{
862 int mirror_count = 1;
863
864 if (!pgio->pg_ops->pg_get_mirror_count)
865 return 0;
866
867 mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req);
868
869 if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX)
870 return -EINVAL;
871
872 if (WARN_ON_ONCE(!pgio->pg_mirrors_dynamic))
873 return -EINVAL;
874
875 pgio->pg_mirror_count = mirror_count;
876
877 return 0;
878}
879
880/*
881 * nfs_pageio_stop_mirroring - stop using mirroring (set mirror count to 1)
882 */
883void nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio)
884{
885 pgio->pg_mirror_count = 1;
886 pgio->pg_mirror_idx = 0;
887}
888
889static void nfs_pageio_cleanup_mirroring(struct nfs_pageio_descriptor *pgio)
890{
891 pgio->pg_mirror_count = 1;
892 pgio->pg_mirror_idx = 0;
893 pgio->pg_mirrors = pgio->pg_mirrors_static;
894 kfree(pgio->pg_mirrors_dynamic);
895 pgio->pg_mirrors_dynamic = NULL;
896}
897
804static bool nfs_match_open_context(const struct nfs_open_context *ctx1, 898static bool nfs_match_open_context(const struct nfs_open_context *ctx1,
805 const struct nfs_open_context *ctx2) 899 const struct nfs_open_context *ctx2)
806{ 900{
@@ -867,19 +961,22 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
867static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, 961static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
868 struct nfs_page *req) 962 struct nfs_page *req)
869{ 963{
964 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
965
870 struct nfs_page *prev = NULL; 966 struct nfs_page *prev = NULL;
871 if (desc->pg_count != 0) { 967
872 prev = nfs_list_entry(desc->pg_list.prev); 968 if (mirror->pg_count != 0) {
969 prev = nfs_list_entry(mirror->pg_list.prev);
873 } else { 970 } else {
874 if (desc->pg_ops->pg_init) 971 if (desc->pg_ops->pg_init)
875 desc->pg_ops->pg_init(desc, req); 972 desc->pg_ops->pg_init(desc, req);
876 desc->pg_base = req->wb_pgbase; 973 mirror->pg_base = req->wb_pgbase;
877 } 974 }
878 if (!nfs_can_coalesce_requests(prev, req, desc)) 975 if (!nfs_can_coalesce_requests(prev, req, desc))
879 return 0; 976 return 0;
880 nfs_list_remove_request(req); 977 nfs_list_remove_request(req);
881 nfs_list_add_request(req, &desc->pg_list); 978 nfs_list_add_request(req, &mirror->pg_list);
882 desc->pg_count += req->wb_bytes; 979 mirror->pg_count += req->wb_bytes;
883 return 1; 980 return 1;
884} 981}
885 982
@@ -888,16 +985,19 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
888 */ 985 */
889static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) 986static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
890{ 987{
891 if (!list_empty(&desc->pg_list)) { 988 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
989
990
991 if (!list_empty(&mirror->pg_list)) {
892 int error = desc->pg_ops->pg_doio(desc); 992 int error = desc->pg_ops->pg_doio(desc);
893 if (error < 0) 993 if (error < 0)
894 desc->pg_error = error; 994 desc->pg_error = error;
895 else 995 else
896 desc->pg_bytes_written += desc->pg_count; 996 mirror->pg_bytes_written += mirror->pg_count;
897 } 997 }
898 if (list_empty(&desc->pg_list)) { 998 if (list_empty(&mirror->pg_list)) {
899 desc->pg_count = 0; 999 mirror->pg_count = 0;
900 desc->pg_base = 0; 1000 mirror->pg_base = 0;
901 } 1001 }
902} 1002}
903 1003
@@ -915,10 +1015,14 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
915static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, 1015static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
916 struct nfs_page *req) 1016 struct nfs_page *req)
917{ 1017{
1018 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
1019
918 struct nfs_page *subreq; 1020 struct nfs_page *subreq;
919 unsigned int bytes_left = 0; 1021 unsigned int bytes_left = 0;
920 unsigned int offset, pgbase; 1022 unsigned int offset, pgbase;
921 1023
1024 WARN_ON_ONCE(desc->pg_mirror_idx >= desc->pg_mirror_count);
1025
922 nfs_page_group_lock(req, false); 1026 nfs_page_group_lock(req, false);
923 1027
924 subreq = req; 1028 subreq = req;
@@ -938,7 +1042,7 @@ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
938 nfs_pageio_doio(desc); 1042 nfs_pageio_doio(desc);
939 if (desc->pg_error < 0) 1043 if (desc->pg_error < 0)
940 return 0; 1044 return 0;
941 if (desc->pg_recoalesce) 1045 if (mirror->pg_recoalesce)
942 return 0; 1046 return 0;
943 /* retry add_request for this subreq */ 1047 /* retry add_request for this subreq */
944 nfs_page_group_lock(req, false); 1048 nfs_page_group_lock(req, false);
@@ -976,14 +1080,16 @@ err_ptr:
976 1080
977static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) 1081static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
978{ 1082{
1083 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
979 LIST_HEAD(head); 1084 LIST_HEAD(head);
980 1085
981 do { 1086 do {
982 list_splice_init(&desc->pg_list, &head); 1087 list_splice_init(&mirror->pg_list, &head);
983 desc->pg_bytes_written -= desc->pg_count; 1088 mirror->pg_bytes_written -= mirror->pg_count;
984 desc->pg_count = 0; 1089 mirror->pg_count = 0;
985 desc->pg_base = 0; 1090 mirror->pg_base = 0;
986 desc->pg_recoalesce = 0; 1091 mirror->pg_recoalesce = 0;
1092
987 desc->pg_moreio = 0; 1093 desc->pg_moreio = 0;
988 1094
989 while (!list_empty(&head)) { 1095 while (!list_empty(&head)) {
@@ -997,11 +1103,11 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
997 return 0; 1103 return 0;
998 break; 1104 break;
999 } 1105 }
1000 } while (desc->pg_recoalesce); 1106 } while (mirror->pg_recoalesce);
1001 return 1; 1107 return 1;
1002} 1108}
1003 1109
1004int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, 1110static int nfs_pageio_add_request_mirror(struct nfs_pageio_descriptor *desc,
1005 struct nfs_page *req) 1111 struct nfs_page *req)
1006{ 1112{
1007 int ret; 1113 int ret;
@@ -1014,9 +1120,78 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
1014 break; 1120 break;
1015 ret = nfs_do_recoalesce(desc); 1121 ret = nfs_do_recoalesce(desc);
1016 } while (ret); 1122 } while (ret);
1123
1017 return ret; 1124 return ret;
1018} 1125}
1019 1126
1127int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
1128 struct nfs_page *req)
1129{
1130 u32 midx;
1131 unsigned int pgbase, offset, bytes;
1132 struct nfs_page *dupreq, *lastreq;
1133
1134 pgbase = req->wb_pgbase;
1135 offset = req->wb_offset;
1136 bytes = req->wb_bytes;
1137
1138 nfs_pageio_setup_mirroring(desc, req);
1139
1140 for (midx = 0; midx < desc->pg_mirror_count; midx++) {
1141 if (midx) {
1142 nfs_page_group_lock(req, false);
1143
1144 /* find the last request */
1145 for (lastreq = req->wb_head;
1146 lastreq->wb_this_page != req->wb_head;
1147 lastreq = lastreq->wb_this_page)
1148 ;
1149
1150 dupreq = nfs_create_request(req->wb_context,
1151 req->wb_page, lastreq, pgbase, bytes);
1152
1153 if (IS_ERR(dupreq)) {
1154 nfs_page_group_unlock(req);
1155 return 0;
1156 }
1157
1158 nfs_lock_request(dupreq);
1159 nfs_page_group_unlock(req);
1160 dupreq->wb_offset = offset;
1161 dupreq->wb_index = req->wb_index;
1162 } else
1163 dupreq = req;
1164
1165 desc->pg_mirror_idx = midx;
1166 if (!nfs_pageio_add_request_mirror(desc, dupreq))
1167 return 0;
1168 }
1169
1170 return 1;
1171}
1172
1173/*
1174 * nfs_pageio_complete_mirror - Complete I/O on the current mirror of an
1175 * nfs_pageio_descriptor
1176 * @desc: pointer to io descriptor
1177 */
1178static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc,
1179 u32 mirror_idx)
1180{
1181 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[mirror_idx];
1182 u32 restore_idx = desc->pg_mirror_idx;
1183
1184 desc->pg_mirror_idx = mirror_idx;
1185 for (;;) {
1186 nfs_pageio_doio(desc);
1187 if (!mirror->pg_recoalesce)
1188 break;
1189 if (!nfs_do_recoalesce(desc))
1190 break;
1191 }
1192 desc->pg_mirror_idx = restore_idx;
1193}
1194
1020/* 1195/*
1021 * nfs_pageio_resend - Transfer requests to new descriptor and resend 1196 * nfs_pageio_resend - Transfer requests to new descriptor and resend
1022 * @hdr - the pgio header to move request from 1197 * @hdr - the pgio header to move request from
@@ -1055,16 +1230,14 @@ EXPORT_SYMBOL_GPL(nfs_pageio_resend);
1055 */ 1230 */
1056void nfs_pageio_complete(struct nfs_pageio_descriptor *desc) 1231void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
1057{ 1232{
1058 for (;;) { 1233 u32 midx;
1059 nfs_pageio_doio(desc); 1234
1060 if (!desc->pg_recoalesce) 1235 for (midx = 0; midx < desc->pg_mirror_count; midx++)
1061 break; 1236 nfs_pageio_complete_mirror(desc, midx);
1062 if (!nfs_do_recoalesce(desc))
1063 break;
1064 }
1065 1237
1066 if (desc->pg_ops->pg_cleanup) 1238 if (desc->pg_ops->pg_cleanup)
1067 desc->pg_ops->pg_cleanup(desc); 1239 desc->pg_ops->pg_cleanup(desc);
1240 nfs_pageio_cleanup_mirroring(desc);
1068} 1241}
1069 1242
1070/** 1243/**
@@ -1080,10 +1253,17 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
1080 */ 1253 */
1081void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index) 1254void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
1082{ 1255{
1083 if (!list_empty(&desc->pg_list)) { 1256 struct nfs_pgio_mirror *mirror;
1084 struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev); 1257 struct nfs_page *prev;
1085 if (index != prev->wb_index + 1) 1258 u32 midx;
1086 nfs_pageio_complete(desc); 1259
1260 for (midx = 0; midx < desc->pg_mirror_count; midx++) {
1261 mirror = &desc->pg_mirrors[midx];
1262 if (!list_empty(&mirror->pg_list)) {
1263 prev = nfs_list_entry(mirror->pg_list.prev);
1264 if (index != prev->wb_index + 1)
1265 nfs_pageio_complete_mirror(desc, midx);
1266 }
1087 } 1267 }
1088} 1268}
1089 1269
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 2da2e771fefe..5f7c422ebb5d 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1646,8 +1646,8 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_cleanup);
1646 * of bytes (maximum @req->wb_bytes) that can be coalesced. 1646 * of bytes (maximum @req->wb_bytes) that can be coalesced.
1647 */ 1647 */
1648size_t 1648size_t
1649pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, 1649pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio,
1650 struct nfs_page *req) 1650 struct nfs_page *prev, struct nfs_page *req)
1651{ 1651{
1652 unsigned int size; 1652 unsigned int size;
1653 u64 seg_end, req_start, seg_left; 1653 u64 seg_end, req_start, seg_left;
@@ -1729,10 +1729,12 @@ static void
1729pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, 1729pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
1730 struct nfs_pgio_header *hdr) 1730 struct nfs_pgio_header *hdr)
1731{ 1731{
1732 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
1733
1732 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { 1734 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
1733 list_splice_tail_init(&hdr->pages, &desc->pg_list); 1735 list_splice_tail_init(&hdr->pages, &mirror->pg_list);
1734 nfs_pageio_reset_write_mds(desc); 1736 nfs_pageio_reset_write_mds(desc);
1735 desc->pg_recoalesce = 1; 1737 mirror->pg_recoalesce = 1;
1736 } 1738 }
1737 nfs_pgio_data_destroy(hdr); 1739 nfs_pgio_data_destroy(hdr);
1738} 1740}
@@ -1781,12 +1783,14 @@ EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
1781int 1783int
1782pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) 1784pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1783{ 1785{
1786 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
1787
1784 struct nfs_pgio_header *hdr; 1788 struct nfs_pgio_header *hdr;
1785 int ret; 1789 int ret;
1786 1790
1787 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); 1791 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops);
1788 if (!hdr) { 1792 if (!hdr) {
1789 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1793 desc->pg_completion_ops->error_cleanup(&mirror->pg_list);
1790 return -ENOMEM; 1794 return -ENOMEM;
1791 } 1795 }
1792 nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); 1796 nfs_pgheader_init(desc, hdr, pnfs_writehdr_free);
@@ -1795,6 +1799,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1795 ret = nfs_generic_pgio(desc, hdr); 1799 ret = nfs_generic_pgio(desc, hdr);
1796 if (!ret) 1800 if (!ret)
1797 pnfs_do_write(desc, hdr, desc->pg_ioflags); 1801 pnfs_do_write(desc, hdr, desc->pg_ioflags);
1802
1798 return ret; 1803 return ret;
1799} 1804}
1800EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); 1805EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
@@ -1839,10 +1844,13 @@ static void
1839pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, 1844pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
1840 struct nfs_pgio_header *hdr) 1845 struct nfs_pgio_header *hdr)
1841{ 1846{
1847 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
1848
1849
1842 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { 1850 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
1843 list_splice_tail_init(&hdr->pages, &desc->pg_list); 1851 list_splice_tail_init(&hdr->pages, &mirror->pg_list);
1844 nfs_pageio_reset_read_mds(desc); 1852 nfs_pageio_reset_read_mds(desc);
1845 desc->pg_recoalesce = 1; 1853 mirror->pg_recoalesce = 1;
1846 } 1854 }
1847 nfs_pgio_data_destroy(hdr); 1855 nfs_pgio_data_destroy(hdr);
1848} 1856}
@@ -1893,12 +1901,14 @@ EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
1893int 1901int
1894pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) 1902pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
1895{ 1903{
1904 struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx];
1905
1896 struct nfs_pgio_header *hdr; 1906 struct nfs_pgio_header *hdr;
1897 int ret; 1907 int ret;
1898 1908
1899 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); 1909 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops);
1900 if (!hdr) { 1910 if (!hdr) {
1901 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1911 desc->pg_completion_ops->error_cleanup(&mirror->pg_list);
1902 return -ENOMEM; 1912 return -ENOMEM;
1903 } 1913 }
1904 nfs_pgheader_init(desc, hdr, pnfs_readhdr_free); 1914 nfs_pgheader_init(desc, hdr, pnfs_readhdr_free);
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 092ab499f2b6..568ecf0a880f 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -70,8 +70,15 @@ EXPORT_SYMBOL_GPL(nfs_pageio_init_read);
70 70
71void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) 71void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
72{ 72{
73 struct nfs_pgio_mirror *mirror;
74
73 pgio->pg_ops = &nfs_pgio_rw_ops; 75 pgio->pg_ops = &nfs_pgio_rw_ops;
74 pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->rsize; 76
77 /* read path should never have more than one mirror */
78 WARN_ON_ONCE(pgio->pg_mirror_count != 1);
79
80 mirror = &pgio->pg_mirrors[0];
81 mirror->pg_bsize = NFS_SERVER(pgio->pg_inode)->rsize;
75} 82}
76EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); 83EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
77 84
@@ -81,6 +88,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
81 struct nfs_page *new; 88 struct nfs_page *new;
82 unsigned int len; 89 unsigned int len;
83 struct nfs_pageio_descriptor pgio; 90 struct nfs_pageio_descriptor pgio;
91 struct nfs_pgio_mirror *pgm;
84 92
85 len = nfs_page_length(page); 93 len = nfs_page_length(page);
86 if (len == 0) 94 if (len == 0)
@@ -97,7 +105,13 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
97 &nfs_async_read_completion_ops); 105 &nfs_async_read_completion_ops);
98 nfs_pageio_add_request(&pgio, new); 106 nfs_pageio_add_request(&pgio, new);
99 nfs_pageio_complete(&pgio); 107 nfs_pageio_complete(&pgio);
100 NFS_I(inode)->read_io += pgio.pg_bytes_written; 108
109 /* It doesn't make sense to do mirrored reads! */
110 WARN_ON_ONCE(pgio.pg_mirror_count != 1);
111
112 pgm = &pgio.pg_mirrors[0];
113 NFS_I(inode)->read_io += pgm->pg_bytes_written;
114
101 return 0; 115 return 0;
102} 116}
103 117
@@ -352,6 +366,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
352 struct list_head *pages, unsigned nr_pages) 366 struct list_head *pages, unsigned nr_pages)
353{ 367{
354 struct nfs_pageio_descriptor pgio; 368 struct nfs_pageio_descriptor pgio;
369 struct nfs_pgio_mirror *pgm;
355 struct nfs_readdesc desc = { 370 struct nfs_readdesc desc = {
356 .pgio = &pgio, 371 .pgio = &pgio,
357 }; 372 };
@@ -387,10 +402,15 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
387 &nfs_async_read_completion_ops); 402 &nfs_async_read_completion_ops);
388 403
389 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); 404 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
390
391 nfs_pageio_complete(&pgio); 405 nfs_pageio_complete(&pgio);
392 NFS_I(inode)->read_io += pgio.pg_bytes_written; 406
393 npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 407 /* It doesn't make sense to do mirrored reads! */
408 WARN_ON_ONCE(pgio.pg_mirror_count != 1);
409
410 pgm = &pgio.pg_mirrors[0];
411 NFS_I(inode)->read_io += pgm->pg_bytes_written;
412 npages = (pgm->pg_bytes_written + PAGE_CACHE_SIZE - 1) >>
413 PAGE_CACHE_SHIFT;
394 nfs_add_stats(inode, NFSIOS_READPAGES, npages); 414 nfs_add_stats(inode, NFSIOS_READPAGES, npages);
395read_complete: 415read_complete:
396 put_nfs_open_context(desc.ctx); 416 put_nfs_open_context(desc.ctx);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2bee165fddcf..ceacfeeb28c2 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -906,7 +906,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
906 if (nfs_write_need_commit(hdr)) { 906 if (nfs_write_need_commit(hdr)) {
907 memcpy(&req->wb_verf, &hdr->verf.verifier, sizeof(req->wb_verf)); 907 memcpy(&req->wb_verf, &hdr->verf.verifier, sizeof(req->wb_verf));
908 nfs_mark_request_commit(req, hdr->lseg, &cinfo, 908 nfs_mark_request_commit(req, hdr->lseg, &cinfo,
909 0); 909 hdr->pgio_mirror_idx);
910 goto next; 910 goto next;
911 } 911 }
912remove_req: 912remove_req:
@@ -1304,8 +1304,14 @@ EXPORT_SYMBOL_GPL(nfs_pageio_init_write);
1304 1304
1305void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) 1305void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
1306{ 1306{
1307 struct nfs_pgio_mirror *mirror;
1308
1307 pgio->pg_ops = &nfs_pgio_rw_ops; 1309 pgio->pg_ops = &nfs_pgio_rw_ops;
1308 pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize; 1310
1311 nfs_pageio_stop_mirroring(pgio);
1312
1313 mirror = &pgio->pg_mirrors[0];
1314 mirror->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize;
1309} 1315}
1310EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); 1316EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
1311 1317