diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-03-13 16:08:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-14 14:38:32 -0400 |
commit | c1336ee472f83a90ede01fdae095ed5d0a2934c9 (patch) | |
tree | 4178d007c524fe51262b3698150c63d38591b521 /net/tipc/msg.c | |
parent | 1149557d64c97dc9adf3103347a1c0e8c06d3b89 (diff) |
tipc: extract bundled buffers by cloning instead of copying
When we currently extract a bundled buffer from a message bundle in
the function tipc_msg_extract(), we allocate a new buffer and explicitly
copy the linear data area.
This is unnecessary, since we can just clone the buffer and do
skb_pull() on the clone to move the data pointer to the correct
position.
This is what we do in this commit.
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index ff8c64cd1cd9..333d2ae1cf76 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -372,38 +372,40 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu) | |||
372 | 372 | ||
373 | /** | 373 | /** |
374 | * tipc_msg_extract(): extract bundled inner packet from buffer | 374 | * tipc_msg_extract(): extract bundled inner packet from buffer |
375 | * @skb: linear outer buffer, to be extracted from. | 375 | * @skb: buffer to be extracted from. |
376 | * @iskb: extracted inner buffer, to be returned | 376 | * @iskb: extracted inner buffer, to be returned |
377 | * @pos: position of msg to be extracted. Returns with pointer of next msg | 377 | * @pos: position in outer message of msg to be extracted. |
378 | * Returns position of next msg | ||
378 | * Consumes outer buffer when last packet extracted | 379 | * Consumes outer buffer when last packet extracted |
379 | * Returns true when when there is an extracted buffer, otherwise false | 380 | * Returns true when when there is an extracted buffer, otherwise false |
380 | */ | 381 | */ |
381 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) | 382 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) |
382 | { | 383 | { |
383 | struct tipc_msg *msg; | 384 | struct tipc_msg *msg; |
384 | int imsz; | 385 | int imsz, offset; |
385 | struct tipc_msg *imsg; | ||
386 | 386 | ||
387 | *iskb = NULL; | ||
387 | if (unlikely(skb_linearize(skb))) | 388 | if (unlikely(skb_linearize(skb))) |
388 | return false; | 389 | goto none; |
390 | |||
389 | msg = buf_msg(skb); | 391 | msg = buf_msg(skb); |
390 | imsg = (struct tipc_msg *)(msg_data(msg) + *pos); | 392 | offset = msg_hdr_sz(msg) + *pos; |
391 | /* Is there space left for shortest possible message? */ | 393 | if (unlikely(offset > (msg_size(msg) - MIN_H_SIZE))) |
392 | if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE)) | ||
393 | goto none; | 394 | goto none; |
394 | imsz = msg_size(imsg); | ||
395 | 395 | ||
396 | /* Is there space left for current message ? */ | 396 | *iskb = skb_clone(skb, GFP_ATOMIC); |
397 | if ((*pos + imsz) > msg_data_sz(msg)) | 397 | if (unlikely(!*iskb)) |
398 | goto none; | 398 | goto none; |
399 | *iskb = tipc_buf_acquire(imsz); | 399 | skb_pull(*iskb, offset); |
400 | if (!*iskb) | 400 | imsz = msg_size(buf_msg(*iskb)); |
401 | skb_trim(*iskb, imsz); | ||
402 | if (unlikely(!tipc_msg_validate(*iskb))) | ||
401 | goto none; | 403 | goto none; |
402 | skb_copy_to_linear_data(*iskb, imsg, imsz); | ||
403 | *pos += align(imsz); | 404 | *pos += align(imsz); |
404 | return true; | 405 | return true; |
405 | none: | 406 | none: |
406 | kfree_skb(skb); | 407 | kfree_skb(skb); |
408 | kfree_skb(*iskb); | ||
407 | *iskb = NULL; | 409 | *iskb = NULL; |
408 | return false; | 410 | return false; |
409 | } | 411 | } |