diff options
Diffstat (limited to 'include/net/sock.h')
-rw-r--r-- | include/net/sock.h | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 3f1a4804bb3f..092b0551e77f 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -253,6 +253,8 @@ struct sock { struct { struct sk_buff *head; struct sk_buff *tail; + int len; + int limit; } sk_backlog; wait_queue_head_t *sk_sleep; struct dst_entry *sk_dst_cache; @@ -317,6 +319,11 @@ struct sock { /* * Hashed lists helper routines */ +static inline struct sock *sk_entry(const struct hlist_node *node) +{ + return hlist_entry(node, struct sock, sk_node); +} + static inline struct sock *__sk_head(const struct hlist_head *head) { return hlist_entry(head->first, struct sock, sk_node); @@ -376,6 +383,7 @@ static __inline__ void __sk_del_node(struct sock *sk) __hlist_del(&sk->sk_node); } +/* NB: equivalent to hlist_del_init_rcu */ static __inline__ int __sk_del_node_init(struct sock *sk) { if (sk_hashed(sk)) { @@ -416,6 +424,7 @@ static __inline__ int sk_del_node_init(struct sock *sk) } return rc; } +#define sk_del_node_init_rcu(sk) sk_del_node_init(sk) static __inline__ int __sk_nulls_del_node_init_rcu(struct sock *sk) { @@ -449,6 +458,12 @@ static __inline__ void sk_add_node(struct sock *sk, struct hlist_head *list) __sk_add_node(sk, list); } +static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list) +{ + sock_hold(sk); + hlist_add_head_rcu(&sk->sk_node, list); +} + static __inline__ void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) { hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); @@ -473,6 +488,8 @@ static __inline__ void sk_add_bind_node(struct sock *sk, #define sk_for_each(__sk, node, list) \ hlist_for_each_entry(__sk, node, list, sk_node) +#define sk_for_each_rcu(__sk, node, list) \ + hlist_for_each_entry_rcu(__sk, node, list, sk_node) #define sk_nulls_for_each(__sk, node, list) \ hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node) #define sk_nulls_for_each_rcu(__sk, node, list) \ @@ -574,8 +591,8 @@ static inline int sk_stream_memory_free(struct sock *sk) return sk->sk_wmem_queued < sk->sk_sndbuf; } -/* The per-socket spinlock must be held here. */ -static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb) +/* OOB backlog add */ +static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) { if (!sk->sk_backlog.tail) { sk->sk_backlog.head = sk->sk_backlog.tail = skb; @@ -586,6 +603,17 @@ static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb) skb->next = NULL; } +/* The per-socket spinlock must be held here. */ +static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb) +{ + if (sk->sk_backlog.len >= max(sk->sk_backlog.limit, sk->sk_rcvbuf << 1)) + return -ENOBUFS; + + __sk_add_backlog(sk, skb); + sk->sk_backlog.len += skb->truesize; + return 0; +} + static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) { return sk->sk_backlog_rcv(sk, skb); @@ -1044,7 +1072,7 @@ extern void sk_common_release(struct sock *sk); extern void sock_init_data(struct socket *sock, struct sock *sk); /** - * sk_filter_release: Release a socket filter + * sk_filter_release - release a socket filter * @fp: filter to remove * * Remove a filter from a socket and release its resources. |