Re: [PATCH 2/3] NFSv4.1: Always clear the NFS_INO_LAYOUTCOMMIT in layoutreturn

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2013-03-20 19:39, Trond Myklebust wrote:
> Note that clearing NFS_INO_LAYOUTCOMMIT is tricky, since it requires
> you to also clear the NFS_LSEG_LAYOUTCOMMIT bits from the layout
> segments.
> The only two sites that need to do this are the ones that call
> pnfs_return_layout() without first doing a layout commit.
> 
> Signed-off-by: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx>
> Cc: Benny Halevy <bhalevy@xxxxxxxxxx>

ACK

> Cc: stable@xxxxxxxxxxxxxxx
> ---
>  fs/nfs/nfs4filelayout.c |  1 -
>  fs/nfs/pnfs.c           | 35 +++++++++++++++++++++++++++--------
>  2 files changed, 27 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
> index c5656c5..22d1062 100644
> --- a/fs/nfs/nfs4filelayout.c
> +++ b/fs/nfs/nfs4filelayout.c
> @@ -129,7 +129,6 @@ static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
>  {
>  	if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
>  		return;
> -	clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
>  	pnfs_return_layout(inode);
>  }
>  
> diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
> index 6f6b356..45badca 100644
> --- a/fs/nfs/pnfs.c
> +++ b/fs/nfs/pnfs.c
> @@ -417,6 +417,16 @@ should_free_lseg(struct pnfs_layout_range *lseg_range,
>  	       lo_seg_intersecting(lseg_range, recall_range);
>  }
>  
> +static bool lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
> +		struct list_head *tmp_list)
> +{
> +	if (!atomic_dec_and_test(&lseg->pls_refcount))
> +		return false;
> +	pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
> +	list_add(&lseg->pls_list, tmp_list);
> +	return true;
> +}
> +
>  /* Returns 1 if lseg is removed from list, 0 otherwise */
>  static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
>  			     struct list_head *tmp_list)
> @@ -430,11 +440,8 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
>  		 */
>  		dprintk("%s: lseg %p ref %d\n", __func__, lseg,
>  			atomic_read(&lseg->pls_refcount));
> -		if (atomic_dec_and_test(&lseg->pls_refcount)) {
> -			pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
> -			list_add(&lseg->pls_list, tmp_list);
> +		if (lseg_dec_and_remove_zero(lseg, tmp_list))
>  			rv = 1;
> -		}
>  	}
>  	return rv;
>  }
> @@ -779,6 +786,21 @@ send_layoutget(struct pnfs_layout_hdr *lo,
>  	return lseg;
>  }
>  
> +static void pnfs_clear_layoutcommit(struct inode *inode,
> +		struct list_head *head)
> +{
> +	struct nfs_inode *nfsi = NFS_I(inode);
> +	struct pnfs_layout_segment *lseg, *tmp;
> +
> +	if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
> +		return;
> +	list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) {
> +		if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
> +			continue;
> +		lseg_dec_and_remove_zero(lseg, head);
> +	}
> +}
> +
>  /*
>   * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
>   * when the layout segment list is empty.
> @@ -810,6 +832,7 @@ _pnfs_return_layout(struct inode *ino)
>  	/* Reference matched in nfs4_layoutreturn_release */
>  	pnfs_get_layout_hdr(lo);
>  	empty = list_empty(&lo->plh_segs);
> +	pnfs_clear_layoutcommit(ino, &tmp_list);
>  	pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
>  	/* Don't send a LAYOUTRETURN if list was initially empty */
>  	if (empty) {
> @@ -822,8 +845,6 @@ _pnfs_return_layout(struct inode *ino)
>  	spin_unlock(&ino->i_lock);
>  	pnfs_free_lseg_list(&tmp_list);
>  
> -	WARN_ON(test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags));
> -
>  	lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
>  	if (unlikely(lrp == NULL)) {
>  		status = -ENOMEM;
> @@ -1460,7 +1481,6 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
>  	dprintk("pnfs write error = %d\n", hdr->pnfs_error);
>  	if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
>  	    PNFS_LAYOUTRET_ON_ERROR) {
> -		clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
>  		pnfs_return_layout(hdr->inode);
>  	}
>  	if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
> @@ -1615,7 +1635,6 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
>  	dprintk("pnfs read error = %d\n", hdr->pnfs_error);
>  	if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
>  	    PNFS_LAYOUTRET_ON_ERROR) {
> -		clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
>  		pnfs_return_layout(hdr->inode);
>  	}
>  	if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux