All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Williams <dan.j.williams@intel.com>
To: "Fabio M. De Francesco"
	<fabio.maria.de.francesco@linux.intel.com>,
	<linux-kernel@vger.kernel.org>
Cc: "Fabio M. De Francesco"
	<fabio.maria.de.francesco@linux.intel.com>,
	"Peter Zijlstra" <peterz@infradead.org>,
	Dan Williams <dan.j.williams@intel.com>,
	Ira Weiny <ira.weiny@intel.com>
Subject: Re: [RFC PATCH v2] cleanup: Add cond_guard() to conditional guards
Date: Tue, 30 Jan 2024 09:02:09 -0800	[thread overview]
Message-ID: <65b92b91a41a8_5cc6f29484@dwillia2-mobl3.amr.corp.intel.com.notmuch> (raw)
In-Reply-To: <20240130164059.25130-1-fabio.maria.de.francesco@linux.intel.com>

Fabio M. De Francesco wrote:
> Add cond_guard() to conditional guards.
> 
> cond_guard() is used for the _interruptible(), _killable(), and _try
> versions of locks. It expects a block where the failure can be handled
> (e.g., calling printk() and returning -EINTR in case of failure).
> 
> As the other guards, it avoids to open code the release of the lock
> after a goto to an 'out' label.
> 
> This remains an RFC because Dan suggested a slightly different syntax:
> 
> 	if (cond_guard(...))
> 		return -EINTR;
> 
> But the scoped_cond_guard() macro omits the if statement:
> 
>     	scoped_cond_guard (...) {
>     	}
> 
> Thus define cond_guard() similarly to scoped_cond_guard() but with a block
> to handle the failure case:
> 
> 	cond_guard(...)
> 		return -EINTR;

That's too subtle for me, because of the mistakes that can be made with
brackets how about a syntax like:

 	cond_guard(..., return -EINTR, ...)

...to make it clear what happens if the lock acquisition fails without
having to remember there is a hidden incomplete "if ()" statement in
that macro? More below...

> 
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Suggested-by: Ira Weiny <ira.weiny@intel.com>
> Signed-off-by: Fabio M. De Francesco <fabio.maria.de.francesco@linux.intel.com>
> ---
>  drivers/cxl/core/region.c | 17 +++++------------
>  include/linux/cleanup.h   | 13 +++++++++++++
>  2 files changed, 18 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 0f05692bfec3..20d405f01df5 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -666,28 +666,21 @@ static size_t show_targetN(struct cxl_region *cxlr, char *buf, int pos)
>  {
>  	struct cxl_region_params *p = &cxlr->params;
>  	struct cxl_endpoint_decoder *cxled;
> -	int rc;
>  
> -	rc = down_read_interruptible(&cxl_region_rwsem);
> -	if (rc)
> -		return rc;
> +	cond_guard(rwsem_read_intr, &cxl_region_rwsem)
> +		return -EINTR;
>  
>  	if (pos >= p->interleave_ways) {
>  		dev_dbg(&cxlr->dev, "position %d out of range %d\n", pos,
>  			p->interleave_ways);
> -		rc = -ENXIO;
> -		goto out;
> +		return -ENXIO;
>  	}
>  
>  	cxled = p->targets[pos];
>  	if (!cxled)
> -		rc = sysfs_emit(buf, "\n");
> +		return sysfs_emit(buf, "\n");
>  	else
> -		rc = sysfs_emit(buf, "%s\n", dev_name(&cxled->cxld.dev));
> -out:
> -	up_read(&cxl_region_rwsem);
> -
> -	return rc;
> +		return sysfs_emit(buf, "%s\n", dev_name(&cxled->cxld.dev));
>  }
>  
>  static int match_free_decoder(struct device *dev, void *data)
> diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
> index c2d09bc4f976..fc850e61a47e 100644
> --- a/include/linux/cleanup.h
> +++ b/include/linux/cleanup.h
> @@ -134,6 +134,15 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
>   *	an anonymous instance of the (guard) class, not recommended for
>   *	conditional locks.
>   *
> + * cond_guard(_name, args...):
> + * 	for conditional locks like mutex_trylock() or down_read_interruptible().
> + * 	It expects a block for handling errors like in the following example:
> + *
> + * 	cond_guard(rwsem_read_intr, &my_sem) {
> + * 		printk(KERN_NOTICE "Try failure in work0()\n");
> + * 		return -EINTR;
> + * 	}
> + *
>   * scoped_guard (name, args...) { }:
>   *	similar to CLASS(name, scope)(args), except the variable (with the
>   *	explicit name 'scope') is declard in a for-loop such that its scope is
> @@ -165,6 +174,10 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
>  
>  #define __guard_ptr(_name) class_##_name##_lock_ptr
>  
> +#define cond_guard(_name, args...) \
> +	CLASS(_name, scope)(args); \
> +	if (!__guard_ptr(_name)(&scope))

This needs to protect against being used within another if () block.
Imagine a case of:

    if (...) {
    	cond_guard(...);
	    <statement>
    } else if (...)

...does that "else if" belong to the first "if ()" or the hidden one
inside the macro?

You can steal the embedded "if ()" trick from scoped_cond_guard() and do
something like (untested):

#define cond_guard(_name, _fail, args...) \
	CLASS(_name, scope)(args); \
	if (!__guard_ptr(_name)(&scope)) _fail; else /* pass */;

  reply	other threads:[~2024-01-30 17:03 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-30 16:38 [RFC PATCH v2] cleanup: Add cond_guard() to conditional guards Fabio M. De Francesco
2024-01-30 17:02 ` Dan Williams [this message]
2024-01-30 17:33   ` Fabio M. De Francesco
2024-01-30 17:58     ` Dan Williams
2024-01-31 13:11       ` Fabio M. De Francesco
2024-01-30 17:55   ` Fabio M. De Francesco
2024-01-30 18:43   ` Ira Weiny
2024-01-30 19:06     ` Dan Williams
2024-01-31  0:04       ` Ira Weiny
2024-01-31  0:43         ` Dan Williams

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=65b92b91a41a8_5cc6f29484@dwillia2-mobl3.amr.corp.intel.com.notmuch \
    --to=dan.j.williams@intel.com \
    --cc=fabio.maria.de.francesco@linux.intel.com \
    --cc=ira.weiny@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.