Variable-size structures are helpful, because you can allocate a structure containing an array of an unkown (at compile time) size at the end. For example, a “nuda_conf” structure containing informations about an MD Array and a “dev_info” structure per disks. The number of disks is unknown at compile time, so the only solution is to use a kalloc/vmalloc. The classical solution is to do :
[code lang=”c”]
struct dev_info { int whatever; struct rdev* rdev; } struct nuda_conf { char* name; int whotever; struct dev_info disks* } ... struct nuda_conf* conf; conf = kzalloc(sizeof(struct nuda_conf)); conf->disks = kzalloc(sizeof(struct dev_info) * NUMER_OF_DISKS);
[/code]
But variable-size structures allows to do only one allocation :
[code lang=”c”]
struct nuda_conf { char* name; int whotever; struct dev_info disks[0]; } struct nuda_conf* conf; conf = kzalloc(sizeof(struct nuda_conf) + sizeof(struct dev_info) * NUMBER_OF_DISKS);
[/code]
This will allocate the memory for the char* and the int of nuda_conf, and the memory for a number of “dev_info”. To access them, one can do conf->disks[N] where N is the disk index.
But, this is limited to one variable-size array. If you do :
[code lang=”c”]
struct nuda_conf { char* name; int whotever; struct dev_info disks[0]; struct indirection_line indirection_table[0]; }
[/code]
The “indirection_table” and the “disks” pointer will point to the same location ! Even if you allocate size for both ! The solution is either to use a classical pointer as in the first example, or handle the memory access yourself :
[code lang=”c”]
struct nuda_conf { char* name; int whotever; } ... conf = kzalloc (sizeof(struct nuda_conf) + sizeof(struct dev_info) * NUMBER_OF_DISKS + sizeof(struct indirection_line)*NUMBER_OF_CHUNKS); struct dev_info* disks = (struct dev_info*)(conf + 1); struct indirection_line* indirection_table = (struct dev_info*)(disks + NUMBER_OF_DISKS);
[/code]
But there is no interest in doing so, and both disks and indirection_table pointers have to be manually computed each time you need them… The use for that is really really really specific (dynamic metadata in packets for example).