aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayout.c
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2012-04-20 14:47:53 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-27 14:10:38 -0400
commitea2cf2282b4278461266013e9c002ee1c66700ff (patch)
tree244de055925710de27206ee0d5d09caa6353bd62 /fs/nfs/nfs4filelayout.c
parent84c53ab5c093058c756dcef1879d38be6de90a3c (diff)
NFS: create struct nfs_commit_info
It is COMMIT that is handled the most differently between the paged and direct paths. Create a structure that encapsulates everything either path needs to know about the commit state. We could use void to hide some of the layout driver stuff, but Trond suggests pulling it out to ensure type checking, given the huge changes being made, and the fact that it doesn't interfere with other drivers. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
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,