This is a very general answer—I confess to having not even read that header file. (If you want to ask detailed, code questions about it, Stack Overflow is the right place.)
What you appear to have missed is that data structures are how programs (and even separate parts of the same program) communicate. Each side of that communication needs to understand the data structure, or else the message is unintelligible.
So, for example, the kernel has a definition of
struct stat somewhere, in some header. Your program also has one, from some different header provided by glibc (though likely it's been copied from the kernel one). When you use the
stat syscall to get information on a file, you pass the kernel the address of a
struct stat. The kernel fills in the information in that data structure. Then your program reads out the information. Your program communicated with the kernel using a data structure.
Another example, if you then pass that
struct stat * to another function in your program (say, one responsible for displaying it), then your program has communicated between two parts of itself using a data structure.
So the tree and hash table implementations in libdevmapper, and in general the data structures in any kernel feature library header, are going to serve one (or more) of a few purposes:
- They're how the library communicates with the kernel.
- They're how the library communicates with your program.
- They're something the library's developers think your program will find useful (e.g., to keep track of devmapper state) and they figure it's small enough and/or closely related enough to include without being bloat.