aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/pagelist.c14
-rw-r--r--fs/nfs/write.c6
-rw-r--r--include/linux/nfs_page.h10
3 files changed, 16 insertions, 14 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index f8a4ba533930..257a7f8b2362 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -85,9 +85,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
85 req->wb_offset = offset; 85 req->wb_offset = offset;
86 req->wb_pgbase = offset; 86 req->wb_pgbase = offset;
87 req->wb_bytes = count; 87 req->wb_bytes = count;
88 atomic_set(&req->wb_count, 1);
89 req->wb_context = get_nfs_open_context(ctx); 88 req->wb_context = get_nfs_open_context(ctx);
90 89 kref_init(&req->wb_kref);
91 return req; 90 return req;
92} 91}
93 92
@@ -160,11 +159,9 @@ void nfs_clear_request(struct nfs_page *req)
160 * 159 *
161 * Note: Should never be called with the spinlock held! 160 * Note: Should never be called with the spinlock held!
162 */ 161 */
163void 162static void nfs_free_request(struct kref *kref)
164nfs_release_request(struct nfs_page *req)
165{ 163{
166 if (!atomic_dec_and_test(&req->wb_count)) 164 struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
167 return;
168 165
169 /* Release struct file or cached credential */ 166 /* Release struct file or cached credential */
170 nfs_clear_request(req); 167 nfs_clear_request(req);
@@ -172,6 +169,11 @@ nfs_release_request(struct nfs_page *req)
172 nfs_page_free(req); 169 nfs_page_free(req);
173} 170}
174 171
172void nfs_release_request(struct nfs_page *req)
173{
174 kref_put(&req->wb_kref, nfs_free_request);
175}
176
175static int nfs_wait_bit_interruptible(void *word) 177static int nfs_wait_bit_interruptible(void *word)
176{ 178{
177 int ret = 0; 179 int ret = 0;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9e7c21da864f..e9404328ac02 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -117,7 +117,7 @@ static struct nfs_page *nfs_page_find_request_locked(struct page *page)
117 if (PagePrivate(page)) { 117 if (PagePrivate(page)) {
118 req = (struct nfs_page *)page_private(page); 118 req = (struct nfs_page *)page_private(page);
119 if (req != NULL) 119 if (req != NULL)
120 atomic_inc(&req->wb_count); 120 kref_get(&req->wb_kref);
121 } 121 }
122 return req; 122 return req;
123} 123}
@@ -398,7 +398,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
398 if (PageDirty(req->wb_page)) 398 if (PageDirty(req->wb_page))
399 set_bit(PG_NEED_FLUSH, &req->wb_flags); 399 set_bit(PG_NEED_FLUSH, &req->wb_flags);
400 nfsi->npages++; 400 nfsi->npages++;
401 atomic_inc(&req->wb_count); 401 kref_get(&req->wb_kref);
402 return 0; 402 return 0;
403} 403}
404 404
@@ -531,7 +531,7 @@ static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, u
531 next = req->wb_index + 1; 531 next = req->wb_index + 1;
532 BUG_ON(!NFS_WBACK_BUSY(req)); 532 BUG_ON(!NFS_WBACK_BUSY(req));
533 533
534 atomic_inc(&req->wb_count); 534 kref_get(&req->wb_kref);
535 spin_unlock(&nfsi->req_lock); 535 spin_unlock(&nfsi->req_lock);
536 error = nfs_wait_on_request(req); 536 error = nfs_wait_on_request(req);
537 nfs_release_request(req); 537 nfs_release_request(req);
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index bd193af80162..c780e7e39f99 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -16,7 +16,7 @@
16#include <linux/sunrpc/auth.h> 16#include <linux/sunrpc/auth.h>
17#include <linux/nfs_xdr.h> 17#include <linux/nfs_xdr.h>
18 18
19#include <asm/atomic.h> 19#include <linux/kref.h>
20 20
21/* 21/*
22 * Valid flags for the radix tree 22 * Valid flags for the radix tree
@@ -42,7 +42,7 @@ struct nfs_page {
42 unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */ 42 unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
43 wb_pgbase, /* Start of page data */ 43 wb_pgbase, /* Start of page data */
44 wb_bytes; /* Length of request */ 44 wb_bytes; /* Length of request */
45 atomic_t wb_count; /* reference count */ 45 struct kref wb_kref; /* reference count */
46 unsigned long wb_flags; 46 unsigned long wb_flags;
47 struct nfs_writeverf wb_verf; /* Commit cookie */ 47 struct nfs_writeverf wb_verf; /* Commit cookie */
48}; 48};
@@ -89,7 +89,7 @@ extern void nfs_clear_page_writeback(struct nfs_page *req);
89 89
90 90
91/* 91/*
92 * Lock the page of an asynchronous request without incrementing the wb_count 92 * Lock the page of an asynchronous request without getting a new reference
93 */ 93 */
94static inline int 94static inline int
95nfs_lock_request_dontget(struct nfs_page *req) 95nfs_lock_request_dontget(struct nfs_page *req)
@@ -98,14 +98,14 @@ nfs_lock_request_dontget(struct nfs_page *req)
98} 98}
99 99
100/* 100/*
101 * Lock the page of an asynchronous request 101 * Lock the page of an asynchronous request and take a reference
102 */ 102 */
103static inline int 103static inline int
104nfs_lock_request(struct nfs_page *req) 104nfs_lock_request(struct nfs_page *req)
105{ 105{
106 if (test_and_set_bit(PG_BUSY, &req->wb_flags)) 106 if (test_and_set_bit(PG_BUSY, &req->wb_flags))
107 return 0; 107 return 0;
108 atomic_inc(&req->wb_count); 108 kref_get(&req->wb_kref);
109 return 1; 109 return 1;
110} 110}
111 111