+static inline int skb_add_data(struct sk_buff *skb,
+ char __user *from, int copy)
+{
+ const int off = skb->len;
+
+ if (skb->ip_summed == CHECKSUM_NONE) {
+ int err = 0;
+ unsigned int csum = csum_and_copy_from_user(from,
+ skb_put(skb, copy),
+ copy, 0, &err);
+ if (!err) {
+ skb->csum = csum_block_add(skb->csum, csum, off);
+ return 0;
+ }
+ } else if (!copy_from_user(skb_put(skb, copy), from, copy))
+ return 0;
+
+ __skb_trim(skb, off);
+ return -EFAULT;
+}
+
+static inline int skb_can_coalesce(struct sk_buff *skb, int i,
+ struct page *page, int off)
+{
+ if (i) {
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
+
+ return page == frag->page &&
+ off == frag->page_offset + frag->size;
+ }
+ return 0;
+}
+