From: David Howells <dhowells@redhat.com>
To: torvalds@osdl.org, akpm@osdl.org
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
netdev@vger.kernel.org, dhowells@redhat.com
Subject: [PATCH 01/16] AF_RXRPC: Move generic skbuff stuff from XFRM code to generic code [try #4]
Date: Wed, 25 Apr 2007 16:49:02 +0100 [thread overview]
Message-ID: <20070425154902.26581.43651.stgit@warthog.cambridge.redhat.com> (raw)
In-Reply-To: <20070425154854.26581.97692.stgit@warthog.cambridge.redhat.com>
Move generic skbuff stuff from XFRM code to generic code so that AF_RXRPC can
use it too.
The kdoc comments I've attached to the functions needs to be checked by whoever
wrote them as I had to make some guesses about the workings of these functions.
Signed-Off-By: David Howells <dhowells@redhat.com>
---
include/linux/skbuff.h | 6 ++
include/net/esp.h | 2 -
net/core/skbuff.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++
net/xfrm/xfrm_algo.c | 169 -------------------------------------------
4 files changed, 194 insertions(+), 171 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5992f65..c905d42 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -83,6 +83,7 @@
*/
struct net_device;
+struct scatterlist;
#ifdef CONFIG_NETFILTER
struct nf_conntrack {
@@ -361,6 +362,11 @@ extern struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
int newheadroom, int newtailroom,
gfp_t priority);
+extern int skb_to_sgvec(struct sk_buff *skb,
+ struct scatterlist *sg, int offset,
+ int len);
+extern int skb_cow_data(struct sk_buff *skb, int tailbits,
+ struct sk_buff **trailer);
extern int skb_pad(struct sk_buff *skb, int pad);
#define dev_kfree_skb(a) kfree_skb(a)
extern void skb_over_panic(struct sk_buff *skb, int len,
diff --git a/include/net/esp.h b/include/net/esp.h
index 713d039..d05d8d2 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -40,8 +40,6 @@ struct esp_data
} auth;
};
-extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len);
-extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb,
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 336958f..aa02bd4 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -55,6 +55,7 @@
#include <linux/cache.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
+#include <linux/scatterlist.h>
#include <net/protocol.h>
#include <net/dst.h>
@@ -2005,6 +2006,190 @@ void __init skb_init(void)
NULL, NULL);
}
+/**
+ * skb_to_sgvec - Fill a scatter-gather list from a socket buffer
+ * @skb: Socket buffer containing the buffers to be mapped
+ * @sg: The scatter-gather list to map into
+ * @offset: The offset into the buffer's contents to start mapping
+ * @len: Length of buffer space to be mapped
+ *
+ * Fill the specified scatter-gather list with mappings/pointers into a
+ * region of the buffer space attached to a socket buffer.
+ */
+int
+skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+{
+ int start = skb_headlen(skb);
+ int i, copy = start - offset;
+ int elt = 0;
+
+ if (copy > 0) {
+ if (copy > len)
+ copy = len;
+ sg[elt].page = virt_to_page(skb->data + offset);
+ sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+ sg[elt].length = copy;
+ elt++;
+ if ((len -= copy) == 0)
+ return elt;
+ offset += copy;
+ }
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + skb_shinfo(skb)->frags[i].size;
+ if ((copy = end - offset) > 0) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ if (copy > len)
+ copy = len;
+ sg[elt].page = frag->page;
+ sg[elt].offset = frag->page_offset+offset-start;
+ sg[elt].length = copy;
+ elt++;
+ if (!(len -= copy))
+ return elt;
+ offset += copy;
+ }
+ start = end;
+ }
+
+ if (skb_shinfo(skb)->frag_list) {
+ struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+ for (; list; list = list->next) {
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + list->len;
+ if ((copy = end - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
+ if ((len -= copy) == 0)
+ return elt;
+ offset += copy;
+ }
+ start = end;
+ }
+ }
+ BUG_ON(len);
+ return elt;
+}
+
+/**
+ * skb_cow_data - Check that a socket buffer's data buffers are writable
+ * @skb: The socket buffer to check.
+ * @tailbits: Amount of trailing space to be added
+ * @trailer: Returned pointer to the skb where the @tailbits space begins
+ *
+ * Make sure that the data buffers attached to a socket buffer are
+ * writable. If they are not, private copies are made of the data buffers
+ * and the socket buffer is set to use these instead.
+ *
+ * If @tailbits is given, make sure that there is space to write @tailbits
+ * bytes of data beyond current end of socket buffer. @trailer will be
+ * set to point to the skb in which this space begins.
+ *
+ * The number of scatterlist elements required to completely map the
+ * COW'd and extended socket buffer will be returned.
+ */
+int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
+{
+ int copyflag;
+ int elt;
+ struct sk_buff *skb1, **skb_p;
+
+ /* If skb is cloned or its head is paged, reallocate
+ * head pulling out all the pages (pages are considered not writable
+ * at the moment even if they are anonymous).
+ */
+ if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
+ __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
+ return -ENOMEM;
+
+ /* Easy case. Most of packets will go this way. */
+ if (!skb_shinfo(skb)->frag_list) {
+ /* A little of trouble, not enough of space for trailer.
+ * This should not happen, when stack is tuned to generate
+ * good frames. OK, on miss we reallocate and reserve even more
+ * space, 128 bytes is fair. */
+
+ if (skb_tailroom(skb) < tailbits &&
+ pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
+ return -ENOMEM;
+
+ /* Voila! */
+ *trailer = skb;
+ return 1;
+ }
+
+ /* Misery. We are in troubles, going to mincer fragments... */
+
+ elt = 1;
+ skb_p = &skb_shinfo(skb)->frag_list;
+ copyflag = 0;
+
+ while ((skb1 = *skb_p) != NULL) {
+ int ntail = 0;
+
+ /* The fragment is partially pulled by someone,
+ * this can happen on input. Copy it and everything
+ * after it. */
+
+ if (skb_shared(skb1))
+ copyflag = 1;
+
+ /* If the skb is the last, worry about trailer. */
+
+ if (skb1->next == NULL && tailbits) {
+ if (skb_shinfo(skb1)->nr_frags ||
+ skb_shinfo(skb1)->frag_list ||
+ skb_tailroom(skb1) < tailbits)
+ ntail = tailbits + 128;
+ }
+
+ if (copyflag ||
+ skb_cloned(skb1) ||
+ ntail ||
+ skb_shinfo(skb1)->nr_frags ||
+ skb_shinfo(skb1)->frag_list) {
+ struct sk_buff *skb2;
+
+ /* Fuck, we are miserable poor guys... */
+ if (ntail == 0)
+ skb2 = skb_copy(skb1, GFP_ATOMIC);
+ else
+ skb2 = skb_copy_expand(skb1,
+ skb_headroom(skb1),
+ ntail,
+ GFP_ATOMIC);
+ if (unlikely(skb2 == NULL))
+ return -ENOMEM;
+
+ if (skb1->sk)
+ skb_set_owner_w(skb2, skb1->sk);
+
+ /* Looking around. Are we still alive?
+ * OK, link new skb, drop old one */
+
+ skb2->next = skb1->next;
+ *skb_p = skb2;
+ kfree_skb(skb1);
+ skb1 = skb2;
+ }
+ elt++;
+ *trailer = skb1;
+ skb_p = &skb1->next;
+ }
+
+ return elt;
+}
+
EXPORT_SYMBOL(___pskb_trim);
EXPORT_SYMBOL(__kfree_skb);
EXPORT_SYMBOL(kfree_skb);
@@ -2039,3 +2224,6 @@ EXPORT_SYMBOL(skb_seq_read);
EXPORT_SYMBOL(skb_abort_seq_read);
EXPORT_SYMBOL(skb_find_text);
EXPORT_SYMBOL(skb_append_datato_frags);
+
+EXPORT_SYMBOL_GPL(skb_to_sgvec);
+EXPORT_SYMBOL_GPL(skb_cow_data);
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index f373a8a..6249a94 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -612,175 +612,6 @@ EXPORT_SYMBOL_GPL(skb_icv_walk);
#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
-/* Looking generic it is not used in another places. */
-
-int
-skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
-{
- int start = skb_headlen(skb);
- int i, copy = start - offset;
- int elt = 0;
-
- if (copy > 0) {
- if (copy > len)
- copy = len;
- sg[elt].page = virt_to_page(skb->data + offset);
- sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
- sg[elt].length = copy;
- elt++;
- if ((len -= copy) == 0)
- return elt;
- offset += copy;
- }
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- int end;
-
- BUG_TRAP(start <= offset + len);
-
- end = start + skb_shinfo(skb)->frags[i].size;
- if ((copy = end - offset) > 0) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- if (copy > len)
- copy = len;
- sg[elt].page = frag->page;
- sg[elt].offset = frag->page_offset+offset-start;
- sg[elt].length = copy;
- elt++;
- if (!(len -= copy))
- return elt;
- offset += copy;
- }
- start = end;
- }
-
- if (skb_shinfo(skb)->frag_list) {
- struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
- for (; list; list = list->next) {
- int end;
-
- BUG_TRAP(start <= offset + len);
-
- end = start + list->len;
- if ((copy = end - offset) > 0) {
- if (copy > len)
- copy = len;
- elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
- if ((len -= copy) == 0)
- return elt;
- offset += copy;
- }
- start = end;
- }
- }
- BUG_ON(len);
- return elt;
-}
-EXPORT_SYMBOL_GPL(skb_to_sgvec);
-
-/* Check that skb data bits are writable. If they are not, copy data
- * to newly created private area. If "tailbits" is given, make sure that
- * tailbits bytes beyond current end of skb are writable.
- *
- * Returns amount of elements of scatterlist to load for subsequent
- * transformations and pointer to writable trailer skb.
- */
-
-int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
-{
- int copyflag;
- int elt;
- struct sk_buff *skb1, **skb_p;
-
- /* If skb is cloned or its head is paged, reallocate
- * head pulling out all the pages (pages are considered not writable
- * at the moment even if they are anonymous).
- */
- if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
- __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
- return -ENOMEM;
-
- /* Easy case. Most of packets will go this way. */
- if (!skb_shinfo(skb)->frag_list) {
- /* A little of trouble, not enough of space for trailer.
- * This should not happen, when stack is tuned to generate
- * good frames. OK, on miss we reallocate and reserve even more
- * space, 128 bytes is fair. */
-
- if (skb_tailroom(skb) < tailbits &&
- pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
- return -ENOMEM;
-
- /* Voila! */
- *trailer = skb;
- return 1;
- }
-
- /* Misery. We are in troubles, going to mincer fragments... */
-
- elt = 1;
- skb_p = &skb_shinfo(skb)->frag_list;
- copyflag = 0;
-
- while ((skb1 = *skb_p) != NULL) {
- int ntail = 0;
-
- /* The fragment is partially pulled by someone,
- * this can happen on input. Copy it and everything
- * after it. */
-
- if (skb_shared(skb1))
- copyflag = 1;
-
- /* If the skb is the last, worry about trailer. */
-
- if (skb1->next == NULL && tailbits) {
- if (skb_shinfo(skb1)->nr_frags ||
- skb_shinfo(skb1)->frag_list ||
- skb_tailroom(skb1) < tailbits)
- ntail = tailbits + 128;
- }
-
- if (copyflag ||
- skb_cloned(skb1) ||
- ntail ||
- skb_shinfo(skb1)->nr_frags ||
- skb_shinfo(skb1)->frag_list) {
- struct sk_buff *skb2;
-
- /* Fuck, we are miserable poor guys... */
- if (ntail == 0)
- skb2 = skb_copy(skb1, GFP_ATOMIC);
- else
- skb2 = skb_copy_expand(skb1,
- skb_headroom(skb1),
- ntail,
- GFP_ATOMIC);
- if (unlikely(skb2 == NULL))
- return -ENOMEM;
-
- if (skb1->sk)
- skb_set_owner_w(skb2, skb1->sk);
-
- /* Looking around. Are we still alive?
- * OK, link new skb, drop old one */
-
- skb2->next = skb1->next;
- *skb_p = skb2;
- kfree_skb(skb1);
- skb1 = skb2;
- }
- elt++;
- *trailer = skb1;
- skb_p = &skb1->next;
- }
-
- return elt;
-}
-EXPORT_SYMBOL_GPL(skb_cow_data);
-
void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
{
if (tail != skb) {
next prev parent reply other threads:[~2007-04-25 15:49 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-25 15:48 [PATCH 00/16] AF_RXRPC socket family and AFS rewrite [try #4] David Howells
2007-04-25 15:49 ` David Howells [this message]
2007-04-25 15:49 ` [PATCH 02/16] cancel_delayed_work: use del_timer() instead of del_timer_sync() " David Howells
2007-04-25 15:49 ` [PATCH 03/16] AF_RXRPC: Key facility changes for AF_RXRPC " David Howells
2007-04-25 15:49 ` [PATCH 04/16] AF_RXRPC: Make it possible to merely try to cancel timers from a module " David Howells
2007-04-25 15:49 ` [PATCH 07/16] AF_RXRPC: Add an interface to the AF_RXRPC module for the AFS filesystem to use " David Howells
2007-04-25 15:49 ` [PATCH 10/16] AFS: Handle multiple mounts of an AFS superblock correctly " David Howells
2007-04-25 15:49 ` [PATCH 11/16] AFS: Add security support " David Howells
2007-04-25 15:49 ` [PATCH 12/16] AFS: Update the AFS fs documentation " David Howells
2007-04-25 15:50 ` [PATCH 13/16] commit ad495d7b6cfcd1bc2eaf06c42699be0bb5d84234 " David Howells
2007-04-25 15:50 ` [PATCH 14/16] AFS: Add support for the CB.GetCapabilities operation " David Howells
2007-04-25 15:50 ` [PATCH 15/16] AFS: Implement the CB.InitCallBackState3 " David Howells
2007-04-25 15:50 ` [PATCH 16/16] AFS: Add "directory write" support " David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070425154902.26581.43651.stgit@warthog.cambridge.redhat.com \
--to=dhowells@redhat.com \
--cc=akpm@osdl.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).