mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branch 'af_unix-fix-inq_len-update-issue'
Jianyu Li says: ==================== af_unix: Fix inq_len update issue From: Jianyu Li <jianyu.li@mediatek.com> This series fix the problem that inq_len is inconsistent with actual remaining byte count when only part of a skb is consumed. ==================== Link: https://patch.msgid.link/20260601113640.231897-1-jianyu.li@mediatek.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
c8e14cc9cc
|
|
@ -2886,7 +2886,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
|
||||
WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb));
|
||||
|
||||
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
|
||||
if (skb == u->oob_skb) {
|
||||
|
|
@ -3063,11 +3063,12 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
|
|||
unix_detach_fds(&scm, skb);
|
||||
}
|
||||
|
||||
if (unix_skb_len(skb))
|
||||
break;
|
||||
|
||||
spin_lock(&sk->sk_receive_queue.lock);
|
||||
WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
|
||||
WRITE_ONCE(u->inq_len, u->inq_len - chunk);
|
||||
if (unix_skb_len(skb)) {
|
||||
spin_unlock(&sk->sk_receive_queue.lock);
|
||||
break;
|
||||
}
|
||||
__skb_unlink(skb, &sk->sk_receive_queue);
|
||||
spin_unlock(&sk->sk_receive_queue.lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
|
||||
#include "kselftest_harness.h"
|
||||
|
||||
#define NR_CHUNKS 100
|
||||
#define MSG_LEN 256
|
||||
#define NR_CHUNKS 100
|
||||
#define MSG_LEN 256
|
||||
#define NR_PARTIAL_READS 3
|
||||
|
||||
FIXTURE(scm_inq)
|
||||
{
|
||||
|
|
@ -120,4 +121,53 @@ TEST_F(scm_inq, basic)
|
|||
recv_chunks(_metadata, self);
|
||||
}
|
||||
|
||||
TEST_F(scm_inq, partial_read)
|
||||
{
|
||||
char buf[MSG_LEN * NR_PARTIAL_READS] = {};
|
||||
char cmsg_buf[CMSG_SPACE(sizeof(int))];
|
||||
struct msghdr msg = {};
|
||||
struct iovec iov = {};
|
||||
struct cmsghdr *cmsg;
|
||||
int err, inq, ret, i;
|
||||
int remain;
|
||||
|
||||
err = setsockopt(self->fd[1], SOL_SOCKET, SO_INQ, &(int){1}, sizeof(int));
|
||||
if (variant->type != SOCK_STREAM) {
|
||||
ASSERT_EQ(-ENOPROTOOPT, -errno);
|
||||
return;
|
||||
}
|
||||
ASSERT_EQ(0, err);
|
||||
|
||||
ret = send(self->fd[0], buf, sizeof(buf), 0);
|
||||
ASSERT_EQ(sizeof(buf), ret);
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsg_buf;
|
||||
msg.msg_controllen = sizeof(cmsg_buf);
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = MSG_LEN;
|
||||
|
||||
for (i = 0; i < NR_PARTIAL_READS; i++) {
|
||||
remain = MSG_LEN * (NR_PARTIAL_READS - 1 - i);
|
||||
|
||||
memset(buf, 0, MSG_LEN);
|
||||
memset(cmsg_buf, 0, sizeof(cmsg_buf));
|
||||
ret = recvmsg(self->fd[1], &msg, 0);
|
||||
ASSERT_EQ(MSG_LEN, ret);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
ASSERT_NE(NULL, cmsg);
|
||||
ASSERT_EQ(CMSG_LEN(sizeof(int)), cmsg->cmsg_len);
|
||||
ASSERT_EQ(SOL_SOCKET, cmsg->cmsg_level);
|
||||
ASSERT_EQ(SCM_INQ, cmsg->cmsg_type);
|
||||
ASSERT_EQ(remain, *(int *)CMSG_DATA(cmsg));
|
||||
|
||||
ret = ioctl(self->fd[1], SIOCINQ, &inq);
|
||||
ASSERT_EQ(0, ret);
|
||||
ASSERT_EQ(remain, inq);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user