Skip to content

Commit

Permalink
NFS: Fix a hang in the writeback path
Browse files Browse the repository at this point in the history
Now that the inode scalability patches have been merged, it is no longer
safe to call igrab() under the inode->i_lock.
Now that we no longer call nfs_clear_request() until the nfs_page is
being freed, we know that we are always holding a reference to the
nfs_open_context, which again holds a reference to the path, and so
the inode cannot be freed until the last nfs_page has been removed
from the radix tree and freed.

We can therefore skip the igrab()/iput() altogether.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Mar 27, 2011
1 parent 16c29da commit 4d65c52
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 13 deletions.
4 changes: 2 additions & 2 deletions fs/nfs/pagelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ void nfs_clear_page_tag_locked(struct nfs_page *req)
nfs_unlock_request(req);
}

/**
/*
* nfs_clear_request - Free up all resources allocated to the request
* @req:
*
* Release page and open context resources associated with a read/write
* request after it has completed.
*/
void nfs_clear_request(struct nfs_page *req)
static void nfs_clear_request(struct nfs_page *req)
{
struct page *page = req->wb_page;
struct nfs_open_context *ctx = req->wb_context;
Expand Down
13 changes: 3 additions & 10 deletions fs/nfs/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
spin_lock(&inode->i_lock);
error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req);
BUG_ON(error);
if (!nfsi->npages) {
igrab(inode);
if (nfs_have_delegation(inode, FMODE_WRITE))
nfsi->change_attr++;
}
if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE))
nfsi->change_attr++;
set_bit(PG_MAPPED, &req->wb_flags);
SetPagePrivate(req->wb_page);
set_page_private(req->wb_page, (unsigned long)req);
Expand Down Expand Up @@ -423,11 +420,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
clear_bit(PG_MAPPED, &req->wb_flags);
radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
nfsi->npages--;
if (!nfsi->npages) {
spin_unlock(&inode->i_lock);
iput(inode);
} else
spin_unlock(&inode->i_lock);
spin_unlock(&inode->i_lock);
nfs_release_request(req);
}

Expand Down
1 change: 0 additions & 1 deletion include/linux/nfs_page.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
struct page *page,
unsigned int offset,
unsigned int count);
extern void nfs_clear_request(struct nfs_page *req);
extern void nfs_release_request(struct nfs_page *req);


Expand Down

0 comments on commit 4d65c52

Please sign in to comment.