aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayout.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4filelayout.c')
-rw-r--r--fs/nfs/nfs4filelayout.c119
1 files changed, 66 insertions, 53 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index e40523f2fe26..fe2cb55ca6b1 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -347,9 +347,11 @@ static void filelayout_commit_count_stats(struct rpc_task *task, void *data)
347static void filelayout_commit_release(void *calldata) 347static void filelayout_commit_release(void *calldata)
348{ 348{
349 struct nfs_commit_data *data = calldata; 349 struct nfs_commit_data *data = calldata;
350 struct nfs_commit_info cinfo;
350 351
351 nfs_commit_release_pages(data); 352 nfs_commit_release_pages(data);
352 if (atomic_dec_and_test(&NFS_I(data->inode)->commits_outstanding)) 353 nfs_init_cinfo(&cinfo, data->inode, data->dreq);
354 if (atomic_dec_and_test(&cinfo.mds->rpcs_out))
353 nfs_commit_clear_lock(NFS_I(data->inode)); 355 nfs_commit_clear_lock(NFS_I(data->inode));
354 put_lseg(data->lseg); 356 put_lseg(data->lseg);
355 nfs_commitdata_release(data); 357 nfs_commitdata_release(data);
@@ -695,17 +697,16 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)
695 697
696static int 698static int
697filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg, 699filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
700 struct nfs_commit_info *cinfo,
698 gfp_t gfp_flags) 701 gfp_t gfp_flags)
699{ 702{
700 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); 703 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
701 struct nfs4_filelayout *flo = FILELAYOUT_FROM_HDR(lseg->pls_layout); 704 struct pnfs_commit_bucket *buckets;
702
703 struct nfs4_fl_commit_bucket *buckets;
704 int size; 705 int size;
705 706
706 if (fl->commit_through_mds) 707 if (fl->commit_through_mds)
707 return 0; 708 return 0;
708 if (flo->commit_info.nbuckets != 0) { 709 if (cinfo->ds->nbuckets != 0) {
709 /* This assumes there is only one IOMODE_RW lseg. What 710 /* This assumes there is only one IOMODE_RW lseg. What
710 * we really want to do is have a layout_hdr level 711 * we really want to do is have a layout_hdr level
711 * dictionary of <multipath_list4, fh> keys, each 712 * dictionary of <multipath_list4, fh> keys, each
@@ -718,25 +719,25 @@ filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
718 size = (fl->stripe_type == STRIPE_SPARSE) ? 719 size = (fl->stripe_type == STRIPE_SPARSE) ?
719 fl->dsaddr->ds_num : fl->dsaddr->stripe_count; 720 fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
720 721
721 buckets = kcalloc(size, sizeof(struct nfs4_fl_commit_bucket), 722 buckets = kcalloc(size, sizeof(struct pnfs_commit_bucket),
722 gfp_flags); 723 gfp_flags);
723 if (!buckets) 724 if (!buckets)
724 return -ENOMEM; 725 return -ENOMEM;
725 else { 726 else {
726 int i; 727 int i;
727 728
728 spin_lock(&lseg->pls_layout->plh_inode->i_lock); 729 spin_lock(cinfo->lock);
729 if (flo->commit_info.nbuckets != 0) 730 if (cinfo->ds->nbuckets != 0)
730 kfree(buckets); 731 kfree(buckets);
731 else { 732 else {
732 flo->commit_info.buckets = buckets; 733 cinfo->ds->buckets = buckets;
733 flo->commit_info.nbuckets = size; 734 cinfo->ds->nbuckets = size;
734 for (i = 0; i < size; i++) { 735 for (i = 0; i < size; i++) {
735 INIT_LIST_HEAD(&buckets[i].written); 736 INIT_LIST_HEAD(&buckets[i].written);
736 INIT_LIST_HEAD(&buckets[i].committing); 737 INIT_LIST_HEAD(&buckets[i].committing);
737 } 738 }
738 } 739 }
739 spin_unlock(&lseg->pls_layout->plh_inode->i_lock); 740 spin_unlock(cinfo->lock);
740 return 0; 741 return 0;
741 } 742 }
742} 743}
@@ -821,6 +822,7 @@ static void
821filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, 822filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
822 struct nfs_page *req) 823 struct nfs_page *req)
823{ 824{
825 struct nfs_commit_info cinfo;
824 int status; 826 int status;
825 827
826 BUG_ON(pgio->pg_lseg != NULL); 828 BUG_ON(pgio->pg_lseg != NULL);
@@ -836,7 +838,8 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
836 /* If no lseg, fall back to write through mds */ 838 /* If no lseg, fall back to write through mds */
837 if (pgio->pg_lseg == NULL) 839 if (pgio->pg_lseg == NULL)
838 goto out_mds; 840 goto out_mds;
839 status = filelayout_alloc_commit_info(pgio->pg_lseg, GFP_NOFS); 841 nfs_init_cinfo(&cinfo, pgio->pg_inode, pgio->pg_dreq);
842 status = filelayout_alloc_commit_info(pgio->pg_lseg, &cinfo, GFP_NOFS);
840 if (status < 0) { 843 if (status < 0) {
841 put_lseg(pgio->pg_lseg); 844 put_lseg(pgio->pg_lseg);
842 pgio->pg_lseg = NULL; 845 pgio->pg_lseg = NULL;
@@ -871,40 +874,42 @@ static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j)
871 * If this will make the bucket empty, it will need to put the lseg reference. 874 * If this will make the bucket empty, it will need to put the lseg reference.
872 */ 875 */
873static void 876static void
874filelayout_clear_request_commit(struct nfs_page *req) 877filelayout_clear_request_commit(struct nfs_page *req,
878 struct nfs_commit_info *cinfo)
875{ 879{
876 struct pnfs_layout_segment *freeme = NULL; 880 struct pnfs_layout_segment *freeme = NULL;
877 struct inode *inode = req->wb_context->dentry->d_inode;
878 881
879 spin_lock(&inode->i_lock); 882 spin_lock(cinfo->lock);
880 if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags)) 883 if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags))
881 goto out; 884 goto out;
885 cinfo->ds->nwritten--;
882 if (list_is_singular(&req->wb_list)) { 886 if (list_is_singular(&req->wb_list)) {
883 struct nfs4_fl_commit_bucket *bucket; 887 struct pnfs_commit_bucket *bucket;
884 888
885 bucket = list_first_entry(&req->wb_list, 889 bucket = list_first_entry(&req->wb_list,
886 struct nfs4_fl_commit_bucket, 890 struct pnfs_commit_bucket,
887 written); 891 written);
888 freeme = bucket->wlseg; 892 freeme = bucket->wlseg;
889 bucket->wlseg = NULL; 893 bucket->wlseg = NULL;
890 } 894 }
891out: 895out:
892 nfs_request_remove_commit_list(req); 896 nfs_request_remove_commit_list(req, cinfo);
893 spin_unlock(&inode->i_lock); 897 spin_unlock(cinfo->lock);
894 put_lseg(freeme); 898 put_lseg(freeme);
895} 899}
896 900
897static struct list_head * 901static struct list_head *
898filelayout_choose_commit_list(struct nfs_page *req, 902filelayout_choose_commit_list(struct nfs_page *req,
899 struct pnfs_layout_segment *lseg) 903 struct pnfs_layout_segment *lseg,
904 struct nfs_commit_info *cinfo)
900{ 905{
901 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); 906 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
902 u32 i, j; 907 u32 i, j;
903 struct list_head *list; 908 struct list_head *list;
904 struct nfs4_fl_commit_bucket *buckets; 909 struct pnfs_commit_bucket *buckets;
905 910
906 if (fl->commit_through_mds) 911 if (fl->commit_through_mds)
907 return &NFS_I(req->wb_context->dentry->d_inode)->commit_list; 912 return &cinfo->mds->list;
908 913
909 /* Note that we are calling nfs4_fl_calc_j_index on each page 914 /* Note that we are calling nfs4_fl_calc_j_index on each page
910 * that ends up being committed to a data server. An attractive 915 * that ends up being committed to a data server. An attractive
@@ -914,7 +919,7 @@ filelayout_choose_commit_list(struct nfs_page *req,
914 */ 919 */
915 j = nfs4_fl_calc_j_index(lseg, req_offset(req)); 920 j = nfs4_fl_calc_j_index(lseg, req_offset(req));
916 i = select_bucket_index(fl, j); 921 i = select_bucket_index(fl, j);
917 buckets = FILELAYOUT_FROM_HDR(lseg->pls_layout)->commit_info.buckets; 922 buckets = cinfo->ds->buckets;
918 list = &buckets[i].written; 923 list = &buckets[i].written;
919 if (list_empty(list)) { 924 if (list_empty(list)) {
920 /* Non-empty buckets hold a reference on the lseg. That ref 925 /* Non-empty buckets hold a reference on the lseg. That ref
@@ -926,17 +931,19 @@ filelayout_choose_commit_list(struct nfs_page *req,
926 buckets[i].wlseg = get_lseg(lseg); 931 buckets[i].wlseg = get_lseg(lseg);
927 } 932 }
928 set_bit(PG_COMMIT_TO_DS, &req->wb_flags); 933 set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
934 cinfo->ds->nwritten++;
929 return list; 935 return list;
930} 936}
931 937
932static void 938static void
933filelayout_mark_request_commit(struct nfs_page *req, 939filelayout_mark_request_commit(struct nfs_page *req,
934 struct pnfs_layout_segment *lseg) 940 struct pnfs_layout_segment *lseg,
941 struct nfs_commit_info *cinfo)
935{ 942{
936 struct list_head *list; 943 struct list_head *list;
937 944
938 list = filelayout_choose_commit_list(req, lseg); 945 list = filelayout_choose_commit_list(req, lseg, cinfo);
939 nfs_request_add_commit_list(req, list); 946 nfs_request_add_commit_list(req, list, cinfo);
940} 947}
941 948
942static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) 949static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
@@ -993,8 +1000,9 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
993} 1000}
994 1001
995static int 1002static int
996filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max, 1003filelayout_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
997 spinlock_t *lock) 1004 struct nfs_commit_info *cinfo,
1005 int max)
998{ 1006{
999 struct list_head *src = &bucket->written; 1007 struct list_head *src = &bucket->written;
1000 struct list_head *dst = &bucket->committing; 1008 struct list_head *dst = &bucket->committing;
@@ -1004,9 +1012,9 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
1004 list_for_each_entry_safe(req, tmp, src, wb_list) { 1012 list_for_each_entry_safe(req, tmp, src, wb_list) {
1005 if (!nfs_lock_request(req)) 1013 if (!nfs_lock_request(req))
1006 continue; 1014 continue;
1007 if (cond_resched_lock(lock)) 1015 if (cond_resched_lock(cinfo->lock))
1008 list_safe_reset_next(req, tmp, wb_list); 1016 list_safe_reset_next(req, tmp, wb_list);
1009 nfs_request_remove_commit_list(req); 1017 nfs_request_remove_commit_list(req, cinfo);
1010 clear_bit(PG_COMMIT_TO_DS, &req->wb_flags); 1018 clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
1011 nfs_list_add_request(req, dst); 1019 nfs_list_add_request(req, dst);
1012 ret++; 1020 ret++;
@@ -1014,6 +1022,8 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
1014 break; 1022 break;
1015 } 1023 }
1016 if (ret) { 1024 if (ret) {
1025 cinfo->ds->nwritten -= ret;
1026 cinfo->ds->ncommitting += ret;
1017 bucket->clseg = bucket->wlseg; 1027 bucket->clseg = bucket->wlseg;
1018 if (list_empty(src)) 1028 if (list_empty(src))
1019 bucket->wlseg = NULL; 1029 bucket->wlseg = NULL;
@@ -1024,37 +1034,32 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
1024} 1034}
1025 1035
1026/* Move reqs from written to committing lists, returning count of number moved. 1036/* Move reqs from written to committing lists, returning count of number moved.
1027 * Note called with i_lock held. 1037 * Note called with cinfo->lock held.
1028 */ 1038 */
1029static int filelayout_scan_commit_lists(struct inode *inode, int max, 1039static int filelayout_scan_commit_lists(struct nfs_commit_info *cinfo,
1030 spinlock_t *lock) 1040 int max)
1031{ 1041{
1032 struct nfs4_fl_commit_info *fl_cinfo;
1033 int i, rv = 0, cnt; 1042 int i, rv = 0, cnt;
1034 1043
1035 fl_cinfo = &FILELAYOUT_FROM_HDR(NFS_I(inode)->layout)->commit_info; 1044 for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
1036 if (fl_cinfo->nbuckets == 0) 1045 cnt = filelayout_scan_ds_commit_list(&cinfo->ds->buckets[i],
1037 goto out_done; 1046 cinfo, max);
1038 for (i = 0; i < fl_cinfo->nbuckets && max != 0; i++) {
1039 cnt = filelayout_scan_ds_commit_list(&fl_cinfo->buckets[i],
1040 max, lock);
1041 max -= cnt; 1047 max -= cnt;
1042 rv += cnt; 1048 rv += cnt;
1043 } 1049 }
1044out_done:
1045 return rv; 1050 return rv;
1046} 1051}
1047 1052
1048static unsigned int 1053static unsigned int
1049alloc_ds_commits(struct inode *inode, struct list_head *list) 1054alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list)
1050{ 1055{
1051 struct nfs4_fl_commit_info *fl_cinfo; 1056 struct pnfs_ds_commit_info *fl_cinfo;
1052 struct nfs4_fl_commit_bucket *bucket; 1057 struct pnfs_commit_bucket *bucket;
1053 struct nfs_commit_data *data; 1058 struct nfs_commit_data *data;
1054 int i, j; 1059 int i, j;
1055 unsigned int nreq = 0; 1060 unsigned int nreq = 0;
1056 1061
1057 fl_cinfo = &FILELAYOUT_FROM_HDR(NFS_I(inode)->layout)->commit_info; 1062 fl_cinfo = cinfo->ds;
1058 bucket = fl_cinfo->buckets; 1063 bucket = fl_cinfo->buckets;
1059 for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) { 1064 for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) {
1060 if (list_empty(&bucket->committing)) 1065 if (list_empty(&bucket->committing))
@@ -1073,7 +1078,7 @@ alloc_ds_commits(struct inode *inode, struct list_head *list)
1073 for (j = i; j < fl_cinfo->nbuckets; j++, bucket++) { 1078 for (j = i; j < fl_cinfo->nbuckets; j++, bucket++) {
1074 if (list_empty(&bucket->committing)) 1079 if (list_empty(&bucket->committing))
1075 continue; 1080 continue;
1076 nfs_retry_commit(&bucket->committing, bucket->clseg); 1081 nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo);
1077 put_lseg(bucket->clseg); 1082 put_lseg(bucket->clseg);
1078 bucket->clseg = NULL; 1083 bucket->clseg = NULL;
1079 } 1084 }
@@ -1084,7 +1089,7 @@ alloc_ds_commits(struct inode *inode, struct list_head *list)
1084/* This follows nfs_commit_list pretty closely */ 1089/* This follows nfs_commit_list pretty closely */
1085static int 1090static int
1086filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, 1091filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1087 int how) 1092 int how, struct nfs_commit_info *cinfo)
1088{ 1093{
1089 struct nfs_commit_data *data, *tmp; 1094 struct nfs_commit_data *data, *tmp;
1090 LIST_HEAD(list); 1095 LIST_HEAD(list);
@@ -1097,17 +1102,17 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1097 list_add(&data->pages, &list); 1102 list_add(&data->pages, &list);
1098 nreq++; 1103 nreq++;
1099 } else 1104 } else
1100 nfs_retry_commit(mds_pages, NULL); 1105 nfs_retry_commit(mds_pages, NULL, cinfo);
1101 } 1106 }
1102 1107
1103 nreq += alloc_ds_commits(inode, &list); 1108 nreq += alloc_ds_commits(cinfo, &list);
1104 1109
1105 if (nreq == 0) { 1110 if (nreq == 0) {
1106 nfs_commit_clear_lock(NFS_I(inode)); 1111 nfs_commit_clear_lock(NFS_I(inode));
1107 goto out; 1112 goto out;
1108 } 1113 }
1109 1114
1110 atomic_add(nreq, &NFS_I(inode)->commits_outstanding); 1115 atomic_add(nreq, &cinfo->mds->rpcs_out);
1111 1116
1112 list_for_each_entry_safe(data, tmp, &list, pages) { 1117 list_for_each_entry_safe(data, tmp, &list, pages) {
1113 list_del_init(&data->pages); 1118 list_del_init(&data->pages);
@@ -1116,14 +1121,15 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1116 nfs_initiate_commit(NFS_CLIENT(inode), data, 1121 nfs_initiate_commit(NFS_CLIENT(inode), data,
1117 data->mds_ops, how); 1122 data->mds_ops, how);
1118 } else { 1123 } else {
1119 struct nfs4_fl_commit_info *fl_cinfo; 1124 struct pnfs_commit_bucket *buckets;
1120 1125
1121 fl_cinfo = &FILELAYOUT_FROM_HDR(data->lseg->pls_layout)->commit_info; 1126 buckets = cinfo->ds->buckets;
1122 nfs_init_commit(data, &fl_cinfo->buckets[data->ds_commit_index].committing, data->lseg); 1127 nfs_init_commit(data, &buckets[data->ds_commit_index].committing, data->lseg);
1123 filelayout_initiate_commit(data, how); 1128 filelayout_initiate_commit(data, how);
1124 } 1129 }
1125 } 1130 }
1126out: 1131out:
1132 cinfo->ds->ncommitting = 0;
1127 return PNFS_ATTEMPTED; 1133 return PNFS_ATTEMPTED;
1128} 1134}
1129 1135
@@ -1148,6 +1154,12 @@ filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
1148 kfree(FILELAYOUT_FROM_HDR(lo)); 1154 kfree(FILELAYOUT_FROM_HDR(lo));
1149} 1155}
1150 1156
1157static struct pnfs_ds_commit_info *
1158filelayout_get_ds_info(struct inode *inode)
1159{
1160 return &FILELAYOUT_FROM_HDR(NFS_I(inode)->layout)->commit_info;
1161}
1162
1151static struct pnfs_layoutdriver_type filelayout_type = { 1163static struct pnfs_layoutdriver_type filelayout_type = {
1152 .id = LAYOUT_NFSV4_1_FILES, 1164 .id = LAYOUT_NFSV4_1_FILES,
1153 .name = "LAYOUT_NFSV4_1_FILES", 1165 .name = "LAYOUT_NFSV4_1_FILES",
@@ -1158,6 +1170,7 @@ static struct pnfs_layoutdriver_type filelayout_type = {
1158 .free_lseg = filelayout_free_lseg, 1170 .free_lseg = filelayout_free_lseg,
1159 .pg_read_ops = &filelayout_pg_read_ops, 1171 .pg_read_ops = &filelayout_pg_read_ops,
1160 .pg_write_ops = &filelayout_pg_write_ops, 1172 .pg_write_ops = &filelayout_pg_write_ops,
1173 .get_ds_info = &filelayout_get_ds_info,
1161 .mark_request_commit = filelayout_mark_request_commit, 1174 .mark_request_commit = filelayout_mark_request_commit,
1162 .clear_request_commit = filelayout_clear_request_commit, 1175 .clear_request_commit = filelayout_clear_request_commit,
1163 .scan_commit_lists = filelayout_scan_commit_lists, 1176 .scan_commit_lists = filelayout_scan_commit_lists,