tipc: refactor function tipc_msg_reverse()
The function tipc_msg_reverse() is reversing the header of a message while reusing the original buffer. We have seen at several occasions that this may have unfortunate side effects when the buffer to be reversed is a clone. In one of the following commits we will again need to reverse cloned buffers, so this is the right time to permanently eliminate this problem. In this commit we let the said function always consume the original buffer and replace it with a new one when applicable. Acked-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>
This commit is contained in:
parent
a337531b94
commit
5cbdbd1a1f
|
@ -499,54 +499,52 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
|
|||
/**
|
||||
* tipc_msg_reverse(): swap source and destination addresses and add error code
|
||||
* @own_node: originating node id for reversed message
|
||||
* @skb: buffer containing message to be reversed; may be replaced.
|
||||
* @skb: buffer containing message to be reversed; will be consumed
|
||||
* @err: error code to be set in message, if any
|
||||
* Consumes buffer at failure
|
||||
* Replaces consumed buffer with new one when successful
|
||||
* Returns true if success, otherwise false
|
||||
*/
|
||||
bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err)
|
||||
{
|
||||
struct sk_buff *_skb = *skb;
|
||||
struct tipc_msg *hdr;
|
||||
struct tipc_msg ohdr;
|
||||
int dlen;
|
||||
struct tipc_msg *_hdr, *hdr;
|
||||
int hlen, dlen;
|
||||
|
||||
if (skb_linearize(_skb))
|
||||
goto exit;
|
||||
hdr = buf_msg(_skb);
|
||||
dlen = min_t(uint, msg_data_sz(hdr), MAX_FORWARD_SIZE);
|
||||
if (msg_dest_droppable(hdr))
|
||||
_hdr = buf_msg(_skb);
|
||||
dlen = min_t(uint, msg_data_sz(_hdr), MAX_FORWARD_SIZE);
|
||||
hlen = msg_hdr_sz(_hdr);
|
||||
|
||||
if (msg_dest_droppable(_hdr))
|
||||
goto exit;
|
||||
if (msg_errcode(hdr))
|
||||
if (msg_errcode(_hdr))
|
||||
goto exit;
|
||||
|
||||
/* Take a copy of original header before altering message */
|
||||
memcpy(&ohdr, hdr, msg_hdr_sz(hdr));
|
||||
/* Never return SHORT header */
|
||||
if (hlen == SHORT_H_SIZE)
|
||||
hlen = BASIC_H_SIZE;
|
||||
|
||||
/* Never return SHORT header; expand by replacing buffer if necessary */
|
||||
if (msg_short(hdr)) {
|
||||
*skb = tipc_buf_acquire(BASIC_H_SIZE + dlen, GFP_ATOMIC);
|
||||
if (!*skb)
|
||||
goto exit;
|
||||
memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
|
||||
kfree_skb(_skb);
|
||||
_skb = *skb;
|
||||
hdr = buf_msg(_skb);
|
||||
memcpy(hdr, &ohdr, BASIC_H_SIZE);
|
||||
msg_set_hdr_sz(hdr, BASIC_H_SIZE);
|
||||
}
|
||||
/* Allocate new buffer to return */
|
||||
*skb = tipc_buf_acquire(hlen + dlen, GFP_ATOMIC);
|
||||
if (!*skb)
|
||||
goto exit;
|
||||
memcpy((*skb)->data, _skb->data, msg_hdr_sz(_hdr));
|
||||
memcpy((*skb)->data + hlen, msg_data(_hdr), dlen);
|
||||
|
||||
/* Now reverse the concerned fields */
|
||||
/* Build reverse header in new buffer */
|
||||
hdr = buf_msg(*skb);
|
||||
msg_set_hdr_sz(hdr, hlen);
|
||||
msg_set_errcode(hdr, err);
|
||||
msg_set_non_seq(hdr, 0);
|
||||
msg_set_origport(hdr, msg_destport(&ohdr));
|
||||
msg_set_destport(hdr, msg_origport(&ohdr));
|
||||
msg_set_destnode(hdr, msg_prevnode(&ohdr));
|
||||
msg_set_origport(hdr, msg_destport(_hdr));
|
||||
msg_set_destport(hdr, msg_origport(_hdr));
|
||||
msg_set_destnode(hdr, msg_prevnode(_hdr));
|
||||
msg_set_prevnode(hdr, own_node);
|
||||
msg_set_orignode(hdr, own_node);
|
||||
msg_set_size(hdr, msg_hdr_sz(hdr) + dlen);
|
||||
skb_trim(_skb, msg_size(hdr));
|
||||
msg_set_size(hdr, hlen + dlen);
|
||||
skb_orphan(_skb);
|
||||
kfree_skb(_skb);
|
||||
return true;
|
||||
exit:
|
||||
kfree_skb(_skb);
|
||||
|
|
Loading…
Reference in New Issue