aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/write.c62
1 files changed, 29 insertions, 33 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d9e5ee594572..2beb1268bb1b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -963,7 +963,7 @@ static void nfs_execute_write(struct nfs_write_data *data)
963 * Generate multiple small requests to write out a single 963 * Generate multiple small requests to write out a single
964 * contiguous dirty area on one page. 964 * contiguous dirty area on one page.
965 */ 965 */
966static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) 966static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
967{ 967{
968 struct nfs_page *req = nfs_list_entry(head->next); 968 struct nfs_page *req = nfs_list_entry(head->next);
969 struct page *page = req->wb_page; 969 struct page *page = req->wb_page;
@@ -1032,16 +1032,13 @@ out_bad:
1032 * This is the case if nfs_updatepage detects a conflicting request 1032 * This is the case if nfs_updatepage detects a conflicting request
1033 * that has been written but not committed. 1033 * that has been written but not committed.
1034 */ 1034 */
1035static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) 1035static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
1036{ 1036{
1037 struct nfs_page *req; 1037 struct nfs_page *req;
1038 struct page **pages; 1038 struct page **pages;
1039 struct nfs_write_data *data; 1039 struct nfs_write_data *data;
1040 unsigned int count; 1040 unsigned int count;
1041 1041
1042 if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE)
1043 return nfs_flush_multi(head, inode, how);
1044
1045 data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages); 1042 data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
1046 if (!data) 1043 if (!data)
1047 goto out_bad; 1044 goto out_bad;
@@ -1074,24 +1071,32 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
1074 return -ENOMEM; 1071 return -ENOMEM;
1075} 1072}
1076 1073
1077static int 1074static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how)
1078nfs_flush_list(struct list_head *head, int wpages, int how)
1079{ 1075{
1080 LIST_HEAD(one_request); 1076 LIST_HEAD(one_request);
1081 struct nfs_page *req; 1077 int (*flush_one)(struct inode *, struct list_head *, int);
1082 int error = 0; 1078 struct nfs_page *req;
1083 unsigned int pages = 0; 1079 int wpages = NFS_SERVER(inode)->wpages;
1080 int wsize = NFS_SERVER(inode)->wsize;
1081 int error;
1084 1082
1085 while (!list_empty(head)) { 1083 flush_one = nfs_flush_one;
1086 pages += nfs_coalesce_requests(head, &one_request, wpages); 1084 if (wsize < PAGE_CACHE_SIZE)
1085 flush_one = nfs_flush_multi;
1086 /* For single writes, FLUSH_STABLE is more efficient */
1087 if (npages <= wpages && npages == NFS_I(inode)->npages
1088 && nfs_list_entry(head->next)->wb_bytes <= wsize)
1089 how |= FLUSH_STABLE;
1090
1091 do {
1092 nfs_coalesce_requests(head, &one_request, wpages);
1087 req = nfs_list_entry(one_request.next); 1093 req = nfs_list_entry(one_request.next);
1088 error = nfs_flush_one(&one_request, req->wb_context->dentry->d_inode, how); 1094 error = flush_one(inode, &one_request, how);
1089 if (error < 0) 1095 if (error < 0)
1090 break; 1096 goto out_err;
1091 } 1097 } while (!list_empty(head));
1092 if (error >= 0) 1098 return 0;
1093 return pages; 1099out_err:
1094
1095 while (!list_empty(head)) { 1100 while (!list_empty(head)) {
1096 req = nfs_list_entry(head->next); 1101 req = nfs_list_entry(head->next);
1097 nfs_list_remove_request(req); 1102 nfs_list_remove_request(req);
@@ -1423,24 +1428,16 @@ static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
1423{ 1428{
1424 struct nfs_inode *nfsi = NFS_I(inode); 1429 struct nfs_inode *nfsi = NFS_I(inode);
1425 LIST_HEAD(head); 1430 LIST_HEAD(head);
1426 int res, 1431 int res;
1427 error = 0;
1428 1432
1429 spin_lock(&nfsi->req_lock); 1433 spin_lock(&nfsi->req_lock);
1430 res = nfs_scan_dirty(inode, &head, idx_start, npages); 1434 res = nfs_scan_dirty(inode, &head, idx_start, npages);
1431 spin_unlock(&nfsi->req_lock); 1435 spin_unlock(&nfsi->req_lock);
1432 if (res) { 1436 if (res) {
1433 struct nfs_server *server = NFS_SERVER(inode); 1437 int error = nfs_flush_list(inode, &head, res, how);
1434 1438 if (error < 0)
1435 /* For single writes, FLUSH_STABLE is more efficient */ 1439 return error;
1436 if (res == nfsi->npages && nfsi->npages <= server->wpages) {
1437 if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize)
1438 how |= FLUSH_STABLE;
1439 }
1440 error = nfs_flush_list(&head, server->wpages, how);
1441 } 1440 }
1442 if (error < 0)
1443 return error;
1444 return res; 1441 return res;
1445} 1442}
1446 1443
@@ -1449,14 +1446,13 @@ int nfs_commit_inode(struct inode *inode, int how)
1449{ 1446{
1450 struct nfs_inode *nfsi = NFS_I(inode); 1447 struct nfs_inode *nfsi = NFS_I(inode);
1451 LIST_HEAD(head); 1448 LIST_HEAD(head);
1452 int res, 1449 int res;
1453 error = 0;
1454 1450
1455 spin_lock(&nfsi->req_lock); 1451 spin_lock(&nfsi->req_lock);
1456 res = nfs_scan_commit(inode, &head, 0, 0); 1452 res = nfs_scan_commit(inode, &head, 0, 0);
1457 spin_unlock(&nfsi->req_lock); 1453 spin_unlock(&nfsi->req_lock);
1458 if (res) { 1454 if (res) {
1459 error = nfs_commit_list(inode, &head, how); 1455 int error = nfs_commit_list(inode, &head, how);
1460 if (error < 0) 1456 if (error < 0)
1461 return error; 1457 return error;
1462 } 1458 }