diff options
Diffstat (limited to 'fs/nfs/write.c')
| -rw-r--r-- | fs/nfs/write.c | 47 |
1 files changed, 22 insertions, 25 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8e9424651bc6..ce5b4a9f2d8b 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | static struct nfs_page * nfs_update_request(struct nfs_open_context*, | 38 | static struct nfs_page * nfs_update_request(struct nfs_open_context*, |
| 39 | struct page *, | 39 | struct page *, |
| 40 | unsigned int, unsigned int); | 40 | unsigned int, unsigned int); |
| 41 | static void nfs_mark_request_dirty(struct nfs_page *req); | ||
| 42 | static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how); | 41 | static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how); |
| 43 | static const struct rpc_call_ops nfs_write_partial_ops; | 42 | static const struct rpc_call_ops nfs_write_partial_ops; |
| 44 | static const struct rpc_call_ops nfs_write_full_ops; | 43 | static const struct rpc_call_ops nfs_write_full_ops; |
| @@ -255,7 +254,8 @@ static void nfs_end_page_writeback(struct page *page) | |||
| 255 | static int nfs_page_mark_flush(struct page *page) | 254 | static int nfs_page_mark_flush(struct page *page) |
| 256 | { | 255 | { |
| 257 | struct nfs_page *req; | 256 | struct nfs_page *req; |
| 258 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | 257 | struct nfs_inode *nfsi = NFS_I(page->mapping->host); |
| 258 | spinlock_t *req_lock = &nfsi->req_lock; | ||
| 259 | int ret; | 259 | int ret; |
| 260 | 260 | ||
| 261 | spin_lock(req_lock); | 261 | spin_lock(req_lock); |
| @@ -279,11 +279,23 @@ static int nfs_page_mark_flush(struct page *page) | |||
| 279 | return ret; | 279 | return ret; |
| 280 | spin_lock(req_lock); | 280 | spin_lock(req_lock); |
| 281 | } | 281 | } |
| 282 | spin_unlock(req_lock); | 282 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
| 283 | /* This request is marked for commit */ | ||
| 284 | spin_unlock(req_lock); | ||
| 285 | nfs_unlock_request(req); | ||
| 286 | return 1; | ||
| 287 | } | ||
| 283 | if (nfs_set_page_writeback(page) == 0) { | 288 | if (nfs_set_page_writeback(page) == 0) { |
| 284 | nfs_list_remove_request(req); | 289 | nfs_list_remove_request(req); |
| 285 | nfs_mark_request_dirty(req); | 290 | /* add the request to the inode's dirty list. */ |
| 286 | } | 291 | radix_tree_tag_set(&nfsi->nfs_page_tree, |
| 292 | req->wb_index, NFS_PAGE_TAG_DIRTY); | ||
| 293 | nfs_list_add_request(req, &nfsi->dirty); | ||
| 294 | nfsi->ndirty++; | ||
| 295 | spin_unlock(req_lock); | ||
| 296 | __mark_inode_dirty(page->mapping->host, I_DIRTY_PAGES); | ||
| 297 | } else | ||
| 298 | spin_unlock(req_lock); | ||
| 287 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); | 299 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); |
| 288 | nfs_unlock_request(req); | 300 | nfs_unlock_request(req); |
| 289 | return ret; | 301 | return ret; |
| @@ -406,24 +418,6 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
| 406 | nfs_release_request(req); | 418 | nfs_release_request(req); |
| 407 | } | 419 | } |
| 408 | 420 | ||
| 409 | /* | ||
| 410 | * Add a request to the inode's dirty list. | ||
| 411 | */ | ||
| 412 | static void | ||
| 413 | nfs_mark_request_dirty(struct nfs_page *req) | ||
| 414 | { | ||
| 415 | struct inode *inode = req->wb_context->dentry->d_inode; | ||
| 416 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 417 | |||
| 418 | spin_lock(&nfsi->req_lock); | ||
| 419 | radix_tree_tag_set(&nfsi->nfs_page_tree, | ||
| 420 | req->wb_index, NFS_PAGE_TAG_DIRTY); | ||
| 421 | nfs_list_add_request(req, &nfsi->dirty); | ||
| 422 | nfsi->ndirty++; | ||
| 423 | spin_unlock(&nfsi->req_lock); | ||
| 424 | __mark_inode_dirty(inode, I_DIRTY_PAGES); | ||
| 425 | } | ||
| 426 | |||
| 427 | static void | 421 | static void |
| 428 | nfs_redirty_request(struct nfs_page *req) | 422 | nfs_redirty_request(struct nfs_page *req) |
| 429 | { | 423 | { |
| @@ -438,7 +432,7 @@ nfs_dirty_request(struct nfs_page *req) | |||
| 438 | { | 432 | { |
| 439 | struct page *page = req->wb_page; | 433 | struct page *page = req->wb_page; |
| 440 | 434 | ||
| 441 | if (page == NULL) | 435 | if (page == NULL || test_bit(PG_NEED_COMMIT, &req->wb_flags)) |
| 442 | return 0; | 436 | return 0; |
| 443 | return !PageWriteback(req->wb_page); | 437 | return !PageWriteback(req->wb_page); |
| 444 | } | 438 | } |
| @@ -456,6 +450,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
| 456 | spin_lock(&nfsi->req_lock); | 450 | spin_lock(&nfsi->req_lock); |
| 457 | nfs_list_add_request(req, &nfsi->commit); | 451 | nfs_list_add_request(req, &nfsi->commit); |
| 458 | nfsi->ncommit++; | 452 | nfsi->ncommit++; |
| 453 | set_bit(PG_NEED_COMMIT, &(req)->wb_flags); | ||
| 459 | spin_unlock(&nfsi->req_lock); | 454 | spin_unlock(&nfsi->req_lock); |
| 460 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 455 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
| 461 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 456 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
| @@ -470,7 +465,7 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
| 470 | static inline | 465 | static inline |
| 471 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 466 | int nfs_reschedule_unstable_write(struct nfs_page *req) |
| 472 | { | 467 | { |
| 473 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 468 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
| 474 | nfs_mark_request_commit(req); | 469 | nfs_mark_request_commit(req); |
| 475 | return 1; | 470 | return 1; |
| 476 | } | 471 | } |
| @@ -557,6 +552,7 @@ static void nfs_cancel_commit_list(struct list_head *head) | |||
| 557 | req = nfs_list_entry(head->next); | 552 | req = nfs_list_entry(head->next); |
| 558 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 553 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
| 559 | nfs_list_remove_request(req); | 554 | nfs_list_remove_request(req); |
| 555 | clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | ||
| 560 | nfs_inode_remove_request(req); | 556 | nfs_inode_remove_request(req); |
| 561 | nfs_unlock_request(req); | 557 | nfs_unlock_request(req); |
| 562 | } | 558 | } |
| @@ -1295,6 +1291,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
| 1295 | while (!list_empty(&data->pages)) { | 1291 | while (!list_empty(&data->pages)) { |
| 1296 | req = nfs_list_entry(data->pages.next); | 1292 | req = nfs_list_entry(data->pages.next); |
| 1297 | nfs_list_remove_request(req); | 1293 | nfs_list_remove_request(req); |
| 1294 | clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | ||
| 1298 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1295 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
| 1299 | 1296 | ||
| 1300 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", | 1297 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", |
