| .. | .. |
|---|
| 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 * |
|---|
| .. | .. |
|---|
| 917 | 863 | pnfs_generic_pg_check_layout(pgio); |
|---|
| 918 | 864 | if (!pgio->pg_lseg) { |
|---|
| 919 | 865 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
|---|
| 920 | | - req->wb_context, |
|---|
| 866 | + nfs_req_openctx(req), |
|---|
| 921 | 867 | 0, |
|---|
| 922 | 868 | NFS4_MAX_UINT64, |
|---|
| 923 | 869 | IOMODE_READ, |
|---|
| .. | .. |
|---|
| 938 | 884 | filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, |
|---|
| 939 | 885 | struct nfs_page *req) |
|---|
| 940 | 886 | { |
|---|
| 941 | | - struct nfs_commit_info cinfo; |
|---|
| 942 | | - int status; |
|---|
| 943 | | - |
|---|
| 944 | 887 | pnfs_generic_pg_check_layout(pgio); |
|---|
| 945 | 888 | if (!pgio->pg_lseg) { |
|---|
| 946 | 889 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
|---|
| 947 | | - req->wb_context, |
|---|
| 890 | + nfs_req_openctx(req), |
|---|
| 948 | 891 | 0, |
|---|
| 949 | 892 | NFS4_MAX_UINT64, |
|---|
| 950 | 893 | IOMODE_RW, |
|---|
| .. | .. |
|---|
| 959 | 902 | |
|---|
| 960 | 903 | /* If no lseg, fall back to write through mds */ |
|---|
| 961 | 904 | 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); |
|---|
| 905 | + nfs_pageio_reset_write_mds(pgio); |
|---|
| 973 | 906 | } |
|---|
| 974 | 907 | |
|---|
| 975 | 908 | static const struct nfs_pageio_ops filelayout_pg_read_ops = { |
|---|
| .. | .. |
|---|
| 1078 | 1011 | return -EAGAIN; |
|---|
| 1079 | 1012 | } |
|---|
| 1080 | 1013 | |
|---|
| 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 | 1014 | static int |
|---|
| 1112 | 1015 | filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, |
|---|
| 1113 | 1016 | int how, struct nfs_commit_info *cinfo) |
|---|
| .. | .. |
|---|
| 1140 | 1043 | struct nfs4_filelayout *flo; |
|---|
| 1141 | 1044 | |
|---|
| 1142 | 1045 | flo = kzalloc(sizeof(*flo), gfp_flags); |
|---|
| 1143 | | - return flo != NULL ? &flo->generic_hdr : NULL; |
|---|
| 1046 | + if (flo == NULL) |
|---|
| 1047 | + return NULL; |
|---|
| 1048 | + pnfs_init_ds_commit_info(&flo->commit_info); |
|---|
| 1049 | + flo->commit_info.ops = &filelayout_commit_ops; |
|---|
| 1050 | + return &flo->generic_hdr; |
|---|
| 1144 | 1051 | } |
|---|
| 1145 | 1052 | |
|---|
| 1146 | 1053 | static void |
|---|
| 1147 | 1054 | filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo) |
|---|
| 1148 | 1055 | { |
|---|
| 1149 | | - kfree(FILELAYOUT_FROM_HDR(lo)); |
|---|
| 1056 | + kfree_rcu(FILELAYOUT_FROM_HDR(lo), generic_hdr.plh_rcu); |
|---|
| 1150 | 1057 | } |
|---|
| 1151 | 1058 | |
|---|
| 1152 | 1059 | static struct pnfs_ds_commit_info * |
|---|
| .. | .. |
|---|
| 1160 | 1067 | return &FILELAYOUT_FROM_HDR(layout)->commit_info; |
|---|
| 1161 | 1068 | } |
|---|
| 1162 | 1069 | |
|---|
| 1070 | +static void |
|---|
| 1071 | +filelayout_setup_ds_info(struct pnfs_ds_commit_info *fl_cinfo, |
|---|
| 1072 | + struct pnfs_layout_segment *lseg) |
|---|
| 1073 | +{ |
|---|
| 1074 | + struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
|---|
| 1075 | + struct inode *inode = lseg->pls_layout->plh_inode; |
|---|
| 1076 | + struct pnfs_commit_array *array, *new; |
|---|
| 1077 | + unsigned int size = (fl->stripe_type == STRIPE_SPARSE) ? |
|---|
| 1078 | + fl->dsaddr->ds_num : fl->dsaddr->stripe_count; |
|---|
| 1079 | + |
|---|
| 1080 | + new = pnfs_alloc_commit_array(size, GFP_NOIO); |
|---|
| 1081 | + if (new) { |
|---|
| 1082 | + spin_lock(&inode->i_lock); |
|---|
| 1083 | + array = pnfs_add_commit_array(fl_cinfo, new, lseg); |
|---|
| 1084 | + spin_unlock(&inode->i_lock); |
|---|
| 1085 | + if (array != new) |
|---|
| 1086 | + pnfs_free_commit_array(new); |
|---|
| 1087 | + } |
|---|
| 1088 | +} |
|---|
| 1089 | + |
|---|
| 1090 | +static void |
|---|
| 1091 | +filelayout_release_ds_info(struct pnfs_ds_commit_info *fl_cinfo, |
|---|
| 1092 | + struct inode *inode) |
|---|
| 1093 | +{ |
|---|
| 1094 | + spin_lock(&inode->i_lock); |
|---|
| 1095 | + pnfs_generic_ds_cinfo_destroy(fl_cinfo); |
|---|
| 1096 | + spin_unlock(&inode->i_lock); |
|---|
| 1097 | +} |
|---|
| 1098 | + |
|---|
| 1099 | +static const struct pnfs_commit_ops filelayout_commit_ops = { |
|---|
| 1100 | + .setup_ds_info = filelayout_setup_ds_info, |
|---|
| 1101 | + .release_ds_info = filelayout_release_ds_info, |
|---|
| 1102 | + .mark_request_commit = filelayout_mark_request_commit, |
|---|
| 1103 | + .clear_request_commit = pnfs_generic_clear_request_commit, |
|---|
| 1104 | + .scan_commit_lists = pnfs_generic_scan_commit_lists, |
|---|
| 1105 | + .recover_commit_reqs = pnfs_generic_recover_commit_reqs, |
|---|
| 1106 | + .search_commit_reqs = pnfs_generic_search_commit_reqs, |
|---|
| 1107 | + .commit_pagelist = filelayout_commit_pagelist, |
|---|
| 1108 | +}; |
|---|
| 1109 | + |
|---|
| 1163 | 1110 | static struct pnfs_layoutdriver_type filelayout_type = { |
|---|
| 1164 | 1111 | .id = LAYOUT_NFSV4_1_FILES, |
|---|
| 1165 | 1112 | .name = "LAYOUT_NFSV4_1_FILES", |
|---|
| 1166 | 1113 | .owner = THIS_MODULE, |
|---|
| 1114 | + .flags = PNFS_LAYOUTGET_ON_OPEN, |
|---|
| 1115 | + .max_layoutget_response = 4096, /* 1 page or so... */ |
|---|
| 1167 | 1116 | .alloc_layout_hdr = filelayout_alloc_layout_hdr, |
|---|
| 1168 | 1117 | .free_layout_hdr = filelayout_free_layout_hdr, |
|---|
| 1169 | 1118 | .alloc_lseg = filelayout_alloc_lseg, |
|---|
| .. | .. |
|---|
| 1171 | 1120 | .pg_read_ops = &filelayout_pg_read_ops, |
|---|
| 1172 | 1121 | .pg_write_ops = &filelayout_pg_write_ops, |
|---|
| 1173 | 1122 | .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 | 1123 | .read_pagelist = filelayout_read_pagelist, |
|---|
| 1181 | 1124 | .write_pagelist = filelayout_write_pagelist, |
|---|
| 1182 | 1125 | .alloc_deviceid_node = filelayout_alloc_deviceid_node, |
|---|