diff options
-rw-r--r-- | fs/nfs/pagelist.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 32 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 2 |
3 files changed, 24 insertions, 12 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 18ee4e99347e..ceb4424614aa 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -397,6 +397,8 @@ static void nfs_free_request(struct nfs_page *req) | |||
397 | WARN_ON_ONCE(test_bit(PG_TEARDOWN, &req->wb_flags)); | 397 | WARN_ON_ONCE(test_bit(PG_TEARDOWN, &req->wb_flags)); |
398 | WARN_ON_ONCE(test_bit(PG_UNLOCKPAGE, &req->wb_flags)); | 398 | WARN_ON_ONCE(test_bit(PG_UNLOCKPAGE, &req->wb_flags)); |
399 | WARN_ON_ONCE(test_bit(PG_UPTODATE, &req->wb_flags)); | 399 | WARN_ON_ONCE(test_bit(PG_UPTODATE, &req->wb_flags)); |
400 | WARN_ON_ONCE(test_bit(PG_WB_END, &req->wb_flags)); | ||
401 | WARN_ON_ONCE(test_bit(PG_REMOVE, &req->wb_flags)); | ||
400 | 402 | ||
401 | /* Release struct file and open context */ | 403 | /* Release struct file and open context */ |
402 | nfs_clear_request(req); | 404 | nfs_clear_request(req); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d0f30f12a8b3..5d752766139d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -201,12 +201,15 @@ static void nfs_set_page_writeback(struct page *page) | |||
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | static void nfs_end_page_writeback(struct page *page) | 204 | static void nfs_end_page_writeback(struct nfs_page *req) |
205 | { | 205 | { |
206 | struct inode *inode = page_file_mapping(page)->host; | 206 | struct inode *inode = page_file_mapping(req->wb_page)->host; |
207 | struct nfs_server *nfss = NFS_SERVER(inode); | 207 | struct nfs_server *nfss = NFS_SERVER(inode); |
208 | 208 | ||
209 | end_page_writeback(page); | 209 | if (!nfs_page_group_sync_on_bit(req, PG_WB_END)) |
210 | return; | ||
211 | |||
212 | end_page_writeback(req->wb_page); | ||
210 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) | 213 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) |
211 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); | 214 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
212 | } | 215 | } |
@@ -397,15 +400,20 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
397 | { | 400 | { |
398 | struct inode *inode = req->wb_context->dentry->d_inode; | 401 | struct inode *inode = req->wb_context->dentry->d_inode; |
399 | struct nfs_inode *nfsi = NFS_I(inode); | 402 | struct nfs_inode *nfsi = NFS_I(inode); |
403 | struct nfs_page *head; | ||
400 | 404 | ||
401 | spin_lock(&inode->i_lock); | 405 | if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) { |
402 | if (likely(!PageSwapCache(req->wb_page))) { | 406 | head = req->wb_head; |
403 | set_page_private(req->wb_page, 0); | 407 | |
404 | ClearPagePrivate(req->wb_page); | 408 | spin_lock(&inode->i_lock); |
405 | clear_bit(PG_MAPPED, &req->wb_flags); | 409 | if (likely(!PageSwapCache(head->wb_page))) { |
410 | set_page_private(head->wb_page, 0); | ||
411 | ClearPagePrivate(head->wb_page); | ||
412 | clear_bit(PG_MAPPED, &head->wb_flags); | ||
413 | } | ||
414 | nfsi->npages--; | ||
415 | spin_unlock(&inode->i_lock); | ||
406 | } | 416 | } |
407 | nfsi->npages--; | ||
408 | spin_unlock(&inode->i_lock); | ||
409 | nfs_release_request(req); | 417 | nfs_release_request(req); |
410 | } | 418 | } |
411 | 419 | ||
@@ -599,7 +607,7 @@ remove_req: | |||
599 | nfs_inode_remove_request(req); | 607 | nfs_inode_remove_request(req); |
600 | next: | 608 | next: |
601 | nfs_unlock_request(req); | 609 | nfs_unlock_request(req); |
602 | nfs_end_page_writeback(req->wb_page); | 610 | nfs_end_page_writeback(req); |
603 | do_destroy = !test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags); | 611 | do_destroy = !test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags); |
604 | nfs_release_request(req); | 612 | nfs_release_request(req); |
605 | } | 613 | } |
@@ -964,7 +972,7 @@ static void nfs_redirty_request(struct nfs_page *req) | |||
964 | { | 972 | { |
965 | nfs_mark_request_dirty(req); | 973 | nfs_mark_request_dirty(req); |
966 | nfs_unlock_request(req); | 974 | nfs_unlock_request(req); |
967 | nfs_end_page_writeback(req->wb_page); | 975 | nfs_end_page_writeback(req); |
968 | nfs_release_request(req); | 976 | nfs_release_request(req); |
969 | } | 977 | } |
970 | 978 | ||
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 6385175a127b..7d9096d95d4a 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -31,6 +31,8 @@ enum { | |||
31 | PG_TEARDOWN, /* page group sync for destroy */ | 31 | PG_TEARDOWN, /* page group sync for destroy */ |
32 | PG_UNLOCKPAGE, /* page group sync bit in read path */ | 32 | PG_UNLOCKPAGE, /* page group sync bit in read path */ |
33 | PG_UPTODATE, /* page group sync bit in read path */ | 33 | PG_UPTODATE, /* page group sync bit in read path */ |
34 | PG_WB_END, /* page group sync bit in write path */ | ||
35 | PG_REMOVE, /* page group sync bit in write path */ | ||
34 | }; | 36 | }; |
35 | 37 | ||
36 | struct nfs_inode; | 38 | struct nfs_inode; |