aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Campbell <Ian.Campbell@citrix.com>2011-08-19 02:25:00 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-22 19:59:54 -0400
commit131ea6675c761f655d43b808dd0fe83d15d5cdd3 (patch)
tree0d8cb6a3ea524f216d846f172c218fababead4a0
parent7ae9ed8d3221c9f7dd4bc2773ff58797487d5ed8 (diff)
net: add APIs for manipulating skb page fragments.
The primary aim is to add skb_frag_(ref|unref) in order to remove the use of bare get/put_page on SKB pages fragments and to isolate users from subsequent changes to the skb_frag_t data structure. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: "Michał Mirosław" <mirq-linux@rere.qmqm.pl> Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/skbuff.h170
1 files changed, 168 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ea0b3746386..7b0e1773f9c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -29,6 +29,7 @@
29#include <linux/rcupdate.h> 29#include <linux/rcupdate.h>
30#include <linux/dmaengine.h> 30#include <linux/dmaengine.h>
31#include <linux/hrtimer.h> 31#include <linux/hrtimer.h>
32#include <linux/dma-mapping.h>
32 33
33/* Don't change this without changing skb_csum_unnecessary! */ 34/* Don't change this without changing skb_csum_unnecessary! */
34#define CHECKSUM_NONE 0 35#define CHECKSUM_NONE 0
@@ -1129,14 +1130,47 @@ static inline int skb_pagelen(const struct sk_buff *skb)
1129 return len + skb_headlen(skb); 1130 return len + skb_headlen(skb);
1130} 1131}
1131 1132
1132static inline void skb_fill_page_desc(struct sk_buff *skb, int i, 1133/**
1133 struct page *page, int off, int size) 1134 * __skb_fill_page_desc - initialise a paged fragment in an skb
1135 * @skb: buffer containing fragment to be initialised
1136 * @i: paged fragment index to initialise
1137 * @page: the page to use for this fragment
1138 * @off: the offset to the data with @page
1139 * @size: the length of the data
1140 *
1141 * Initialises the @i'th fragment of @skb to point to &size bytes at
1142 * offset @off within @page.
1143 *
1144 * Does not take any additional reference on the fragment.
1145 */
1146static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
1147 struct page *page, int off, int size)
1134{ 1148{
1135 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 1149 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
1136 1150
1137 frag->page = page; 1151 frag->page = page;
1138 frag->page_offset = off; 1152 frag->page_offset = off;
1139 frag->size = size; 1153 frag->size = size;
1154}
1155
1156/**
1157 * skb_fill_page_desc - initialise a paged fragment in an skb
1158 * @skb: buffer containing fragment to be initialised
1159 * @i: paged fragment index to initialise
1160 * @page: the page to use for this fragment
1161 * @off: the offset to the data with @page
1162 * @size: the length of the data
1163 *
1164 * As per __skb_fill_page_desc() -- initialises the @i'th fragment of
1165 * @skb to point to &size bytes at offset @off within @page. In
1166 * addition updates @skb such that @i is the last fragment.
1167 *
1168 * Does not take any additional reference on the fragment.
1169 */
1170static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
1171 struct page *page, int off, int size)
1172{
1173 __skb_fill_page_desc(skb, i, page, off, size);
1140 skb_shinfo(skb)->nr_frags = i + 1; 1174 skb_shinfo(skb)->nr_frags = i + 1;
1141} 1175}
1142 1176
@@ -1631,6 +1665,138 @@ static inline void netdev_free_page(struct net_device *dev, struct page *page)
1631} 1665}
1632 1666
1633/** 1667/**
1668 * skb_frag_page - retrieve the page refered to by a paged fragment
1669 * @frag: the paged fragment
1670 *
1671 * Returns the &struct page associated with @frag.
1672 */
1673static inline struct page *skb_frag_page(const skb_frag_t *frag)
1674{
1675 return frag->page;
1676}
1677
1678/**
1679 * __skb_frag_ref - take an addition reference on a paged fragment.
1680 * @frag: the paged fragment
1681 *
1682 * Takes an additional reference on the paged fragment @frag.
1683 */
1684static inline void __skb_frag_ref(skb_frag_t *frag)
1685{
1686 get_page(skb_frag_page(frag));
1687}
1688
1689/**
1690 * skb_frag_ref - take an addition reference on a paged fragment of an skb.
1691 * @skb: the buffer
1692 * @f: the fragment offset.
1693 *
1694 * Takes an additional reference on the @f'th paged fragment of @skb.
1695 */
1696static inline void skb_frag_ref(struct sk_buff *skb, int f)
1697{
1698 __skb_frag_ref(&skb_shinfo(skb)->frags[f]);
1699}
1700
1701/**
1702 * __skb_frag_unref - release a reference on a paged fragment.
1703 * @frag: the paged fragment
1704 *
1705 * Releases a reference on the paged fragment @frag.
1706 */
1707static inline void __skb_frag_unref(skb_frag_t *frag)
1708{
1709 put_page(skb_frag_page(frag));
1710}
1711
1712/**
1713 * skb_frag_unref - release a reference on a paged fragment of an skb.
1714 * @skb: the buffer
1715 * @f: the fragment offset
1716 *
1717 * Releases a reference on the @f'th paged fragment of @skb.
1718 */
1719static inline void skb_frag_unref(struct sk_buff *skb, int f)
1720{
1721 __skb_frag_unref(&skb_shinfo(skb)->frags[f]);
1722}
1723
1724/**
1725 * skb_frag_address - gets the address of the data contained in a paged fragment
1726 * @frag: the paged fragment buffer
1727 *
1728 * Returns the address of the data within @frag. The page must already
1729 * be mapped.
1730 */
1731static inline void *skb_frag_address(const skb_frag_t *frag)
1732{
1733 return page_address(skb_frag_page(frag)) + frag->page_offset;
1734}
1735
1736/**
1737 * skb_frag_address_safe - gets the address of the data contained in a paged fragment
1738 * @frag: the paged fragment buffer
1739 *
1740 * Returns the address of the data within @frag. Checks that the page
1741 * is mapped and returns %NULL otherwise.
1742 */
1743static inline void *skb_frag_address_safe(const skb_frag_t *frag)
1744{
1745 void *ptr = page_address(skb_frag_page(frag));
1746 if (unlikely(!ptr))
1747 return NULL;
1748
1749 return ptr + frag->page_offset;
1750}
1751
1752/**
1753 * __skb_frag_set_page - sets the page contained in a paged fragment
1754 * @frag: the paged fragment
1755 * @page: the page to set
1756 *
1757 * Sets the fragment @frag to contain @page.
1758 */
1759static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page)
1760{
1761 frag->page = page;
1762 __skb_frag_ref(frag);
1763}
1764
1765/**
1766 * skb_frag_set_page - sets the page contained in a paged fragment of an skb
1767 * @skb: the buffer
1768 * @f: the fragment offset
1769 * @page: the page to set
1770 *
1771 * Sets the @f'th fragment of @skb to contain @page.
1772 */
1773static inline void skb_frag_set_page(struct sk_buff *skb, int f,
1774 struct page *page)
1775{
1776 __skb_frag_set_page(&skb_shinfo(skb)->frags[f], page);
1777}
1778
1779/**
1780 * skb_frag_dma_map - maps a paged fragment via the DMA API
1781 * @device: the device to map the fragment to
1782 * @frag: the paged fragment to map
1783 * @offset: the offset within the fragment (starting at the
1784 * fragment's own offset)
1785 * @size: the number of bytes to map
1786 * @direction: the direction of the mapping (%PCI_DMA_*)
1787 *
1788 * Maps the page associated with @frag to @device.
1789 */
1790static inline dma_addr_t skb_frag_dma_map(struct device *dev,
1791 const skb_frag_t *frag,
1792 size_t offset, size_t size,
1793 enum dma_data_direction dir)
1794{
1795 return dma_map_page(dev, skb_frag_page(frag),
1796 frag->page_offset + offset, size, dir);
1797}
1798
1799/**
1634 * skb_clone_writable - is the header of a clone writable 1800 * skb_clone_writable - is the header of a clone writable
1635 * @skb: buffer to check 1801 * @skb: buffer to check
1636 * @len: length up to which to write 1802 * @len: length up to which to write