diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:50 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:50 -0500 |
commit | 7d46a49f512e8d10b23353781a8ba85edd4fa640 (patch) | |
tree | 8da455d9f2f80f6c8ee82ec85449d2eb0ea12aba | |
parent | deb7d638262019cbac5d15ab74ffd1c29242c7cb (diff) |
NFS: Clean up nfs_flush_list()
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/write.c | 62 |
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 | */ |
966 | static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) | 966 | static 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 | */ |
1035 | static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) | 1035 | static 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 | ||
1077 | static int | 1074 | static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how) |
1078 | nfs_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; | 1099 | out_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 | } |