aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:27 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:27 -0500
commit788e7a89a03e364855583c0ab4649b94925efbb9 (patch)
tree4434c93af133a92f550ba0ecc8d3254cb222e72d /fs/nfs/write.c
parent7117bf3dfb10b534a017260d9fc643bc1d0afd2a (diff)
NFS: Cleanup of NFS write code in preparation for asynchronous o_direct
This patch inverts the callback hierarchy for NFS write calls. Instead of having the NFSv2/v3/v4-specific code set up the RPC callback ops, we allow the original caller to do so. This allows for more flexibility w.r.t. how to set up and tear down the nfs_write_data structure while still allowing the NFSv3/v4 code to perform error handling. The greater flexibility is needed by the asynchronous O_DIRECT code, which wants to be able to hold on to the original nfs_write_data structures after the WRITE RPC call has completed in order to be able to replay them if the COMMIT call determines that the server has rebooted. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c92
1 files changed, 66 insertions, 26 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e7c8361cf201..5912274ff1a1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -77,12 +77,14 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*,
77 struct inode *, 77 struct inode *,
78 struct page *, 78 struct page *,
79 unsigned int, unsigned int); 79 unsigned int, unsigned int);
80static void nfs_writeback_done_partial(struct nfs_write_data *, int); 80static int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
81static void nfs_writeback_done_full(struct nfs_write_data *, int);
82static int nfs_wait_on_write_congestion(struct address_space *, int); 81static int nfs_wait_on_write_congestion(struct address_space *, int);
83static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int); 82static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
84static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, 83static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
85 unsigned int npages, int how); 84 unsigned int npages, int how);
85static const struct rpc_call_ops nfs_write_partial_ops;
86static const struct rpc_call_ops nfs_write_full_ops;
87static const struct rpc_call_ops nfs_commit_ops;
86 88
87static kmem_cache_t *nfs_wdata_cachep; 89static kmem_cache_t *nfs_wdata_cachep;
88mempool_t *nfs_wdata_mempool; 90mempool_t *nfs_wdata_mempool;
@@ -872,10 +874,12 @@ static inline int flush_task_priority(int how)
872 */ 874 */
873static void nfs_write_rpcsetup(struct nfs_page *req, 875static void nfs_write_rpcsetup(struct nfs_page *req,
874 struct nfs_write_data *data, 876 struct nfs_write_data *data,
877 const struct rpc_call_ops *call_ops,
875 unsigned int count, unsigned int offset, 878 unsigned int count, unsigned int offset,
876 int how) 879 int how)
877{ 880{
878 struct inode *inode; 881 struct inode *inode;
882 int flags;
879 883
880 /* Set up the RPC argument and reply structs 884 /* Set up the RPC argument and reply structs
881 * NB: take care not to mess about with data->commit et al. */ 885 * NB: take care not to mess about with data->commit et al. */
@@ -896,6 +900,9 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
896 data->res.verf = &data->verf; 900 data->res.verf = &data->verf;
897 nfs_fattr_init(&data->fattr); 901 nfs_fattr_init(&data->fattr);
898 902
903 /* Set up the initial task struct. */
904 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
905 rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
899 NFS_PROTO(inode)->write_setup(data, how); 906 NFS_PROTO(inode)->write_setup(data, how);
900 907
901 data->task.tk_priority = flush_task_priority(how); 908 data->task.tk_priority = flush_task_priority(how);
@@ -959,14 +966,15 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
959 list_del_init(&data->pages); 966 list_del_init(&data->pages);
960 967
961 data->pagevec[0] = page; 968 data->pagevec[0] = page;
962 data->complete = nfs_writeback_done_partial;
963 969
964 if (nbytes > wsize) { 970 if (nbytes > wsize) {
965 nfs_write_rpcsetup(req, data, wsize, offset, how); 971 nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
972 wsize, offset, how);
966 offset += wsize; 973 offset += wsize;
967 nbytes -= wsize; 974 nbytes -= wsize;
968 } else { 975 } else {
969 nfs_write_rpcsetup(req, data, nbytes, offset, how); 976 nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
977 nbytes, offset, how);
970 nbytes = 0; 978 nbytes = 0;
971 } 979 }
972 nfs_execute_write(data); 980 nfs_execute_write(data);
@@ -1020,9 +1028,8 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
1020 } 1028 }
1021 req = nfs_list_entry(data->pages.next); 1029 req = nfs_list_entry(data->pages.next);
1022 1030
1023 data->complete = nfs_writeback_done_full;
1024 /* Set up the argument struct */ 1031 /* Set up the argument struct */
1025 nfs_write_rpcsetup(req, data, count, 0, how); 1032 nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
1026 1033
1027 nfs_execute_write(data); 1034 nfs_execute_write(data);
1028 return 0; 1035 return 0;
@@ -1066,8 +1073,9 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
1066/* 1073/*
1067 * Handle a write reply that flushed part of a page. 1074 * Handle a write reply that flushed part of a page.
1068 */ 1075 */
1069static void nfs_writeback_done_partial(struct nfs_write_data *data, int status) 1076static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
1070{ 1077{
1078 struct nfs_write_data *data = calldata;
1071 struct nfs_page *req = data->req; 1079 struct nfs_page *req = data->req;
1072 struct page *page = req->wb_page; 1080 struct page *page = req->wb_page;
1073 1081
@@ -1077,11 +1085,14 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
1077 req->wb_bytes, 1085 req->wb_bytes,
1078 (long long)req_offset(req)); 1086 (long long)req_offset(req));
1079 1087
1080 if (status < 0) { 1088 if (nfs_writeback_done(task, data) != 0)
1089 return;
1090
1091 if (task->tk_status < 0) {
1081 ClearPageUptodate(page); 1092 ClearPageUptodate(page);
1082 SetPageError(page); 1093 SetPageError(page);
1083 req->wb_context->error = status; 1094 req->wb_context->error = task->tk_status;
1084 dprintk(", error = %d\n", status); 1095 dprintk(", error = %d\n", task->tk_status);
1085 } else { 1096 } else {
1086#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1097#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1087 if (data->verf.committed < NFS_FILE_SYNC) { 1098 if (data->verf.committed < NFS_FILE_SYNC) {
@@ -1102,6 +1113,11 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
1102 nfs_writepage_release(req); 1113 nfs_writepage_release(req);
1103} 1114}
1104 1115
1116static const struct rpc_call_ops nfs_write_partial_ops = {
1117 .rpc_call_done = nfs_writeback_done_partial,
1118 .rpc_release = nfs_writedata_release,
1119};
1120
1105/* 1121/*
1106 * Handle a write reply that flushes a whole page. 1122 * Handle a write reply that flushes a whole page.
1107 * 1123 *
@@ -1109,11 +1125,15 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
1109 * writebacks since the page->count is kept > 1 for as long 1125 * writebacks since the page->count is kept > 1 for as long
1110 * as the page has a write request pending. 1126 * as the page has a write request pending.
1111 */ 1127 */
1112static void nfs_writeback_done_full(struct nfs_write_data *data, int status) 1128static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
1113{ 1129{
1130 struct nfs_write_data *data = calldata;
1114 struct nfs_page *req; 1131 struct nfs_page *req;
1115 struct page *page; 1132 struct page *page;
1116 1133
1134 if (nfs_writeback_done(task, data) != 0)
1135 return;
1136
1117 /* Update attributes as result of writeback. */ 1137 /* Update attributes as result of writeback. */
1118 while (!list_empty(&data->pages)) { 1138 while (!list_empty(&data->pages)) {
1119 req = nfs_list_entry(data->pages.next); 1139 req = nfs_list_entry(data->pages.next);
@@ -1126,13 +1146,13 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1126 req->wb_bytes, 1146 req->wb_bytes,
1127 (long long)req_offset(req)); 1147 (long long)req_offset(req));
1128 1148
1129 if (status < 0) { 1149 if (task->tk_status < 0) {
1130 ClearPageUptodate(page); 1150 ClearPageUptodate(page);
1131 SetPageError(page); 1151 SetPageError(page);
1132 req->wb_context->error = status; 1152 req->wb_context->error = task->tk_status;
1133 end_page_writeback(page); 1153 end_page_writeback(page);
1134 nfs_inode_remove_request(req); 1154 nfs_inode_remove_request(req);
1135 dprintk(", error = %d\n", status); 1155 dprintk(", error = %d\n", task->tk_status);
1136 goto next; 1156 goto next;
1137 } 1157 }
1138 end_page_writeback(page); 1158 end_page_writeback(page);
@@ -1154,18 +1174,28 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1154 } 1174 }
1155} 1175}
1156 1176
1177static const struct rpc_call_ops nfs_write_full_ops = {
1178 .rpc_call_done = nfs_writeback_done_full,
1179 .rpc_release = nfs_writedata_release,
1180};
1181
1182
1157/* 1183/*
1158 * This function is called when the WRITE call is complete. 1184 * This function is called when the WRITE call is complete.
1159 */ 1185 */
1160void nfs_writeback_done(struct rpc_task *task, void *calldata) 1186static int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
1161{ 1187{
1162 struct nfs_write_data *data = calldata;
1163 struct nfs_writeargs *argp = &data->args; 1188 struct nfs_writeargs *argp = &data->args;
1164 struct nfs_writeres *resp = &data->res; 1189 struct nfs_writeres *resp = &data->res;
1190 int status;
1165 1191
1166 dprintk("NFS: %4d nfs_writeback_done (status %d)\n", 1192 dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
1167 task->tk_pid, task->tk_status); 1193 task->tk_pid, task->tk_status);
1168 1194
1195 /* Call the NFS version-specific code */
1196 status = NFS_PROTO(data->inode)->write_done(task, data);
1197 if (status != 0)
1198 return status;
1169 nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); 1199 nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
1170 1200
1171#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1201#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -1210,7 +1240,7 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
1210 argp->stable = NFS_FILE_SYNC; 1240 argp->stable = NFS_FILE_SYNC;
1211 } 1241 }
1212 rpc_restart_call(task); 1242 rpc_restart_call(task);
1213 return; 1243 return -EAGAIN;
1214 } 1244 }
1215 if (time_before(complain, jiffies)) { 1245 if (time_before(complain, jiffies)) {
1216 printk(KERN_WARNING 1246 printk(KERN_WARNING
@@ -1221,11 +1251,7 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
1221 /* Can't do anything about it except throw an error. */ 1251 /* Can't do anything about it except throw an error. */
1222 task->tk_status = -EIO; 1252 task->tk_status = -EIO;
1223 } 1253 }
1224 1254 return 0;
1225 /*
1226 * Process the nfs_page list
1227 */
1228 data->complete(data, task->tk_status);
1229} 1255}
1230 1256
1231 1257
@@ -1239,10 +1265,12 @@ void nfs_commit_release(void *wdata)
1239 * Set up the argument/result storage required for the RPC call. 1265 * Set up the argument/result storage required for the RPC call.
1240 */ 1266 */
1241static void nfs_commit_rpcsetup(struct list_head *head, 1267static void nfs_commit_rpcsetup(struct list_head *head,
1242 struct nfs_write_data *data, int how) 1268 struct nfs_write_data *data,
1269 int how)
1243{ 1270{
1244 struct nfs_page *first; 1271 struct nfs_page *first;
1245 struct inode *inode; 1272 struct inode *inode;
1273 int flags;
1246 1274
1247 /* Set up the RPC argument and reply structs 1275 /* Set up the RPC argument and reply structs
1248 * NB: take care not to mess about with data->commit et al. */ 1276 * NB: take care not to mess about with data->commit et al. */
@@ -1262,7 +1290,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1262 data->res.fattr = &data->fattr; 1290 data->res.fattr = &data->fattr;
1263 data->res.verf = &data->verf; 1291 data->res.verf = &data->verf;
1264 nfs_fattr_init(&data->fattr); 1292 nfs_fattr_init(&data->fattr);
1265 1293
1294 /* Set up the initial task struct. */
1295 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
1296 rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data);
1266 NFS_PROTO(inode)->commit_setup(data, how); 1297 NFS_PROTO(inode)->commit_setup(data, how);
1267 1298
1268 data->task.tk_priority = flush_task_priority(how); 1299 data->task.tk_priority = flush_task_priority(how);
@@ -1303,7 +1334,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1303/* 1334/*
1304 * COMMIT call returned 1335 * COMMIT call returned
1305 */ 1336 */
1306void nfs_commit_done(struct rpc_task *task, void *calldata) 1337static void nfs_commit_done(struct rpc_task *task, void *calldata)
1307{ 1338{
1308 struct nfs_write_data *data = calldata; 1339 struct nfs_write_data *data = calldata;
1309 struct nfs_page *req; 1340 struct nfs_page *req;
@@ -1312,6 +1343,10 @@ void nfs_commit_done(struct rpc_task *task, void *calldata)
1312 dprintk("NFS: %4d nfs_commit_done (status %d)\n", 1343 dprintk("NFS: %4d nfs_commit_done (status %d)\n",
1313 task->tk_pid, task->tk_status); 1344 task->tk_pid, task->tk_status);
1314 1345
1346 /* Call the NFS version-specific code */
1347 if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
1348 return;
1349
1315 while (!list_empty(&data->pages)) { 1350 while (!list_empty(&data->pages)) {
1316 req = nfs_list_entry(data->pages.next); 1351 req = nfs_list_entry(data->pages.next);
1317 nfs_list_remove_request(req); 1352 nfs_list_remove_request(req);
@@ -1345,6 +1380,11 @@ void nfs_commit_done(struct rpc_task *task, void *calldata)
1345 } 1380 }
1346 sub_page_state(nr_unstable,res); 1381 sub_page_state(nr_unstable,res);
1347} 1382}
1383
1384static const struct rpc_call_ops nfs_commit_ops = {
1385 .rpc_call_done = nfs_commit_done,
1386 .rpc_release = nfs_commit_release,
1387};
1348#endif 1388#endif
1349 1389
1350static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, 1390static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,