diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 076075eb676c..150397279b8d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -40,10 +40,12 @@ | |||
40 | * Local function declarations | 40 | * Local function declarations |
41 | */ | 41 | */ |
42 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, | 42 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, |
43 | struct inode *inode, int ioflags); | 43 | struct inode *inode, int ioflags, |
44 | const struct nfs_pgio_completion_ops *compl_ops); | ||
44 | static void nfs_redirty_request(struct nfs_page *req); | 45 | static void nfs_redirty_request(struct nfs_page *req); |
45 | static const struct rpc_call_ops nfs_write_common_ops; | 46 | static const struct rpc_call_ops nfs_write_common_ops; |
46 | static const struct rpc_call_ops nfs_commit_ops; | 47 | static const struct rpc_call_ops nfs_commit_ops; |
48 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; | ||
47 | 49 | ||
48 | static struct kmem_cache *nfs_wdata_cachep; | 50 | static struct kmem_cache *nfs_wdata_cachep; |
49 | static mempool_t *nfs_wdata_mempool; | 51 | static mempool_t *nfs_wdata_mempool; |
@@ -128,7 +130,7 @@ void nfs_writedata_release(struct nfs_write_data *wdata) | |||
128 | else | 130 | else |
129 | wdata->header = NULL; | 131 | wdata->header = NULL; |
130 | if (atomic_dec_and_test(&hdr->refcnt)) | 132 | if (atomic_dec_and_test(&hdr->refcnt)) |
131 | nfs_write_completion(hdr); | 133 | hdr->completion_ops->completion(hdr); |
132 | } | 134 | } |
133 | 135 | ||
134 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | 136 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) |
@@ -337,7 +339,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc | |||
337 | struct nfs_pageio_descriptor pgio; | 339 | struct nfs_pageio_descriptor pgio; |
338 | int err; | 340 | int err; |
339 | 341 | ||
340 | nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc)); | 342 | nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc), |
343 | &nfs_async_write_completion_ops); | ||
341 | err = nfs_do_writepage(page, wbc, &pgio); | 344 | err = nfs_do_writepage(page, wbc, &pgio); |
342 | nfs_pageio_complete(&pgio); | 345 | nfs_pageio_complete(&pgio); |
343 | if (err < 0) | 346 | if (err < 0) |
@@ -380,7 +383,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
380 | 383 | ||
381 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | 384 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
382 | 385 | ||
383 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); | 386 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), |
387 | &nfs_async_write_completion_ops); | ||
384 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); | 388 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
385 | nfs_pageio_complete(&pgio); | 389 | nfs_pageio_complete(&pgio); |
386 | 390 | ||
@@ -558,7 +562,7 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
558 | 562 | ||
559 | #endif | 563 | #endif |
560 | 564 | ||
561 | void nfs_write_completion(struct nfs_pgio_header *hdr) | 565 | static void nfs_write_completion(struct nfs_pgio_header *hdr) |
562 | { | 566 | { |
563 | unsigned long bytes = 0; | 567 | unsigned long bytes = 0; |
564 | 568 | ||
@@ -1000,7 +1004,7 @@ static void nfs_redirty_request(struct nfs_page *req) | |||
1000 | nfs_end_page_writeback(page); | 1004 | nfs_end_page_writeback(page); |
1001 | } | 1005 | } |
1002 | 1006 | ||
1003 | void nfs_async_write_error(struct list_head *head) | 1007 | static void nfs_async_write_error(struct list_head *head) |
1004 | { | 1008 | { |
1005 | struct nfs_page *req; | 1009 | struct nfs_page *req; |
1006 | 1010 | ||
@@ -1011,6 +1015,11 @@ void nfs_async_write_error(struct list_head *head) | |||
1011 | } | 1015 | } |
1012 | } | 1016 | } |
1013 | 1017 | ||
1018 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = { | ||
1019 | .error_cleanup = nfs_async_write_error, | ||
1020 | .completion = nfs_write_completion, | ||
1021 | }; | ||
1022 | |||
1014 | /* | 1023 | /* |
1015 | * Generate multiple small requests to write out a single | 1024 | * Generate multiple small requests to write out a single |
1016 | * contiguous dirty area on one page. | 1025 | * contiguous dirty area on one page. |
@@ -1060,7 +1069,7 @@ out_bad: | |||
1060 | list_del(&data->list); | 1069 | list_del(&data->list); |
1061 | nfs_writedata_release(data); | 1070 | nfs_writedata_release(data); |
1062 | } | 1071 | } |
1063 | nfs_async_write_error(&hdr->pages); | 1072 | desc->pg_completion_ops->error_cleanup(&hdr->pages); |
1064 | return -ENOMEM; | 1073 | return -ENOMEM; |
1065 | } | 1074 | } |
1066 | 1075 | ||
@@ -1084,7 +1093,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, | |||
1084 | data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base, | 1093 | data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base, |
1085 | desc->pg_count)); | 1094 | desc->pg_count)); |
1086 | if (!data) { | 1095 | if (!data) { |
1087 | nfs_async_write_error(head); | 1096 | desc->pg_completion_ops->error_cleanup(head); |
1088 | ret = -ENOMEM; | 1097 | ret = -ENOMEM; |
1089 | goto out; | 1098 | goto out; |
1090 | } | 1099 | } |
@@ -1125,7 +1134,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1125 | 1134 | ||
1126 | whdr = nfs_writehdr_alloc(); | 1135 | whdr = nfs_writehdr_alloc(); |
1127 | if (!whdr) { | 1136 | if (!whdr) { |
1128 | nfs_async_write_error(&desc->pg_list); | 1137 | desc->pg_completion_ops->error_cleanup(&hdr->pages); |
1129 | return -ENOMEM; | 1138 | return -ENOMEM; |
1130 | } | 1139 | } |
1131 | hdr = &whdr->header; | 1140 | hdr = &whdr->header; |
@@ -1139,7 +1148,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1139 | else | 1148 | else |
1140 | set_bit(NFS_IOHDR_REDO, &hdr->flags); | 1149 | set_bit(NFS_IOHDR_REDO, &hdr->flags); |
1141 | if (atomic_dec_and_test(&hdr->refcnt)) | 1150 | if (atomic_dec_and_test(&hdr->refcnt)) |
1142 | nfs_write_completion(hdr); | 1151 | hdr->completion_ops->completion(hdr); |
1143 | return ret; | 1152 | return ret; |
1144 | } | 1153 | } |
1145 | 1154 | ||
@@ -1149,9 +1158,10 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = { | |||
1149 | }; | 1158 | }; |
1150 | 1159 | ||
1151 | void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 1160 | void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, |
1152 | struct inode *inode, int ioflags) | 1161 | struct inode *inode, int ioflags, |
1162 | const struct nfs_pgio_completion_ops *compl_ops) | ||
1153 | { | 1163 | { |
1154 | nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, | 1164 | nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, compl_ops, |
1155 | NFS_SERVER(inode)->wsize, ioflags); | 1165 | NFS_SERVER(inode)->wsize, ioflags); |
1156 | } | 1166 | } |
1157 | 1167 | ||
@@ -1163,10 +1173,11 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) | |||
1163 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); | 1173 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); |
1164 | 1174 | ||
1165 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 1175 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
1166 | struct inode *inode, int ioflags) | 1176 | struct inode *inode, int ioflags, |
1177 | const struct nfs_pgio_completion_ops *compl_ops) | ||
1167 | { | 1178 | { |
1168 | if (!pnfs_pageio_init_write(pgio, inode, ioflags)) | 1179 | if (!pnfs_pageio_init_write(pgio, inode, ioflags, compl_ops)) |
1169 | nfs_pageio_init_write_mds(pgio, inode, ioflags); | 1180 | nfs_pageio_init_write_mds(pgio, inode, ioflags, compl_ops); |
1170 | } | 1181 | } |
1171 | 1182 | ||
1172 | void nfs_write_prepare(struct rpc_task *task, void *calldata) | 1183 | void nfs_write_prepare(struct rpc_task *task, void *calldata) |