set_sndbuf: case SO_SNDBUF: /* Don't error on this BSD doesn't and if you think * about it this is right. Otherwise apps have to * play 'guess the biggest size' games. RCVBUF/SNDBUF * are treated in BSD as hints */ val = min_t(u32, val, sysctl_wmem_max); sk->sk_userlocks |= SOCK_SNDBUF_LOCK; sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF); /* Wake up sending tasks if we upped the value. */ sk->sk_write_space(sk); break;
set_rcvbuf: case SO_RCVBUF: /* Don't error on this BSD doesn't and if you think * about it this is right. Otherwise apps have to * play 'guess the biggest size' games. RCVBUF/SNDBUF * are treated in BSD as hints */ val = min_t(u32, val, sysctl_rmem_max); sk->sk_userlocks |= SOCK_RCVBUF_LOCK; /* * We double it on the way in to account for * "struct sk_buff" etc. overhead. Applications * assume that the SO_RCVBUF setting they make will * allow that much actual data to be received on that * socket. * * Applications are unaware that "struct sk_buff" and * other overheads allocate from the receive buffer * during socket buffer allocation. * * And after considering the possible alternatives, * returning the value we actually used in getsockopt * is the most desirable behavior. */ sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF); break;
for (i = 0; i < shinfo->nr_frags; i++) __skb_frag_unref(&shinfo->frags[i]);
/* * If skb buf is from userspace, we need to notify the caller * the lower device DMA has done; */ if (shinfo->tx_flags & SKBTX_DEV_ZEROCOPY) { structubuf_info *uarg;
uarg = shinfo->destructor_arg; if (uarg->callback) uarg->callback(uarg, true); }
if (shinfo->frag_list) kfree_skb_list(shinfo->frag_list);
可以在Linux kernel 4.8.14版本中看到max_t(u32, val * 2, SOCK_MIN_SNDBUF);和max_t(u32, val * 2, SOCK_MIN_RCVBUF);被修改为了max_t(int, val * 2, SOCK_MIN_SNDBUF);以及max_t(int, val * 2, SOCK_MIN_RCVBUF);。