Re: [PATCH 07/20] xfs: split iop_unlock

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

 



On Thu, Jun 13, 2019 at 08:02:47PM +0200, Christoph Hellwig wrote:
> The iop_unlock method is called when comitting or cancelling a
> transaction.  In the latter case, the transaction may or may not be
> aborted.  While there is no known problem with the current code in
> practice, this implementation is limited in that any log item
> implementation that might want to differentiate between a commit and a
> cancellation must rely on the aborted state.  The aborted bit is only
> set when the cancelled transaction is dirty, however.  This means that
> there is no way to distinguish between a commit and a clean transaction
> cancellation.
> 
> For example, intent log items currently rely on this distinction.  The
> log item is either transferred to the CIL on commit or released on
> transaction cancel. There is currently no possibility for a clean intent
> log item in a transaction, but if that state is ever introduced a cancel
> of such a transaction will immediately result in memory leaks of the
> associated log item(s).  This is an interface deficiency and landmine.
> 
> To clean this up, replace the iop_unlock method with an iop_release
> method that is specific to transaction cancel.  The existing
> iop_committing method occurs at the same time as iop_unlock in the
> commit path and there is no need for two separate callbacks here.
> Overload the iop_committing method with the current commit time
> iop_unlock implementations to eliminate the need for the latter and
> further simplify the interface.
> 
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> ---

Reviewed-by: Brian Foster <bfoster@xxxxxxxxxx>

