| .. | .. |
|---|
| 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, |
|---|