Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion drivers/hid/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,12 @@ EXPORT_SYMBOL_GPL(hid_snto32);

static u32 s32ton(__s32 value, unsigned n)
{
s32 a = value >> (n - 1);
s32 a;

if (!value || !n)
return 0;

a = value >> (n - 1);
if (a && a != -1)
return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
return value & ((1 << n) - 1);
Expand Down
2 changes: 2 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/idr.h>
#include <linux/leds.h>
#include <linux/rculist.h>
#include <linux/srcu.h>

#include <net/bluetooth/hci.h>
#include <net/bluetooth/hci_sync.h>
Expand Down Expand Up @@ -348,6 +349,7 @@ struct amp_assoc {

struct hci_dev {
struct list_head list;
struct srcu_struct srcu;
struct mutex lock;

struct ida unset_handle_ida;
Expand Down
21 changes: 15 additions & 6 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,12 @@ static inline void sk_wmem_queued_add(struct sock *sk, int val)
WRITE_ONCE(sk->sk_wmem_queued, sk->sk_wmem_queued + val);
}

static inline void sk_forward_alloc_add(struct sock *sk, int val)
{
/* Paired with lockless reads of sk->sk_forward_alloc */
WRITE_ONCE(sk->sk_forward_alloc, sk->sk_forward_alloc + val);
}

void sk_stream_write_space(struct sock *sk);

/* OOB backlog add */
Expand Down Expand Up @@ -1298,7 +1304,9 @@ struct proto {
unsigned int inuse_idx;
#endif

#if IS_ENABLED(CONFIG_MPTCP)
int (*forward_alloc_get)(const struct sock *sk);
#endif

bool (*stream_memory_free)(const struct sock *sk, int wake);
bool (*sock_is_readable)(struct sock *sk);
Expand Down Expand Up @@ -1405,10 +1413,11 @@ INDIRECT_CALLABLE_DECLARE(bool tcp_stream_memory_free(const struct sock *sk, int

static inline int sk_forward_alloc_get(const struct sock *sk)
{
if (!sk->sk_prot->forward_alloc_get)
return sk->sk_forward_alloc;

return sk->sk_prot->forward_alloc_get(sk);
#if IS_ENABLED(CONFIG_MPTCP)
if (sk->sk_prot->forward_alloc_get)
return sk->sk_prot->forward_alloc_get(sk);
#endif
return READ_ONCE(sk->sk_forward_alloc);
}

static inline bool __sk_stream_memory_free(const struct sock *sk, int wake)
Expand Down Expand Up @@ -1709,7 +1718,7 @@ static inline void sk_mem_charge(struct sock *sk, int size)
{
if (!sk_has_account(sk))
return;
sk->sk_forward_alloc -= size;
sk_forward_alloc_add(sk, -size);
}

/* the following macros control memory reclaiming in mptcp_rmem_uncharge()
Expand All @@ -1721,7 +1730,7 @@ static inline void sk_mem_uncharge(struct sock *sk, int size)
{
if (!sk_has_account(sk))
return;
sk->sk_forward_alloc += size;
sk_forward_alloc_add(sk, size);
sk_mem_reclaim(sk);
}

Expand Down
34 changes: 30 additions & 4 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static int hci_linkpol_req(struct hci_request *req, unsigned long opt)

/* Get HCI device by index.
* Device is held on return. */
struct hci_dev *hci_dev_get(int index)
static struct hci_dev *__hci_dev_get(int index, int *srcu_index)
{
struct hci_dev *hdev = NULL, *d;

Expand All @@ -122,13 +122,31 @@ struct hci_dev *hci_dev_get(int index)
list_for_each_entry(d, &hci_dev_list, list) {
if (d->id == index) {
hdev = hci_dev_hold(d);
if (srcu_index)
*srcu_index = srcu_read_lock(&d->srcu);
break;
}
}
read_unlock(&hci_dev_list_lock);
return hdev;
}

struct hci_dev *hci_dev_get(int index)
{
return __hci_dev_get(index, NULL);
}

static struct hci_dev *hci_dev_get_srcu(int index, int *srcu_index)
{
return __hci_dev_get(index, srcu_index);
}

static void hci_dev_put_srcu(struct hci_dev *hdev, int srcu_index)
{
srcu_read_unlock(&hdev->srcu, srcu_index);
hci_dev_put(hdev);
}

/* ---- Inquiry support ---- */

bool hci_discovery_active(struct hci_dev *hdev)
Expand Down Expand Up @@ -639,9 +657,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)
int hci_dev_reset(__u16 dev)
{
struct hci_dev *hdev;
int err;
int err, srcu_index;

hdev = hci_dev_get(dev);
hdev = hci_dev_get_srcu(dev, &srcu_index);
if (!hdev)
return -ENODEV;

Expand All @@ -663,7 +681,7 @@ int hci_dev_reset(__u16 dev)
err = hci_dev_do_reset(hdev);

done:
hci_dev_put(hdev);
hci_dev_put_srcu(hdev, srcu_index);
return err;
}

Expand Down Expand Up @@ -2465,6 +2483,11 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
if (!hdev)
return NULL;

if (init_srcu_struct(&hdev->srcu)) {
kfree(hdev);
return NULL;
}

hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
hdev->esco_type = (ESCO_HV1);
hdev->link_mode = (HCI_LM_ACCEPT);
Expand Down Expand Up @@ -2725,6 +2748,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);

synchronize_srcu(&hdev->srcu);
cleanup_srcu_struct(&hdev->srcu);

cancel_work_sync(&hdev->power_on);

hci_cmd_sync_clear(hdev);
Expand Down
8 changes: 4 additions & 4 deletions net/core/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,7 @@ static int sock_reserve_memory(struct sock *sk, int bytes)
mem_cgroup_uncharge_skmem(sk->sk_memcg, pages);
return -ENOMEM;
}
sk->sk_forward_alloc += pages << PAGE_SHIFT;
sk_forward_alloc_add(sk, pages << PAGE_SHIFT);

sk->sk_reserved_mem += pages << PAGE_SHIFT;

Expand Down Expand Up @@ -3027,10 +3027,10 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
{
int ret, amt = sk_mem_pages(size);

sk->sk_forward_alloc += amt << PAGE_SHIFT;
sk_forward_alloc_add(sk, amt << PAGE_SHIFT);
ret = __sk_mem_raise_allocated(sk, size, amt, kind);
if (!ret)
sk->sk_forward_alloc -= amt << PAGE_SHIFT;
sk_forward_alloc_add(sk, -(amt << PAGE_SHIFT));
return ret;
}
EXPORT_SYMBOL(__sk_mem_schedule);
Expand Down Expand Up @@ -3063,7 +3063,7 @@ EXPORT_SYMBOL(__sk_mem_reduce_allocated);
void __sk_mem_reclaim(struct sock *sk, int amount)
{
amount >>= PAGE_SHIFT;
sk->sk_forward_alloc -= amount << PAGE_SHIFT;
sk_forward_alloc_add(sk, -(amount << PAGE_SHIFT));
__sk_mem_reduce_allocated(sk, amount);
}
EXPORT_SYMBOL(__sk_mem_reclaim);
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -3435,7 +3435,7 @@ void sk_forced_mem_schedule(struct sock *sk, int size)
if (delta <= 0)
return;
amt = sk_mem_pages(delta);
sk->sk_forward_alloc += amt << PAGE_SHIFT;
sk_forward_alloc_add(sk, amt << PAGE_SHIFT);
sk_memory_allocated_add(sk, amt);

if (mem_cgroup_sockets_enabled && sk->sk_memcg)
Expand Down
18 changes: 8 additions & 10 deletions net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1456,12 +1456,12 @@ static bool udp_skb_has_head_state(struct sk_buff *skb)
}

/* fully reclaim rmem/fwd memory allocated for skb */
static void udp_rmem_release(struct sock *sk, int size, int partial,
bool rx_queue_lock_held)
static void udp_rmem_release(struct sock *sk, unsigned int size,
int partial, bool rx_queue_lock_held)
{
struct udp_sock *up = udp_sk(sk);
struct sk_buff_head *sk_queue;
int amt;
unsigned int amt;

if (likely(partial)) {
up->forward_deficit += size;
Expand All @@ -1481,10 +1481,8 @@ static void udp_rmem_release(struct sock *sk, int size, int partial,
if (!rx_queue_lock_held)
spin_lock(&sk_queue->lock);


sk->sk_forward_alloc += size;
amt = (sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1);
sk->sk_forward_alloc -= amt;
amt = (size + sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1);
sk_forward_alloc_add(sk, size - amt);

if (amt)
__sk_mem_reduce_allocated(sk, amt >> PAGE_SHIFT);
Expand Down Expand Up @@ -1590,7 +1588,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
sk->sk_forward_alloc += delta;
}

sk->sk_forward_alloc -= size;
sk_forward_alloc_add(sk, -size);

/* no need to setup a destructor, we will explicitly release the
* forward allocated memory on dequeue
Expand Down Expand Up @@ -1669,7 +1667,7 @@ EXPORT_SYMBOL_GPL(skb_consume_udp);

static struct sk_buff *__first_packet_length(struct sock *sk,
struct sk_buff_head *rcvq,
int *total)
unsigned int *total)
{
struct sk_buff *skb;

Expand Down Expand Up @@ -1702,8 +1700,8 @@ static int first_packet_length(struct sock *sk)
{
struct sk_buff_head *rcvq = &udp_sk(sk)->reader_queue;
struct sk_buff_head *sk_queue = &sk->sk_receive_queue;
unsigned int total = 0;
struct sk_buff *skb;
int total = 0;
int res;

spin_lock_bh(&rcvq->lock);
Expand Down
4 changes: 2 additions & 2 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1855,7 +1855,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
goto do_error;

/* data successfully copied into the write queue */
sk->sk_forward_alloc -= total_ts;
sk_forward_alloc_add(sk, -total_ts);
copied += psize;
dfrag->data_len += psize;
frag_truesize += psize;
Expand Down Expand Up @@ -3316,7 +3316,7 @@ void mptcp_destroy_common(struct mptcp_sock *msk, unsigned int flags)
/* move all the rx fwd alloc into the sk_mem_reclaim_final in
* inet_sock_destruct() will dispose it
*/
sk->sk_forward_alloc += msk->rmem_fwd_alloc;
sk_forward_alloc_add(sk, msk->rmem_fwd_alloc);
WRITE_ONCE(msk->rmem_fwd_alloc, 0);
mptcp_token_destroy(msk);
mptcp_pm_free_anno_list(msk);
Expand Down
43 changes: 35 additions & 8 deletions net/sunrpc/svcsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,20 +255,47 @@ svc_tcp_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
}

static int
svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg)
svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
{
union {
struct cmsghdr cmsg;
u8 buf[CMSG_SPACE(sizeof(u8))];
} u;
struct socket *sock = svsk->sk_sock;
u8 alert[2];
struct kvec alert_kvec = {
.iov_base = alert,
.iov_len = sizeof(alert),
};
struct msghdr msg = {
.msg_flags = *msg_flags,
.msg_control = &u,
.msg_controllen = sizeof(u),
};
int ret;

iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
alert_kvec.iov_len);
ret = sock_recvmsg(sock, &msg, MSG_DONTWAIT);
if (ret > 0 &&
tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) {
iov_iter_revert(&msg.msg_iter, ret);
ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN);
}
return ret;
}

static int
svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg)
{
int ret;
struct socket *sock = svsk->sk_sock;

msg->msg_control = &u;
msg->msg_controllen = sizeof(u);
ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
if (unlikely(msg->msg_controllen != sizeof(u)))
ret = svc_tcp_sock_process_cmsg(sock, msg, &u.cmsg, ret);
if (msg->msg_flags & MSG_CTRUNC) {
msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
if (ret == 0 || ret == -EIO)
ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags);
}
return ret;
}

Expand Down Expand Up @@ -322,7 +349,7 @@ static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen,
iov_iter_advance(&msg.msg_iter, seek);
buflen -= seek;
}
len = svc_tcp_sock_recv_cmsg(svsk, &msg);
len = svc_tcp_sock_recvmsg(svsk, &msg);
if (len > 0)
svc_flush_bvec(bvec, len, seek);

Expand Down Expand Up @@ -1018,7 +1045,7 @@ static ssize_t svc_tcp_read_marker(struct svc_sock *svsk,
iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
iov.iov_len = want;
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, want);
len = svc_tcp_sock_recv_cmsg(svsk, &msg);
len = svc_tcp_sock_recvmsg(svsk, &msg);
if (len < 0)
return len;
svsk->sk_tcplen += len;
Expand Down