>  fs/xfs/xfs_bmap_item.c     | 17 +++++++----------
>  fs/xfs/xfs_buf_item.c      | 15 ++++++++++++---
>  fs/xfs/xfs_dquot_item.c    | 19 +++++++++++--------
>  fs/xfs/xfs_extfree_item.c  | 17 +++++++----------
>  fs/xfs/xfs_icreate_item.c  | 10 +++-------
>  fs/xfs/xfs_inode_item.c    | 11 ++++++-----
>  fs/xfs/xfs_log_cil.c       |  2 --
>  fs/xfs/xfs_refcount_item.c | 17 +++++++----------
>  fs/xfs/xfs_rmap_item.c     | 17 +++++++----------
>  fs/xfs/xfs_trace.h         |  2 +-
>  fs/xfs/xfs_trans.c         |  7 +++----
>  fs/xfs/xfs_trans.h         |  4 ++--
>  fs/xfs/xfs_trans_buf.c     |  2 +-
>  13 files changed, 67 insertions(+), 73 deletions(-)
> 
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index 8e57df6d5581..56c1ab161f3b 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -119,11 +119,10 @@ xfs_bui_item_unpin(
>   * constructed and thus we free the BUI here directly.
>   */
>  STATIC void
> -xfs_bui_item_unlock(
> +xfs_bui_item_release(
>  	struct xfs_log_item	*lip)
>  {
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags))
> -		xfs_bui_release(BUI_ITEM(lip));
> +	xfs_bui_release(BUI_ITEM(lip));
>  }
>  
>  /*
> @@ -133,7 +132,7 @@ static const struct xfs_item_ops xfs_bui_item_ops = {
>  	.iop_size	= xfs_bui_item_size,
>  	.iop_format	= xfs_bui_item_format,
>  	.iop_unpin	= xfs_bui_item_unpin,
> -	.iop_unlock	= xfs_bui_item_unlock,
> +	.iop_release	= xfs_bui_item_release,
>  };
>  
>  /*
> @@ -200,15 +199,13 @@ xfs_bud_item_format(
>   * BUD.
>   */
>  STATIC void
> -xfs_bud_item_unlock(
> +xfs_bud_item_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_bud_log_item	*budp = BUD_ITEM(lip);
>  
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
> -		xfs_bui_release(budp->bud_buip);
> -		kmem_zone_free(xfs_bud_zone, budp);
> -	}
> +	xfs_bui_release(budp->bud_buip);
> +	kmem_zone_free(xfs_bud_zone, budp);
>  }
>  
>  /*
> @@ -242,7 +239,7 @@ xfs_bud_item_committed(
>  static const struct xfs_item_ops xfs_bud_item_ops = {
>  	.iop_size	= xfs_bud_item_size,
>  	.iop_format	= xfs_bud_item_format,
> -	.iop_unlock	= xfs_bud_item_unlock,
> +	.iop_release	= xfs_bud_item_release,
>  	.iop_committed	= xfs_bud_item_committed,
>  };
>  
> diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
> index 423f1a042ed8..dc98d669884e 100644
> --- a/fs/xfs/xfs_buf_item.c
> +++ b/fs/xfs/xfs_buf_item.c
> @@ -594,7 +594,7 @@ xfs_buf_item_put(
>   * free the item.
>   */
>  STATIC void
> -xfs_buf_item_unlock(
> +xfs_buf_item_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_buf_log_item	*bip = BUF_ITEM(lip);
> @@ -609,7 +609,7 @@ xfs_buf_item_unlock(
>  						   &lip->li_flags);
>  #endif
>  
> -	trace_xfs_buf_item_unlock(bip);
> +	trace_xfs_buf_item_release(bip);
>  
>  	/*
>  	 * The bli dirty state should match whether the blf has logged segments
> @@ -639,6 +639,14 @@ xfs_buf_item_unlock(
>  	xfs_buf_relse(bp);
>  }
>  
> +STATIC void
> +xfs_buf_item_committing(
> +	struct xfs_log_item	*lip,
> +	xfs_lsn_t		commit_lsn)
> +{
> +	return xfs_buf_item_release(lip);
> +}
> +
>  /*
>   * This is called to find out where the oldest active copy of the
>   * buf log item in the on disk log resides now that the last log
> @@ -679,7 +687,8 @@ static const struct xfs_item_ops xfs_buf_item_ops = {
>  	.iop_format	= xfs_buf_item_format,
>  	.iop_pin	= xfs_buf_item_pin,
>  	.iop_unpin	= xfs_buf_item_unpin,
> -	.iop_unlock	= xfs_buf_item_unlock,
> +	.iop_release	= xfs_buf_item_release,
> +	.iop_committing	= xfs_buf_item_committing,
>  	.iop_committed	= xfs_buf_item_committed,
>  	.iop_push	= xfs_buf_item_push,
>  };
> diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
> index a61a8a770d7f..b8fd81641dfc 100644
> --- a/fs/xfs/xfs_dquot_item.c
> +++ b/fs/xfs/xfs_dquot_item.c
> @@ -197,14 +197,8 @@ xfs_qm_dquot_logitem_push(
>  	return rval;
>  }
>  
> -/*
> - * Unlock the dquot associated with the log item.
> - * Clear the fields of the dquot and dquot log item that
> - * are specific to the current transaction.  If the
> - * hold flags is set, do not unlock the dquot.
> - */
>  STATIC void
> -xfs_qm_dquot_logitem_unlock(
> +xfs_qm_dquot_logitem_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_dquot	*dqp = DQUOT_ITEM(lip)->qli_dquot;
> @@ -220,6 +214,14 @@ xfs_qm_dquot_logitem_unlock(
>  	xfs_dqunlock(dqp);
>  }
>  
> +STATIC void
> +xfs_qm_dquot_logitem_committing(
> +	struct xfs_log_item	*lip,
> +	xfs_lsn_t		commit_lsn)
> +{
> +	return xfs_qm_dquot_logitem_release(lip);
> +}
> +
>  /*
>   * This is the ops vector for dquots
>   */
> @@ -228,7 +230,8 @@ static const struct xfs_item_ops xfs_dquot_item_ops = {
>  	.iop_format	= xfs_qm_dquot_logitem_format,
>  	.iop_pin	= xfs_qm_dquot_logitem_pin,
>  	.iop_unpin	= xfs_qm_dquot_logitem_unpin,
> -	.iop_unlock	= xfs_qm_dquot_logitem_unlock,
> +	.iop_release	= xfs_qm_dquot_logitem_release,
> +	.iop_committing	= xfs_qm_dquot_logitem_committing,
>  	.iop_push	= xfs_qm_dquot_logitem_push,
>  	.iop_error	= xfs_dquot_item_error
>  };
> diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
> index 655ed0445750..a73a3cff8502 100644
> --- a/fs/xfs/xfs_extfree_item.c
> +++ b/fs/xfs/xfs_extfree_item.c
> @@ -129,11 +129,10 @@ xfs_efi_item_unpin(
>   * constructed and thus we free the EFI here directly.
>   */
>  STATIC void
> -xfs_efi_item_unlock(
> +xfs_efi_item_release(
>  	struct xfs_log_item	*lip)
>  {
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags))
> -		xfs_efi_release(EFI_ITEM(lip));
> +	xfs_efi_release(EFI_ITEM(lip));
>  }
>  
>  /*
> @@ -143,7 +142,7 @@ static const struct xfs_item_ops xfs_efi_item_ops = {
>  	.iop_size	= xfs_efi_item_size,
>  	.iop_format	= xfs_efi_item_format,
>  	.iop_unpin	= xfs_efi_item_unpin,
> -	.iop_unlock	= xfs_efi_item_unlock,
> +	.iop_release	= xfs_efi_item_release,
>  };
>  
>  
> @@ -299,15 +298,13 @@ xfs_efd_item_format(
>   * the transaction is cancelled, drop our reference to the EFI and free the EFD.
>   */
>  STATIC void
> -xfs_efd_item_unlock(
> +xfs_efd_item_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);
>  
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
> -		xfs_efi_release(efdp->efd_efip);
> -		xfs_efd_item_free(efdp);
> -	}
> +	xfs_efi_release(efdp->efd_efip);
> +	xfs_efd_item_free(efdp);
>  }
>  
>  /*
> @@ -341,7 +338,7 @@ xfs_efd_item_committed(
>  static const struct xfs_item_ops xfs_efd_item_ops = {
>  	.iop_size	= xfs_efd_item_size,
>  	.iop_format	= xfs_efd_item_format,
> -	.iop_unlock	= xfs_efd_item_unlock,
> +	.iop_release	= xfs_efd_item_release,
>  	.iop_committed	= xfs_efd_item_committed,
>  };
>  
> diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
> index cbaabc55f0c9..9aceb35dce24 100644
> --- a/fs/xfs/xfs_icreate_item.c
> +++ b/fs/xfs/xfs_icreate_item.c
> @@ -57,14 +57,10 @@ xfs_icreate_item_format(
>  }
>  
>  STATIC void
> -xfs_icreate_item_unlock(
> +xfs_icreate_item_release(
>  	struct xfs_log_item	*lip)
>  {
> -	struct xfs_icreate_item	*icp = ICR_ITEM(lip);
> -
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags))
> -		kmem_zone_free(xfs_icreate_zone, icp);
> -	return;
> +	kmem_zone_free(xfs_icreate_zone, ICR_ITEM(lip));
>  }
>  
>  /*
> @@ -89,7 +85,7 @@ xfs_icreate_item_committed(
>  static const struct xfs_item_ops xfs_icreate_item_ops = {
>  	.iop_size	= xfs_icreate_item_size,
>  	.iop_format	= xfs_icreate_item_format,
> -	.iop_unlock	= xfs_icreate_item_unlock,
> +	.iop_release	= xfs_icreate_item_release,
>  	.iop_committed	= xfs_icreate_item_committed,
>  };
>  
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index fa1c4fe2ffbf..a00f0b6aecc7 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -565,7 +565,7 @@ xfs_inode_item_push(
>   * Unlock the inode associated with the inode log item.
>   */
>  STATIC void
> -xfs_inode_item_unlock(
> +xfs_inode_item_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_inode_log_item *iip = INODE_ITEM(lip);
> @@ -621,9 +621,10 @@ xfs_inode_item_committed(
>  STATIC void
>  xfs_inode_item_committing(
>  	struct xfs_log_item	*lip,
> -	xfs_lsn_t		lsn)
> +	xfs_lsn_t		commit_lsn)
>  {
> -	INODE_ITEM(lip)->ili_last_lsn = lsn;
> +	INODE_ITEM(lip)->ili_last_lsn = commit_lsn;
> +	return xfs_inode_item_release(lip);
>  }
>  
>  /*
> @@ -634,10 +635,10 @@ static const struct xfs_item_ops xfs_inode_item_ops = {
>  	.iop_format	= xfs_inode_item_format,
>  	.iop_pin	= xfs_inode_item_pin,
>  	.iop_unpin	= xfs_inode_item_unpin,
> -	.iop_unlock	= xfs_inode_item_unlock,
> +	.iop_release	= xfs_inode_item_release,
>  	.iop_committed	= xfs_inode_item_committed,
>  	.iop_push	= xfs_inode_item_push,
> -	.iop_committing = xfs_inode_item_committing,
> +	.iop_committing	= xfs_inode_item_committing,
>  	.iop_error	= xfs_inode_item_error
>  };
>  
> diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
> index c856bfce5bf2..4cb459f21ad4 100644
> --- a/fs/xfs/xfs_log_cil.c
> +++ b/fs/xfs/xfs_log_cil.c
> @@ -1024,8 +1024,6 @@ xfs_log_commit_cil(
>  		xfs_trans_del_item(lip);
>  		if (lip->li_ops->iop_committing)
>  			lip->li_ops->iop_committing(lip, xc_commit_lsn);
> -		if (lip->li_ops->iop_unlock)
> -			lip->li_ops->iop_unlock(lip);
>  	}
>  	xlog_cil_push_background(log);
>  
> diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> index 03a61886fe2a..9f8fb23dcc81 100644
> --- a/fs/xfs/xfs_refcount_item.c
> +++ b/fs/xfs/xfs_refcount_item.c
> @@ -118,11 +118,10 @@ xfs_cui_item_unpin(
>   * constructed and thus we free the CUI here directly.
>   */
>  STATIC void
> -xfs_cui_item_unlock(
> +xfs_cui_item_release(
>  	struct xfs_log_item	*lip)
>  {
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags))
> -		xfs_cui_release(CUI_ITEM(lip));
> +	xfs_cui_release(CUI_ITEM(lip));
>  }
>  
>  /*
> @@ -132,7 +131,7 @@ static const struct xfs_item_ops xfs_cui_item_ops = {
>  	.iop_size	= xfs_cui_item_size,
>  	.iop_format	= xfs_cui_item_format,
>  	.iop_unpin	= xfs_cui_item_unpin,
> -	.iop_unlock	= xfs_cui_item_unlock,
> +	.iop_release	= xfs_cui_item_release,
>  };
>  
>  /*
> @@ -205,15 +204,13 @@ xfs_cud_item_format(
>   * CUD.
>   */
>  STATIC void
> -xfs_cud_item_unlock(
> +xfs_cud_item_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_cud_log_item	*cudp = CUD_ITEM(lip);
>  
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
> -		xfs_cui_release(cudp->cud_cuip);
> -		kmem_zone_free(xfs_cud_zone, cudp);
> -	}
> +	xfs_cui_release(cudp->cud_cuip);
> +	kmem_zone_free(xfs_cud_zone, cudp);
>  }
>  
>  /*
> @@ -247,7 +244,7 @@ xfs_cud_item_committed(
>  static const struct xfs_item_ops xfs_cud_item_ops = {
>  	.iop_size	= xfs_cud_item_size,
>  	.iop_format	= xfs_cud_item_format,
> -	.iop_unlock	= xfs_cud_item_unlock,
> +	.iop_release	= xfs_cud_item_release,
>  	.iop_committed	= xfs_cud_item_committed,
>  };
>  
> diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
> index df9f2505c5f3..e907bd169de5 100644
> --- a/fs/xfs/xfs_rmap_item.c
> +++ b/fs/xfs/xfs_rmap_item.c
> @@ -117,11 +117,10 @@ xfs_rui_item_unpin(
>   * constructed and thus we free the RUI here directly.
>   */
>  STATIC void
> -xfs_rui_item_unlock(
> +xfs_rui_item_release(
>  	struct xfs_log_item	*lip)
>  {
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags))
> -		xfs_rui_release(RUI_ITEM(lip));
> +	xfs_rui_release(RUI_ITEM(lip));
>  }
>  
>  /*
> @@ -131,7 +130,7 @@ static const struct xfs_item_ops xfs_rui_item_ops = {
>  	.iop_size	= xfs_rui_item_size,
>  	.iop_format	= xfs_rui_item_format,
>  	.iop_unpin	= xfs_rui_item_unpin,
> -	.iop_unlock	= xfs_rui_item_unlock,
> +	.iop_release	= xfs_rui_item_release,
>  };
>  
>  /*
> @@ -226,15 +225,13 @@ xfs_rud_item_format(
>   * RUD.
>   */
>  STATIC void
> -xfs_rud_item_unlock(
> +xfs_rud_item_release(
>  	struct xfs_log_item	*lip)
>  {
>  	struct xfs_rud_log_item	*rudp = RUD_ITEM(lip);
>  
> -	if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
> -		xfs_rui_release(rudp->rud_ruip);
> -		kmem_zone_free(xfs_rud_zone, rudp);
> -	}
> +	xfs_rui_release(rudp->rud_ruip);
> +	kmem_zone_free(xfs_rud_zone, rudp);
>  }
>  
>  /*
> @@ -268,7 +265,7 @@ xfs_rud_item_committed(
>  static const struct xfs_item_ops xfs_rud_item_ops = {
>  	.iop_size	= xfs_rud_item_size,
>  	.iop_format	= xfs_rud_item_format,
> -	.iop_unlock	= xfs_rud_item_unlock,
> +	.iop_release	= xfs_rud_item_release,
>  	.iop_committed	= xfs_rud_item_committed,
>  };
>  
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index 195a9cdb954e..65c920554b96 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -475,7 +475,7 @@ DEFINE_BUF_ITEM_EVENT(xfs_buf_item_ordered);
>  DEFINE_BUF_ITEM_EVENT(xfs_buf_item_pin);
>  DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unpin);
>  DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unpin_stale);
> -DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unlock);
> +DEFINE_BUF_ITEM_EVENT(xfs_buf_item_release);
>  DEFINE_BUF_ITEM_EVENT(xfs_buf_item_committed);
>  DEFINE_BUF_ITEM_EVENT(xfs_buf_item_push);
>  DEFINE_BUF_ITEM_EVENT(xfs_trans_get_buf);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index b0e77e4c1bfe..5fe69ea07367 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -780,9 +780,8 @@ xfs_trans_free_items(
>  		xfs_trans_del_item(lip);
>  		if (abort)
>  			set_bit(XFS_LI_ABORTED, &lip->li_flags);
> -
> -		if (lip->li_ops->iop_unlock)
> -			lip->li_ops->iop_unlock(lip);
> +		if (lip->li_ops->iop_release)
> +			lip->li_ops->iop_release(lip);
>  	}
>  }
>  
> @@ -815,7 +814,7 @@ xfs_log_item_batch_insert(
>   *
>   * If we are called with the aborted flag set, it is because a log write during
>   * a CIL checkpoint commit has failed. In this case, all the items in the
> - * checkpoint have already gone through iop_committed and iop_unlock, which
> + * checkpoint have already gone through iop_committed and iop_committing, which
>   * means that checkpoint commit abort handling is treated exactly the same
>   * as an iclog write error even though we haven't started any IO yet. Hence in
>   * this case all we need to do is iop_committed processing, followed by an
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index c6e1c5704a8c..7bd1867613c2 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -72,9 +72,9 @@ struct xfs_item_ops {
>  	void (*iop_pin)(xfs_log_item_t *);
>  	void (*iop_unpin)(xfs_log_item_t *, int remove);
>  	uint (*iop_push)(struct xfs_log_item *, struct list_head *);
> -	void (*iop_unlock)(xfs_log_item_t *);
> +	void (*iop_committing)(struct xfs_log_item *, xfs_lsn_t commit_lsn);
> +	void (*iop_release)(struct xfs_log_item *);
>  	xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
> -	void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
>  	void (*iop_error)(xfs_log_item_t *, xfs_buf_t *);
>  };
>  
> diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
> index 7d65ebf1e847..3dca9cf40a9f 100644
> --- a/fs/xfs/xfs_trans_buf.c
> +++ b/fs/xfs/xfs_trans_buf.c
> @@ -428,7 +428,7 @@ xfs_trans_brelse(
>  
>  /*
>   * Mark the buffer as not needing to be unlocked when the buf item's
> - * iop_unlock() routine is called.  The buffer must already be locked
> + * iop_committing() routine is called.  The buffer must already be locked
>   * and associated with the given transaction.
>   */
>  /* ARGSUSED */
> -- 
> 2.20.1
> 



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux