Solved libzfs_handle_t

What is it, and why does zfs_create need it?

I have been blankly staring at libzfs_dataset.c, libzfs_core.c, libzfs_util.c and many other files for hours, and could use hints if anybody has any.

As far as I can tell, it is kind of like a *DIR for datasets, but on the other hand they seem to be invoked before any dataset exists, and operations performed on them.

Help?
 
Ok, I think what it basically is is a kind of structure for the different functions that build up a dataset to refer to as they operate, rather than some random name and path or some other less solid thing.

You initialize it, run whatever functions are needed to create the dataset, which will all refer to and modify it, and then finally create the dataset using it. Name is for the user, libzfs_handle_t is for zfs. I will operate under this assumption and report back if anything breaks. If anybody reads this and has any insight to offer, it will be very much appreciated.
 
it looks like an opaque pointer to a structure that holds file handles to /dev/zfs, /etc/zfs/exports and some other stuff
most likely all the userland api talks to the kernel via /dev/zfs ioctls (semi wild guess) so take it like a sort of api handle
 
Here is an interesting piece of code from libzfs_dataset.c:

Code:
zfs_handle_t *
make_dataset_handle(libzfs_handle_t *hdl, const char *path)
{
	zfs_cmd_t zc = {"\0"};

	zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));

	if (zhp == NULL)
		return (NULL);

	zhp->zfs_hdl = hdl;
	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
	zcmd_alloc_dst_nvlist(hdl, &zc, 0);

	if (get_stats_ioctl(zhp, &zc) == -1) {
		zcmd_free_nvlists(&zc);
		free(zhp);
		return (NULL);
	}
	if (make_dataset_handle_common(zhp, &zc) == -1) {
		free(zhp);
		zhp = NULL;
	}
	zcmd_free_nvlists(&zc);
	return (zhp);
}

The zfs_handle_t seems to be a wider structer that incorporates libzfs_handle_t, along with name (which is the path) and presumably other things. That's at least a clue, a zfs_handle seems to be a specific thing that refers to a specific dataset. But what kills me is that it takes libzfs_handle_t as an argument. It expects it to already exist. And, in fact, lzc_create() (from libzfs_core) doesn't even take any handles. It just takes the name. The only reason I am even bothering about the handle is that populate_create_encryption_params_nvlists(), from libzfs_crypto.c, does take it, and you need that function at least to create an encryption for the dataset.

So I can sort of make a zfs_handle_t happen, but I need a libzfs_handle_t for it, and I am not sure if I can just conjure one from thin air and hope it gets populated, or if I need to initialize it somehow as with zfs_handle_t.
 
And to corroborate that it is a kind of interface to the zfs dev, from the function you mentioned in libzfs_utils.c:

Code:
if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR|O_EXCL|O_CLOEXEC)) < 0) {
        free(hdl);
        return (NULL);
    }

And then it initializes a bunch of stuff that I guess is related to it:

Code:
    zfs_prop_init();
    zpool_prop_init();
    zpool_feature_init();
    vdev_prop_init();
    libzfs_mnttab_init(hdl);
    fletcher_4_init();

I guess this is what zfs uses to get information from the zfs dev on how to manipulate certain inputs, and maybe lzc_create() is so simple and straightforward that it has no need to make use of such facilities.

Another possibility is that it just assumes that you would never call it without first having gone through many of the functions that do make use of it.

---

I should probably be embarassed, but I am only now realizing the obvious fact that zfs_main.c has a main(). In it, libzfs_init() is run, so initializing the handle is the first thing to do. It then probably keeps track of every operation until you close everything down and exit. lzc_create() would then interact with it indirectly, by setting values that the handle will refer to after if required.

To the best of my understanding here.
 
Did read it, even wrote the guy, but never got an answer. Possibly because I was a dick about his "zest" name, even though I think the idea is brilliant.

I might give a go at some very basic interface once I'm done my project. I feel the knowledge I've picked up wading through these libraries might allow me to contribute some.

It's all very beautiful code, frankly. To get ZEST going, all one really would have to do is get to the core of each desired operation, strip it of everything, add as needed, and repeat for each new function you feel might be warranted. When I say strip, I don't mean libzfs or libzfs_core or any of the rest of the code, I mean all of it. The useful functionality is there, it is just scattered to the high winds. I'm not angry at it, they had to focus their limited resources and they chose zfs(8). Possibly perhaps I will be able to do something about that in the future.

That article is great, by the way, recommended.
 
Back
Top