From: Trond Myklebust Date: Tue, 5 Dec 2006 00:35:35 -0500 NFS: Store pointer to the nfs_page in page->private This will allow fast lookup of the nfs_page from the struct page instead of having to search the radix tree. Signed-off-by: Trond Myklebust --- 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 310fdec..6df8319 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -155,6 +155,29 @@ void nfs_writedata_release(void *wdata) nfs_writedata_free(wdata); } +static struct nfs_page *nfs_page_find_request_locked(struct page *page) +{ + struct nfs_page *req = NULL; + + if (PagePrivate(page)) { + req = (struct nfs_page *)page_private(page); + if (req != NULL) + atomic_inc(&req->wb_count); + } + return req; +} + +static struct nfs_page *nfs_page_find_request(struct page *page) +{ + struct nfs_page *req = NULL; + spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; + + spin_lock(req_lock); + req = nfs_page_find_request_locked(page); + spin_unlock(req_lock); + return req; +} + /* Adjust the file length if we're writing beyond the end */ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) { @@ -429,6 +452,7 @@ static int nfs_inode_add_request(struct nfsi->change_attr++; } SetPagePrivate(req->wb_page); + set_page_private(req->wb_page, (unsigned long)req); nfsi->npages++; atomic_inc(&req->wb_count); return 0; @@ -445,6 +469,7 @@ static void nfs_inode_remove_request(str BUG_ON (!NFS_WBACK_BUSY(req)); spin_lock(&nfsi->req_lock); + set_page_private(req->wb_page, 0); ClearPagePrivate(req->wb_page); radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); nfsi->npages--; @@ -459,33 +484,6 @@ static void nfs_inode_remove_request(str } /* - * Find a request - */ -static inline struct nfs_page * -_nfs_find_request(struct inode *inode, unsigned long index) -{ - struct nfs_inode *nfsi = NFS_I(inode); - struct nfs_page *req; - - req = (struct nfs_page*)radix_tree_lookup(&nfsi->nfs_page_tree, index); - if (req) - atomic_inc(&req->wb_count); - return req; -} - -static struct nfs_page * -nfs_find_request(struct inode *inode, unsigned long index) -{ - struct nfs_page *req; - struct nfs_inode *nfsi = NFS_I(inode); - - spin_lock(&nfsi->req_lock); - req = _nfs_find_request(inode, index); - spin_unlock(&nfsi->req_lock); - return req; -} - -/* * Add a request to the inode's dirty list. */ static void @@ -699,10 +697,11 @@ static struct nfs_page * nfs_update_requ * A request for the page we wish to update */ spin_lock(&nfsi->req_lock); - req = _nfs_find_request(inode, page->index); + req = nfs_page_find_request_locked(page); if (req) { if (!nfs_lock_request_dontget(req)) { int error; + spin_unlock(&nfsi->req_lock); error = nfs_wait_on_request(req); nfs_release_request(req); @@ -770,7 +769,6 @@ static struct nfs_page * nfs_update_requ int nfs_flush_incompatible(struct file *file, struct page *page) { struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; - struct inode *inode = page->mapping->host; struct nfs_page *req; int status = 0; /* @@ -781,11 +779,13 @@ int nfs_flush_incompatible(struct file * * Also do the same if we find a request from an existing * dropped page. */ - req = nfs_find_request(inode, page->index); - if (req) { - if (req->wb_page != page || ctx != req->wb_context) - status = nfs_wb_page(inode, page); + req = nfs_page_find_request(page); + if (req != NULL) { + int do_flush = req->wb_page != page || req->wb_context != ctx; + nfs_release_request(req); + if (do_flush) + status = nfs_wb_page(page->mapping->host, page); } return (status < 0) ? status : 0; }