All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: Dan Carpenter <dan.carpenter@linaro.org>,
	Li Ming <ming4.li@intel.com>, <linux-cxl@vger.kernel.org>
Subject: Re: [bug report] cxl/port: Use scoped_guard()/guard() to drop device_lock() for cxl_port
Date: Thu, 17 Oct 2024 16:04:45 +0100	[thread overview]
Message-ID: <20241017160445.00005c50@Huawei.com> (raw)
In-Reply-To: <671044082f7de_3ee22945a@dwillia2-xfh.jf.intel.com.notmuch>

On Wed, 16 Oct 2024 15:54:00 -0700
Dan Williams <dan.j.williams@intel.com> wrote:

> Dan Carpenter wrote:
> > Hello Li Ming,
> > 
> > Commit 7f569e917b78 ("cxl/port: Use scoped_guard()/guard() to drop
> > device_lock() for cxl_port") from Aug 30, 2024 (linux-next), leads to
> > the following (unpublished) Smatch static checker warning:
> > 
> > 	drivers/cxl/core/port.c:1591 add_port_attach_ep()
> > 	warn: re-assigning __cleanup__ ptr 'port'
> > 
> > drivers/cxl/core/port.c
> >     1542 static int add_port_attach_ep(struct cxl_memdev *cxlmd,
> >     1543                               struct device *uport_dev,
> >     1544                               struct device *dport_dev)
> >     1545 {
> >     1546         struct device *dparent = grandparent(dport_dev);
> >     1547         struct cxl_dport *dport, *parent_dport;
> >     1548         resource_size_t component_reg_phys;
> >     1549         int rc;
> >     1550 
> >     1551         if (!dparent) {
> >     1552                 /*
> >     1553                  * The iteration reached the topology root without finding the
> >     1554                  * CXL-root 'cxl_port' on a previous iteration, fail for now to
> >     1555                  * be re-probed after platform driver attaches.
> >     1556                  */
> >     1557                 dev_dbg(&cxlmd->dev, "%s is a root dport\n",
> >     1558                         dev_name(dport_dev));
> >     1559                 return -ENXIO;
> >     1560         }
> >     1561 
> >     1562         struct cxl_port *parent_port __free(put_cxl_port) =
> >     1563                 find_cxl_port(dparent, &parent_dport);
> >     1564         if (!parent_port) {
> >     1565                 /* iterate to create this parent_port */
> >     1566                 return -EAGAIN;
> >     1567         }
> >     1568 
> >     1569         /*
> >     1570          * Definition with __free() here to keep the sequence of
> >     1571          * dereferencing the device of the port before the parent_port releasing.
> >     1572          */
> >     1573         struct cxl_port *port __free(put_cxl_port) = NULL;
> >                                   ^^^^^^^^^^^^^^^^^^^^^^^^
> > We free port when we exit the function, fine.
> > 
> >     1574         scoped_guard(device, &parent_port->dev) {
> >     1575                 if (!parent_port->dev.driver) {
> >     1576                         dev_warn(&cxlmd->dev,
> >     1577                                  "port %s:%s disabled, failed to enumerate CXL.mem\n",
> >     1578                                  dev_name(&parent_port->dev), dev_name(uport_dev));
> >     1579                         return -ENXIO;
> >     1580                 }
> >     1581 
> >     1582                 port = find_cxl_port_at(parent_port, dport_dev, &dport);
> >     1583                 if (!port) {
> >     1584                         component_reg_phys = find_component_registers(uport_dev);
> >     1585                         port = devm_cxl_add_port(&parent_port->dev, uport_dev,

> >     1586                                                  component_reg_phys, parent_dport);
> > 
> > This port from devm_cxl_add_port() needs to be undone.  

devm cleanup should sweep that up if we suceed here but fail on one of the remaining calls.

> 
> I also think the bug originates in:
> 
> dd2617ebd2a6 cxl/port: Use __free() to drop put_device() for cxl_port
> 
> ...where the wrong port is cleaned up, but I want to revert the
> scoped_guard() conversion first to make that cleanup easier.
> 
> In general for CXL I want to say that no function should be converted to
> use cleanup helpers unless all gotos are removed at once, and if the
> conversion needs to reach for scoped_guard() reconsider even attempting
> the conversion. I.e. scoped_guard() is a leading indicator for needing
> code refactoring.

I don't think it's a bug and ultimately Dan C didn't say it was.
It's ugly but a simpler path to resolve it logically is to
stop using the variable port for two purposes.


struct cxl_port *port __free(put_cxl_port) = NULL;
	scoped_guard(device, &parent_port->dev) {
		if (!parent_port->dev.driver) {
			dev_warn(&cxlmd->dev,
				 "port %s:%s disabled, failed to enumerate CXL.mem\n",
				 dev_name(&parent_port->dev), dev_name(uport_dev));
			return -ENXIO;
		}

		port = find_cxl_port_at(parent_port, dport_dev, &dport);
		if (!port) {
			struct cxl_dport *yadp;

			component_reg_phys = find_component_registers(uport_dev);
//rename (yet another dport :)

			yadp = devm_cxl_add_port(&parent_port->dev, uport_dev,
						 component_reg_phys, parent_dport);
			if (IS_ERR(yadp))
				return PTR_ERR(yadp);
//port is correctly null. We haven't found one yet, so all the auto cleanup is fine.


			/* retry find to pick up the new dport information */
			port = find_cxl_port_at(parent_port, dport_dev, &dport);
			if (!port)
				return -ENXIO;
		}
	}

Whilst I don't like the code, I'm not sure a revert is the best way out.

Jonathan

> 


  reply	other threads:[~2024-10-17 15:04 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-16 18:59 [bug report] cxl/port: Use scoped_guard()/guard() to drop device_lock() for cxl_port Dan Carpenter
2024-10-16 21:52 ` Dan Williams
2024-10-16 22:54 ` Dan Williams
2024-10-17 15:04   ` Jonathan Cameron [this message]
2024-10-17 16:32     ` Dan Williams
2024-10-17 17:12       ` Jonathan Cameron
2024-10-17 18:56     ` Dan Carpenter

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=20241017160445.00005c50@Huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=dan.carpenter@linaro.org \
    --cc=dan.j.williams@intel.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=ming4.li@intel.com \
    /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.