All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Abeni <pabeni@redhat.com>
To: ouster@cs.stanford.edu
Cc: horms@kernel.org, netdev@vger.kernel.org, kuba@kernel.org,
	pabeni@redhat.com, edumazet@google.com
Subject: Re: [net-next,v17,13/14] net: homa: create homa_plumbing.c
Date: Wed, 18 Mar 2026 08:21:49 +0100	[thread overview]
Message-ID: <20260318072149.269101-1-pabeni@redhat.com> (raw)
In-Reply-To: <20260316223228.2611-14-ouster@cs.stanford.edu>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.

For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
net: homa: create homa_plumbing.c

homa_plumbing.c contains functions that connect Homa to the rest of
the Linux kernel, such as dispatch tables used by Linux and the
top-level functions that Linux invokes from those dispatch tables.

> diff --git a/net/homa/homa_plumbing.c b/net/homa/homa_plumbing.c
> --- /dev/null
> +++ b/net/homa/homa_plumbing.c

[ ... ]

> +/**
> + * homa_ioc_info() - The top-level function that implements the
> + * HOMAIOCINFO ioctl for Homa sockets.
> + * @sock:  Socket for this request
> + * @arg:   The address in user space of the argument to ioctl, which
> + *          is a homa_info struct.
> + *
> + * Return:  0 on success, otherwise a negative errno. Sets hsk->error_msg
> + *          on errors.
> + */
> +int homa_ioc_info(struct socket *sock, unsigned long arg)
> +{
> +	struct homa_sock *hsk = homa_sk(sock->sk);
> +	struct homa_rpc_info rinfo;
> +	struct homa_info hinfo;
> +	struct homa_rpc *rpc;
> +	int bytes_avl;
> +	char *dst;
> +
> +	if (unlikely(copy_from_user(&hinfo, (void __user *)arg,
> +				    sizeof(hinfo)))) {
> +		hsk->error_msg = "invalid address for homa_info";
> +		return -EFAULT;
> +	}
> +
> +	if (!homa_protect_rpcs(hsk)) {
> +		hsk->error_msg = "socket has been shut down";
> +		return -ESHUTDOWN;
> +	}
> +	hinfo.bpool_avail_bytes = homa_pool_avail_bytes(hsk->buffer_pool);
> +	hinfo.port = hsk->port;
> +	dst = (char *)hinfo.rpc_info;
> +	bytes_avl = hinfo.rpc_info_length;
> +	hinfo.num_rpcs = 0;
> +	list_for_each_entry_rcu(rpc, &hsk->active_rpcs, active_links) {
                                ^^^^

Is rcu_read_lock() needed around this list_for_each_entry_rcu() loop?

All three other functions that use the same homa_protect_rpcs() +
list_for_each_entry_rcu pattern (homa_abort_rpcs in homa_rpc.c,
homa_timer in homa_timer.c, and homa_abort_sock_rpcs in homa_rpc.c)
bracket the traversal with rcu_read_lock()/rcu_read_unlock().

The homa_protect_rpcs() mechanism prevents RPC reaping via an atomic
counter, but doesn't provide RCU read-side protection.

Without rcu_read_lock(), list_for_each_entry_rcu() triggers a lockdep
RCU warning, and on PREEMPT_RCU configurations the reader can be
preempted during traversal without the RCU subsystem knowing a reader
is active, breaking the RCU contract.

> +		homa_rpc_lock(rpc);
> +		if (rpc->state == RPC_DEAD) {
> +			homa_rpc_unlock(rpc);
> +			continue;
> +		}
> +		homa_rpc_get_info(rpc, &rinfo);
> +		homa_rpc_unlock(rpc);
> +		if (dst && bytes_avl >= sizeof(rinfo)) {
> +			if (copy_to_user((void __user *)dst, &rinfo,
> +					 sizeof(rinfo))) {
> +				homa_unprotect_rpcs(hsk);
> +				hsk->error_msg = "couldn't copy homa_rpc_info to user space: invalid or read-only address?";
> +				return -EFAULT;
> +			}
> +			dst += sizeof(rinfo);
> +			bytes_avl -= sizeof(rinfo);
> +		}
> +		hinfo.num_rpcs++;
> +	}
> +	homa_unprotect_rpcs(hsk);

[ ... ]

> +/**
> + * homa_socket() - Implements the socket(2) system call for sockets.
> + * @sk:    Socket on which the system call was invoked. The non-Homa
> + *         parts have already been initialized.
> + *
> + * Return: always 0 (success).
> + */
> +int homa_socket(struct sock *sk)
> +{
> +	struct homa_sock *hsk = homa_sk(sk);
> +	int result;
> +
> +	result = homa_sock_init(hsk);
> +	if (result != 0) {
> +		homa_sock_shutdown(hsk);
                ^^^^^^^^^^^^^^^^^^^

Can this trigger a spinlock bug?

When homa_sock_init() fails because homa_pool_alloc() returns
ERR_PTR(-ENOMEM), it returns before spin_lock_init(&hsk->lock) is
called in homa_sock_init().

The error path then calls homa_sock_shutdown(hsk), whose first action
is homa_sock_lock(hsk) = spin_lock_bh(&hsk->lock) on the
never-initialized spinlock.

With CONFIG_DEBUG_SPINLOCK, the lock's magic field (zero from slab
allocation) doesn't match SPINLOCK_MAGIC (0xdead4ead), causing
spin_bug() to call BUG().

While homa_sock_shutdown() would immediately return after checking
!hsk->homa (NULL), the BUG() fires inside spin_lock_bh() before that
check is reached.

This is reachable under memory pressure.

> +		homa_sock_destroy(&hsk->sock);
> +	}
> +	return result;
> +}

