@@ -416,6 +416,7 @@ struct ubuf_info {
struct {
u32 id;
u16 len;
+ u16 zerocopy:1;
u32 bytelen;
};
};
@@ -1257,6 +1258,7 @@ static inline void skb_zcopy_clear(struct sk_buff *skb, bool zerocopy)
struct ubuf_info *uarg = skb_zcopy(skb);
if (uarg) {
+ uarg->zerocopy = uarg->zerocopy && zerocopy;
sock_zerocopy_put(uarg);
skb_shinfo(skb)->tx_flags &= ~SKBTX_ZEROCOPY_FRAG;
}
@@ -23,6 +23,8 @@ struct sock_extended_err {
#define SO_EE_OFFENDER(ee) ((struct sockaddr*)((ee)+1))
+#define SO_EE_CODE_ZEROCOPY_COPIED 1
+
/**
* struct scm_timestamping - timestamps exposed through cmsg
*
@@ -943,6 +943,7 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
uarg->callback = sock_zerocopy_callback;
uarg->id = ((u32)atomic_inc_return(&sk->sk_zckey)) - 1;
uarg->len = 1;
+ uarg->zerocopy = 1;
uarg->bytelen = size;
atomic_set(&uarg->refcnt, 0);
sock_hold(sk);
@@ -1039,6 +1040,8 @@ void sock_zerocopy_callback(struct ubuf_info *uarg, bool success)
serr->ee.ee_origin = SO_EE_ORIGIN_ZEROCOPY;
serr->ee.ee_data = hi;
serr->ee.ee_info = lo;
+ if (!success)
+ serr->ee.ee_code |= SO_EE_CODE_ZEROCOPY_COPIED;
spin_lock_irqsave(&q->lock, flags);
tail = skb_peek_tail(q);
@@ -1061,7 +1064,7 @@ void sock_zerocopy_put(struct ubuf_info *uarg)
{
if (uarg && atomic_dec_and_test(&uarg->refcnt)) {
if (uarg->callback)
- uarg->callback(uarg, true);
+ uarg->callback(uarg, uarg->zerocopy);
else
consume_skb(skb_from_uarg(uarg));
}