diff options
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 88 |
1 files changed, 41 insertions, 47 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 026e01f70274..9c3f823e76a9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -166,7 +166,7 @@ EXPORT_SYMBOL(sk_ns_capable); | |||
166 | /** | 166 | /** |
167 | * sk_capable - Socket global capability test | 167 | * sk_capable - Socket global capability test |
168 | * @sk: Socket to use a capability on or through | 168 | * @sk: Socket to use a capability on or through |
169 | * @cap: The global capbility to use | 169 | * @cap: The global capability to use |
170 | * | 170 | * |
171 | * Test to see if the opener of the socket had when the socket was | 171 | * Test to see if the opener of the socket had when the socket was |
172 | * created and the current process has the capability @cap in all user | 172 | * created and the current process has the capability @cap in all user |
@@ -183,7 +183,7 @@ EXPORT_SYMBOL(sk_capable); | |||
183 | * @sk: Socket to use a capability on or through | 183 | * @sk: Socket to use a capability on or through |
184 | * @cap: The capability to use | 184 | * @cap: The capability to use |
185 | * | 185 | * |
186 | * Test to see if the opener of the socket had when the socke was created | 186 | * Test to see if the opener of the socket had when the socket was created |
187 | * and the current process has the capability @cap over the network namespace | 187 | * and the current process has the capability @cap over the network namespace |
188 | * the socket is a member of. | 188 | * the socket is a member of. |
189 | */ | 189 | */ |
@@ -491,7 +491,7 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) | |||
491 | 491 | ||
492 | skb->dev = NULL; | 492 | skb->dev = NULL; |
493 | 493 | ||
494 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { | 494 | if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { |
495 | atomic_inc(&sk->sk_drops); | 495 | atomic_inc(&sk->sk_drops); |
496 | goto discard_and_relse; | 496 | goto discard_and_relse; |
497 | } | 497 | } |
@@ -848,24 +848,25 @@ set_rcvbuf: | |||
848 | ret = -EINVAL; | 848 | ret = -EINVAL; |
849 | break; | 849 | break; |
850 | } | 850 | } |
851 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | 851 | if (val & SOF_TIMESTAMPING_OPT_ID && |
852 | val & SOF_TIMESTAMPING_TX_HARDWARE); | 852 | !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { |
853 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE, | 853 | if (sk->sk_protocol == IPPROTO_TCP) { |
854 | val & SOF_TIMESTAMPING_TX_SOFTWARE); | 854 | if (sk->sk_state != TCP_ESTABLISHED) { |
855 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE, | 855 | ret = -EINVAL; |
856 | val & SOF_TIMESTAMPING_RX_HARDWARE); | 856 | break; |
857 | } | ||
858 | sk->sk_tskey = tcp_sk(sk)->snd_una; | ||
859 | } else { | ||
860 | sk->sk_tskey = 0; | ||
861 | } | ||
862 | } | ||
863 | sk->sk_tsflags = val; | ||
857 | if (val & SOF_TIMESTAMPING_RX_SOFTWARE) | 864 | if (val & SOF_TIMESTAMPING_RX_SOFTWARE) |
858 | sock_enable_timestamp(sk, | 865 | sock_enable_timestamp(sk, |
859 | SOCK_TIMESTAMPING_RX_SOFTWARE); | 866 | SOCK_TIMESTAMPING_RX_SOFTWARE); |
860 | else | 867 | else |
861 | sock_disable_timestamp(sk, | 868 | sock_disable_timestamp(sk, |
862 | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)); | 869 | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)); |
863 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_SOFTWARE, | ||
864 | val & SOF_TIMESTAMPING_SOFTWARE); | ||
865 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE, | ||
866 | val & SOF_TIMESTAMPING_SYS_HARDWARE); | ||
867 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE, | ||
868 | val & SOF_TIMESTAMPING_RAW_HARDWARE); | ||
869 | break; | 870 | break; |
870 | 871 | ||
871 | case SO_RCVLOWAT: | 872 | case SO_RCVLOWAT: |
@@ -1091,21 +1092,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
1091 | break; | 1092 | break; |
1092 | 1093 | ||
1093 | case SO_TIMESTAMPING: | 1094 | case SO_TIMESTAMPING: |
1094 | v.val = 0; | 1095 | v.val = sk->sk_tsflags; |
1095 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | ||
1096 | v.val |= SOF_TIMESTAMPING_TX_HARDWARE; | ||
1097 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | ||
1098 | v.val |= SOF_TIMESTAMPING_TX_SOFTWARE; | ||
1099 | if (sock_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE)) | ||
1100 | v.val |= SOF_TIMESTAMPING_RX_HARDWARE; | ||
1101 | if (sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE)) | ||
1102 | v.val |= SOF_TIMESTAMPING_RX_SOFTWARE; | ||
1103 | if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) | ||
1104 | v.val |= SOF_TIMESTAMPING_SOFTWARE; | ||
1105 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE)) | ||
1106 | v.val |= SOF_TIMESTAMPING_SYS_HARDWARE; | ||
1107 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE)) | ||
1108 | v.val |= SOF_TIMESTAMPING_RAW_HARDWARE; | ||
1109 | break; | 1096 | break; |
1110 | 1097 | ||
1111 | case SO_RCVTIMEO: | 1098 | case SO_RCVTIMEO: |
@@ -1478,6 +1465,7 @@ static void sk_update_clone(const struct sock *sk, struct sock *newsk) | |||
1478 | struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | 1465 | struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) |
1479 | { | 1466 | { |
1480 | struct sock *newsk; | 1467 | struct sock *newsk; |
1468 | bool is_charged = true; | ||
1481 | 1469 | ||
1482 | newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family); | 1470 | newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family); |
1483 | if (newsk != NULL) { | 1471 | if (newsk != NULL) { |
@@ -1522,9 +1510,13 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1522 | 1510 | ||
1523 | filter = rcu_dereference_protected(newsk->sk_filter, 1); | 1511 | filter = rcu_dereference_protected(newsk->sk_filter, 1); |
1524 | if (filter != NULL) | 1512 | if (filter != NULL) |
1525 | sk_filter_charge(newsk, filter); | 1513 | /* though it's an empty new sock, the charging may fail |
1514 | * if sysctl_optmem_max was changed between creation of | ||
1515 | * original socket and cloning | ||
1516 | */ | ||
1517 | is_charged = sk_filter_charge(newsk, filter); | ||
1526 | 1518 | ||
1527 | if (unlikely(xfrm_sk_clone_policy(newsk))) { | 1519 | if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk))) { |
1528 | /* It is still raw copy of parent, so invalidate | 1520 | /* It is still raw copy of parent, so invalidate |
1529 | * destructor and make plain sk_free() */ | 1521 | * destructor and make plain sk_free() */ |
1530 | newsk->sk_destruct = NULL; | 1522 | newsk->sk_destruct = NULL; |
@@ -1830,6 +1822,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
1830 | order); | 1822 | order); |
1831 | if (page) | 1823 | if (page) |
1832 | goto fill_page; | 1824 | goto fill_page; |
1825 | /* Do not retry other high order allocations */ | ||
1826 | order = 1; | ||
1827 | max_page_order = 0; | ||
1833 | } | 1828 | } |
1834 | order--; | 1829 | order--; |
1835 | } | 1830 | } |
@@ -1871,16 +1866,14 @@ EXPORT_SYMBOL(sock_alloc_send_skb); | |||
1871 | * skb_page_frag_refill - check that a page_frag contains enough room | 1866 | * skb_page_frag_refill - check that a page_frag contains enough room |
1872 | * @sz: minimum size of the fragment we want to get | 1867 | * @sz: minimum size of the fragment we want to get |
1873 | * @pfrag: pointer to page_frag | 1868 | * @pfrag: pointer to page_frag |
1874 | * @prio: priority for memory allocation | 1869 | * @gfp: priority for memory allocation |
1875 | * | 1870 | * |
1876 | * Note: While this allocator tries to use high order pages, there is | 1871 | * Note: While this allocator tries to use high order pages, there is |
1877 | * no guarantee that allocations succeed. Therefore, @sz MUST be | 1872 | * no guarantee that allocations succeed. Therefore, @sz MUST be |
1878 | * less or equal than PAGE_SIZE. | 1873 | * less or equal than PAGE_SIZE. |
1879 | */ | 1874 | */ |
1880 | bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) | 1875 | bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp) |
1881 | { | 1876 | { |
1882 | int order; | ||
1883 | |||
1884 | if (pfrag->page) { | 1877 | if (pfrag->page) { |
1885 | if (atomic_read(&pfrag->page->_count) == 1) { | 1878 | if (atomic_read(&pfrag->page->_count) == 1) { |
1886 | pfrag->offset = 0; | 1879 | pfrag->offset = 0; |
@@ -1891,20 +1884,21 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) | |||
1891 | put_page(pfrag->page); | 1884 | put_page(pfrag->page); |
1892 | } | 1885 | } |
1893 | 1886 | ||
1894 | order = SKB_FRAG_PAGE_ORDER; | 1887 | pfrag->offset = 0; |
1895 | do { | 1888 | if (SKB_FRAG_PAGE_ORDER) { |
1896 | gfp_t gfp = prio; | 1889 | pfrag->page = alloc_pages(gfp | __GFP_COMP | |
1897 | 1890 | __GFP_NOWARN | __GFP_NORETRY, | |
1898 | if (order) | 1891 | SKB_FRAG_PAGE_ORDER); |
1899 | gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; | ||
1900 | pfrag->page = alloc_pages(gfp, order); | ||
1901 | if (likely(pfrag->page)) { | 1892 | if (likely(pfrag->page)) { |
1902 | pfrag->offset = 0; | 1893 | pfrag->size = PAGE_SIZE << SKB_FRAG_PAGE_ORDER; |
1903 | pfrag->size = PAGE_SIZE << order; | ||
1904 | return true; | 1894 | return true; |
1905 | } | 1895 | } |
1906 | } while (--order >= 0); | 1896 | } |
1907 | 1897 | pfrag->page = alloc_page(gfp); | |
1898 | if (likely(pfrag->page)) { | ||
1899 | pfrag->size = PAGE_SIZE; | ||
1900 | return true; | ||
1901 | } | ||
1908 | return false; | 1902 | return false; |
1909 | } | 1903 | } |
1910 | EXPORT_SYMBOL(skb_page_frag_refill); | 1904 | EXPORT_SYMBOL(skb_page_frag_refill); |