esp: avoid unneeded kmap_atomic call
esp(6)_output_head uses skb_page_frag_refill to allocate a buffer for the esp trailer. It accesses the page with kmap_atomic to handle highmem. But skb_page_frag_refill can return compound pages, of which kmap_atomic only maps the first underlying page. skb_page_frag_refill does not return highmem, because flag __GFP_HIGHMEM is not set. ESP uses it in the same manner as TCP. That also does not call kmap_atomic, but directly uses page_address, in skb_copy_to_page_nocache. Do the same for ESP. This issue has become easier to trigger with recent kmap local debugging feature CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP. Fixes:cac2661c53
("esp4: Avoid skb_cow_data whenever possible") Fixes:03e2a30f6a
("esp6: Avoid skb_cow_data whenever possible") Signed-off-by: Willem de Bruijn <willemb@google.com> Acked-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Родитель
97550f6fa5
Коммит
9bd6b629c3
|
@ -443,7 +443,6 @@ static int esp_output_encap(struct xfrm_state *x, struct sk_buff *skb,
|
||||||
int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
|
int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
|
||||||
{
|
{
|
||||||
u8 *tail;
|
u8 *tail;
|
||||||
u8 *vaddr;
|
|
||||||
int nfrags;
|
int nfrags;
|
||||||
int esph_offset;
|
int esph_offset;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
@ -485,14 +484,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
|
||||||
page = pfrag->page;
|
page = pfrag->page;
|
||||||
get_page(page);
|
get_page(page);
|
||||||
|
|
||||||
vaddr = kmap_atomic(page);
|
tail = page_address(page) + pfrag->offset;
|
||||||
|
|
||||||
tail = vaddr + pfrag->offset;
|
|
||||||
|
|
||||||
esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
|
esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
|
||||||
|
|
||||||
kunmap_atomic(vaddr);
|
|
||||||
|
|
||||||
nfrags = skb_shinfo(skb)->nr_frags;
|
nfrags = skb_shinfo(skb)->nr_frags;
|
||||||
|
|
||||||
__skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
|
__skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
|
||||||
|
|
|
@ -478,7 +478,6 @@ static int esp6_output_encap(struct xfrm_state *x, struct sk_buff *skb,
|
||||||
int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
|
int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
|
||||||
{
|
{
|
||||||
u8 *tail;
|
u8 *tail;
|
||||||
u8 *vaddr;
|
|
||||||
int nfrags;
|
int nfrags;
|
||||||
int esph_offset;
|
int esph_offset;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
@ -519,14 +518,10 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
|
||||||
page = pfrag->page;
|
page = pfrag->page;
|
||||||
get_page(page);
|
get_page(page);
|
||||||
|
|
||||||
vaddr = kmap_atomic(page);
|
tail = page_address(page) + pfrag->offset;
|
||||||
|
|
||||||
tail = vaddr + pfrag->offset;
|
|
||||||
|
|
||||||
esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
|
esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
|
||||||
|
|
||||||
kunmap_atomic(vaddr);
|
|
||||||
|
|
||||||
nfrags = skb_shinfo(skb)->nr_frags;
|
nfrags = skb_shinfo(skb)->nr_frags;
|
||||||
|
|
||||||
__skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
|
__skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче