.. | .. |
---|
49 | 49 | MODULE_DESCRIPTION("The NFSv4 file layout driver"); |
---|
50 | 50 | |
---|
51 | 51 | #define FILELAYOUT_POLL_RETRY_MAX (15*HZ) |
---|
| 52 | +static const struct pnfs_commit_ops filelayout_commit_ops; |
---|
52 | 53 | |
---|
53 | 54 | static loff_t |
---|
54 | 55 | filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg, |
---|
.. | .. |
---|
186 | 187 | pnfs_error_mark_layout_for_return(inode, lseg); |
---|
187 | 188 | pnfs_set_lo_fail(lseg); |
---|
188 | 189 | rpc_wake_up(&tbl->slot_tbl_waitq); |
---|
189 | | - /* fall through */ |
---|
| 190 | + fallthrough; |
---|
190 | 191 | default: |
---|
191 | 192 | reset: |
---|
192 | 193 | dprintk("%s Retry through MDS. Error %d\n", __func__, |
---|
.. | .. |
---|
750 | 751 | /* This assumes a single RW lseg */ |
---|
751 | 752 | if (lseg->pls_range.iomode == IOMODE_RW) { |
---|
752 | 753 | struct nfs4_filelayout *flo; |
---|
| 754 | + struct inode *inode; |
---|
753 | 755 | |
---|
754 | 756 | flo = FILELAYOUT_FROM_HDR(lseg->pls_layout); |
---|
755 | | - flo->commit_info.nbuckets = 0; |
---|
756 | | - kfree(flo->commit_info.buckets); |
---|
757 | | - flo->commit_info.buckets = NULL; |
---|
| 757 | + inode = flo->generic_hdr.plh_inode; |
---|
| 758 | + spin_lock(&inode->i_lock); |
---|
| 759 | + pnfs_generic_ds_cinfo_release_lseg(&flo->commit_info, lseg); |
---|
| 760 | + spin_unlock(&inode->i_lock); |
---|
758 | 761 | } |
---|
759 | 762 | _filelayout_free_lseg(fl); |
---|
760 | | -} |
---|
761 | | - |
---|
762 | | -static int |
---|
763 | | -filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg, |
---|
764 | | - struct nfs_commit_info *cinfo, |
---|
765 | | - gfp_t gfp_flags) |
---|
766 | | -{ |
---|
767 | | - struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
---|
768 | | - struct pnfs_commit_bucket *buckets; |
---|
769 | | - int size, i; |
---|
770 | | - |
---|
771 | | - if (fl->commit_through_mds) |
---|
772 | | - return 0; |
---|
773 | | - |
---|
774 | | - size = (fl->stripe_type == STRIPE_SPARSE) ? |
---|
775 | | - fl->dsaddr->ds_num : fl->dsaddr->stripe_count; |
---|
776 | | - |
---|
777 | | - if (cinfo->ds->nbuckets >= size) { |
---|
778 | | - /* This assumes there is only one IOMODE_RW lseg. What |
---|
779 | | - * we really want to do is have a layout_hdr level |
---|
780 | | - * dictionary of <multipath_list4, fh> keys, each |
---|
781 | | - * associated with a struct list_head, populated by calls |
---|
782 | | - * to filelayout_write_pagelist(). |
---|
783 | | - * */ |
---|
784 | | - return 0; |
---|
785 | | - } |
---|
786 | | - |
---|
787 | | - buckets = kcalloc(size, sizeof(struct pnfs_commit_bucket), |
---|
788 | | - gfp_flags); |
---|
789 | | - if (!buckets) |
---|
790 | | - return -ENOMEM; |
---|
791 | | - for (i = 0; i < size; i++) { |
---|
792 | | - INIT_LIST_HEAD(&buckets[i].written); |
---|
793 | | - INIT_LIST_HEAD(&buckets[i].committing); |
---|
794 | | - /* mark direct verifier as unset */ |
---|
795 | | - buckets[i].direct_verf.committed = NFS_INVALID_STABLE_HOW; |
---|
796 | | - } |
---|
797 | | - |
---|
798 | | - spin_lock(&cinfo->inode->i_lock); |
---|
799 | | - if (cinfo->ds->nbuckets >= size) |
---|
800 | | - goto out; |
---|
801 | | - for (i = 0; i < cinfo->ds->nbuckets; i++) { |
---|
802 | | - list_splice(&cinfo->ds->buckets[i].written, |
---|
803 | | - &buckets[i].written); |
---|
804 | | - list_splice(&cinfo->ds->buckets[i].committing, |
---|
805 | | - &buckets[i].committing); |
---|
806 | | - buckets[i].direct_verf.committed = |
---|
807 | | - cinfo->ds->buckets[i].direct_verf.committed; |
---|
808 | | - buckets[i].wlseg = cinfo->ds->buckets[i].wlseg; |
---|
809 | | - buckets[i].clseg = cinfo->ds->buckets[i].clseg; |
---|
810 | | - } |
---|
811 | | - swap(cinfo->ds->buckets, buckets); |
---|
812 | | - cinfo->ds->nbuckets = size; |
---|
813 | | -out: |
---|
814 | | - spin_unlock(&cinfo->inode->i_lock); |
---|
815 | | - kfree(buckets); |
---|
816 | | - return 0; |
---|
817 | 763 | } |
---|
818 | 764 | |
---|
819 | 765 | static struct pnfs_layout_segment * |
---|
.. | .. |
---|
837 | 783 | return &fl->generic_hdr; |
---|
838 | 784 | } |
---|
839 | 785 | |
---|
| 786 | +static bool |
---|
| 787 | +filelayout_lseg_is_striped(const struct nfs4_filelayout_segment *flseg) |
---|
| 788 | +{ |
---|
| 789 | + return flseg->num_fh > 1; |
---|
| 790 | +} |
---|
| 791 | + |
---|
840 | 792 | /* |
---|
841 | 793 | * filelayout_pg_test(). Called by nfs_can_coalesce_requests() |
---|
842 | 794 | * |
---|
.. | .. |
---|
857 | 809 | size = pnfs_generic_pg_test(pgio, prev, req); |
---|
858 | 810 | if (!size) |
---|
859 | 811 | return 0; |
---|
| 812 | + else if (!filelayout_lseg_is_striped(FILELAYOUT_LSEG(pgio->pg_lseg))) |
---|
| 813 | + return size; |
---|
860 | 814 | |
---|
861 | 815 | /* see if req and prev are in the same stripe */ |
---|
862 | 816 | if (prev) { |
---|
.. | .. |
---|
917 | 871 | pnfs_generic_pg_check_layout(pgio); |
---|
918 | 872 | if (!pgio->pg_lseg) { |
---|
919 | 873 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
---|
920 | | - req->wb_context, |
---|
| 874 | + nfs_req_openctx(req), |
---|
921 | 875 | 0, |
---|
922 | 876 | NFS4_MAX_UINT64, |
---|
923 | 877 | IOMODE_READ, |
---|
.. | .. |
---|
938 | 892 | filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, |
---|
939 | 893 | struct nfs_page *req) |
---|
940 | 894 | { |
---|
941 | | - struct nfs_commit_info cinfo; |
---|
942 | | - int status; |
---|
943 | | - |
---|
944 | 895 | pnfs_generic_pg_check_layout(pgio); |
---|
945 | 896 | if (!pgio->pg_lseg) { |
---|
946 | 897 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
---|
947 | | - req->wb_context, |
---|
| 898 | + nfs_req_openctx(req), |
---|
948 | 899 | 0, |
---|
949 | 900 | NFS4_MAX_UINT64, |
---|
950 | 901 | IOMODE_RW, |
---|
.. | .. |
---|
959 | 910 | |
---|
960 | 911 | /* If no lseg, fall back to write through mds */ |
---|
961 | 912 | if (pgio->pg_lseg == NULL) |
---|
962 | | - goto out_mds; |
---|
963 | | - nfs_init_cinfo(&cinfo, pgio->pg_inode, pgio->pg_dreq); |
---|
964 | | - status = filelayout_alloc_commit_info(pgio->pg_lseg, &cinfo, GFP_NOFS); |
---|
965 | | - if (status < 0) { |
---|
966 | | - pnfs_put_lseg(pgio->pg_lseg); |
---|
967 | | - pgio->pg_lseg = NULL; |
---|
968 | | - goto out_mds; |
---|
969 | | - } |
---|
970 | | - return; |
---|
971 | | -out_mds: |
---|
972 | | - nfs_pageio_reset_write_mds(pgio); |
---|
| 913 | + nfs_pageio_reset_write_mds(pgio); |
---|
973 | 914 | } |
---|
974 | 915 | |
---|
975 | 916 | static const struct nfs_pageio_ops filelayout_pg_read_ops = { |
---|
.. | .. |
---|
1078 | 1019 | return -EAGAIN; |
---|
1079 | 1020 | } |
---|
1080 | 1021 | |
---|
1081 | | -/* filelayout_search_commit_reqs - Search lists in @cinfo for the head reqest |
---|
1082 | | - * for @page |
---|
1083 | | - * @cinfo - commit info for current inode |
---|
1084 | | - * @page - page to search for matching head request |
---|
1085 | | - * |
---|
1086 | | - * Returns a the head request if one is found, otherwise returns NULL. |
---|
1087 | | - */ |
---|
1088 | | -static struct nfs_page * |
---|
1089 | | -filelayout_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page) |
---|
1090 | | -{ |
---|
1091 | | - struct nfs_page *freq, *t; |
---|
1092 | | - struct pnfs_commit_bucket *b; |
---|
1093 | | - int i; |
---|
1094 | | - |
---|
1095 | | - /* Linearly search the commit lists for each bucket until a matching |
---|
1096 | | - * request is found */ |
---|
1097 | | - for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { |
---|
1098 | | - list_for_each_entry_safe(freq, t, &b->written, wb_list) { |
---|
1099 | | - if (freq->wb_page == page) |
---|
1100 | | - return freq->wb_head; |
---|
1101 | | - } |
---|
1102 | | - list_for_each_entry_safe(freq, t, &b->committing, wb_list) { |
---|
1103 | | - if (freq->wb_page == page) |
---|
1104 | | - return freq->wb_head; |
---|
1105 | | - } |
---|
1106 | | - } |
---|
1107 | | - |
---|
1108 | | - return NULL; |
---|
1109 | | -} |
---|
1110 | | - |
---|
1111 | 1022 | static int |
---|
1112 | 1023 | filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, |
---|
1113 | 1024 | int how, struct nfs_commit_info *cinfo) |
---|
.. | .. |
---|
1140 | 1051 | struct nfs4_filelayout *flo; |
---|
1141 | 1052 | |
---|
1142 | 1053 | flo = kzalloc(sizeof(*flo), gfp_flags); |
---|
1143 | | - return flo != NULL ? &flo->generic_hdr : NULL; |
---|
| 1054 | + if (flo == NULL) |
---|
| 1055 | + return NULL; |
---|
| 1056 | + pnfs_init_ds_commit_info(&flo->commit_info); |
---|
| 1057 | + flo->commit_info.ops = &filelayout_commit_ops; |
---|
| 1058 | + return &flo->generic_hdr; |
---|
1144 | 1059 | } |
---|
1145 | 1060 | |
---|
1146 | 1061 | static void |
---|
1147 | 1062 | filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo) |
---|
1148 | 1063 | { |
---|
1149 | | - kfree(FILELAYOUT_FROM_HDR(lo)); |
---|
| 1064 | + kfree_rcu(FILELAYOUT_FROM_HDR(lo), generic_hdr.plh_rcu); |
---|
1150 | 1065 | } |
---|
1151 | 1066 | |
---|
1152 | 1067 | static struct pnfs_ds_commit_info * |
---|
.. | .. |
---|
1160 | 1075 | return &FILELAYOUT_FROM_HDR(layout)->commit_info; |
---|
1161 | 1076 | } |
---|
1162 | 1077 | |
---|
| 1078 | +static void |
---|
| 1079 | +filelayout_setup_ds_info(struct pnfs_ds_commit_info *fl_cinfo, |
---|
| 1080 | + struct pnfs_layout_segment *lseg) |
---|
| 1081 | +{ |
---|
| 1082 | + struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
---|
| 1083 | + struct inode *inode = lseg->pls_layout->plh_inode; |
---|
| 1084 | + struct pnfs_commit_array *array, *new; |
---|
| 1085 | + unsigned int size = (fl->stripe_type == STRIPE_SPARSE) ? |
---|
| 1086 | + fl->dsaddr->ds_num : fl->dsaddr->stripe_count; |
---|
| 1087 | + |
---|
| 1088 | + new = pnfs_alloc_commit_array(size, GFP_NOIO); |
---|
| 1089 | + if (new) { |
---|
| 1090 | + spin_lock(&inode->i_lock); |
---|
| 1091 | + array = pnfs_add_commit_array(fl_cinfo, new, lseg); |
---|
| 1092 | + spin_unlock(&inode->i_lock); |
---|
| 1093 | + if (array != new) |
---|
| 1094 | + pnfs_free_commit_array(new); |
---|
| 1095 | + } |
---|
| 1096 | +} |
---|
| 1097 | + |
---|
| 1098 | +static void |
---|
| 1099 | +filelayout_release_ds_info(struct pnfs_ds_commit_info *fl_cinfo, |
---|
| 1100 | + struct inode *inode) |
---|
| 1101 | +{ |
---|
| 1102 | + spin_lock(&inode->i_lock); |
---|
| 1103 | + pnfs_generic_ds_cinfo_destroy(fl_cinfo); |
---|
| 1104 | + spin_unlock(&inode->i_lock); |
---|
| 1105 | +} |
---|
| 1106 | + |
---|
| 1107 | +static const struct pnfs_commit_ops filelayout_commit_ops = { |
---|
| 1108 | + .setup_ds_info = filelayout_setup_ds_info, |
---|
| 1109 | + .release_ds_info = filelayout_release_ds_info, |
---|
| 1110 | + .mark_request_commit = filelayout_mark_request_commit, |
---|
| 1111 | + .clear_request_commit = pnfs_generic_clear_request_commit, |
---|
| 1112 | + .scan_commit_lists = pnfs_generic_scan_commit_lists, |
---|
| 1113 | + .recover_commit_reqs = pnfs_generic_recover_commit_reqs, |
---|
| 1114 | + .search_commit_reqs = pnfs_generic_search_commit_reqs, |
---|
| 1115 | + .commit_pagelist = filelayout_commit_pagelist, |
---|
| 1116 | +}; |
---|
| 1117 | + |
---|
1163 | 1118 | static struct pnfs_layoutdriver_type filelayout_type = { |
---|
1164 | 1119 | .id = LAYOUT_NFSV4_1_FILES, |
---|
1165 | 1120 | .name = "LAYOUT_NFSV4_1_FILES", |
---|
1166 | 1121 | .owner = THIS_MODULE, |
---|
| 1122 | + .flags = PNFS_LAYOUTGET_ON_OPEN, |
---|
| 1123 | + .max_layoutget_response = 4096, /* 1 page or so... */ |
---|
1167 | 1124 | .alloc_layout_hdr = filelayout_alloc_layout_hdr, |
---|
1168 | 1125 | .free_layout_hdr = filelayout_free_layout_hdr, |
---|
1169 | 1126 | .alloc_lseg = filelayout_alloc_lseg, |
---|
.. | .. |
---|
1171 | 1128 | .pg_read_ops = &filelayout_pg_read_ops, |
---|
1172 | 1129 | .pg_write_ops = &filelayout_pg_write_ops, |
---|
1173 | 1130 | .get_ds_info = &filelayout_get_ds_info, |
---|
1174 | | - .mark_request_commit = filelayout_mark_request_commit, |
---|
1175 | | - .clear_request_commit = pnfs_generic_clear_request_commit, |
---|
1176 | | - .scan_commit_lists = pnfs_generic_scan_commit_lists, |
---|
1177 | | - .recover_commit_reqs = pnfs_generic_recover_commit_reqs, |
---|
1178 | | - .search_commit_reqs = filelayout_search_commit_reqs, |
---|
1179 | | - .commit_pagelist = filelayout_commit_pagelist, |
---|
1180 | 1131 | .read_pagelist = filelayout_read_pagelist, |
---|
1181 | 1132 | .write_pagelist = filelayout_write_pagelist, |
---|
1182 | 1133 | .alloc_deviceid_node = filelayout_alloc_deviceid_node, |
---|