NFS: Fix a hang in the writeback path
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>
This commit is contained in:
		
					parent
					
						
							
								16c29dafcc
							
						
					
				
			
			
				commit
				
					
						4d65c520fb
					
				
			
		
					 3 changed files with 5 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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))
 | 
			
		||||
	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);
 | 
			
		||||
| 
						 | 
				
			
			@ -423,10 +420,6 @@ 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);
 | 
			
		||||
	nfs_release_request(req);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue