diff options
author | Anna Schumaker <Anna.Schumaker@netapp.com> | 2014-05-06 09:12:36 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-05-28 18:41:12 -0400 |
commit | ef2c488c073f4f0b3a200745dd8d608c01d69c39 (patch) | |
tree | 7bb53a2479bb8df2bb66b0943f4814e0abb20f8b /fs/nfs/write.c | |
parent | 844c9e691d8723853ca8f2de0207683538645824 (diff) |
NFS: Create a generic_pgio function
These functions are almost identical on both the read and write side.
FLUSH_COND_STABLE will never be set for the read path, so leaving it in
the generic code won't hurt anything.
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 97 |
1 files changed, 1 insertions, 96 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 02d088b1d8e4..0e34c7024195 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1044,101 +1044,6 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = { | |||
1044 | .completion = nfs_write_completion, | 1044 | .completion = nfs_write_completion, |
1045 | }; | 1045 | }; |
1046 | 1046 | ||
1047 | /* | ||
1048 | * Generate multiple small requests to write out a single | ||
1049 | * contiguous dirty area on one page. | ||
1050 | */ | ||
1051 | static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, | ||
1052 | struct nfs_pgio_header *hdr) | ||
1053 | { | ||
1054 | struct nfs_page *req = hdr->req; | ||
1055 | struct page *page = req->wb_page; | ||
1056 | struct nfs_pgio_data *data; | ||
1057 | size_t wsize = desc->pg_bsize, nbytes; | ||
1058 | unsigned int offset; | ||
1059 | int requests = 0; | ||
1060 | struct nfs_commit_info cinfo; | ||
1061 | |||
1062 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | ||
1063 | |||
1064 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1065 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) || | ||
1066 | desc->pg_count > wsize)) | ||
1067 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
1068 | |||
1069 | |||
1070 | offset = 0; | ||
1071 | nbytes = desc->pg_count; | ||
1072 | do { | ||
1073 | size_t len = min(nbytes, wsize); | ||
1074 | |||
1075 | data = nfs_pgio_data_alloc(hdr, 1); | ||
1076 | if (!data) | ||
1077 | return nfs_pgio_error(desc, hdr); | ||
1078 | data->pages.pagevec[0] = page; | ||
1079 | nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo); | ||
1080 | list_add(&data->list, &hdr->rpc_list); | ||
1081 | requests++; | ||
1082 | nbytes -= len; | ||
1083 | offset += len; | ||
1084 | } while (nbytes != 0); | ||
1085 | nfs_list_remove_request(req); | ||
1086 | nfs_list_add_request(req, &hdr->pages); | ||
1087 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | /* | ||
1092 | * Create an RPC task for the given write request and kick it. | ||
1093 | * The page must have been locked by the caller. | ||
1094 | * | ||
1095 | * It may happen that the page we're passed is not marked dirty. | ||
1096 | * This is the case if nfs_updatepage detects a conflicting request | ||
1097 | * that has been written but not committed. | ||
1098 | */ | ||
1099 | static int nfs_flush_one(struct nfs_pageio_descriptor *desc, | ||
1100 | struct nfs_pgio_header *hdr) | ||
1101 | { | ||
1102 | struct nfs_page *req; | ||
1103 | struct page **pages; | ||
1104 | struct nfs_pgio_data *data; | ||
1105 | struct list_head *head = &desc->pg_list; | ||
1106 | struct nfs_commit_info cinfo; | ||
1107 | |||
1108 | data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base, | ||
1109 | desc->pg_count)); | ||
1110 | if (!data) | ||
1111 | return nfs_pgio_error(desc, hdr); | ||
1112 | |||
1113 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | ||
1114 | pages = data->pages.pagevec; | ||
1115 | while (!list_empty(head)) { | ||
1116 | req = nfs_list_entry(head->next); | ||
1117 | nfs_list_remove_request(req); | ||
1118 | nfs_list_add_request(req, &hdr->pages); | ||
1119 | *pages++ = req->wb_page; | ||
1120 | } | ||
1121 | |||
1122 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1123 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo))) | ||
1124 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
1125 | |||
1126 | /* Set up the argument struct */ | ||
1127 | nfs_pgio_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo); | ||
1128 | list_add(&data->list, &hdr->rpc_list); | ||
1129 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | ||
1134 | struct nfs_pgio_header *hdr) | ||
1135 | { | ||
1136 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | ||
1137 | return nfs_flush_multi(desc, hdr); | ||
1138 | return nfs_flush_one(desc, hdr); | ||
1139 | } | ||
1140 | EXPORT_SYMBOL_GPL(nfs_generic_flush); | ||
1141 | |||
1142 | static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | 1047 | static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) |
1143 | { | 1048 | { |
1144 | struct nfs_rw_header *whdr; | 1049 | struct nfs_rw_header *whdr; |
@@ -1153,7 +1058,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1153 | hdr = &whdr->header; | 1058 | hdr = &whdr->header; |
1154 | nfs_pgheader_init(desc, hdr, nfs_rw_header_free); | 1059 | nfs_pgheader_init(desc, hdr, nfs_rw_header_free); |
1155 | atomic_inc(&hdr->refcnt); | 1060 | atomic_inc(&hdr->refcnt); |
1156 | ret = nfs_generic_flush(desc, hdr); | 1061 | ret = nfs_generic_pgio(desc, hdr); |
1157 | if (ret == 0) | 1062 | if (ret == 0) |
1158 | ret = nfs_do_multiple_writes(&hdr->rpc_list, | 1063 | ret = nfs_do_multiple_writes(&hdr->rpc_list, |
1159 | desc->pg_rpc_callops, | 1064 | desc->pg_rpc_callops, |