mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-15 23:14:31 +08:00
Merge branch 'generic-zcopy_-functions'
Jonathan Lemon says: ==================== Generic zcopy_* functions This is set of cleanup patches for zerocopy which are intended to allow a introduction of a different zerocopy implementation. The top level API will use the skb_zcopy_*() functions, while the current TCP specific zerocopy ends up using msg_zerocopy_*() calls. There should be no functional changes from these patches. ==================== Link: https://lore.kernel.org/r/20210106221841.1880536-1-jonathan.lemon@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
58334e7537
@ -722,12 +722,10 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,
|
||||
tap = rcu_dereference(q->tap);
|
||||
/* copy skb_ubuf_info for callback when skb has no error */
|
||||
if (zerocopy) {
|
||||
skb_shinfo(skb)->destructor_arg = msg_control;
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
skb_zcopy_init(skb, msg_control);
|
||||
} else if (msg_control) {
|
||||
struct ubuf_info *uarg = msg_control;
|
||||
uarg->callback(uarg, false);
|
||||
uarg->callback(NULL, uarg, false);
|
||||
}
|
||||
|
||||
if (tap) {
|
||||
|
@ -1814,12 +1814,10 @@ drop:
|
||||
|
||||
/* copy skb_ubuf_info for callback when skb has no error */
|
||||
if (zerocopy) {
|
||||
skb_shinfo(skb)->destructor_arg = msg_control;
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
skb_zcopy_init(skb, msg_control);
|
||||
} else if (msg_control) {
|
||||
struct ubuf_info *uarg = msg_control;
|
||||
uarg->callback(uarg, false);
|
||||
uarg->callback(NULL, uarg, false);
|
||||
}
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
@ -399,7 +399,8 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
|
||||
void xenvif_carrier_on(struct xenvif *vif);
|
||||
|
||||
/* Callback from stack when TX packet can be released */
|
||||
void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success);
|
||||
void xenvif_zerocopy_callback(struct sk_buff *skb, struct ubuf_info *ubuf,
|
||||
bool zerocopy_success);
|
||||
|
||||
/* Unmap a pending page and release it back to the guest */
|
||||
void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
|
||||
|
@ -47,7 +47,7 @@
|
||||
/* Number of bytes allowed on the internal guest Rx queue. */
|
||||
#define XENVIF_RX_QUEUE_BYTES (XEN_NETIF_RX_RING_SIZE/2 * PAGE_SIZE)
|
||||
|
||||
/* This function is used to set SKBTX_DEV_ZEROCOPY as well as
|
||||
/* This function is used to set SKBFL_ZEROCOPY_ENABLE as well as
|
||||
* increasing the inflight counter. We need to increase the inflight
|
||||
* counter because core driver calls into xenvif_zerocopy_callback
|
||||
* which calls xenvif_skb_zerocopy_complete.
|
||||
@ -55,7 +55,7 @@
|
||||
void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||||
skb_shinfo(skb)->flags |= SKBFL_ZEROCOPY_ENABLE;
|
||||
atomic_inc(&queue->inflight_packets);
|
||||
}
|
||||
|
||||
|
@ -1091,7 +1091,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
|
||||
uarg = skb_shinfo(skb)->destructor_arg;
|
||||
/* increase inflight counter to offset decrement in callback */
|
||||
atomic_inc(&queue->inflight_packets);
|
||||
uarg->callback(uarg, true);
|
||||
uarg->callback(NULL, uarg, true);
|
||||
skb_shinfo(skb)->destructor_arg = NULL;
|
||||
|
||||
/* Fill the skb with the new (local) frags. */
|
||||
@ -1228,7 +1228,8 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
|
||||
return work_done;
|
||||
}
|
||||
|
||||
void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success)
|
||||
void xenvif_zerocopy_callback(struct sk_buff *skb, struct ubuf_info *ubuf,
|
||||
bool zerocopy_success)
|
||||
{
|
||||
unsigned long flags;
|
||||
pending_ring_idx_t index;
|
||||
|
@ -381,7 +381,8 @@ static void vhost_zerocopy_signal_used(struct vhost_net *net,
|
||||
}
|
||||
}
|
||||
|
||||
static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
|
||||
static void vhost_zerocopy_callback(struct sk_buff *skb,
|
||||
struct ubuf_info *ubuf, bool success)
|
||||
{
|
||||
struct vhost_net_ubuf_ref *ubufs = ubuf->ctx;
|
||||
struct vhost_virtqueue *vq = ubufs->vq;
|
||||
@ -902,6 +903,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
|
||||
ubuf->callback = vhost_zerocopy_callback;
|
||||
ubuf->ctx = nvq->ubufs;
|
||||
ubuf->desc = nvq->upend_idx;
|
||||
ubuf->flags = SKBFL_ZEROCOPY_FRAG;
|
||||
refcount_set(&ubuf->refcnt, 1);
|
||||
msg.msg_control = &ctl;
|
||||
ctl.type = TUN_MSG_UBUF;
|
||||
|
@ -430,27 +430,31 @@ enum {
|
||||
/* device driver is going to provide hardware time stamp */
|
||||
SKBTX_IN_PROGRESS = 1 << 2,
|
||||
|
||||
/* device driver supports TX zero-copy buffers */
|
||||
SKBTX_DEV_ZEROCOPY = 1 << 3,
|
||||
|
||||
/* generate wifi status information (where possible) */
|
||||
SKBTX_WIFI_STATUS = 1 << 4,
|
||||
|
||||
/* generate software time stamp when entering packet scheduling */
|
||||
SKBTX_SCHED_TSTAMP = 1 << 6,
|
||||
};
|
||||
|
||||
#define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \
|
||||
SKBTX_SCHED_TSTAMP)
|
||||
#define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | SKBTX_ANY_SW_TSTAMP)
|
||||
|
||||
/* Definitions for flags in struct skb_shared_info */
|
||||
enum {
|
||||
/* use zcopy routines */
|
||||
SKBFL_ZEROCOPY_ENABLE = BIT(0),
|
||||
|
||||
/* This indicates at least one fragment might be overwritten
|
||||
* (as in vmsplice(), sendfile() ...)
|
||||
* If we need to compute a TX checksum, we'll need to copy
|
||||
* all frags to avoid possible bad checksum
|
||||
*/
|
||||
SKBTX_SHARED_FRAG = 1 << 5,
|
||||
|
||||
/* generate software time stamp when entering packet scheduling */
|
||||
SKBTX_SCHED_TSTAMP = 1 << 6,
|
||||
SKBFL_SHARED_FRAG = BIT(1),
|
||||
};
|
||||
|
||||
#define SKBTX_ZEROCOPY_FRAG (SKBTX_DEV_ZEROCOPY | SKBTX_SHARED_FRAG)
|
||||
#define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \
|
||||
SKBTX_SCHED_TSTAMP)
|
||||
#define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | SKBTX_ANY_SW_TSTAMP)
|
||||
#define SKBFL_ZEROCOPY_FRAG (SKBFL_ZEROCOPY_ENABLE | SKBFL_SHARED_FRAG)
|
||||
|
||||
/*
|
||||
* The callback notifies userspace to release buffers when skb DMA is done in
|
||||
@ -461,7 +465,8 @@ enum {
|
||||
* The desc field is used to track userspace buffer index.
|
||||
*/
|
||||
struct ubuf_info {
|
||||
void (*callback)(struct ubuf_info *, bool zerocopy_success);
|
||||
void (*callback)(struct sk_buff *, struct ubuf_info *,
|
||||
bool zerocopy_success);
|
||||
union {
|
||||
struct {
|
||||
unsigned long desc;
|
||||
@ -475,6 +480,7 @@ struct ubuf_info {
|
||||
};
|
||||
};
|
||||
refcount_t refcnt;
|
||||
u8 flags;
|
||||
|
||||
struct mmpin {
|
||||
struct user_struct *user;
|
||||
@ -487,19 +493,14 @@ struct ubuf_info {
|
||||
int mm_account_pinned_pages(struct mmpin *mmp, size_t size);
|
||||
void mm_unaccount_pinned_pages(struct mmpin *mmp);
|
||||
|
||||
struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size);
|
||||
struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
|
||||
struct ubuf_info *uarg);
|
||||
struct ubuf_info *msg_zerocopy_alloc(struct sock *sk, size_t size);
|
||||
struct ubuf_info *msg_zerocopy_realloc(struct sock *sk, size_t size,
|
||||
struct ubuf_info *uarg);
|
||||
|
||||
static inline void sock_zerocopy_get(struct ubuf_info *uarg)
|
||||
{
|
||||
refcount_inc(&uarg->refcnt);
|
||||
}
|
||||
void msg_zerocopy_put_abort(struct ubuf_info *uarg, bool have_uref);
|
||||
|
||||
void sock_zerocopy_put(struct ubuf_info *uarg);
|
||||
void sock_zerocopy_put_abort(struct ubuf_info *uarg, bool have_uref);
|
||||
|
||||
void sock_zerocopy_callback(struct ubuf_info *uarg, bool success);
|
||||
void msg_zerocopy_callback(struct sk_buff *skb, struct ubuf_info *uarg,
|
||||
bool success);
|
||||
|
||||
int skb_zerocopy_iter_dgram(struct sk_buff *skb, struct msghdr *msg, int len);
|
||||
int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb,
|
||||
@ -510,7 +511,7 @@ int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb,
|
||||
* the end of the header data, ie. at skb->end.
|
||||
*/
|
||||
struct skb_shared_info {
|
||||
__u8 __unused;
|
||||
__u8 flags;
|
||||
__u8 meta_len;
|
||||
__u8 nr_frags;
|
||||
__u8 tx_flags;
|
||||
@ -1437,11 +1438,22 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
|
||||
|
||||
static inline struct ubuf_info *skb_zcopy(struct sk_buff *skb)
|
||||
{
|
||||
bool is_zcopy = skb && skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY;
|
||||
bool is_zcopy = skb && skb_shinfo(skb)->flags & SKBFL_ZEROCOPY_ENABLE;
|
||||
|
||||
return is_zcopy ? skb_uarg(skb) : NULL;
|
||||
}
|
||||
|
||||
static inline void net_zcopy_get(struct ubuf_info *uarg)
|
||||
{
|
||||
refcount_inc(&uarg->refcnt);
|
||||
}
|
||||
|
||||
static inline void skb_zcopy_init(struct sk_buff *skb, struct ubuf_info *uarg)
|
||||
{
|
||||
skb_shinfo(skb)->destructor_arg = uarg;
|
||||
skb_shinfo(skb)->flags |= uarg->flags;
|
||||
}
|
||||
|
||||
static inline void skb_zcopy_set(struct sk_buff *skb, struct ubuf_info *uarg,
|
||||
bool *have_ref)
|
||||
{
|
||||
@ -1449,16 +1461,15 @@ static inline void skb_zcopy_set(struct sk_buff *skb, struct ubuf_info *uarg,
|
||||
if (unlikely(have_ref && *have_ref))
|
||||
*have_ref = false;
|
||||
else
|
||||
sock_zerocopy_get(uarg);
|
||||
skb_shinfo(skb)->destructor_arg = uarg;
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_ZEROCOPY_FRAG;
|
||||
net_zcopy_get(uarg);
|
||||
skb_zcopy_init(skb, uarg);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void skb_zcopy_set_nouarg(struct sk_buff *skb, void *val)
|
||||
{
|
||||
skb_shinfo(skb)->destructor_arg = (void *)((uintptr_t) val | 0x1UL);
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_ZEROCOPY_FRAG;
|
||||
skb_shinfo(skb)->flags |= SKBFL_ZEROCOPY_FRAG;
|
||||
}
|
||||
|
||||
static inline bool skb_zcopy_is_nouarg(struct sk_buff *skb)
|
||||
@ -1471,33 +1482,32 @@ static inline void *skb_zcopy_get_nouarg(struct sk_buff *skb)
|
||||
return (void *)((uintptr_t) skb_shinfo(skb)->destructor_arg & ~0x1UL);
|
||||
}
|
||||
|
||||
/* Release a reference on a zerocopy structure */
|
||||
static inline void skb_zcopy_clear(struct sk_buff *skb, bool zerocopy)
|
||||
static inline void net_zcopy_put(struct ubuf_info *uarg)
|
||||
{
|
||||
struct ubuf_info *uarg = skb_zcopy(skb);
|
||||
if (uarg)
|
||||
uarg->callback(NULL, uarg, true);
|
||||
}
|
||||
|
||||
static inline void net_zcopy_put_abort(struct ubuf_info *uarg, bool have_uref)
|
||||
{
|
||||
if (uarg) {
|
||||
if (skb_zcopy_is_nouarg(skb)) {
|
||||
/* no notification callback */
|
||||
} else if (uarg->callback == sock_zerocopy_callback) {
|
||||
uarg->zerocopy = uarg->zerocopy && zerocopy;
|
||||
sock_zerocopy_put(uarg);
|
||||
} else {
|
||||
uarg->callback(uarg, zerocopy);
|
||||
}
|
||||
|
||||
skb_shinfo(skb)->tx_flags &= ~SKBTX_ZEROCOPY_FRAG;
|
||||
if (uarg->callback == msg_zerocopy_callback)
|
||||
msg_zerocopy_put_abort(uarg, have_uref);
|
||||
else if (have_uref)
|
||||
net_zcopy_put(uarg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Abort a zerocopy operation and revert zckey on error in send syscall */
|
||||
static inline void skb_zcopy_abort(struct sk_buff *skb)
|
||||
/* Release a reference on a zerocopy structure */
|
||||
static inline void skb_zcopy_clear(struct sk_buff *skb, bool zerocopy_success)
|
||||
{
|
||||
struct ubuf_info *uarg = skb_zcopy(skb);
|
||||
|
||||
if (uarg) {
|
||||
sock_zerocopy_put_abort(uarg, false);
|
||||
skb_shinfo(skb)->tx_flags &= ~SKBTX_ZEROCOPY_FRAG;
|
||||
if (!skb_zcopy_is_nouarg(skb))
|
||||
uarg->callback(skb, uarg, zerocopy_success);
|
||||
|
||||
skb_shinfo(skb)->flags &= ~SKBFL_ZEROCOPY_FRAG;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2776,7 +2786,7 @@ static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask)
|
||||
if (likely(!skb_zcopy(skb)))
|
||||
return 0;
|
||||
if (!skb_zcopy_is_nouarg(skb) &&
|
||||
skb_uarg(skb)->callback == sock_zerocopy_callback)
|
||||
skb_uarg(skb)->callback == msg_zerocopy_callback)
|
||||
return 0;
|
||||
return skb_copy_ubufs(skb, gfp_mask);
|
||||
}
|
||||
@ -3323,7 +3333,7 @@ static inline int skb_linearize(struct sk_buff *skb)
|
||||
static inline bool skb_has_shared_frag(const struct sk_buff *skb)
|
||||
{
|
||||
return skb_is_nonlinear(skb) &&
|
||||
skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
|
||||
skb_shinfo(skb)->flags & SKBFL_SHARED_FRAG;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -605,13 +605,14 @@ static void skb_release_data(struct sk_buff *skb)
|
||||
&shinfo->dataref))
|
||||
return;
|
||||
|
||||
skb_zcopy_clear(skb, true);
|
||||
|
||||
for (i = 0; i < shinfo->nr_frags; i++)
|
||||
__skb_frag_unref(&shinfo->frags[i]);
|
||||
|
||||
if (shinfo->frag_list)
|
||||
kfree_skb_list(shinfo->frag_list);
|
||||
|
||||
skb_zcopy_clear(skb, true);
|
||||
skb_free_head(skb);
|
||||
}
|
||||
|
||||
@ -1093,7 +1094,7 @@ void mm_unaccount_pinned_pages(struct mmpin *mmp)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mm_unaccount_pinned_pages);
|
||||
|
||||
struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
|
||||
struct ubuf_info *msg_zerocopy_alloc(struct sock *sk, size_t size)
|
||||
{
|
||||
struct ubuf_info *uarg;
|
||||
struct sk_buff *skb;
|
||||
@ -1113,25 +1114,26 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uarg->callback = sock_zerocopy_callback;
|
||||
uarg->callback = msg_zerocopy_callback;
|
||||
uarg->id = ((u32)atomic_inc_return(&sk->sk_zckey)) - 1;
|
||||
uarg->len = 1;
|
||||
uarg->bytelen = size;
|
||||
uarg->zerocopy = 1;
|
||||
uarg->flags = SKBFL_ZEROCOPY_FRAG;
|
||||
refcount_set(&uarg->refcnt, 1);
|
||||
sock_hold(sk);
|
||||
|
||||
return uarg;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_zerocopy_alloc);
|
||||
EXPORT_SYMBOL_GPL(msg_zerocopy_alloc);
|
||||
|
||||
static inline struct sk_buff *skb_from_uarg(struct ubuf_info *uarg)
|
||||
{
|
||||
return container_of((void *)uarg, struct sk_buff, cb);
|
||||
}
|
||||
|
||||
struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
|
||||
struct ubuf_info *uarg)
|
||||
struct ubuf_info *msg_zerocopy_realloc(struct sock *sk, size_t size,
|
||||
struct ubuf_info *uarg)
|
||||
{
|
||||
if (uarg) {
|
||||
const u32 byte_limit = 1 << 19; /* limit to a few TSO */
|
||||
@ -1163,16 +1165,16 @@ struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
|
||||
|
||||
/* no extra ref when appending to datagram (MSG_MORE) */
|
||||
if (sk->sk_type == SOCK_STREAM)
|
||||
sock_zerocopy_get(uarg);
|
||||
net_zcopy_get(uarg);
|
||||
|
||||
return uarg;
|
||||
}
|
||||
}
|
||||
|
||||
new_alloc:
|
||||
return sock_zerocopy_alloc(sk, size);
|
||||
return msg_zerocopy_alloc(sk, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_zerocopy_realloc);
|
||||
EXPORT_SYMBOL_GPL(msg_zerocopy_realloc);
|
||||
|
||||
static bool skb_zerocopy_notify_extend(struct sk_buff *skb, u32 lo, u16 len)
|
||||
{
|
||||
@ -1194,7 +1196,7 @@ static bool skb_zerocopy_notify_extend(struct sk_buff *skb, u32 lo, u16 len)
|
||||
return true;
|
||||
}
|
||||
|
||||
void sock_zerocopy_callback(struct ubuf_info *uarg, bool success)
|
||||
static void __msg_zerocopy_callback(struct ubuf_info *uarg)
|
||||
{
|
||||
struct sk_buff *tail, *skb = skb_from_uarg(uarg);
|
||||
struct sock_exterr_skb *serr;
|
||||
@ -1222,7 +1224,7 @@ 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)
|
||||
if (!uarg->zerocopy)
|
||||
serr->ee.ee_code |= SO_EE_CODE_ZEROCOPY_COPIED;
|
||||
|
||||
q = &sk->sk_error_queue;
|
||||
@ -1241,32 +1243,28 @@ release:
|
||||
consume_skb(skb);
|
||||
sock_put(sk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_zerocopy_callback);
|
||||
|
||||
void sock_zerocopy_put(struct ubuf_info *uarg)
|
||||
void msg_zerocopy_callback(struct sk_buff *skb, struct ubuf_info *uarg,
|
||||
bool success)
|
||||
{
|
||||
if (uarg && refcount_dec_and_test(&uarg->refcnt)) {
|
||||
if (uarg->callback)
|
||||
uarg->callback(uarg, uarg->zerocopy);
|
||||
else
|
||||
consume_skb(skb_from_uarg(uarg));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_zerocopy_put);
|
||||
uarg->zerocopy = uarg->zerocopy & success;
|
||||
|
||||
void sock_zerocopy_put_abort(struct ubuf_info *uarg, bool have_uref)
|
||||
if (refcount_dec_and_test(&uarg->refcnt))
|
||||
__msg_zerocopy_callback(uarg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(msg_zerocopy_callback);
|
||||
|
||||
void msg_zerocopy_put_abort(struct ubuf_info *uarg, bool have_uref)
|
||||
{
|
||||
if (uarg) {
|
||||
struct sock *sk = skb_from_uarg(uarg)->sk;
|
||||
struct sock *sk = skb_from_uarg(uarg)->sk;
|
||||
|
||||
atomic_dec(&sk->sk_zckey);
|
||||
uarg->len--;
|
||||
atomic_dec(&sk->sk_zckey);
|
||||
uarg->len--;
|
||||
|
||||
if (have_uref)
|
||||
sock_zerocopy_put(uarg);
|
||||
}
|
||||
if (have_uref)
|
||||
msg_zerocopy_callback(NULL, uarg, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_zerocopy_put_abort);
|
||||
EXPORT_SYMBOL_GPL(msg_zerocopy_put_abort);
|
||||
|
||||
int skb_zerocopy_iter_dgram(struct sk_buff *skb, struct msghdr *msg, int len)
|
||||
{
|
||||
@ -1330,7 +1328,7 @@ static int skb_zerocopy_clone(struct sk_buff *nskb, struct sk_buff *orig,
|
||||
* @skb: the skb to modify
|
||||
* @gfp_mask: allocation priority
|
||||
*
|
||||
* This must be called on SKBTX_DEV_ZEROCOPY skb.
|
||||
* This must be called on skb with SKBFL_ZEROCOPY_ENABLE.
|
||||
* It will copy all frags into kernel and drop the reference
|
||||
* to userspace pages.
|
||||
*
|
||||
@ -3267,8 +3265,7 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
|
||||
{
|
||||
int pos = skb_headlen(skb);
|
||||
|
||||
skb_shinfo(skb1)->tx_flags |= skb_shinfo(skb)->tx_flags &
|
||||
SKBTX_SHARED_FRAG;
|
||||
skb_shinfo(skb1)->flags |= skb_shinfo(skb)->flags & SKBFL_SHARED_FRAG;
|
||||
skb_zerocopy_clone(skb1, skb, 0);
|
||||
if (len < pos) /* Split line is inside header. */
|
||||
skb_split_inside_header(skb, skb1, len, pos);
|
||||
@ -3957,8 +3954,8 @@ normal:
|
||||
skb_copy_from_linear_data_offset(head_skb, offset,
|
||||
skb_put(nskb, hsize), hsize);
|
||||
|
||||
skb_shinfo(nskb)->tx_flags |= skb_shinfo(head_skb)->tx_flags &
|
||||
SKBTX_SHARED_FRAG;
|
||||
skb_shinfo(nskb)->flags |= skb_shinfo(head_skb)->flags &
|
||||
SKBFL_SHARED_FRAG;
|
||||
|
||||
if (skb_orphan_frags(frag_skb, GFP_ATOMIC) ||
|
||||
skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC))
|
||||
|
@ -1018,7 +1018,7 @@ static int __ip_append_data(struct sock *sk,
|
||||
csummode = CHECKSUM_PARTIAL;
|
||||
|
||||
if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) {
|
||||
uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb));
|
||||
uarg = msg_zerocopy_realloc(sk, length, skb_zcopy(skb));
|
||||
if (!uarg)
|
||||
return -ENOBUFS;
|
||||
extra_uref = !skb_zcopy(skb); /* only ref on new uarg */
|
||||
@ -1230,8 +1230,7 @@ alloc_new_skb:
|
||||
error_efault:
|
||||
err = -EFAULT;
|
||||
error:
|
||||
if (uarg)
|
||||
sock_zerocopy_put_abort(uarg, extra_uref);
|
||||
net_zcopy_put_abort(uarg, extra_uref);
|
||||
cork->length -= length;
|
||||
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
|
||||
refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
|
||||
|
@ -1010,7 +1010,7 @@ new_segment:
|
||||
}
|
||||
|
||||
if (!(flags & MSG_NO_SHARED_FRAGS))
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
|
||||
|
||||
skb->len += copy;
|
||||
skb->data_len += copy;
|
||||
@ -1217,7 +1217,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
|
||||
|
||||
if (flags & MSG_ZEROCOPY && size && sock_flag(sk, SOCK_ZEROCOPY)) {
|
||||
skb = tcp_write_queue_tail(sk);
|
||||
uarg = sock_zerocopy_realloc(sk, size, skb_zcopy(skb));
|
||||
uarg = msg_zerocopy_realloc(sk, size, skb_zcopy(skb));
|
||||
if (!uarg) {
|
||||
err = -ENOBUFS;
|
||||
goto out_err;
|
||||
@ -1429,7 +1429,7 @@ out:
|
||||
tcp_push(sk, flags, mss_now, tp->nonagle, size_goal);
|
||||
}
|
||||
out_nopush:
|
||||
sock_zerocopy_put(uarg);
|
||||
net_zcopy_put(uarg);
|
||||
return copied + copied_syn;
|
||||
|
||||
do_error:
|
||||
@ -1440,7 +1440,7 @@ do_fault:
|
||||
if (copied + copied_syn)
|
||||
goto out;
|
||||
out_err:
|
||||
sock_zerocopy_put_abort(uarg, true);
|
||||
net_zcopy_put_abort(uarg, true);
|
||||
err = sk_stream_error(sk, flags, err);
|
||||
/* make sure we wake any epoll edge trigger waiter */
|
||||
if (unlikely(tcp_rtx_and_write_queues_empty(sk) && err == -EAGAIN)) {
|
||||
|
@ -1471,7 +1471,7 @@ emsgsize:
|
||||
csummode = CHECKSUM_PARTIAL;
|
||||
|
||||
if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) {
|
||||
uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb));
|
||||
uarg = msg_zerocopy_realloc(sk, length, skb_zcopy(skb));
|
||||
if (!uarg)
|
||||
return -ENOBUFS;
|
||||
extra_uref = !skb_zcopy(skb); /* only ref on new uarg */
|
||||
@ -1715,8 +1715,7 @@ alloc_new_skb:
|
||||
error_efault:
|
||||
err = -EFAULT;
|
||||
error:
|
||||
if (uarg)
|
||||
sock_zerocopy_put_abort(uarg, extra_uref);
|
||||
net_zcopy_put_abort(uarg, extra_uref);
|
||||
cork->length -= length;
|
||||
IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
|
||||
refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
|
||||
|
@ -786,7 +786,7 @@ static ssize_t kcm_sendpage(struct socket *sock, struct page *page,
|
||||
|
||||
if (skb_can_coalesce(skb, i, page, offset)) {
|
||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], size);
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
|
||||
goto coalesced;
|
||||
}
|
||||
|
||||
@ -834,7 +834,7 @@ static ssize_t kcm_sendpage(struct socket *sock, struct page *page,
|
||||
|
||||
get_page(page);
|
||||
skb_fill_page_desc(skb, i, page, offset, size);
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
|
||||
|
||||
coalesced:
|
||||
skb->len += size;
|
||||
|
Loading…
Reference in New Issue
Block a user