diff options
Diffstat (limited to 'include/net/dst.h')
-rw-r--r-- | include/net/dst.h | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index aac5a5fcfda9..27207a13f2a6 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -168,6 +168,12 @@ static inline void dst_use(struct dst_entry *dst, unsigned long time) | |||
168 | dst->lastuse = time; | 168 | dst->lastuse = time; |
169 | } | 169 | } |
170 | 170 | ||
171 | static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) | ||
172 | { | ||
173 | dst->__use++; | ||
174 | dst->lastuse = time; | ||
175 | } | ||
176 | |||
171 | static inline | 177 | static inline |
172 | struct dst_entry * dst_clone(struct dst_entry * dst) | 178 | struct dst_entry * dst_clone(struct dst_entry * dst) |
173 | { | 179 | { |
@@ -177,11 +183,47 @@ struct dst_entry * dst_clone(struct dst_entry * dst) | |||
177 | } | 183 | } |
178 | 184 | ||
179 | extern void dst_release(struct dst_entry *dst); | 185 | extern void dst_release(struct dst_entry *dst); |
186 | |||
187 | static inline void refdst_drop(unsigned long refdst) | ||
188 | { | ||
189 | if (!(refdst & SKB_DST_NOREF)) | ||
190 | dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK)); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * skb_dst_drop - drops skb dst | ||
195 | * @skb: buffer | ||
196 | * | ||
197 | * Drops dst reference count if a reference was taken. | ||
198 | */ | ||
180 | static inline void skb_dst_drop(struct sk_buff *skb) | 199 | static inline void skb_dst_drop(struct sk_buff *skb) |
181 | { | 200 | { |
182 | if (skb->_skb_dst) | 201 | if (skb->_skb_refdst) { |
183 | dst_release(skb_dst(skb)); | 202 | refdst_drop(skb->_skb_refdst); |
184 | skb->_skb_dst = 0UL; | 203 | skb->_skb_refdst = 0UL; |
204 | } | ||
205 | } | ||
206 | |||
207 | static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb) | ||
208 | { | ||
209 | nskb->_skb_refdst = oskb->_skb_refdst; | ||
210 | if (!(nskb->_skb_refdst & SKB_DST_NOREF)) | ||
211 | dst_clone(skb_dst(nskb)); | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * skb_dst_force - makes sure skb dst is refcounted | ||
216 | * @skb: buffer | ||
217 | * | ||
218 | * If dst is not yet refcounted, let's do it | ||
219 | */ | ||
220 | static inline void skb_dst_force(struct sk_buff *skb) | ||
221 | { | ||
222 | if (skb_dst_is_noref(skb)) { | ||
223 | WARN_ON(!rcu_read_lock_held()); | ||
224 | skb->_skb_refdst &= ~SKB_DST_NOREF; | ||
225 | dst_clone(skb_dst(skb)); | ||
226 | } | ||
185 | } | 227 | } |
186 | 228 | ||
187 | /* Children define the path of the packet through the | 229 | /* Children define the path of the packet through the |