aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c89
1 files changed, 45 insertions, 44 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 3107908e5f3f..9449b6835509 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -89,24 +89,38 @@ static mempool_t *nfs_commit_mempool;
89 89
90static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion); 90static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
91 91
92static inline struct nfs_write_data *nfs_commit_alloc(void) 92static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
93{ 93{
94 struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS); 94 struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
95
95 if (p) { 96 if (p) {
96 memset(p, 0, sizeof(*p)); 97 memset(p, 0, sizeof(*p));
97 INIT_LIST_HEAD(&p->pages); 98 INIT_LIST_HEAD(&p->pages);
99 if (pagecount < NFS_PAGEVEC_SIZE)
100 p->pagevec = &p->page_array[0];
101 else {
102 size_t size = ++pagecount * sizeof(struct page *);
103 p->pagevec = kmalloc(size, GFP_NOFS);
104 if (p->pagevec) {
105 memset(p->pagevec, 0, size);
106 } else {
107 mempool_free(p, nfs_commit_mempool);
108 p = NULL;
109 }
110 }
98 } 111 }
99 return p; 112 return p;
100} 113}
101 114
102static inline void nfs_commit_free(struct nfs_write_data *p) 115static inline void nfs_commit_free(struct nfs_write_data *p)
103{ 116{
117 if (p && (p->pagevec != &p->page_array[0]))
118 kfree(p->pagevec);
104 mempool_free(p, nfs_commit_mempool); 119 mempool_free(p, nfs_commit_mempool);
105} 120}
106 121
107static void nfs_writedata_release(struct rpc_task *task) 122void nfs_writedata_release(void *wdata)
108{ 123{
109 struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
110 nfs_writedata_free(wdata); 124 nfs_writedata_free(wdata);
111} 125}
112 126
@@ -168,7 +182,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
168 int result, written = 0; 182 int result, written = 0;
169 struct nfs_write_data *wdata; 183 struct nfs_write_data *wdata;
170 184
171 wdata = nfs_writedata_alloc(); 185 wdata = nfs_writedata_alloc(1);
172 if (!wdata) 186 if (!wdata)
173 return -ENOMEM; 187 return -ENOMEM;
174 188
@@ -232,19 +246,16 @@ static int nfs_writepage_async(struct nfs_open_context *ctx,
232 unsigned int offset, unsigned int count) 246 unsigned int offset, unsigned int count)
233{ 247{
234 struct nfs_page *req; 248 struct nfs_page *req;
235 int status;
236 249
237 req = nfs_update_request(ctx, inode, page, offset, count); 250 req = nfs_update_request(ctx, inode, page, offset, count);
238 status = (IS_ERR(req)) ? PTR_ERR(req) : 0; 251 if (IS_ERR(req))
239 if (status < 0) 252 return PTR_ERR(req);
240 goto out;
241 /* Update file length */ 253 /* Update file length */
242 nfs_grow_file(page, offset, count); 254 nfs_grow_file(page, offset, count);
243 /* Set the PG_uptodate flag? */ 255 /* Set the PG_uptodate flag? */
244 nfs_mark_uptodate(page, offset, count); 256 nfs_mark_uptodate(page, offset, count);
245 nfs_unlock_request(req); 257 nfs_unlock_request(req);
246 out: 258 return 0;
247 return status;
248} 259}
249 260
250static int wb_priority(struct writeback_control *wbc) 261static int wb_priority(struct writeback_control *wbc)
@@ -304,11 +315,8 @@ do_it:
304 lock_kernel(); 315 lock_kernel();
305 if (!IS_SYNC(inode) && inode_referenced) { 316 if (!IS_SYNC(inode) && inode_referenced) {
306 err = nfs_writepage_async(ctx, inode, page, 0, offset); 317 err = nfs_writepage_async(ctx, inode, page, 0, offset);
307 if (err >= 0) { 318 if (!wbc->for_writepages)
308 err = 0; 319 nfs_flush_inode(inode, 0, 0, wb_priority(wbc));
309 if (wbc->for_reclaim)
310 nfs_flush_inode(inode, 0, 0, FLUSH_STABLE);
311 }
312 } else { 320 } else {
313 err = nfs_writepage_sync(ctx, inode, page, 0, 321 err = nfs_writepage_sync(ctx, inode, page, 0,
314 offset, priority); 322 offset, priority);
@@ -877,9 +885,6 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
877 885
878 data->task.tk_priority = flush_task_priority(how); 886 data->task.tk_priority = flush_task_priority(how);
879 data->task.tk_cookie = (unsigned long)inode; 887 data->task.tk_cookie = (unsigned long)inode;
880 data->task.tk_calldata = data;
881 /* Release requests */
882 data->task.tk_release = nfs_writedata_release;
883 888
884 dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n", 889 dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
885 data->task.tk_pid, 890 data->task.tk_pid,
@@ -919,7 +924,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
919 924
920 nbytes = req->wb_bytes; 925 nbytes = req->wb_bytes;
921 for (;;) { 926 for (;;) {
922 data = nfs_writedata_alloc(); 927 data = nfs_writedata_alloc(1);
923 if (!data) 928 if (!data)
924 goto out_bad; 929 goto out_bad;
925 list_add(&data->pages, &list); 930 list_add(&data->pages, &list);
@@ -983,7 +988,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
983 if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE) 988 if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE)
984 return nfs_flush_multi(head, inode, how); 989 return nfs_flush_multi(head, inode, how);
985 990
986 data = nfs_writedata_alloc(); 991 data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
987 if (!data) 992 if (!data)
988 goto out_bad; 993 goto out_bad;
989 994
@@ -1137,9 +1142,9 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1137/* 1142/*
1138 * This function is called when the WRITE call is complete. 1143 * This function is called when the WRITE call is complete.
1139 */ 1144 */
1140void nfs_writeback_done(struct rpc_task *task) 1145void nfs_writeback_done(struct rpc_task *task, void *calldata)
1141{ 1146{
1142 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; 1147 struct nfs_write_data *data = calldata;
1143 struct nfs_writeargs *argp = &data->args; 1148 struct nfs_writeargs *argp = &data->args;
1144 struct nfs_writeres *resp = &data->res; 1149 struct nfs_writeres *resp = &data->res;
1145 1150
@@ -1206,9 +1211,8 @@ void nfs_writeback_done(struct rpc_task *task)
1206 1211
1207 1212
1208#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1213#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1209static void nfs_commit_release(struct rpc_task *task) 1214void nfs_commit_release(void *wdata)
1210{ 1215{
1211 struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
1212 nfs_commit_free(wdata); 1216 nfs_commit_free(wdata);
1213} 1217}
1214 1218
@@ -1244,9 +1248,6 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1244 1248
1245 data->task.tk_priority = flush_task_priority(how); 1249 data->task.tk_priority = flush_task_priority(how);
1246 data->task.tk_cookie = (unsigned long)inode; 1250 data->task.tk_cookie = (unsigned long)inode;
1247 data->task.tk_calldata = data;
1248 /* Release requests */
1249 data->task.tk_release = nfs_commit_release;
1250 1251
1251 dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid); 1252 dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid);
1252} 1253}
@@ -1255,12 +1256,12 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1255 * Commit dirty pages 1256 * Commit dirty pages
1256 */ 1257 */
1257static int 1258static int
1258nfs_commit_list(struct list_head *head, int how) 1259nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1259{ 1260{
1260 struct nfs_write_data *data; 1261 struct nfs_write_data *data;
1261 struct nfs_page *req; 1262 struct nfs_page *req;
1262 1263
1263 data = nfs_commit_alloc(); 1264 data = nfs_commit_alloc(NFS_SERVER(inode)->wpages);
1264 1265
1265 if (!data) 1266 if (!data)
1266 goto out_bad; 1267 goto out_bad;
@@ -1283,10 +1284,9 @@ nfs_commit_list(struct list_head *head, int how)
1283/* 1284/*
1284 * COMMIT call returned 1285 * COMMIT call returned
1285 */ 1286 */
1286void 1287void nfs_commit_done(struct rpc_task *task, void *calldata)
1287nfs_commit_done(struct rpc_task *task)
1288{ 1288{
1289 struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata; 1289 struct nfs_write_data *data = calldata;
1290 struct nfs_page *req; 1290 struct nfs_page *req;
1291 int res = 0; 1291 int res = 0;
1292 1292
@@ -1366,7 +1366,7 @@ int nfs_commit_inode(struct inode *inode, int how)
1366 res = nfs_scan_commit(inode, &head, 0, 0); 1366 res = nfs_scan_commit(inode, &head, 0, 0);
1367 spin_unlock(&nfsi->req_lock); 1367 spin_unlock(&nfsi->req_lock);
1368 if (res) { 1368 if (res) {
1369 error = nfs_commit_list(&head, how); 1369 error = nfs_commit_list(inode, &head, how);
1370 if (error < 0) 1370 if (error < 0)
1371 return error; 1371 return error;
1372 } 1372 }
@@ -1377,22 +1377,23 @@ int nfs_commit_inode(struct inode *inode, int how)
1377int nfs_sync_inode(struct inode *inode, unsigned long idx_start, 1377int nfs_sync_inode(struct inode *inode, unsigned long idx_start,
1378 unsigned int npages, int how) 1378 unsigned int npages, int how)
1379{ 1379{
1380 int error, 1380 int nocommit = how & FLUSH_NOCOMMIT;
1381 wait; 1381 int wait = how & FLUSH_WAIT;
1382 int error;
1382 1383
1383 wait = how & FLUSH_WAIT; 1384 how &= ~(FLUSH_WAIT|FLUSH_NOCOMMIT);
1384 how &= ~FLUSH_WAIT;
1385 1385
1386 do { 1386 do {
1387 error = 0; 1387 if (wait) {
1388 if (wait)
1389 error = nfs_wait_on_requests(inode, idx_start, npages); 1388 error = nfs_wait_on_requests(inode, idx_start, npages);
1390 if (error == 0) 1389 if (error != 0)
1391 error = nfs_flush_inode(inode, idx_start, npages, how); 1390 continue;
1392#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1391 }
1393 if (error == 0) 1392 error = nfs_flush_inode(inode, idx_start, npages, how);
1393 if (error != 0)
1394 continue;
1395 if (!nocommit)
1394 error = nfs_commit_inode(inode, how); 1396 error = nfs_commit_inode(inode, how);
1395#endif
1396 } while (error > 0); 1397 } while (error > 0);
1397 return error; 1398 return error;
1398} 1399}