struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
				     unsigned int size,
				     gfp_t gfp_mask)
{
	struct sk_buff *skb;
	u8 *data;

	/* Get the HEAD */
	skb = kmem_cache_alloc(skbuff_head_cache,
			       gfp_mask & ~__GFP_DMA);
	if (!skb)
		goto out;

	/* Get the DATA. */
	size = SKB_DATA_ALIGN(size);
	data = kmem_cache_alloc(cp, gfp_mask);
	if (!data)
		goto nodata;

	memset(skb, 0, offsetof(struct sk_buff, truesize));
	skb->truesize = size + sizeof(struct sk_buff);
	atomic_set(&skb->users, 1);
	skb->head = data;
	skb->data = data;
	skb->tail = data;
	skb->end  = data + size;

	atomic_set(&(skb_shinfo(skb)->dataref), 1);
	skb_shinfo(skb)->nr_frags  = 0;
	skb_shinfo(skb)->tso_size = 0;
	skb_shinfo(skb)->tso_segs = 0;
	skb_shinfo(skb)->frag_list = NULL;
out:
	return skb;
nodata:
	kmem_cache_free(skbuff_head_cache, skb);
	skb = NULL;
	goto out;
}
struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
				     unsigned int size,
				     gfp_t gfp_mask)
{
	struct sk_buff *skb;
	u8 *data;

	 
	skb = kmem_cache_alloc(skbuff_head_cache,
			       gfp_mask & ~__GFP_DMA);
	if (!skb)
		goto out;

	 
	size = SKB_DATA_ALIGN(size);
	data = kmem_cache_alloc(cp, gfp_mask);
	if (!data)
		goto nodata;

	memset(skb, 0, offsetof(struct sk_buff, truesize));
	skb->truesize = size + sizeof(struct sk_buff);
	atomic_set(&skb->users, 1);
	skb->head = data;
	skb->data = data;
	skb->tail = data;
	skb->end  = data + size;

	atomic_set(&(skb_shinfo(skb)->dataref), 1);
	skb_shinfo(skb)->nr_frags  = 0;
	skb_shinfo(skb)->tso_size = 0;
	skb_shinfo(skb)->tso_segs = 0;
	skb_shinfo(skb)->frag_list = NULL;
out:
	return skb;
nodata:
	kmem_cache_free(skbuff_head_cache, skb);
	skb = NULL;
	goto out;
}