diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 71 |
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 | |||
537 | nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) | 539 | nfs_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 | |||
561 | nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) | 566 | nfs_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) |
1360 | int nfs_commit_inode(struct inode *inode, unsigned long idx_start, | 1356 | int 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; |