linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Oliver Hartkopp <socketcan@hartkopp.net>
To: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Eric Dumazet <edumazet@google.com>,
	Norbert Slusarek <nslusarek@gmx.net>,
	Thadeu Lima de Souza Cascardo <cascardo@canonical.com>,
	linux-can@vger.kernel.org
Subject: Re: [PATCH RFC] can: bcm: use call_rcu() instead of costly synchronize_rcu()
Date: Mon, 4 Jul 2022 06:37:19 +0200	[thread overview]
Message-ID: <fc0c14b9-4417-7d92-6eb6-7ce5a52da8d0@hartkopp.net> (raw)
In-Reply-To: <20220520183239.19111-1-socketcan@hartkopp.net>

Hello Marc,

unfortunately I did not get any feedback/review on this patch from the 
original authors.

But I think this fix should go into Linux 5.4+

Best regards,
Oliver

On 20.05.22 20:32, Oliver Hartkopp wrote:
> In commit d5f9023fa61e ("can: bcm: delay release of struct bcm_op after
> synchronize_rcu()") Thadeu Lima de Souza Cascardo introduced two
> synchronize_rcu() calls in bcm_release() (only once at socket close) and
> in bcm_delete_rx_op() (called on removal of each single bcm_op).
> 
> Unfortunately this slow removal of the bcm_op's affects user space
> applications like cansniffer where the modification of a filter removes
> 2048 bcm_op's which blocks the cansniffer application for 40(!) seconds.
> 
> In commit 181d4447905d ("can: gw: use call_rcu() instead of costly
> synchronize_rcu()") Eric Dumazet replaced the synchronize_rcu() calls
> with several call_rcu()'s to safely remove the data structures after the
> removal of CAN ID subscriptions with can_rx_unregister() calls.
> 
> This patch adopts Erics approach for the can-bcm which should be
> applicable since the removal of tasklet_kill() in bcm_remove_op() and
> the introduction of the HRTIMER_MODE_SOFT timer handling in Linux 5.4.
> 
> Fixes: d5f9023fa61e ("can: bcm: delay release of struct bcm_op after synchronize_rcu()") # >= 5.4
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Norbert Slusarek <nslusarek@gmx.net>
> Cc: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> ---
>   net/can/bcm.c | 18 ++++++++++++++----
>   1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/net/can/bcm.c b/net/can/bcm.c
> index 65ee1b784a30..e60161bec850 100644
> --- a/net/can/bcm.c
> +++ b/net/can/bcm.c
> @@ -98,10 +98,11 @@ static inline u64 get_u64(const struct canfd_frame *cp, int offset)
>   	return *(u64 *)(cp->data + offset);
>   }
>   
>   struct bcm_op {
>   	struct list_head list;
> +	struct rcu_head rcu;
>   	int ifindex;
>   	canid_t can_id;
>   	u32 flags;
>   	unsigned long frames_abs, frames_filtered;
>   	struct bcm_timeval ival1, ival2;
> @@ -716,24 +717,31 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
>   	}
>   
>   	return NULL;
>   }
>   
> -static void bcm_remove_op(struct bcm_op *op)
> +static void bcm_free_op_rcu(struct rcu_head *rcu_head)
>   {
> -	hrtimer_cancel(&op->timer);
> -	hrtimer_cancel(&op->thrtimer);
> +	struct bcm_op *op = container_of(rcu_head, struct bcm_op, rcu);
>   
>   	if ((op->frames) && (op->frames != &op->sframe))
>   		kfree(op->frames);
>   
>   	if ((op->last_frames) && (op->last_frames != &op->last_sframe))
>   		kfree(op->last_frames);
>   
>   	kfree(op);
>   }
>   
> +static void bcm_remove_op(struct bcm_op *op)
> +{
> +	hrtimer_cancel(&op->timer);
> +	hrtimer_cancel(&op->thrtimer);
> +
> +	call_rcu(&op->rcu, bcm_free_op_rcu);
> +}
> +
>   static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
>   {
>   	if (op->rx_reg_dev == dev) {
>   		can_rx_unregister(dev_net(dev), dev, op->can_id,
>   				  REGMASK(op->can_id), bcm_rx_handler, op);
> @@ -755,10 +763,13 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
>   
>   	list_for_each_entry_safe(op, n, ops, list) {
>   		if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
>   		    (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME)) {
>   
> +			/* disable automatic timer on frame reception */
> +			op->flags |= RX_NO_AUTOTIMER;
> +
>   			/*
>   			 * Don't care if we're bound or not (due to netdev
>   			 * problems) can_rx_unregister() is always a save
>   			 * thing to do here.
>   			 */
> @@ -783,11 +794,10 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
>   						  op->can_id,
>   						  REGMASK(op->can_id),
>   						  bcm_rx_handler, op);
>   
>   			list_del(&op->list);
> -			synchronize_rcu();
>   			bcm_remove_op(op);
>   			return 1; /* done */
>   		}
>   	}
>   

      reply	other threads:[~2022-07-04  4:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-20 18:32 [PATCH RFC] can: bcm: use call_rcu() instead of costly synchronize_rcu() Oliver Hartkopp
2022-07-04  4:37 ` Oliver Hartkopp [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fc0c14b9-4417-7d92-6eb6-7ce5a52da8d0@hartkopp.net \
    --to=socketcan@hartkopp.net \
    --cc=cascardo@canonical.com \
    --cc=edumazet@google.com \
    --cc=linux-can@vger.kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=nslusarek@gmx.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).