diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
| -rw-r--r-- | fs/nfs/pnfs.c | 57 | 
1 files changed, 39 insertions, 18 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index bbc49caa7a8..76875bfcf19 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -651,7 +651,14 @@ out_err_free:  	return NULL;  } -/* Initiates a LAYOUTRETURN(FILE) */ +/* + * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr + * when the layout segment list is empty. + * + * Note that a pnfs_layout_hdr can exist with an empty layout segment + * list when LAYOUTGET has failed, or when LAYOUTGET succeeded, but the + * deviceid is marked invalid. + */  int  _pnfs_return_layout(struct inode *ino)  { @@ -660,22 +667,31 @@ _pnfs_return_layout(struct inode *ino)  	LIST_HEAD(tmp_list);  	struct nfs4_layoutreturn *lrp;  	nfs4_stateid stateid; -	int status = 0; +	int status = 0, empty; -	dprintk("--> %s\n", __func__); +	dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);  	spin_lock(&ino->i_lock);  	lo = nfsi->layout; -	if (!lo) { +	if (!lo || pnfs_test_layout_returned(lo)) {  		spin_unlock(&ino->i_lock); -		dprintk("%s: no layout to return\n", __func__); -		return status; +		dprintk("NFS: %s no layout to return\n", __func__); +		goto out;  	}  	stateid = nfsi->layout->plh_stateid;  	/* Reference matched in nfs4_layoutreturn_release */  	get_layout_hdr(lo); +	empty = list_empty(&lo->plh_segs);  	mark_matching_lsegs_invalid(lo, &tmp_list, NULL); +	/* Don't send a LAYOUTRETURN if list was initially empty */ +	if (empty) { +		spin_unlock(&ino->i_lock); +		put_layout_hdr(lo); +		dprintk("NFS: %s no layout segments to return\n", __func__); +		goto out; +	}  	lo->plh_block_lgets++; +	pnfs_mark_layout_returned(lo);  	spin_unlock(&ino->i_lock);  	pnfs_free_lseg_list(&tmp_list); @@ -686,6 +702,7 @@ _pnfs_return_layout(struct inode *ino)  		status = -ENOMEM;  		set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags);  		set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags); +		pnfs_clear_layout_returned(lo);  		put_layout_hdr(lo);  		goto out;  	} @@ -1075,6 +1092,10 @@ pnfs_update_layout(struct inode *ino,  	get_layout_hdr(lo);  	if (list_empty(&lo->plh_segs))  		first = true; + +	/* Enable LAYOUTRETURNs */ +	pnfs_clear_layout_returned(lo); +  	spin_unlock(&ino->i_lock);  	if (first) {  		/* The lo must be on the clp list if there is any @@ -1209,7 +1230,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *  }  EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); -bool +void  pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,  		      const struct nfs_pgio_completion_ops *compl_ops)  { @@ -1217,13 +1238,12 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,  	struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;  	if (ld == NULL) -		return false; -	nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, -			server->rsize, 0); -	return true; +		nfs_pageio_init_read(pgio, inode, compl_ops); +	else +		nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, server->rsize, 0);  } -bool +void  pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,  		       int ioflags,  		       const struct nfs_pgio_completion_ops *compl_ops) @@ -1232,10 +1252,9 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,  	struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;  	if (ld == NULL) -		return false; -	nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, -			server->wsize, ioflags); -	return true; +		nfs_pageio_init_write(pgio, inode, ioflags, compl_ops); +	else +		nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, server->wsize, ioflags);  }  bool @@ -1272,7 +1291,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode,  	LIST_HEAD(failed);  	/* Resend all requests through the MDS */ -	nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE, compl_ops); +	nfs_pageio_init_write(&pgio, inode, FLUSH_STABLE, compl_ops);  	while (!list_empty(head)) {  		struct nfs_page *req = nfs_list_entry(head->next); @@ -1388,6 +1407,7 @@ static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)  	put_lseg(hdr->lseg);  	nfs_writehdr_free(hdr);  } +EXPORT_SYMBOL_GPL(pnfs_writehdr_free);  int  pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) @@ -1427,7 +1447,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode,  	LIST_HEAD(failed);  	/* Resend all requests through the MDS */ -	nfs_pageio_init_read_mds(&pgio, inode, compl_ops); +	nfs_pageio_init_read(&pgio, inode, compl_ops);  	while (!list_empty(head)) {  		struct nfs_page *req = nfs_list_entry(head->next); @@ -1542,6 +1562,7 @@ static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)  	put_lseg(hdr->lseg);  	nfs_readhdr_free(hdr);  } +EXPORT_SYMBOL_GPL(pnfs_readhdr_free);  int  pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)  |