diff options
-rw-r--r-- | fs/nfs/inode.c | 4 | ||||
-rw-r--r-- | fs/nfs/write.c | 49 |
2 files changed, 39 insertions, 14 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 35f7e4bc680e..1d57fe9f49a9 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -882,6 +882,10 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
882 | struct nfs_inode *nfsi = NFS_I(inode); | 882 | struct nfs_inode *nfsi = NFS_I(inode); |
883 | int ret = 0; | 883 | int ret = 0; |
884 | 884 | ||
885 | /* swapfiles are not supposed to be shared. */ | ||
886 | if (IS_SWAPFILE(inode)) | ||
887 | goto out; | ||
888 | |||
885 | if (nfs_mapping_need_revalidate_inode(inode)) { | 889 | if (nfs_mapping_need_revalidate_inode(inode)) { |
886 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 890 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
887 | if (ret < 0) | 891 | if (ret < 0) |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d0feca32b4fe..974e9c2d31fd 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -139,15 +139,28 @@ static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | |||
139 | set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | 139 | set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
140 | } | 140 | } |
141 | 141 | ||
142 | static struct nfs_page *nfs_page_find_request_locked(struct page *page) | 142 | static struct nfs_page * |
143 | nfs_page_find_request_locked(struct nfs_inode *nfsi, struct page *page) | ||
143 | { | 144 | { |
144 | struct nfs_page *req = NULL; | 145 | struct nfs_page *req = NULL; |
145 | 146 | ||
146 | if (PagePrivate(page)) { | 147 | if (PagePrivate(page)) |
147 | req = (struct nfs_page *)page_private(page); | 148 | req = (struct nfs_page *)page_private(page); |
148 | if (req != NULL) | 149 | else if (unlikely(PageSwapCache(page))) { |
149 | kref_get(&req->wb_kref); | 150 | struct nfs_page *freq, *t; |
151 | |||
152 | /* Linearly search the commit list for the correct req */ | ||
153 | list_for_each_entry_safe(freq, t, &nfsi->commit_info.list, wb_list) { | ||
154 | if (freq->wb_page == page) { | ||
155 | req = freq; | ||
156 | break; | ||
157 | } | ||
158 | } | ||
150 | } | 159 | } |
160 | |||
161 | if (req) | ||
162 | kref_get(&req->wb_kref); | ||
163 | |||
151 | return req; | 164 | return req; |
152 | } | 165 | } |
153 | 166 | ||
@@ -157,7 +170,7 @@ static struct nfs_page *nfs_page_find_request(struct page *page) | |||
157 | struct nfs_page *req = NULL; | 170 | struct nfs_page *req = NULL; |
158 | 171 | ||
159 | spin_lock(&inode->i_lock); | 172 | spin_lock(&inode->i_lock); |
160 | req = nfs_page_find_request_locked(page); | 173 | req = nfs_page_find_request_locked(NFS_I(inode), page); |
161 | spin_unlock(&inode->i_lock); | 174 | spin_unlock(&inode->i_lock); |
162 | return req; | 175 | return req; |
163 | } | 176 | } |
@@ -258,7 +271,7 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblo | |||
258 | 271 | ||
259 | spin_lock(&inode->i_lock); | 272 | spin_lock(&inode->i_lock); |
260 | for (;;) { | 273 | for (;;) { |
261 | req = nfs_page_find_request_locked(page); | 274 | req = nfs_page_find_request_locked(NFS_I(inode), page); |
262 | if (req == NULL) | 275 | if (req == NULL) |
263 | break; | 276 | break; |
264 | if (nfs_lock_request(req)) | 277 | if (nfs_lock_request(req)) |
@@ -413,9 +426,15 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
413 | spin_lock(&inode->i_lock); | 426 | spin_lock(&inode->i_lock); |
414 | if (!nfsi->npages && NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) | 427 | if (!nfsi->npages && NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) |
415 | inode->i_version++; | 428 | inode->i_version++; |
416 | set_bit(PG_MAPPED, &req->wb_flags); | 429 | /* |
417 | SetPagePrivate(req->wb_page); | 430 | * Swap-space should not get truncated. Hence no need to plug the race |
418 | set_page_private(req->wb_page, (unsigned long)req); | 431 | * with invalidate/truncate. |
432 | */ | ||
433 | if (likely(!PageSwapCache(req->wb_page))) { | ||
434 | set_bit(PG_MAPPED, &req->wb_flags); | ||
435 | SetPagePrivate(req->wb_page); | ||
436 | set_page_private(req->wb_page, (unsigned long)req); | ||
437 | } | ||
419 | nfsi->npages++; | 438 | nfsi->npages++; |
420 | kref_get(&req->wb_kref); | 439 | kref_get(&req->wb_kref); |
421 | spin_unlock(&inode->i_lock); | 440 | spin_unlock(&inode->i_lock); |
@@ -432,9 +451,11 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
432 | BUG_ON (!NFS_WBACK_BUSY(req)); | 451 | BUG_ON (!NFS_WBACK_BUSY(req)); |
433 | 452 | ||
434 | spin_lock(&inode->i_lock); | 453 | spin_lock(&inode->i_lock); |
435 | set_page_private(req->wb_page, 0); | 454 | if (likely(!PageSwapCache(req->wb_page))) { |
436 | ClearPagePrivate(req->wb_page); | 455 | set_page_private(req->wb_page, 0); |
437 | clear_bit(PG_MAPPED, &req->wb_flags); | 456 | ClearPagePrivate(req->wb_page); |
457 | clear_bit(PG_MAPPED, &req->wb_flags); | ||
458 | } | ||
438 | nfsi->npages--; | 459 | nfsi->npages--; |
439 | spin_unlock(&inode->i_lock); | 460 | spin_unlock(&inode->i_lock); |
440 | nfs_release_request(req); | 461 | nfs_release_request(req); |
@@ -730,7 +751,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
730 | spin_lock(&inode->i_lock); | 751 | spin_lock(&inode->i_lock); |
731 | 752 | ||
732 | for (;;) { | 753 | for (;;) { |
733 | req = nfs_page_find_request_locked(page); | 754 | req = nfs_page_find_request_locked(NFS_I(inode), page); |
734 | if (req == NULL) | 755 | if (req == NULL) |
735 | goto out_unlock; | 756 | goto out_unlock; |
736 | 757 | ||
@@ -1744,7 +1765,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
1744 | */ | 1765 | */ |
1745 | int nfs_wb_page(struct inode *inode, struct page *page) | 1766 | int nfs_wb_page(struct inode *inode, struct page *page) |
1746 | { | 1767 | { |
1747 | loff_t range_start = page_offset(page); | 1768 | loff_t range_start = page_file_offset(page); |
1748 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | 1769 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); |
1749 | struct writeback_control wbc = { | 1770 | struct writeback_control wbc = { |
1750 | .sync_mode = WB_SYNC_ALL, | 1771 | .sync_mode = WB_SYNC_ALL, |