NFS: Store pointer to the nfs_page in page->private
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 5 Dec 2006 05:35:35 +0000 (00:35 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 6 Dec 2006 15:46:36 +0000 (10:46 -0500)
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 <Trond.Myklebust@netapp.com>
fs/nfs/write.c

index 310fdec..6df8319 100644 (file)
@@ -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 inode *inode, struct nfs_page *req)
                        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(struct nfs_page *req)
        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--;
@@ -458,33 +483,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        nfs_release_request(req);
 }
 
-/*
- * 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.
  */
@@ -699,10 +697,11 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                 * 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_request(struct nfs_open_context* ctx,
 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 *file, struct page *page)
         * 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;
 }