Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Weston Andros Adamson and committed by
Tom Haynes
a7d42ddb b57ff130

+311 -67
+14 -3
fs/nfs/direct.c
··· 360 360 spin_lock(&dreq->lock); 361 361 if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0)) 362 362 dreq->error = hdr->error; 363 - else 364 - dreq->count += hdr->good_bytes; 363 + else { 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 371 spin_unlock(&dreq->lock); 366 372 367 373 while (!list_empty(&hdr->pages)) { ··· 730 724 dreq->error = hdr->error; 731 725 } 732 726 if (dreq->error == 0) { 733 - dreq->count += hdr->good_bytes; 727 + /* 728 + * FIXME: right now this only accounts for bytes written 729 + * to the first mirror 730 + */ 731 + if (hdr->pgio_mirror_idx == 0) 732 + dreq->count += hdr->good_bytes; 734 733 if (nfs_write_need_commit(hdr)) { 735 734 if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) 736 735 request_commit = true;
+1
fs/nfs/internal.h
··· 469 469 struct nfs_direct_req *dreq); 470 470 int nfs_key_timeout_notify(struct file *filp, struct inode *inode); 471 471 bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx); 472 + void nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio); 472 473 473 474 #ifdef CONFIG_MIGRATION 474 475 extern int nfs_migrate_page(struct address_space *,
+2 -1
fs/nfs/objlayout/objio_osd.c
··· 537 537 static size_t objio_pg_test(struct nfs_pageio_descriptor *pgio, 538 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 541 unsigned int size; 541 542 542 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 546 (unsigned long)pgio->pg_layout_private) 546 547 return 0; 547 548
+225 -45
fs/nfs/pagelist.c
··· 46 46 struct nfs_pgio_header *hdr, 47 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 53 hdr->inode = desc->pg_inode; 51 54 hdr->cred = hdr->req->wb_context->cred; 52 55 hdr->io_start = req_offset(hdr->req); 53 - hdr->good_bytes = desc->pg_count; 56 + hdr->good_bytes = mirror->pg_count; 54 57 hdr->dreq = desc->pg_dreq; 55 58 hdr->layout_private = desc->pg_layout_private; 56 59 hdr->release = release; 57 60 hdr->completion_ops = desc->pg_completion_ops; 58 61 if (hdr->completion_ops->init_hdr) 59 62 hdr->completion_ops->init_hdr(hdr); 63 + 64 + hdr->pgio_mirror_idx = desc->pg_mirror_idx; 60 65 } 61 66 EXPORT_SYMBOL_GPL(nfs_pgheader_init); 62 67 ··· 485 480 size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, 486 481 struct nfs_page *prev, struct nfs_page *req) 487 482 { 488 - if (desc->pg_count > desc->pg_bsize) { 483 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 484 + 485 + 486 + if (mirror->pg_count > mirror->pg_bsize) { 489 487 /* should never happen */ 490 488 WARN_ON_ONCE(1); 491 489 return 0; ··· 498 490 * Limit the request size so that we can still allocate a page array 499 491 * for it without upsetting the slab allocator. 500 492 */ 501 - if (((desc->pg_count + req->wb_bytes) >> PAGE_SHIFT) * 493 + if (((mirror->pg_count + req->wb_bytes) >> PAGE_SHIFT) * 502 494 sizeof(struct page) > PAGE_SIZE) 503 495 return 0; 504 496 505 - return min(desc->pg_bsize - desc->pg_count, (size_t)req->wb_bytes); 497 + return min(mirror->pg_bsize - mirror->pg_count, (size_t)req->wb_bytes); 506 498 } 507 499 EXPORT_SYMBOL_GPL(nfs_generic_pg_test); 508 500 ··· 659 651 static int nfs_pgio_error(struct nfs_pageio_descriptor *desc, 660 652 struct nfs_pgio_header *hdr) 661 653 { 654 + struct nfs_pgio_mirror *mirror; 655 + u32 midx; 656 + 662 657 set_bit(NFS_IOHDR_REDO, &hdr->flags); 663 658 nfs_pgio_data_destroy(hdr); 664 659 hdr->completion_ops->completion(hdr); 665 - desc->pg_completion_ops->error_cleanup(&desc->pg_list); 660 + /* TODO: Make sure it's right to clean up all mirrors here 661 + * and not just hdr->pgio_mirror_idx */ 662 + for (midx = 0; midx < desc->pg_mirror_count; midx++) { 663 + mirror = &desc->pg_mirrors[midx]; 664 + desc->pg_completion_ops->error_cleanup(&mirror->pg_list); 665 + } 666 666 return -ENOMEM; 667 667 } 668 668 ··· 685 669 hdr->rw_ops->rw_release(hdr); 686 670 nfs_pgio_data_destroy(hdr); 687 671 hdr->completion_ops->completion(hdr); 672 + } 673 + 674 + static void nfs_pageio_mirror_init(struct nfs_pgio_mirror *mirror, 675 + unsigned int bsize) 676 + { 677 + INIT_LIST_HEAD(&mirror->pg_list); 678 + mirror->pg_bytes_written = 0; 679 + mirror->pg_count = 0; 680 + mirror->pg_bsize = bsize; 681 + mirror->pg_base = 0; 682 + mirror->pg_recoalesce = 0; 688 683 } 689 684 690 685 /** ··· 714 687 size_t bsize, 715 688 int io_flags) 716 689 { 717 - INIT_LIST_HEAD(&desc->pg_list); 718 - desc->pg_bytes_written = 0; 719 - desc->pg_count = 0; 720 - desc->pg_bsize = bsize; 721 - desc->pg_base = 0; 690 + struct nfs_pgio_mirror *new; 691 + int i; 692 + 722 693 desc->pg_moreio = 0; 723 - desc->pg_recoalesce = 0; 724 694 desc->pg_inode = inode; 725 695 desc->pg_ops = pg_ops; 726 696 desc->pg_completion_ops = compl_ops; ··· 727 703 desc->pg_lseg = NULL; 728 704 desc->pg_dreq = NULL; 729 705 desc->pg_layout_private = NULL; 706 + desc->pg_bsize = bsize; 707 + 708 + desc->pg_mirror_count = 1; 709 + desc->pg_mirror_idx = 0; 710 + 711 + if (pg_ops->pg_get_mirror_count) { 712 + /* until we have a request, we don't have an lseg and no 713 + * idea how many mirrors there will be */ 714 + new = kcalloc(NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX, 715 + sizeof(struct nfs_pgio_mirror), GFP_KERNEL); 716 + desc->pg_mirrors_dynamic = new; 717 + desc->pg_mirrors = new; 718 + 719 + for (i = 0; i < NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX; i++) 720 + nfs_pageio_mirror_init(&desc->pg_mirrors[i], bsize); 721 + } else { 722 + desc->pg_mirrors_dynamic = NULL; 723 + desc->pg_mirrors = desc->pg_mirrors_static; 724 + nfs_pageio_mirror_init(&desc->pg_mirrors[0], bsize); 725 + } 730 726 } 731 727 EXPORT_SYMBOL_GPL(nfs_pageio_init); 732 728 ··· 782 738 int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, 783 739 struct nfs_pgio_header *hdr) 784 740 { 741 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 742 + 785 743 struct nfs_page *req; 786 744 struct page **pages, 787 745 *last_page; 788 - struct list_head *head = &desc->pg_list; 746 + struct list_head *head = &mirror->pg_list; 789 747 struct nfs_commit_info cinfo; 790 748 unsigned int pagecount, pageused; 791 749 792 - pagecount = nfs_page_array_len(desc->pg_base, desc->pg_count); 750 + pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); 793 751 if (!nfs_pgarray_set(&hdr->page_array, pagecount)) 794 752 return nfs_pgio_error(desc, hdr); 795 753 ··· 819 773 desc->pg_ioflags &= ~FLUSH_COND_STABLE; 820 774 821 775 /* Set up the argument struct */ 822 - nfs_pgio_rpcsetup(hdr, desc->pg_count, 0, desc->pg_ioflags, &cinfo); 776 + nfs_pgio_rpcsetup(hdr, mirror->pg_count, 0, desc->pg_ioflags, &cinfo); 823 777 desc->pg_rpc_callops = &nfs_pgio_common_ops; 824 778 return 0; 825 779 } ··· 827 781 828 782 static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc) 829 783 { 784 + struct nfs_pgio_mirror *mirror; 830 785 struct nfs_pgio_header *hdr; 831 786 int ret; 832 787 788 + mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 789 + 833 790 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); 834 791 if (!hdr) { 835 - desc->pg_completion_ops->error_cleanup(&desc->pg_list); 792 + /* TODO: make sure this is right with mirroring - or 793 + * should it back out all mirrors? */ 794 + desc->pg_completion_ops->error_cleanup(&mirror->pg_list); 836 795 return -ENOMEM; 837 796 } 838 797 nfs_pgheader_init(desc, hdr, nfs_pgio_header_free); ··· 850 799 desc->pg_rpc_callops, 851 800 desc->pg_ioflags, 0); 852 801 return ret; 802 + } 803 + 804 + /* 805 + * nfs_pageio_setup_mirroring - determine if mirroring is to be used 806 + * by calling the pg_get_mirror_count op 807 + */ 808 + static int nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio, 809 + struct nfs_page *req) 810 + { 811 + int mirror_count = 1; 812 + 813 + if (!pgio->pg_ops->pg_get_mirror_count) 814 + return 0; 815 + 816 + mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req); 817 + 818 + if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX) 819 + return -EINVAL; 820 + 821 + if (WARN_ON_ONCE(!pgio->pg_mirrors_dynamic)) 822 + return -EINVAL; 823 + 824 + pgio->pg_mirror_count = mirror_count; 825 + 826 + return 0; 827 + } 828 + 829 + /* 830 + * nfs_pageio_stop_mirroring - stop using mirroring (set mirror count to 1) 831 + */ 832 + void nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio) 833 + { 834 + pgio->pg_mirror_count = 1; 835 + pgio->pg_mirror_idx = 0; 836 + } 837 + 838 + static void nfs_pageio_cleanup_mirroring(struct nfs_pageio_descriptor *pgio) 839 + { 840 + pgio->pg_mirror_count = 1; 841 + pgio->pg_mirror_idx = 0; 842 + pgio->pg_mirrors = pgio->pg_mirrors_static; 843 + kfree(pgio->pg_mirrors_dynamic); 844 + pgio->pg_mirrors_dynamic = NULL; 853 845 } 854 846 855 847 static bool nfs_match_open_context(const struct nfs_open_context *ctx1, ··· 961 867 static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, 962 868 struct nfs_page *req) 963 869 { 870 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 871 + 964 872 struct nfs_page *prev = NULL; 965 - if (desc->pg_count != 0) { 966 - prev = nfs_list_entry(desc->pg_list.prev); 873 + 874 + if (mirror->pg_count != 0) { 875 + prev = nfs_list_entry(mirror->pg_list.prev); 967 876 } else { 968 877 if (desc->pg_ops->pg_init) 969 878 desc->pg_ops->pg_init(desc, req); 970 - desc->pg_base = req->wb_pgbase; 879 + mirror->pg_base = req->wb_pgbase; 971 880 } 972 881 if (!nfs_can_coalesce_requests(prev, req, desc)) 973 882 return 0; 974 883 nfs_list_remove_request(req); 975 - nfs_list_add_request(req, &desc->pg_list); 976 - desc->pg_count += req->wb_bytes; 884 + nfs_list_add_request(req, &mirror->pg_list); 885 + mirror->pg_count += req->wb_bytes; 977 886 return 1; 978 887 } 979 888 ··· 985 888 */ 986 889 static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) 987 890 { 988 - if (!list_empty(&desc->pg_list)) { 891 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 892 + 893 + 894 + if (!list_empty(&mirror->pg_list)) { 989 895 int error = desc->pg_ops->pg_doio(desc); 990 896 if (error < 0) 991 897 desc->pg_error = error; 992 898 else 993 - desc->pg_bytes_written += desc->pg_count; 899 + mirror->pg_bytes_written += mirror->pg_count; 994 900 } 995 - if (list_empty(&desc->pg_list)) { 996 - desc->pg_count = 0; 997 - desc->pg_base = 0; 901 + if (list_empty(&mirror->pg_list)) { 902 + mirror->pg_count = 0; 903 + mirror->pg_base = 0; 998 904 } 999 905 } 1000 906 ··· 1015 915 static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, 1016 916 struct nfs_page *req) 1017 917 { 918 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 919 + 1018 920 struct nfs_page *subreq; 1019 921 unsigned int bytes_left = 0; 1020 922 unsigned int offset, pgbase; 923 + 924 + WARN_ON_ONCE(desc->pg_mirror_idx >= desc->pg_mirror_count); 1021 925 1022 926 nfs_page_group_lock(req, false); 1023 927 ··· 1042 938 nfs_pageio_doio(desc); 1043 939 if (desc->pg_error < 0) 1044 940 return 0; 1045 - if (desc->pg_recoalesce) 941 + if (mirror->pg_recoalesce) 1046 942 return 0; 1047 943 /* retry add_request for this subreq */ 1048 944 nfs_page_group_lock(req, false); ··· 1080 976 1081 977 static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) 1082 978 { 979 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 1083 980 LIST_HEAD(head); 1084 981 1085 982 do { 1086 - list_splice_init(&desc->pg_list, &head); 1087 - desc->pg_bytes_written -= desc->pg_count; 1088 - desc->pg_count = 0; 1089 - desc->pg_base = 0; 1090 - desc->pg_recoalesce = 0; 983 + list_splice_init(&mirror->pg_list, &head); 984 + mirror->pg_bytes_written -= mirror->pg_count; 985 + mirror->pg_count = 0; 986 + mirror->pg_base = 0; 987 + mirror->pg_recoalesce = 0; 988 + 1091 989 desc->pg_moreio = 0; 1092 990 1093 991 while (!list_empty(&head)) { ··· 1103 997 return 0; 1104 998 break; 1105 999 } 1106 - } while (desc->pg_recoalesce); 1000 + } while (mirror->pg_recoalesce); 1107 1001 return 1; 1108 1002 } 1109 1003 1110 - int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, 1004 + static int nfs_pageio_add_request_mirror(struct nfs_pageio_descriptor *desc, 1111 1005 struct nfs_page *req) 1112 1006 { 1113 1007 int ret; ··· 1120 1014 break; 1121 1015 ret = nfs_do_recoalesce(desc); 1122 1016 } while (ret); 1017 + 1123 1018 return ret; 1019 + } 1020 + 1021 + int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, 1022 + struct nfs_page *req) 1023 + { 1024 + u32 midx; 1025 + unsigned int pgbase, offset, bytes; 1026 + struct nfs_page *dupreq, *lastreq; 1027 + 1028 + pgbase = req->wb_pgbase; 1029 + offset = req->wb_offset; 1030 + bytes = req->wb_bytes; 1031 + 1032 + nfs_pageio_setup_mirroring(desc, req); 1033 + 1034 + for (midx = 0; midx < desc->pg_mirror_count; midx++) { 1035 + if (midx) { 1036 + nfs_page_group_lock(req, false); 1037 + 1038 + /* find the last request */ 1039 + for (lastreq = req->wb_head; 1040 + lastreq->wb_this_page != req->wb_head; 1041 + lastreq = lastreq->wb_this_page) 1042 + ; 1043 + 1044 + dupreq = nfs_create_request(req->wb_context, 1045 + req->wb_page, lastreq, pgbase, bytes); 1046 + 1047 + if (IS_ERR(dupreq)) { 1048 + nfs_page_group_unlock(req); 1049 + return 0; 1050 + } 1051 + 1052 + nfs_lock_request(dupreq); 1053 + nfs_page_group_unlock(req); 1054 + dupreq->wb_offset = offset; 1055 + dupreq->wb_index = req->wb_index; 1056 + } else 1057 + dupreq = req; 1058 + 1059 + desc->pg_mirror_idx = midx; 1060 + if (!nfs_pageio_add_request_mirror(desc, dupreq)) 1061 + return 0; 1062 + } 1063 + 1064 + return 1; 1065 + } 1066 + 1067 + /* 1068 + * nfs_pageio_complete_mirror - Complete I/O on the current mirror of an 1069 + * nfs_pageio_descriptor 1070 + * @desc: pointer to io descriptor 1071 + */ 1072 + static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc, 1073 + u32 mirror_idx) 1074 + { 1075 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[mirror_idx]; 1076 + u32 restore_idx = desc->pg_mirror_idx; 1077 + 1078 + desc->pg_mirror_idx = mirror_idx; 1079 + for (;;) { 1080 + nfs_pageio_doio(desc); 1081 + if (!mirror->pg_recoalesce) 1082 + break; 1083 + if (!nfs_do_recoalesce(desc)) 1084 + break; 1085 + } 1086 + desc->pg_mirror_idx = restore_idx; 1124 1087 } 1125 1088 1126 1089 /* ··· 1230 1055 */ 1231 1056 void nfs_pageio_complete(struct nfs_pageio_descriptor *desc) 1232 1057 { 1233 - for (;;) { 1234 - nfs_pageio_doio(desc); 1235 - if (!desc->pg_recoalesce) 1236 - break; 1237 - if (!nfs_do_recoalesce(desc)) 1238 - break; 1239 - } 1058 + u32 midx; 1059 + 1060 + for (midx = 0; midx < desc->pg_mirror_count; midx++) 1061 + nfs_pageio_complete_mirror(desc, midx); 1240 1062 1241 1063 if (desc->pg_ops->pg_cleanup) 1242 1064 desc->pg_ops->pg_cleanup(desc); 1065 + nfs_pageio_cleanup_mirroring(desc); 1243 1066 } 1244 1067 1245 1068 /** ··· 1253 1080 */ 1254 1081 void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index) 1255 1082 { 1256 - if (!list_empty(&desc->pg_list)) { 1257 - struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev); 1258 - if (index != prev->wb_index + 1) 1259 - nfs_pageio_complete(desc); 1083 + struct nfs_pgio_mirror *mirror; 1084 + struct nfs_page *prev; 1085 + u32 midx; 1086 + 1087 + for (midx = 0; midx < desc->pg_mirror_count; midx++) { 1088 + mirror = &desc->pg_mirrors[midx]; 1089 + if (!list_empty(&mirror->pg_list)) { 1090 + prev = nfs_list_entry(mirror->pg_list.prev); 1091 + if (index != prev->wb_index + 1) 1092 + nfs_pageio_complete_mirror(desc, midx); 1093 + } 1260 1094 } 1261 1095 } 1262 1096
+18 -8
fs/nfs/pnfs.c
··· 1646 1646 * of bytes (maximum @req->wb_bytes) that can be coalesced. 1647 1647 */ 1648 1648 size_t 1649 - pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, 1650 - struct nfs_page *req) 1649 + pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, 1650 + struct nfs_page *prev, struct nfs_page *req) 1651 1651 { 1652 1652 unsigned int size; 1653 1653 u64 seg_end, req_start, seg_left; ··· 1729 1729 pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, 1730 1730 struct nfs_pgio_header *hdr) 1731 1731 { 1732 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 1733 + 1732 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 1736 nfs_pageio_reset_write_mds(desc); 1735 - desc->pg_recoalesce = 1; 1737 + mirror->pg_recoalesce = 1; 1736 1738 } 1737 1739 nfs_pgio_data_destroy(hdr); 1738 1740 } ··· 1783 1781 int 1784 1782 pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) 1785 1783 { 1784 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 1785 + 1786 1786 struct nfs_pgio_header *hdr; 1787 1787 int ret; 1788 1788 1789 1789 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); 1790 1790 if (!hdr) { 1791 - desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1791 + desc->pg_completion_ops->error_cleanup(&mirror->pg_list); 1792 1792 return -ENOMEM; 1793 1793 } 1794 1794 nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); ··· 1799 1795 ret = nfs_generic_pgio(desc, hdr); 1800 1796 if (!ret) 1801 1797 pnfs_do_write(desc, hdr, desc->pg_ioflags); 1798 + 1802 1799 return ret; 1803 1800 } 1804 1801 EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); ··· 1844 1839 pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, 1845 1840 struct nfs_pgio_header *hdr) 1846 1841 { 1842 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 1843 + 1844 + 1847 1845 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { 1848 - list_splice_tail_init(&hdr->pages, &desc->pg_list); 1846 + list_splice_tail_init(&hdr->pages, &mirror->pg_list); 1849 1847 nfs_pageio_reset_read_mds(desc); 1850 - desc->pg_recoalesce = 1; 1848 + mirror->pg_recoalesce = 1; 1851 1849 } 1852 1850 nfs_pgio_data_destroy(hdr); 1853 1851 } ··· 1901 1893 int 1902 1894 pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) 1903 1895 { 1896 + struct nfs_pgio_mirror *mirror = &desc->pg_mirrors[desc->pg_mirror_idx]; 1897 + 1904 1898 struct nfs_pgio_header *hdr; 1905 1899 int ret; 1906 1900 1907 1901 hdr = nfs_pgio_header_alloc(desc->pg_rw_ops); 1908 1902 if (!hdr) { 1909 - desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1903 + desc->pg_completion_ops->error_cleanup(&mirror->pg_list); 1910 1904 return -ENOMEM; 1911 1905 } 1912 1906 nfs_pgheader_init(desc, hdr, pnfs_readhdr_free);
+25 -5
fs/nfs/read.c
··· 70 70 71 71 void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) 72 72 { 73 + struct nfs_pgio_mirror *mirror; 74 + 73 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 } 76 83 EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); 77 84 ··· 88 81 struct nfs_page *new; 89 82 unsigned int len; 90 83 struct nfs_pageio_descriptor pgio; 84 + struct nfs_pgio_mirror *pgm; 91 85 92 86 len = nfs_page_length(page); 93 87 if (len == 0) ··· 105 97 &nfs_async_read_completion_ops); 106 98 nfs_pageio_add_request(&pgio, new); 107 99 nfs_pageio_complete(&pgio); 108 - NFS_I(inode)->read_io += pgio.pg_bytes_written; 100 + 101 + /* It doesn't make sense to do mirrored reads! */ 102 + WARN_ON_ONCE(pgio.pg_mirror_count != 1); 103 + 104 + pgm = &pgio.pg_mirrors[0]; 105 + NFS_I(inode)->read_io += pgm->pg_bytes_written; 106 + 109 107 return 0; 110 108 } 111 109 ··· 366 352 struct list_head *pages, unsigned nr_pages) 367 353 { 368 354 struct nfs_pageio_descriptor pgio; 355 + struct nfs_pgio_mirror *pgm; 369 356 struct nfs_readdesc desc = { 370 357 .pgio = &pgio, 371 358 }; ··· 402 387 &nfs_async_read_completion_ops); 403 388 404 389 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); 405 - 406 390 nfs_pageio_complete(&pgio); 407 - NFS_I(inode)->read_io += pgio.pg_bytes_written; 408 - npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 391 + 392 + /* It doesn't make sense to do mirrored reads! */ 393 + WARN_ON_ONCE(pgio.pg_mirror_count != 1); 394 + 395 + pgm = &pgio.pg_mirrors[0]; 396 + NFS_I(inode)->read_io += pgm->pg_bytes_written; 397 + npages = (pgm->pg_bytes_written + PAGE_CACHE_SIZE - 1) >> 398 + PAGE_CACHE_SHIFT; 409 399 nfs_add_stats(inode, NFSIOS_READPAGES, npages); 410 400 read_complete: 411 401 put_nfs_open_context(desc.ctx);
+8 -2
fs/nfs/write.c
··· 906 906 if (nfs_write_need_commit(hdr)) { 907 907 memcpy(&req->wb_verf, &hdr->verf.verifier, sizeof(req->wb_verf)); 908 908 nfs_mark_request_commit(req, hdr->lseg, &cinfo, 909 - 0); 909 + hdr->pgio_mirror_idx); 910 910 goto next; 911 911 } 912 912 remove_req: ··· 1304 1304 1305 1305 void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) 1306 1306 { 1307 + struct nfs_pgio_mirror *mirror; 1308 + 1307 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 } 1310 1316 EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); 1311 1317
+17 -3
include/linux/nfs_page.h
··· 58 58 size_t (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, 59 59 struct nfs_page *); 60 60 int (*pg_doio)(struct nfs_pageio_descriptor *); 61 + unsigned int (*pg_get_mirror_count)(struct nfs_pageio_descriptor *, 62 + struct nfs_page *); 61 63 void (*pg_cleanup)(struct nfs_pageio_descriptor *); 62 64 }; 63 65 ··· 76 74 struct rpc_task_setup *, int); 77 75 }; 78 76 79 - struct nfs_pageio_descriptor { 77 + struct nfs_pgio_mirror { 80 78 struct list_head pg_list; 81 79 unsigned long pg_bytes_written; 82 80 size_t pg_count; 83 81 size_t pg_bsize; 84 82 unsigned int pg_base; 85 - unsigned char pg_moreio : 1, 86 - pg_recoalesce : 1; 83 + unsigned char pg_recoalesce : 1; 84 + }; 87 85 86 + struct nfs_pageio_descriptor { 87 + unsigned char pg_moreio : 1; 88 88 struct inode *pg_inode; 89 89 const struct nfs_pageio_ops *pg_ops; 90 90 const struct nfs_rw_ops *pg_rw_ops; ··· 97 93 struct pnfs_layout_segment *pg_lseg; 98 94 struct nfs_direct_req *pg_dreq; 99 95 void *pg_layout_private; 96 + unsigned int pg_bsize; /* default bsize for mirrors */ 97 + 98 + u32 pg_mirror_count; 99 + struct nfs_pgio_mirror *pg_mirrors; 100 + struct nfs_pgio_mirror pg_mirrors_static[1]; 101 + struct nfs_pgio_mirror *pg_mirrors_dynamic; 102 + u32 pg_mirror_idx; /* current mirror */ 100 103 }; 104 + 105 + /* arbitrarily selected limit to number of mirrors */ 106 + #define NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX 16 101 107 102 108 #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) 103 109
+1
include/linux/nfs_xdr.h
··· 1329 1329 struct nfs_page_array page_array; 1330 1330 struct nfs_client *ds_clp; /* pNFS data server */ 1331 1331 int ds_commit_idx; /* ds index if ds_clp is set */ 1332 + int pgio_mirror_idx;/* mirror index in pgio layer */ 1332 1333 }; 1333 1334 1334 1335 struct nfs_mds_commit_info {