aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/inode.c6
-rw-r--r--fs/nfs/internal.h12
-rw-r--r--fs/nfs/nfs4filelayout.c119
-rw-r--r--fs/nfs/nfs4filelayout.h14
-rw-r--r--fs/nfs/pnfs.h72
-rw-r--r--fs/nfs/write.c158
-rw-r--r--include/linux/nfs_fs.h5
-rw-r--r--include/linux/nfs_xdr.h27
8 files changed, 248 insertions, 165 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index e8bbfa5b3500..59a12c6a8df6 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1547,7 +1547,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
1547 nfsi->delegation_state = 0; 1547 nfsi->delegation_state = 0;
1548 init_rwsem(&nfsi->rwsem); 1548 init_rwsem(&nfsi->rwsem);
1549 nfsi->layout = NULL; 1549 nfsi->layout = NULL;
1550 atomic_set(&nfsi->commits_outstanding, 0); 1550 atomic_set(&nfsi->commit_info.rpcs_out, 0);
1551#endif 1551#endif
1552} 1552}
1553 1553
@@ -1559,9 +1559,9 @@ static void init_once(void *foo)
1559 INIT_LIST_HEAD(&nfsi->open_files); 1559 INIT_LIST_HEAD(&nfsi->open_files);
1560 INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); 1560 INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
1561 INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); 1561 INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
1562 INIT_LIST_HEAD(&nfsi->commit_list); 1562 INIT_LIST_HEAD(&nfsi->commit_info.list);
1563 nfsi->npages = 0; 1563 nfsi->npages = 0;
1564 nfsi->ncommit = 0; 1564 nfsi->commit_info.ncommit = 0;
1565 atomic_set(&nfsi->silly_count, 1); 1565 atomic_set(&nfsi->silly_count, 1);
1566 INIT_HLIST_HEAD(&nfsi->silly_list); 1566 INIT_HLIST_HEAD(&nfsi->silly_list);
1567 init_waitqueue_head(&nfsi->waitqueue); 1567 init_waitqueue_head(&nfsi->waitqueue);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index cd5d4a300bc9..145e9e7dc8ce 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -346,12 +346,18 @@ extern void nfs_init_commit(struct nfs_commit_data *data,
346 struct list_head *head, 346 struct list_head *head,
347 struct pnfs_layout_segment *lseg); 347 struct pnfs_layout_segment *lseg);
348void nfs_retry_commit(struct list_head *page_list, 348void nfs_retry_commit(struct list_head *page_list,
349 struct pnfs_layout_segment *lseg); 349 struct pnfs_layout_segment *lseg,
350 struct nfs_commit_info *cinfo);
350void nfs_commit_clear_lock(struct nfs_inode *nfsi); 351void nfs_commit_clear_lock(struct nfs_inode *nfsi);
351void nfs_commitdata_release(struct nfs_commit_data *data); 352void nfs_commitdata_release(struct nfs_commit_data *data);
352void nfs_commit_release_pages(struct nfs_commit_data *data); 353void nfs_commit_release_pages(struct nfs_commit_data *data);
353void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *head); 354void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst,
354void nfs_request_remove_commit_list(struct nfs_page *req); 355 struct nfs_commit_info *cinfo);
356void nfs_request_remove_commit_list(struct nfs_page *req,
357 struct nfs_commit_info *cinfo);
358void nfs_init_cinfo(struct nfs_commit_info *cinfo,
359 struct inode *inode,
360 struct nfs_direct_req *dreq);
355 361
356#ifdef CONFIG_MIGRATION 362#ifdef CONFIG_MIGRATION
357extern int nfs_migrate_page(struct address_space *, 363extern int nfs_migrate_page(struct address_space *,
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,
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 333a3ac97606..96b89bbddf4f 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -74,18 +74,6 @@ struct nfs4_file_layout_dsaddr {
74 struct nfs4_pnfs_ds *ds_list[1]; 74 struct nfs4_pnfs_ds *ds_list[1];
75}; 75};
76 76
77struct nfs4_fl_commit_bucket {
78 struct list_head written;
79 struct list_head committing;
80 struct pnfs_layout_segment *wlseg;
81 struct pnfs_layout_segment *clseg;
82};
83
84struct nfs4_fl_commit_info {
85 int nbuckets;
86 struct nfs4_fl_commit_bucket *buckets;
87};
88
89struct nfs4_filelayout_segment { 77struct nfs4_filelayout_segment {
90 struct pnfs_layout_segment generic_hdr; 78 struct pnfs_layout_segment generic_hdr;
91 u32 stripe_type; 79 u32 stripe_type;
@@ -100,7 +88,7 @@ struct nfs4_filelayout_segment {
100 88
101struct nfs4_filelayout { 89struct nfs4_filelayout {
102 struct pnfs_layout_hdr generic_hdr; 90 struct pnfs_layout_hdr generic_hdr;
103 struct nfs4_fl_commit_info commit_info; 91 struct pnfs_ds_commit_info commit_info;
104}; 92};
105 93
106static inline struct nfs4_filelayout * 94static inline struct nfs4_filelayout *
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 734e4eff7fb0..4cd8760c2f89 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -94,11 +94,18 @@ struct pnfs_layoutdriver_type {
94 const struct nfs_pageio_ops *pg_read_ops; 94 const struct nfs_pageio_ops *pg_read_ops;
95 const struct nfs_pageio_ops *pg_write_ops; 95 const struct nfs_pageio_ops *pg_write_ops;
96 96
97 struct pnfs_ds_commit_info *(*get_ds_info) (struct inode *inode);
97 void (*mark_request_commit) (struct nfs_page *req, 98 void (*mark_request_commit) (struct nfs_page *req,
98 struct pnfs_layout_segment *lseg); 99 struct pnfs_layout_segment *lseg,
99 void (*clear_request_commit) (struct nfs_page *req); 100 struct nfs_commit_info *cinfo);
100 int (*scan_commit_lists) (struct inode *inode, int max, spinlock_t *lock); 101 void (*clear_request_commit) (struct nfs_page *req,
101 int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how); 102 struct nfs_commit_info *cinfo);
103 int (*scan_commit_lists) (struct nfs_commit_info *cinfo,
104 int max);
105 int (*commit_pagelist)(struct inode *inode,
106 struct list_head *mds_pages,
107 int how,
108 struct nfs_commit_info *cinfo);
102 109
103 /* 110 /*
104 * Return PNFS_ATTEMPTED to indicate the layout code has attempted 111 * Return PNFS_ATTEMPTED to indicate the layout code has attempted
@@ -263,49 +270,57 @@ static inline int pnfs_enabled_sb(struct nfs_server *nfss)
263} 270}
264 271
265static inline int 272static inline int
266pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how) 273pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how,
274 struct nfs_commit_info *cinfo)
267{ 275{
268 if (!test_and_clear_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags)) 276 if (cinfo->ds == NULL || cinfo->ds->ncommitting == 0)
269 return PNFS_NOT_ATTEMPTED; 277 return PNFS_NOT_ATTEMPTED;
270 return NFS_SERVER(inode)->pnfs_curr_ld->commit_pagelist(inode, mds_pages, how); 278 return NFS_SERVER(inode)->pnfs_curr_ld->commit_pagelist(inode, mds_pages, how, cinfo);
279}
280
281static inline struct pnfs_ds_commit_info *
282pnfs_get_ds_info(struct inode *inode)
283{
284 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
285
286 if (ld == NULL || ld->get_ds_info == NULL)
287 return NULL;
288 return ld->get_ds_info(inode);
271} 289}
272 290
273static inline bool 291static inline bool
274pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) 292pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
293 struct nfs_commit_info *cinfo)
275{ 294{
276 struct inode *inode = req->wb_context->dentry->d_inode; 295 struct inode *inode = req->wb_context->dentry->d_inode;
277 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; 296 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
278 297
279 if (lseg == NULL || ld->mark_request_commit == NULL) 298 if (lseg == NULL || ld->mark_request_commit == NULL)
280 return false; 299 return false;
281 ld->mark_request_commit(req, lseg); 300 ld->mark_request_commit(req, lseg, cinfo);
282 return true; 301 return true;
283} 302}
284 303
285static inline bool 304static inline bool
286pnfs_clear_request_commit(struct nfs_page *req) 305pnfs_clear_request_commit(struct nfs_page *req, struct nfs_commit_info *cinfo)
287{ 306{
288 struct inode *inode = req->wb_context->dentry->d_inode; 307 struct inode *inode = req->wb_context->dentry->d_inode;
289 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; 308 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
290 309
291 if (ld == NULL || ld->clear_request_commit == NULL) 310 if (ld == NULL || ld->clear_request_commit == NULL)
292 return false; 311 return false;
293 ld->clear_request_commit(req); 312 ld->clear_request_commit(req, cinfo);
294 return true; 313 return true;
295} 314}
296 315
297static inline int 316static inline int
298pnfs_scan_commit_lists(struct inode *inode, int max, spinlock_t *lock) 317pnfs_scan_commit_lists(struct inode *inode, struct nfs_commit_info *cinfo,
318 int max)
299{ 319{
300 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; 320 if (cinfo->ds == NULL || cinfo->ds->nwritten == 0)
301 int ret;
302
303 if (ld == NULL || ld->scan_commit_lists == NULL)
304 return 0; 321 return 0;
305 ret = ld->scan_commit_lists(inode, max, lock); 322 else
306 if (ret != 0) 323 return NFS_SERVER(inode)->pnfs_curr_ld->scan_commit_lists(cinfo, max);
307 set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags);
308 return ret;
309} 324}
310 325
311/* Should the pNFS client commit and return the layout upon a setattr */ 326/* Should the pNFS client commit and return the layout upon a setattr */
@@ -409,25 +424,34 @@ static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, st
409} 424}
410 425
411static inline int 426static inline int
412pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how) 427pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how,
428 struct nfs_commit_info *cinfo)
413{ 429{
414 return PNFS_NOT_ATTEMPTED; 430 return PNFS_NOT_ATTEMPTED;
415} 431}
416 432
433static inline struct pnfs_ds_commit_info *
434pnfs_get_ds_info(struct inode *inode)
435{
436 return NULL;
437}
438
417static inline bool 439static inline bool
418pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) 440pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
441 struct nfs_commit_info *cinfo)
419{ 442{
420 return false; 443 return false;
421} 444}
422 445
423static inline bool 446static inline bool
424pnfs_clear_request_commit(struct nfs_page *req) 447pnfs_clear_request_commit(struct nfs_page *req, struct nfs_commit_info *cinfo)
425{ 448{
426 return false; 449 return false;
427} 450}
428 451
429static inline int 452static inline int
430pnfs_scan_commit_lists(struct inode *inode, int max, spinlock_t *lock) 453pnfs_scan_commit_lists(struct inode *inode, struct nfs_commit_info *cinfo,
454 int max)
431{ 455{
432 return 0; 456 return 0;
433} 457}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2500f1cf1996..18bf70055272 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -452,65 +452,79 @@ nfs_mark_request_dirty(struct nfs_page *req)
452/** 452/**
453 * nfs_request_add_commit_list - add request to a commit list 453 * nfs_request_add_commit_list - add request to a commit list
454 * @req: pointer to a struct nfs_page 454 * @req: pointer to a struct nfs_page
455 * @head: commit list head 455 * @dst: commit list head
456 * @cinfo: holds list lock and accounting info
456 * 457 *
457 * This sets the PG_CLEAN bit, updates the inode global count of 458 * This sets the PG_CLEAN bit, updates the cinfo count of
458 * number of outstanding requests requiring a commit as well as 459 * number of outstanding requests requiring a commit as well as
459 * the MM page stats. 460 * the MM page stats.
460 * 461 *
461 * The caller must _not_ hold the inode->i_lock, but must be 462 * The caller must _not_ hold the cinfo->lock, but must be
462 * holding the nfs_page lock. 463 * holding the nfs_page lock.
463 */ 464 */
464void 465void
465nfs_request_add_commit_list(struct nfs_page *req, struct list_head *head) 466nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst,
467 struct nfs_commit_info *cinfo)
466{ 468{
467 struct inode *inode = req->wb_context->dentry->d_inode;
468
469 set_bit(PG_CLEAN, &(req)->wb_flags); 469 set_bit(PG_CLEAN, &(req)->wb_flags);
470 spin_lock(&inode->i_lock); 470 spin_lock(cinfo->lock);
471 nfs_list_add_request(req, head); 471 nfs_list_add_request(req, dst);
472 NFS_I(inode)->ncommit++; 472 cinfo->mds->ncommit++;
473 spin_unlock(&inode->i_lock); 473 spin_unlock(cinfo->lock);
474 inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); 474 inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
475 inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); 475 inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE);
476 __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 476 __mark_inode_dirty(req->wb_context->dentry->d_inode, I_DIRTY_DATASYNC);
477} 477}
478EXPORT_SYMBOL_GPL(nfs_request_add_commit_list); 478EXPORT_SYMBOL_GPL(nfs_request_add_commit_list);
479 479
480/** 480/**
481 * nfs_request_remove_commit_list - Remove request from a commit list 481 * nfs_request_remove_commit_list - Remove request from a commit list
482 * @req: pointer to a nfs_page 482 * @req: pointer to a nfs_page
483 * @cinfo: holds list lock and accounting info
483 * 484 *
484 * This clears the PG_CLEAN bit, and updates the inode global count of 485 * This clears the PG_CLEAN bit, and updates the cinfo's count of
485 * number of outstanding requests requiring a commit 486 * number of outstanding requests requiring a commit
486 * It does not update the MM page stats. 487 * It does not update the MM page stats.
487 * 488 *
488 * The caller _must_ hold the inode->i_lock and the nfs_page lock. 489 * The caller _must_ hold the cinfo->lock and the nfs_page lock.
489 */ 490 */
490void 491void
491nfs_request_remove_commit_list(struct nfs_page *req) 492nfs_request_remove_commit_list(struct nfs_page *req,
493 struct nfs_commit_info *cinfo)
492{ 494{
493 struct inode *inode = req->wb_context->dentry->d_inode;
494
495 if (!test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) 495 if (!test_and_clear_bit(PG_CLEAN, &(req)->wb_flags))
496 return; 496 return;
497 nfs_list_remove_request(req); 497 nfs_list_remove_request(req);
498 NFS_I(inode)->ncommit--; 498 cinfo->mds->ncommit--;
499} 499}
500EXPORT_SYMBOL_GPL(nfs_request_remove_commit_list); 500EXPORT_SYMBOL_GPL(nfs_request_remove_commit_list);
501 501
502static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
503 struct inode *inode)
504{
505 cinfo->lock = &inode->i_lock;
506 cinfo->mds = &NFS_I(inode)->commit_info;
507 cinfo->ds = pnfs_get_ds_info(inode);
508}
509
510void nfs_init_cinfo(struct nfs_commit_info *cinfo,
511 struct inode *inode,
512 struct nfs_direct_req *dreq)
513{
514 nfs_init_cinfo_from_inode(cinfo, inode);
515}
516EXPORT_SYMBOL_GPL(nfs_init_cinfo);
502 517
503/* 518/*
504 * Add a request to the inode's commit list. 519 * Add a request to the inode's commit list.
505 */ 520 */
506static void 521static void
507nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) 522nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
523 struct nfs_commit_info *cinfo)
508{ 524{
509 struct inode *inode = req->wb_context->dentry->d_inode; 525 if (pnfs_mark_request_commit(req, lseg, cinfo))
510
511 if (pnfs_mark_request_commit(req, lseg))
512 return; 526 return;
513 nfs_request_add_commit_list(req, &NFS_I(inode)->commit_list); 527 nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo);
514} 528}
515 529
516static void 530static void
@@ -525,11 +539,13 @@ nfs_clear_request_commit(struct nfs_page *req)
525{ 539{
526 if (test_bit(PG_CLEAN, &req->wb_flags)) { 540 if (test_bit(PG_CLEAN, &req->wb_flags)) {
527 struct inode *inode = req->wb_context->dentry->d_inode; 541 struct inode *inode = req->wb_context->dentry->d_inode;
542 struct nfs_commit_info cinfo;
528 543
529 if (!pnfs_clear_request_commit(req)) { 544 nfs_init_cinfo_from_inode(&cinfo, inode);
530 spin_lock(&inode->i_lock); 545 if (!pnfs_clear_request_commit(req, &cinfo)) {
531 nfs_request_remove_commit_list(req); 546 spin_lock(cinfo.lock);
532 spin_unlock(&inode->i_lock); 547 nfs_request_remove_commit_list(req, &cinfo);
548 spin_unlock(cinfo.lock);
533 } 549 }
534 nfs_clear_page_commit(req->wb_page); 550 nfs_clear_page_commit(req->wb_page);
535 } 551 }
@@ -545,7 +561,8 @@ int nfs_write_need_commit(struct nfs_write_data *data)
545 561
546#else 562#else
547static void 563static void
548nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) 564nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
565 struct nfs_commit_info *cinfo)
549{ 566{
550} 567}
551 568
@@ -564,10 +581,12 @@ int nfs_write_need_commit(struct nfs_write_data *data)
564 581
565static void nfs_write_completion(struct nfs_pgio_header *hdr) 582static void nfs_write_completion(struct nfs_pgio_header *hdr)
566{ 583{
584 struct nfs_commit_info cinfo;
567 unsigned long bytes = 0; 585 unsigned long bytes = 0;
568 586
569 if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) 587 if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
570 goto out; 588 goto out;
589 nfs_init_cinfo_from_inode(&cinfo, hdr->inode);
571 while (!list_empty(&hdr->pages)) { 590 while (!list_empty(&hdr->pages)) {
572 struct nfs_page *req = nfs_list_entry(hdr->pages.next); 591 struct nfs_page *req = nfs_list_entry(hdr->pages.next);
573 struct page *page = req->wb_page; 592 struct page *page = req->wb_page;
@@ -585,7 +604,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
585 goto next; 604 goto next;
586 } 605 }
587 if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) { 606 if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) {
588 nfs_mark_request_commit(req, hdr->lseg); 607 nfs_mark_request_commit(req, hdr->lseg, &cinfo);
589 goto next; 608 goto next;
590 } 609 }
591remove_req: 610remove_req:
@@ -599,16 +618,16 @@ out:
599} 618}
600 619
601#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 620#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
602static int 621static unsigned long
603nfs_need_commit(struct nfs_inode *nfsi) 622nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
604{ 623{
605 return nfsi->ncommit > 0; 624 return cinfo->mds->ncommit;
606} 625}
607 626
608/* i_lock held by caller */ 627/* cinfo->lock held by caller */
609static int 628static int
610nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max, 629nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
611 spinlock_t *lock) 630 struct nfs_commit_info *cinfo, int max)
612{ 631{
613 struct nfs_page *req, *tmp; 632 struct nfs_page *req, *tmp;
614 int ret = 0; 633 int ret = 0;
@@ -616,9 +635,9 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max,
616 list_for_each_entry_safe(req, tmp, src, wb_list) { 635 list_for_each_entry_safe(req, tmp, src, wb_list) {
617 if (!nfs_lock_request(req)) 636 if (!nfs_lock_request(req))
618 continue; 637 continue;
619 if (cond_resched_lock(lock)) 638 if (cond_resched_lock(cinfo->lock))
620 list_safe_reset_next(req, tmp, wb_list); 639 list_safe_reset_next(req, tmp, wb_list);
621 nfs_request_remove_commit_list(req); 640 nfs_request_remove_commit_list(req, cinfo);
622 nfs_list_add_request(req, dst); 641 nfs_list_add_request(req, dst);
623 ret++; 642 ret++;
624 if (ret == max) 643 if (ret == max)
@@ -630,37 +649,38 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max,
630/* 649/*
631 * nfs_scan_commit - Scan an inode for commit requests 650 * nfs_scan_commit - Scan an inode for commit requests
632 * @inode: NFS inode to scan 651 * @inode: NFS inode to scan
633 * @dst: destination list 652 * @dst: mds destination list
653 * @cinfo: mds and ds lists of reqs ready to commit
634 * 654 *
635 * Moves requests from the inode's 'commit' request list. 655 * Moves requests from the inode's 'commit' request list.
636 * The requests are *not* checked to ensure that they form a contiguous set. 656 * The requests are *not* checked to ensure that they form a contiguous set.
637 */ 657 */
638static int 658static int
639nfs_scan_commit(struct inode *inode, struct list_head *dst) 659nfs_scan_commit(struct inode *inode, struct list_head *dst,
660 struct nfs_commit_info *cinfo)
640{ 661{
641 struct nfs_inode *nfsi = NFS_I(inode);
642 int ret = 0; 662 int ret = 0;
643 663
644 spin_lock(&inode->i_lock); 664 spin_lock(cinfo->lock);
645 if (nfsi->ncommit > 0) { 665 if (cinfo->mds->ncommit > 0) {
646 const int max = INT_MAX; 666 const int max = INT_MAX;
647 667
648 ret = nfs_scan_commit_list(&nfsi->commit_list, dst, max, 668 ret = nfs_scan_commit_list(&cinfo->mds->list, dst,
649 &inode->i_lock); 669 cinfo, max);
650 ret += pnfs_scan_commit_lists(inode, max - ret, 670 ret += pnfs_scan_commit_lists(inode, cinfo, max - ret);
651 &inode->i_lock);
652 } 671 }
653 spin_unlock(&inode->i_lock); 672 spin_unlock(cinfo->lock);
654 return ret; 673 return ret;
655} 674}
656 675
657#else 676#else
658static inline int nfs_need_commit(struct nfs_inode *nfsi) 677static unsigned long nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
659{ 678{
660 return 0; 679 return 0;
661} 680}
662 681
663static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst) 682static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst,
683 struct nfs_commit_info *cinfo)
664{ 684{
665 return 0; 685 return 0;
666} 686}
@@ -929,7 +949,7 @@ EXPORT_SYMBOL_GPL(nfs_initiate_write);
929 */ 949 */
930static void nfs_write_rpcsetup(struct nfs_write_data *data, 950static void nfs_write_rpcsetup(struct nfs_write_data *data,
931 unsigned int count, unsigned int offset, 951 unsigned int count, unsigned int offset,
932 int how) 952 int how, struct nfs_commit_info *cinfo)
933{ 953{
934 struct nfs_page *req = data->header->req; 954 struct nfs_page *req = data->header->req;
935 955
@@ -950,7 +970,7 @@ static void nfs_write_rpcsetup(struct nfs_write_data *data,
950 case 0: 970 case 0:
951 break; 971 break;
952 case FLUSH_COND_STABLE: 972 case FLUSH_COND_STABLE:
953 if (nfs_need_commit(NFS_I(data->header->inode))) 973 if (nfs_reqs_to_commit(cinfo))
954 break; 974 break;
955 default: 975 default:
956 data->args.stable = NFS_FILE_SYNC; 976 data->args.stable = NFS_FILE_SYNC;
@@ -1034,12 +1054,14 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
1034 unsigned int offset; 1054 unsigned int offset;
1035 int requests = 0; 1055 int requests = 0;
1036 int ret = 0; 1056 int ret = 0;
1057 struct nfs_commit_info cinfo;
1037 1058
1059 nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
1038 nfs_list_remove_request(req); 1060 nfs_list_remove_request(req);
1039 nfs_list_add_request(req, &hdr->pages); 1061 nfs_list_add_request(req, &hdr->pages);
1040 1062
1041 if ((desc->pg_ioflags & FLUSH_COND_STABLE) && 1063 if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
1042 (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || 1064 (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) ||
1043 desc->pg_count > wsize)) 1065 desc->pg_count > wsize))
1044 desc->pg_ioflags &= ~FLUSH_COND_STABLE; 1066 desc->pg_ioflags &= ~FLUSH_COND_STABLE;
1045 1067
@@ -1053,7 +1075,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
1053 if (!data) 1075 if (!data)
1054 goto out_bad; 1076 goto out_bad;
1055 data->pages.pagevec[0] = page; 1077 data->pages.pagevec[0] = page;
1056 nfs_write_rpcsetup(data, len, offset, desc->pg_ioflags); 1078 nfs_write_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
1057 list_add(&data->list, &hdr->rpc_list); 1079 list_add(&data->list, &hdr->rpc_list);
1058 requests++; 1080 requests++;
1059 nbytes -= len; 1081 nbytes -= len;
@@ -1088,6 +1110,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
1088 struct nfs_write_data *data; 1110 struct nfs_write_data *data;
1089 struct list_head *head = &desc->pg_list; 1111 struct list_head *head = &desc->pg_list;
1090 int ret = 0; 1112 int ret = 0;
1113 struct nfs_commit_info cinfo;
1091 1114
1092 data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base, 1115 data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base,
1093 desc->pg_count)); 1116 desc->pg_count));
@@ -1097,6 +1120,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
1097 goto out; 1120 goto out;
1098 } 1121 }
1099 1122
1123 nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
1100 pages = data->pages.pagevec; 1124 pages = data->pages.pagevec;
1101 while (!list_empty(head)) { 1125 while (!list_empty(head)) {
1102 req = nfs_list_entry(head->next); 1126 req = nfs_list_entry(head->next);
@@ -1106,11 +1130,11 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
1106 } 1130 }
1107 1131
1108 if ((desc->pg_ioflags & FLUSH_COND_STABLE) && 1132 if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
1109 (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) 1133 (desc->pg_moreio || nfs_reqs_to_commit(&cinfo)))
1110 desc->pg_ioflags &= ~FLUSH_COND_STABLE; 1134 desc->pg_ioflags &= ~FLUSH_COND_STABLE;
1111 1135
1112 /* Set up the argument struct */ 1136 /* Set up the argument struct */
1113 nfs_write_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags); 1137 nfs_write_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo);
1114 list_add(&data->list, &hdr->rpc_list); 1138 list_add(&data->list, &hdr->rpc_list);
1115 desc->pg_rpc_callops = &nfs_write_common_ops; 1139 desc->pg_rpc_callops = &nfs_write_common_ops;
1116out: 1140out:
@@ -1417,14 +1441,15 @@ void nfs_init_commit(struct nfs_commit_data *data,
1417EXPORT_SYMBOL_GPL(nfs_init_commit); 1441EXPORT_SYMBOL_GPL(nfs_init_commit);
1418 1442
1419void nfs_retry_commit(struct list_head *page_list, 1443void nfs_retry_commit(struct list_head *page_list,
1420 struct pnfs_layout_segment *lseg) 1444 struct pnfs_layout_segment *lseg,
1445 struct nfs_commit_info *cinfo)
1421{ 1446{
1422 struct nfs_page *req; 1447 struct nfs_page *req;
1423 1448
1424 while (!list_empty(page_list)) { 1449 while (!list_empty(page_list)) {
1425 req = nfs_list_entry(page_list->next); 1450 req = nfs_list_entry(page_list->next);
1426 nfs_list_remove_request(req); 1451 nfs_list_remove_request(req);
1427 nfs_mark_request_commit(req, lseg); 1452 nfs_mark_request_commit(req, lseg, cinfo);
1428 dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); 1453 dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
1429 dec_bdi_stat(req->wb_page->mapping->backing_dev_info, 1454 dec_bdi_stat(req->wb_page->mapping->backing_dev_info,
1430 BDI_RECLAIMABLE); 1455 BDI_RECLAIMABLE);
@@ -1437,7 +1462,8 @@ EXPORT_SYMBOL_GPL(nfs_retry_commit);
1437 * Commit dirty pages 1462 * Commit dirty pages
1438 */ 1463 */
1439static int 1464static int
1440nfs_commit_list(struct inode *inode, struct list_head *head, int how) 1465nfs_commit_list(struct inode *inode, struct list_head *head, int how,
1466 struct nfs_commit_info *cinfo)
1441{ 1467{
1442 struct nfs_commit_data *data; 1468 struct nfs_commit_data *data;
1443 1469
@@ -1450,7 +1476,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1450 nfs_init_commit(data, head, NULL); 1476 nfs_init_commit(data, head, NULL);
1451 return nfs_initiate_commit(NFS_CLIENT(inode), data, data->mds_ops, how); 1477 return nfs_initiate_commit(NFS_CLIENT(inode), data, data->mds_ops, how);
1452 out_bad: 1478 out_bad:
1453 nfs_retry_commit(head, NULL); 1479 nfs_retry_commit(head, NULL, cinfo);
1454 nfs_commit_clear_lock(NFS_I(inode)); 1480 nfs_commit_clear_lock(NFS_I(inode));
1455 return -ENOMEM; 1481 return -ENOMEM;
1456} 1482}
@@ -1524,30 +1550,32 @@ static const struct rpc_call_ops nfs_commit_ops = {
1524}; 1550};
1525 1551
1526static int nfs_generic_commit_list(struct inode *inode, struct list_head *head, 1552static int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
1527 int how) 1553 int how, struct nfs_commit_info *cinfo)
1528{ 1554{
1529 int status; 1555 int status;
1530 1556
1531 status = pnfs_commit_list(inode, head, how); 1557 status = pnfs_commit_list(inode, head, how, cinfo);
1532 if (status == PNFS_NOT_ATTEMPTED) 1558 if (status == PNFS_NOT_ATTEMPTED)
1533 status = nfs_commit_list(inode, head, how); 1559 status = nfs_commit_list(inode, head, how, cinfo);
1534 return status; 1560 return status;
1535} 1561}
1536 1562
1537int nfs_commit_inode(struct inode *inode, int how) 1563int nfs_commit_inode(struct inode *inode, int how)
1538{ 1564{
1539 LIST_HEAD(head); 1565 LIST_HEAD(head);
1566 struct nfs_commit_info cinfo;
1540 int may_wait = how & FLUSH_SYNC; 1567 int may_wait = how & FLUSH_SYNC;
1541 int res; 1568 int res;
1542 1569
1543 res = nfs_commit_set_lock(NFS_I(inode), may_wait); 1570 res = nfs_commit_set_lock(NFS_I(inode), may_wait);
1544 if (res <= 0) 1571 if (res <= 0)
1545 goto out_mark_dirty; 1572 goto out_mark_dirty;
1546 res = nfs_scan_commit(inode, &head); 1573 nfs_init_cinfo_from_inode(&cinfo, inode);
1574 res = nfs_scan_commit(inode, &head, &cinfo);
1547 if (res) { 1575 if (res) {
1548 int error; 1576 int error;
1549 1577
1550 error = nfs_generic_commit_list(inode, &head, how); 1578 error = nfs_generic_commit_list(inode, &head, how, &cinfo);
1551 if (error < 0) 1579 if (error < 0)
1552 return error; 1580 return error;
1553 if (!may_wait) 1581 if (!may_wait)
@@ -1578,14 +1606,14 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
1578 int ret = 0; 1606 int ret = 0;
1579 1607
1580 /* no commits means nothing needs to be done */ 1608 /* no commits means nothing needs to be done */
1581 if (!nfsi->ncommit) 1609 if (!nfsi->commit_info.ncommit)
1582 return ret; 1610 return ret;
1583 1611
1584 if (wbc->sync_mode == WB_SYNC_NONE) { 1612 if (wbc->sync_mode == WB_SYNC_NONE) {
1585 /* Don't commit yet if this is a non-blocking flush and there 1613 /* Don't commit yet if this is a non-blocking flush and there
1586 * are a lot of outstanding writes for this mapping. 1614 * are a lot of outstanding writes for this mapping.
1587 */ 1615 */
1588 if (nfsi->ncommit <= (nfsi->npages >> 1)) 1616 if (nfsi->commit_info.ncommit <= (nfsi->npages >> 1))
1589 goto out_mark_dirty; 1617 goto out_mark_dirty;
1590 1618
1591 /* don't wait for the COMMIT response */ 1619 /* don't wait for the COMMIT response */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 8d3a2b804201..8a88c16662c5 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -179,8 +179,7 @@ struct nfs_inode {
179 __be32 cookieverf[2]; 179 __be32 cookieverf[2];
180 180
181 unsigned long npages; 181 unsigned long npages;
182 unsigned long ncommit; 182 struct nfs_mds_commit_info commit_info;
183 struct list_head commit_list;
184 183
185 /* Open contexts for shared mmap writes */ 184 /* Open contexts for shared mmap writes */
186 struct list_head open_files; 185 struct list_head open_files;
@@ -201,7 +200,6 @@ struct nfs_inode {
201 200
202 /* pNFS layout information */ 201 /* pNFS layout information */
203 struct pnfs_layout_hdr *layout; 202 struct pnfs_layout_hdr *layout;
204 atomic_t commits_outstanding;
205#endif /* CONFIG_NFS_V4*/ 203#endif /* CONFIG_NFS_V4*/
206#ifdef CONFIG_NFS_FSCACHE 204#ifdef CONFIG_NFS_FSCACHE
207 struct fscache_cookie *fscache; 205 struct fscache_cookie *fscache;
@@ -230,7 +228,6 @@ struct nfs_inode {
230#define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ 228#define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */
231#define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ 229#define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */
232#define NFS_INO_COMMIT (7) /* inode is committing unstable writes */ 230#define NFS_INO_COMMIT (7) /* inode is committing unstable writes */
233#define NFS_INO_PNFS_COMMIT (8) /* use pnfs code for commit */
234#define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */ 231#define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */
235#define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */ 232#define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */
236 233
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 38687b87ca9b..224e1e82670c 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1079,6 +1079,21 @@ struct nfstime4 {
1079}; 1079};
1080 1080
1081#ifdef CONFIG_NFS_V4_1 1081#ifdef CONFIG_NFS_V4_1
1082
1083struct pnfs_commit_bucket {
1084 struct list_head written;
1085 struct list_head committing;
1086 struct pnfs_layout_segment *wlseg;
1087 struct pnfs_layout_segment *clseg;
1088};
1089
1090struct pnfs_ds_commit_info {
1091 int nwritten;
1092 int ncommitting;
1093 int nbuckets;
1094 struct pnfs_commit_bucket *buckets;
1095};
1096
1082#define NFS4_EXCHANGE_ID_LEN (48) 1097#define NFS4_EXCHANGE_ID_LEN (48)
1083struct nfs41_exchange_id_args { 1098struct nfs41_exchange_id_args {
1084 struct nfs_client *client; 1099 struct nfs_client *client;
@@ -1242,6 +1257,18 @@ struct nfs_write_header {
1242 struct nfs_write_data rpc_data; 1257 struct nfs_write_data rpc_data;
1243}; 1258};
1244 1259
1260struct nfs_mds_commit_info {
1261 atomic_t rpcs_out;
1262 unsigned long ncommit;
1263 struct list_head list;
1264};
1265
1266struct nfs_commit_info {
1267 spinlock_t *lock;
1268 struct nfs_mds_commit_info *mds;
1269 struct pnfs_ds_commit_info *ds;
1270};
1271
1245struct nfs_commit_data { 1272struct nfs_commit_data {
1246 struct rpc_task task; 1273 struct rpc_task task;
1247 struct inode *inode; 1274 struct inode *inode;