From: Jakub Kicinski <kuba@kernel.org>
To: Maxime Chevallier <maxime.chevallier@bootlin.com>
Cc: davem@davemloft.net, "Andrew Lunn" <andrew@lunn.ch>,
"Eric Dumazet" <edumazet@google.com>,
"Paolo Abeni" <pabeni@redhat.com>,
"Heiner Kallweit" <hkallweit1@gmail.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
thomas.petazzoni@bootlin.com,
linux-arm-kernel@lists.infradead.org,
"Christophe Leroy" <christophe.leroy@csgroup.eu>,
"Herve Codina" <herve.codina@bootlin.com>,
"Florian Fainelli" <f.fainelli@gmail.com>,
"Russell King" <linux@armlinux.org.uk>,
"Vladimir Oltean" <vladimir.oltean@nxp.com>,
"Köry Maincent" <kory.maincent@bootlin.com>,
"Oleksij Rempel" <o.rempel@pengutronix.de>,
"Simon Horman" <horms@kernel.org>,
"Romain Gantois" <romain.gantois@bootlin.com>,
"Piergiorgio Beruto" <piergiorgio.beruto@gmail.com>
Subject: Re: [PATCH net-next v7 1/3] net: ethtool: Introduce per-PHY DUMP operations
Date: Thu, 24 Apr 2025 18:03:33 -0700 [thread overview]
Message-ID: <20250424180333.035ff7d3@kernel.org> (raw)
In-Reply-To: <20250422161717.164440-2-maxime.chevallier@bootlin.com>
On Tue, 22 Apr 2025 18:17:14 +0200 Maxime Chevallier wrote:
> +/* perphy ->start() handler for GET requests */
Just because I think there are real bugs, I will allow myself an
uber-nit of asking to spell the perphy as per-PHY or such in the
comment? :)
> +static int ethnl_perphy_start(struct netlink_callback *cb)
> +{
> + struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb);
> + const struct genl_dumpit_info *info = genl_dumpit_info(cb);
> + struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx;
> + struct ethnl_reply_data *reply_data;
> + const struct ethnl_request_ops *ops;
> + struct ethnl_req_info *req_info;
> + struct genlmsghdr *ghdr;
> + int ret;
> +
> + BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
> +
> + ghdr = nlmsg_data(cb->nlh);
> + ops = ethnl_default_requests[ghdr->cmd];
> + if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd))
> + return -EOPNOTSUPP;
> + req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
> + if (!req_info)
> + return -ENOMEM;
> + reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL);
> + if (!reply_data) {
> + ret = -ENOMEM;
> + goto free_req_info;
> + }
> +
> + /* Don't ignore the dev even for DUMP requests */
another nit, this comment wasn't super clear without looking at the dump
for non-per-phy case. Maybe:
/* Unlike per-dev dump, don't ignore dev. The dump handler
* will notice it and dump PHYs from given dev.
*/
?
> + ret = ethnl_default_parse(req_info, &info->info, ops, false);
> + if (ret < 0)
> + goto free_reply_data;
> +
> + ctx->ops = ops;
> + ctx->req_info = req_info;
> + ctx->reply_data = reply_data;
> + ctx->pos_ifindex = 0;
> +
> + return 0;
> +
> +free_reply_data:
> + kfree(reply_data);
> +free_req_info:
> + kfree(req_info);
> +
> + return ret;
> +}
> +
> +static int ethnl_perphy_dump_one_dev(struct sk_buff *skb,
> + struct net_device *dev,
> + struct ethnl_perphy_dump_ctx *ctx,
> + const struct genl_info *info)
> +{
> + struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx;
> + struct phy_device_node *pdn;
> + int ret = 0;
> +
> + if (!dev->link_topo)
> + return 0;
Now for the bugs..
> + xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn,
> + ctx->pos_phyindex) {
> + ethnl_ctx->req_info->phy_index = ctx->pos_phyindex;
> +
> + /* We can re-use the original dump_one as ->prepare_data in
> + * commands use ethnl_req_get_phydev(), which gets the PHY from
> + * the req_info->phy_index
> + */
> + ret = ethnl_default_dump_one(skb, dev, ethnl_ctx, info);
> + if (ret)
> + break;
return ret;
> + }
ctx->pos_phyindex = 0;
return 0;
IOW I don't see you resetting the pos_phyindex, so I think you'd only
dump correctly the first device? The next device will try to dump its
PHYs starting from the last index of the previous dev's PHY? [1]
> + return ret;
> +}
> +
> +static int ethnl_perphy_dump_all_dev(struct sk_buff *skb,
> + struct ethnl_perphy_dump_ctx *ctx,
> + const struct genl_info *info)
> +{
> + struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx;
> + struct net *net = sock_net(skb->sk);
> + netdevice_tracker dev_tracker;
> + struct net_device *dev;
> + int ret = 0;
> +
> + rcu_read_lock();
> + for_each_netdev_dump(net, dev, ethnl_ctx->pos_ifindex) {
> + netdev_hold(dev, &dev_tracker, GFP_ATOMIC);
> + rcu_read_unlock();
> +
> + /* per-PHY commands use ethnl_req_get_phydev(), which needs the
> + * net_device in the req_info
> + */
> + ethnl_ctx->req_info->dev = dev;
> + ret = ethnl_perphy_dump_one_dev(skb, dev, ctx, info);
> +
> + rcu_read_lock();
> + netdev_put(dev, &dev_tracker);
missing
ethnl_ctx->req_info->dev = NULL;
right? Otherwise if we need to send multiple skbs the "continuation"
one will think we're doing a filtered dump.
Looking at commits 7c93a88785dae6 and c0111878d45e may be helpful,
but I doubt you can test it on a real system, filling even 4kB
may be hard for small messages :(
> + if (ret < 0 && ret != -EOPNOTSUPP) {
> + if (likely(skb->len))
> + ret = skb->len;
> + break;
> + }
> + ret = 0;
[1] or you can clear the pos_index here
> + }
> + rcu_read_unlock();
> +
> + return ret;
> +}
> +
> +/* perphy ->dumpit() handler for GET requests. */
> +static int ethnl_perphy_dumpit(struct sk_buff *skb,
> + struct netlink_callback *cb)
> +{
> + struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb);
> + struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx;
> + int ret = 0;
> +
> + if (ethnl_ctx->req_info->dev) {
> + ret = ethnl_perphy_dump_one_dev(skb, ethnl_ctx->req_info->dev,
> + ctx, genl_info_dump(cb));
> + if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len))
> + ret = skb->len;
> +
> + netdev_put(ethnl_ctx->req_info->dev,
> + ðnl_ctx->req_info->dev_tracker);
You have to release this in .done
dumpit gets called multiple times until we run out of objects to dump.
OTOH user may close the socket without finishing the dump operation.
So all .dumpit implementations must be "balanced". The only state we
should touch in them is the dump context to know where to pick up from
next time.
> + } else {
> + ret = ethnl_perphy_dump_all_dev(skb, ctx, genl_info_dump(cb));
> + }
> +
> + return ret;
> +}
next prev parent reply other threads:[~2025-04-25 1:05 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-22 16:17 [PATCH net-next v7 0/3] net: ethtool: Introduce ethnl dump helpers Maxime Chevallier
2025-04-22 16:17 ` [PATCH net-next v7 1/3] net: ethtool: Introduce per-PHY DUMP operations Maxime Chevallier
2025-04-25 1:03 ` Jakub Kicinski [this message]
2025-04-25 7:01 ` Maxime Chevallier
2025-04-26 0:10 ` Jakub Kicinski
2025-04-28 8:44 ` Maxime Chevallier
2025-04-30 6:32 ` Maxime Chevallier
2025-05-01 13:15 ` Jakub Kicinski
2025-04-22 16:17 ` [PATCH net-next v7 2/3] net: ethtool: phy: Convert the PHY_GET command to generic phy dump Maxime Chevallier
2025-04-22 16:17 ` [PATCH net-next v7 3/3] net: ethtool: netlink: Use netdev_hold for dumpit() operations Maxime Chevallier
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=20250424180333.035ff7d3@kernel.org \
--to=kuba@kernel.org \
--cc=andrew@lunn.ch \
--cc=christophe.leroy@csgroup.eu \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=f.fainelli@gmail.com \
--cc=herve.codina@bootlin.com \
--cc=hkallweit1@gmail.com \
--cc=horms@kernel.org \
--cc=kory.maincent@bootlin.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=maxime.chevallier@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=o.rempel@pengutronix.de \
--cc=pabeni@redhat.com \
--cc=piergiorgio.beruto@gmail.com \
--cc=romain.gantois@bootlin.com \
--cc=thomas.petazzoni@bootlin.com \
--cc=vladimir.oltean@nxp.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 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).