I have a specific question regarding using net_device module in linux kernel.
Lets address this code example please.
When i init my device, i call alloc_netdev and provide it with the private data size , so it will properly allocate it.
Now, What happens when i call snull_cleanup when i wish to stop using this device. i see it basically free's the structure (including the private data).
The question is, what if the code currently running is an inside function inside my device module which uses the private data got by cally netdev_priv(), holdes a reference to the private data, and all of the sudden i get a context switch in kernel-space towards the snull_cleanup function - which frees the private data.
Then, when switching context back to the function holding the reference to the private data, wouldnt i get a reference to a freed structure?
I would be glad if you could sort this issue out for me, thanks
My initial thought was that it doesn't make sense: it's your private data so deal with by yourself - you have allocated it, so you have to free it. That's a common pattern for private data - you can see it, for example, in struct bio
. But what I saw was a really dirty hack.
So, I looked at alloc_netdev code and that's what I've found.
You don't allocate your private struct, you can pass size to alloc_netdev
. If you pass size of your private data to alloc_netdev
(first argument), then it will make allocation of size:
ALIGN_OF_32( sizeof(struct net_device) + sizeof(struct snull_private) )
So your private data is inherent part of struct net_device - it's appended after it
Whole struct net_device
you're working with
+-------------------------------+
| +---------------------------+ |
| | | |
| | | |
| | Actual struct net_device | |
| | | |
| | | |
| +---------------------------+ |
| | --> Your private data <-- | |
| +---------------------------+ |
| | Alignment to 32 | |
| +---------------------------+ |
+-------------------------------+
To get private data you use netdev_priv
that just adds size of struct net_device
to pointer thus getting start address of your private data:
static inline void *netdev_priv(const struct net_device *dev)
{
return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN);
}
Freeing device with free_netdev
will deallocate whole structure including private data. Though it will not be done immediately, so you'll be able to access your data some time.
This tricky thing will make working with your struct cache friendly, thus boosting your performance. Looks like this private data assumed to make sense only for lifetime of net_device, so if you want to have some data after destroying net_device you can embed net_device itself into your structure, so your structure will be kind of a wrapper.