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.c71
1 files changed, 32 insertions, 39 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 58a39b0486a7..5130eda231d7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -352,7 +352,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
352 if (err < 0) 352 if (err < 0)
353 goto out; 353 goto out;
354 } 354 }
355 err = nfs_commit_inode(inode, 0, 0, wb_priority(wbc)); 355 err = nfs_commit_inode(inode, wb_priority(wbc));
356 if (err > 0) { 356 if (err > 0) {
357 wbc->nr_to_write -= err; 357 wbc->nr_to_write -= err;
358 err = 0; 358 err = 0;
@@ -446,6 +446,8 @@ nfs_mark_request_dirty(struct nfs_page *req)
446 struct nfs_inode *nfsi = NFS_I(inode); 446 struct nfs_inode *nfsi = NFS_I(inode);
447 447
448 spin_lock(&nfsi->req_lock); 448 spin_lock(&nfsi->req_lock);
449 radix_tree_tag_set(&nfsi->nfs_page_tree,
450 req->wb_index, NFS_PAGE_TAG_DIRTY);
449 nfs_list_add_request(req, &nfsi->dirty); 451 nfs_list_add_request(req, &nfsi->dirty);
450 nfsi->ndirty++; 452 nfsi->ndirty++;
451 spin_unlock(&nfsi->req_lock); 453 spin_unlock(&nfsi->req_lock);
@@ -537,12 +539,15 @@ static int
537nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) 539nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
538{ 540{
539 struct nfs_inode *nfsi = NFS_I(inode); 541 struct nfs_inode *nfsi = NFS_I(inode);
540 int res; 542 int res = 0;
541 res = nfs_scan_list(&nfsi->dirty, dst, idx_start, npages); 543
542 nfsi->ndirty -= res; 544 if (nfsi->ndirty != 0) {
543 sub_page_state(nr_dirty,res); 545 res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);
544 if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty)) 546 nfsi->ndirty -= res;
545 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n"); 547 sub_page_state(nr_dirty,res);
548 if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
549 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
550 }
546 return res; 551 return res;
547} 552}
548 553
@@ -561,11 +566,14 @@ static int
561nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) 566nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
562{ 567{
563 struct nfs_inode *nfsi = NFS_I(inode); 568 struct nfs_inode *nfsi = NFS_I(inode);
564 int res; 569 int res = 0;
565 res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages); 570
566 nfsi->ncommit -= res; 571 if (nfsi->ncommit != 0) {
567 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) 572 res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);
568 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); 573 nfsi->ncommit -= res;
574 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
575 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
576 }
569 return res; 577 return res;
570} 578}
571#endif 579#endif
@@ -1209,36 +1217,24 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1209 struct nfs_write_data *data, int how) 1217 struct nfs_write_data *data, int how)
1210{ 1218{
1211 struct rpc_task *task = &data->task; 1219 struct rpc_task *task = &data->task;
1212 struct nfs_page *first, *last; 1220 struct nfs_page *first;
1213 struct inode *inode; 1221 struct inode *inode;
1214 loff_t start, end, len;
1215 1222
1216 /* Set up the RPC argument and reply structs 1223 /* Set up the RPC argument and reply structs
1217 * NB: take care not to mess about with data->commit et al. */ 1224 * NB: take care not to mess about with data->commit et al. */
1218 1225
1219 list_splice_init(head, &data->pages); 1226 list_splice_init(head, &data->pages);
1220 first = nfs_list_entry(data->pages.next); 1227 first = nfs_list_entry(data->pages.next);
1221 last = nfs_list_entry(data->pages.prev);
1222 inode = first->wb_context->dentry->d_inode; 1228 inode = first->wb_context->dentry->d_inode;
1223 1229
1224 /*
1225 * Determine the offset range of requests in the COMMIT call.
1226 * We rely on the fact that data->pages is an ordered list...
1227 */
1228 start = req_offset(first);
1229 end = req_offset(last) + last->wb_bytes;
1230 len = end - start;
1231 /* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
1232 if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))
1233 len = 0;
1234
1235 data->inode = inode; 1230 data->inode = inode;
1236 data->cred = first->wb_context->cred; 1231 data->cred = first->wb_context->cred;
1237 1232
1238 data->args.fh = NFS_FH(data->inode); 1233 data->args.fh = NFS_FH(data->inode);
1239 data->args.offset = start; 1234 /* Note: we always request a commit of the entire inode */
1240 data->args.count = len; 1235 data->args.offset = 0;
1241 data->res.count = len; 1236 data->args.count = 0;
1237 data->res.count = 0;
1242 data->res.fattr = &data->fattr; 1238 data->res.fattr = &data->fattr;
1243 data->res.verf = &data->verf; 1239 data->res.verf = &data->verf;
1244 1240
@@ -1357,8 +1353,7 @@ static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
1357} 1353}
1358 1354
1359#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1355#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1360int nfs_commit_inode(struct inode *inode, unsigned long idx_start, 1356int nfs_commit_inode(struct inode *inode, int how)
1361 unsigned int npages, int how)
1362{ 1357{
1363 struct nfs_inode *nfsi = NFS_I(inode); 1358 struct nfs_inode *nfsi = NFS_I(inode);
1364 LIST_HEAD(head); 1359 LIST_HEAD(head);
@@ -1366,15 +1361,13 @@ int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
1366 error = 0; 1361 error = 0;
1367 1362
1368 spin_lock(&nfsi->req_lock); 1363 spin_lock(&nfsi->req_lock);
1369 res = nfs_scan_commit(inode, &head, idx_start, npages); 1364 res = nfs_scan_commit(inode, &head, 0, 0);
1365 spin_unlock(&nfsi->req_lock);
1370 if (res) { 1366 if (res) {
1371 res += nfs_scan_commit(inode, &head, 0, 0);
1372 spin_unlock(&nfsi->req_lock);
1373 error = nfs_commit_list(&head, how); 1367 error = nfs_commit_list(&head, how);
1374 } else 1368 if (error < 0)
1375 spin_unlock(&nfsi->req_lock); 1369 return error;
1376 if (error < 0) 1370 }
1377 return error;
1378 return res; 1371 return res;
1379} 1372}
1380#endif 1373#endif
@@ -1396,7 +1389,7 @@ int nfs_sync_inode(struct inode *inode, unsigned long idx_start,
1396 error = nfs_flush_inode(inode, idx_start, npages, how); 1389 error = nfs_flush_inode(inode, idx_start, npages, how);
1397#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1390#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1398 if (error == 0) 1391 if (error == 0)
1399 error = nfs_commit_inode(inode, idx_start, npages, how); 1392 error = nfs_commit_inode(inode, how);
1400#endif 1393#endif
1401 } while (error > 0); 1394 } while (error > 0);
1402 return error; 1395 return error;