[ ... ]

> +/**
> + * homa_getsockopt() - Implements the getsockopt system call for Homa sockets.
> + * @sk:      Socket on which the system call was invoked.
> + * @level:   Selects level in the network stack to handle the request;
> + *           must be IPPROTO_HOMA.
> + * @optname: Identifies a particular setsockopt operation.
> + * @optval:  Address in user space where the option's value should be stored.
> + * @optlen:  Number of bytes available at optval; will be overwritten with
> + *           actual number of bytes stored.
> + * Return:   0 on success, otherwise a negative errno. Sets hsk->error_msg
> + *           on errors.
> + */
> +int homa_getsockopt(struct sock *sk, int level, int optname,
> +		    char __user *optval, int __user *optlen)
> +{
> +	struct homa_sock *hsk = homa_sk(sk);
> +	struct homa_rcvbuf_args rcvbuf_args;
> +	int is_server;
> +	void *result;
> +	int len;
> +
> +	if (copy_from_sockptr(&len, USER_SOCKPTR(optlen), sizeof(int))) {
> +		hsk->error_msg = "invalid address for optlen argument to getsockopt";
> +		return -EFAULT;
> +	}
> +
> +	if (level != IPPROTO_HOMA) {
> +		hsk->error_msg = "homa_setsockopt invoked with level not IPPROTO_HOMA";
                                 ^^^^^^^^^^^^^^

This isn't a bug, but the error message says 'homa_setsockopt' instead
of 'homa_getsockopt'. This is a copy-paste error from homa_setsockopt().

The error_msg field is returned to applications via the HOMAIOCINFO
ioctl, so users debugging socket option failures would see a misleading
message pointing to the wrong function.

> +		return -ENOPROTOOPT;
> +	}
> +	if (optname == SO_HOMA_RCVBUF) {

[ ... ]

> +/**
> + * homa_recvmsg() - Receive a message from a Homa socket.
> + * @sk:          Socket on which the system call was invoked.
> + * @msg:         Controlling information for the receive.
> + * @len:         Total bytes of space available in msg->msg_iov; not used.
> + * @flags:       Flags from system call; only MSG_DONTWAIT is used.
> + * @addr_len:    Store the length of the sender address here
> + * Return:       The length of the message on success, otherwise a negative
> + *               errno. Sets hsk->error_msg on errors.
> + */
> +int homa_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
> +		 int *addr_len)
> +{

[ ... ]

> +	if (rpc->error) {
> +		hsk->error_msg = "RPC failed";
> +		result = rpc->error;
> +	} else {
> +		result = rpc->msgin.length;
> +	}
> +	result = rpc->error ? rpc->error : rpc->msgin.length;
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This isn't a bug, but there's redundant dead-store code here.

The if/else block assigns 'result' to either 'rpc->error' or
'rpc->msgin.length', but the next line immediately overwrites 'result'
with the identical ternary expression.

The two 'result = ...' assignments inside the if/else are dead stores
that are always overwritten. The if/else block's only surviving side
effect is setting 'hsk->error_msg = "RPC failed"' when rpc->error is
nonzero.

This appears to be an editing mistake where either the if/else should
be the authoritative result assignment (and the ternary deleted), or
the ternary should remain and the if/else should be simplified to only
set error_msg (removing its result assignments).

> +
> +	/* Collect result information. */
> +	control.id = rpc->id;

[ ... ]

> +/**
> + * homa_hrtimer() - This function is invoked by the hrtimer mechanism to
> + * wake up the timer thread. Runs at IRQ level.
> + * @timer:   The timer that triggered; not used.
> + *
> + * Return:   Always HRTIMER_RESTART.
> + */
> +enum hrtimer_restart homa_hrtimer(struct hrtimer *timer)
> +{
> +	wake_up_process(timer_kthread);
> +	return HRTIMER_NORESTART;
        ^^^^^^^^^^^^^^^^^^^^^^

The kernel-doc comment states 'Return: Always HRTIMER_RESTART' but the
function returns HRTIMER_NORESTART.

The runtime behavior is correct (homa_timer_main re-arms the hrtimer
explicitly via hrtimer_start on each loop iteration, so HRTIMER_NORESTART
is the intended return value), but the comment contradicts the code.

This misleads readers into believing the timer auto-restarts, when it
does not.

> +}


  reply	other threads:[~2026-03-18  7:22 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-16 22:32 [PATCH net-next v17 00/14] Begin upstreaming Homa transport protocol John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 01/14] net: homa: define user-visible API for Homa John Ousterhout
2026-03-17 10:10   ` kernel test robot
2026-03-17 18:40   ` kernel test robot
2026-03-16 22:32 ` [PATCH net-next v17 02/14] net: homa: create homa_wire.h John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 03/14] net: homa: create shared Homa header files John Ousterhout
2026-03-18  7:20   ` [net-next,v17,03/14] " Paolo Abeni
2026-03-19 20:37     ` John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 04/14] net: homa: create homa_pool.h and homa_pool.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 05/14] net: homa: create homa_peer.h and homa_peer.c John Ousterhout
2026-03-18  7:21   ` [net-next,v17,05/14] " Paolo Abeni
2026-03-20 17:13     ` John Ousterhout
2026-03-20 17:20       ` Paolo Abeni
2026-03-16 22:32 ` [PATCH net-next v17 06/14] net: homa: create homa_sock.h and homa_sock.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 07/14] net: homa: create homa_interest.h and homa_interest.c John Ousterhout
2026-03-18  7:21   ` [net-next,v17,07/14] " Paolo Abeni
2026-03-16 22:32 ` [PATCH net-next v17 08/14] net: homa: create homa_rpc.h and homa_rpc.c John Ousterhout
2026-03-18  7:21   ` [net-next,v17,08/14] " Paolo Abeni
2026-03-23 22:43     ` John Ousterhout
2026-03-24  8:55       ` Paolo Abeni
2026-04-03 23:04         ` John Ousterhout
2026-04-07  6:07           ` Paolo Abeni
2026-03-16 22:32 ` [PATCH net-next v17 09/14] net: homa: create homa_outgoing.c John Ousterhout
2026-03-18  7:21   ` [net-next,v17,09/14] " Paolo Abeni
2026-03-20 18:21     ` John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 10/14] net: homa: create homa_utils.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 11/14] net: homa: create homa_incoming.c John Ousterhout
2026-03-18  7:21   ` [net-next,v17,11/14] " Paolo Abeni
2026-03-20 20:51     ` John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 12/14] net: homa: create homa_timer.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 13/14] net: homa: create homa_plumbing.c John Ousterhout
2026-03-18  7:21   ` Paolo Abeni [this message]
2026-03-20 21:49     ` [net-next,v17,13/14] " John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 14/14] net: homa: create Makefile and Kconfig John Ousterhout
2026-03-17 18:51   ` kernel test robot
2026-03-17 19:26   ` kernel test robot

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=20260318072149.269101-1-pabeni@redhat.com \
    --to=pabeni@redhat.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=ouster@cs.stanford.edu \
    /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.