aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/sock.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/sock.h')
-rw-r--r--include/net/sock.h48
1 files changed, 31 insertions, 17 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 092b0551e77f..56df440a950b 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -51,6 +51,7 @@
51#include <linux/skbuff.h> /* struct sk_buff */ 51#include <linux/skbuff.h> /* struct sk_buff */
52#include <linux/mm.h> 52#include <linux/mm.h>
53#include <linux/security.h> 53#include <linux/security.h>
54#include <linux/slab.h>
54 55
55#include <linux/filter.h> 56#include <linux/filter.h>
56#include <linux/rculist_nulls.h> 57#include <linux/rculist_nulls.h>
@@ -261,7 +262,7 @@ struct sock {
261#ifdef CONFIG_XFRM 262#ifdef CONFIG_XFRM
262 struct xfrm_policy *sk_policy[2]; 263 struct xfrm_policy *sk_policy[2];
263#endif 264#endif
264 rwlock_t sk_dst_lock; 265 spinlock_t sk_dst_lock;
265 atomic_t sk_rmem_alloc; 266 atomic_t sk_rmem_alloc;
266 atomic_t sk_wmem_alloc; 267 atomic_t sk_wmem_alloc;
267 atomic_t sk_omem_alloc; 268 atomic_t sk_omem_alloc;
@@ -1191,7 +1192,8 @@ extern unsigned long sock_i_ino(struct sock *sk);
1191static inline struct dst_entry * 1192static inline struct dst_entry *
1192__sk_dst_get(struct sock *sk) 1193__sk_dst_get(struct sock *sk)
1193{ 1194{
1194 return sk->sk_dst_cache; 1195 return rcu_dereference_check(sk->sk_dst_cache, rcu_read_lock_held() ||
1196 sock_owned_by_user(sk));
1195} 1197}
1196 1198
1197static inline struct dst_entry * 1199static inline struct dst_entry *
@@ -1199,50 +1201,62 @@ sk_dst_get(struct sock *sk)
1199{ 1201{
1200 struct dst_entry *dst; 1202 struct dst_entry *dst;
1201 1203
1202 read_lock(&sk->sk_dst_lock); 1204 rcu_read_lock();
1203 dst = sk->sk_dst_cache; 1205 dst = rcu_dereference(sk->sk_dst_cache);
1204 if (dst) 1206 if (dst)
1205 dst_hold(dst); 1207 dst_hold(dst);
1206 read_unlock(&sk->sk_dst_lock); 1208 rcu_read_unlock();
1207 return dst; 1209 return dst;
1208} 1210}
1209 1211
1212extern void sk_reset_txq(struct sock *sk);
1213
1214static inline void dst_negative_advice(struct sock *sk)
1215{
1216 struct dst_entry *ndst, *dst = __sk_dst_get(sk);
1217
1218 if (dst && dst->ops->negative_advice) {
1219 ndst = dst->ops->negative_advice(dst);
1220
1221 if (ndst != dst) {
1222 rcu_assign_pointer(sk->sk_dst_cache, ndst);
1223 sk_reset_txq(sk);
1224 }
1225 }
1226}
1227
1210static inline void 1228static inline void
1211__sk_dst_set(struct sock *sk, struct dst_entry *dst) 1229__sk_dst_set(struct sock *sk, struct dst_entry *dst)
1212{ 1230{
1213 struct dst_entry *old_dst; 1231 struct dst_entry *old_dst;
1214 1232
1215 sk_tx_queue_clear(sk); 1233 sk_tx_queue_clear(sk);
1216 old_dst = sk->sk_dst_cache; 1234 old_dst = rcu_dereference_check(sk->sk_dst_cache,
1217 sk->sk_dst_cache = dst; 1235 lockdep_is_held(&sk->sk_dst_lock));
1236 rcu_assign_pointer(sk->sk_dst_cache, dst);
1218 dst_release(old_dst); 1237 dst_release(old_dst);
1219} 1238}
1220 1239
1221static inline void 1240static inline void
1222sk_dst_set(struct sock *sk, struct dst_entry *dst) 1241sk_dst_set(struct sock *sk, struct dst_entry *dst)
1223{ 1242{
1224 write_lock(&sk->sk_dst_lock); 1243 spin_lock(&sk->sk_dst_lock);
1225 __sk_dst_set(sk, dst); 1244 __sk_dst_set(sk, dst);
1226 write_unlock(&sk->sk_dst_lock); 1245 spin_unlock(&sk->sk_dst_lock);
1227} 1246}
1228 1247
1229static inline void 1248static inline void
1230__sk_dst_reset(struct sock *sk) 1249__sk_dst_reset(struct sock *sk)
1231{ 1250{
1232 struct dst_entry *old_dst; 1251 __sk_dst_set(sk, NULL);
1233
1234 sk_tx_queue_clear(sk);
1235 old_dst = sk->sk_dst_cache;
1236 sk->sk_dst_cache = NULL;
1237 dst_release(old_dst);
1238} 1252}
1239 1253
1240static inline void 1254static inline void
1241sk_dst_reset(struct sock *sk) 1255sk_dst_reset(struct sock *sk)
1242{ 1256{
1243 write_lock(&sk->sk_dst_lock); 1257 spin_lock(&sk->sk_dst_lock);
1244 __sk_dst_reset(sk); 1258 __sk_dst_reset(sk);
1245 write_unlock(&sk->sk_dst_lock); 1259 spin_unlock(&sk->sk_dst_lock);
1246} 1260}
1247 1261
1248extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); 1262extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);