diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/write.c | 66 |
1 files changed, 33 insertions, 33 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 310fdeca6250..6df8319de060 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -155,6 +155,29 @@ void nfs_writedata_release(void *wdata) | |||
155 | nfs_writedata_free(wdata); | 155 | nfs_writedata_free(wdata); |
156 | } | 156 | } |
157 | 157 | ||
158 | static struct nfs_page *nfs_page_find_request_locked(struct page *page) | ||
159 | { | ||
160 | struct nfs_page *req = NULL; | ||
161 | |||
162 | if (PagePrivate(page)) { | ||
163 | req = (struct nfs_page *)page_private(page); | ||
164 | if (req != NULL) | ||
165 | atomic_inc(&req->wb_count); | ||
166 | } | ||
167 | return req; | ||
168 | } | ||
169 | |||
170 | static struct nfs_page *nfs_page_find_request(struct page *page) | ||
171 | { | ||
172 | struct nfs_page *req = NULL; | ||
173 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | ||
174 | |||
175 | spin_lock(req_lock); | ||
176 | req = nfs_page_find_request_locked(page); | ||
177 | spin_unlock(req_lock); | ||
178 | return req; | ||
179 | } | ||
180 | |||
158 | /* Adjust the file length if we're writing beyond the end */ | 181 | /* Adjust the file length if we're writing beyond the end */ |
159 | static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) | 182 | static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) |
160 | { | 183 | { |
@@ -429,6 +452,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
429 | nfsi->change_attr++; | 452 | nfsi->change_attr++; |
430 | } | 453 | } |
431 | SetPagePrivate(req->wb_page); | 454 | SetPagePrivate(req->wb_page); |
455 | set_page_private(req->wb_page, (unsigned long)req); | ||
432 | nfsi->npages++; | 456 | nfsi->npages++; |
433 | atomic_inc(&req->wb_count); | 457 | atomic_inc(&req->wb_count); |
434 | return 0; | 458 | return 0; |
@@ -445,6 +469,7 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
445 | BUG_ON (!NFS_WBACK_BUSY(req)); | 469 | BUG_ON (!NFS_WBACK_BUSY(req)); |
446 | 470 | ||
447 | spin_lock(&nfsi->req_lock); | 471 | spin_lock(&nfsi->req_lock); |
472 | set_page_private(req->wb_page, 0); | ||
448 | ClearPagePrivate(req->wb_page); | 473 | ClearPagePrivate(req->wb_page); |
449 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 474 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
450 | nfsi->npages--; | 475 | nfsi->npages--; |
@@ -459,33 +484,6 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
459 | } | 484 | } |
460 | 485 | ||
461 | /* | 486 | /* |
462 | * Find a request | ||
463 | */ | ||
464 | static inline struct nfs_page * | ||
465 | _nfs_find_request(struct inode *inode, unsigned long index) | ||
466 | { | ||
467 | struct nfs_inode *nfsi = NFS_I(inode); | ||
468 | struct nfs_page *req; | ||
469 | |||
470 | req = (struct nfs_page*)radix_tree_lookup(&nfsi->nfs_page_tree, index); | ||
471 | if (req) | ||
472 | atomic_inc(&req->wb_count); | ||
473 | return req; | ||
474 | } | ||
475 | |||
476 | static struct nfs_page * | ||
477 | nfs_find_request(struct inode *inode, unsigned long index) | ||
478 | { | ||
479 | struct nfs_page *req; | ||
480 | struct nfs_inode *nfsi = NFS_I(inode); | ||
481 | |||
482 | spin_lock(&nfsi->req_lock); | ||
483 | req = _nfs_find_request(inode, index); | ||
484 | spin_unlock(&nfsi->req_lock); | ||
485 | return req; | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * Add a request to the inode's dirty list. | 487 | * Add a request to the inode's dirty list. |
490 | */ | 488 | */ |
491 | static void | 489 | static void |
@@ -699,10 +697,11 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
699 | * A request for the page we wish to update | 697 | * A request for the page we wish to update |
700 | */ | 698 | */ |
701 | spin_lock(&nfsi->req_lock); | 699 | spin_lock(&nfsi->req_lock); |
702 | req = _nfs_find_request(inode, page->index); | 700 | req = nfs_page_find_request_locked(page); |
703 | if (req) { | 701 | if (req) { |
704 | if (!nfs_lock_request_dontget(req)) { | 702 | if (!nfs_lock_request_dontget(req)) { |
705 | int error; | 703 | int error; |
704 | |||
706 | spin_unlock(&nfsi->req_lock); | 705 | spin_unlock(&nfsi->req_lock); |
707 | error = nfs_wait_on_request(req); | 706 | error = nfs_wait_on_request(req); |
708 | nfs_release_request(req); | 707 | nfs_release_request(req); |
@@ -770,7 +769,6 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
770 | int nfs_flush_incompatible(struct file *file, struct page *page) | 769 | int nfs_flush_incompatible(struct file *file, struct page *page) |
771 | { | 770 | { |
772 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; | 771 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; |
773 | struct inode *inode = page->mapping->host; | ||
774 | struct nfs_page *req; | 772 | struct nfs_page *req; |
775 | int status = 0; | 773 | int status = 0; |
776 | /* | 774 | /* |
@@ -781,11 +779,13 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
781 | * Also do the same if we find a request from an existing | 779 | * Also do the same if we find a request from an existing |
782 | * dropped page. | 780 | * dropped page. |
783 | */ | 781 | */ |
784 | req = nfs_find_request(inode, page->index); | 782 | req = nfs_page_find_request(page); |
785 | if (req) { | 783 | if (req != NULL) { |
786 | if (req->wb_page != page || ctx != req->wb_context) | 784 | int do_flush = req->wb_page != page || req->wb_context != ctx; |
787 | status = nfs_wb_page(inode, page); | 785 | |
788 | nfs_release_request(req); | 786 | nfs_release_request(req); |
787 | if (do_flush) | ||
788 | status = nfs_wb_page(page->mapping->host, page); | ||
789 | } | 789 | } |
790 | return (status < 0) ? status : 0; | 790 | return (status < 0) ? status : 0; |
791 | } | 791 | } |