diff options
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index e525f8c..ced60e2 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -73,13 +73,13 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, * Returns message data size or errno */ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, - unsigned int len, int max_size, struct sk_buff **buf) + u32 num_sect, unsigned int total_len, int max_size, + struct sk_buff **buf) { - int dsz, sz, hsz; - unsigned char *to; + int dsz, sz, hsz, pos, res, cnt; - dsz = len; - hsz = msg_hdr_sz(hdr); + dsz = total_len; + pos = hsz = msg_hdr_sz(hdr); sz = hsz + dsz; msg_set_size(hdr, sz); if (unlikely(sz > max_size)) { @@ -91,11 +91,16 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, if (!(*buf)) return -ENOMEM; skb_copy_to_linear_data(*buf, hdr, hsz); - to = (*buf)->data + hsz; - if (len && memcpy_fromiovecend(to, msg_sect, 0, dsz)) { - kfree_skb(*buf); - *buf = NULL; - return -EFAULT; + for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { + skb_copy_to_linear_data_offset(*buf, pos, + msg_sect[cnt].iov_base, + msg_sect[cnt].iov_len); + pos += msg_sect[cnt].iov_len; } - return dsz; + if (likely(res)) + return dsz; + + kfree_skb(*buf); + *buf = NULL; + return -EFAULT; } |