The random rantings of a concerned programmer.

Jul 17

Invoking mount(2) in FreeBSD 8.x

Category: Random

So I’m still writing Go bindings for a lot of common FreeBSD functionality. Yesterday I implemented a means to list all mounted filesystems, so today I’m writing the bindings to mount(2) to mount/umount them.

If you look at the man page for mount, you’ll see that the function signature looks like this:

    int mount(const char *type, const char *dir, int flags, void *data);

The void* should scare you.

I haven’t been able to dig up any information about what the fuck should be passed to it (granted, I haven’t looked very hard because, judging from the contents of src/sbin/mount_*/*.c in the FreeBSD sources, it’s been entirely superseded by nmount.

    int nmount(struct iovec *iov, u_int niov, int flags);

Poking around, struct iovec (eventually included from sys/uio.h) is defined as this:

struct iovec {
    void *iov_base;
    size_t iov_len;
}

Effectively, nmount takes an array of these structs which effectively form a flattened vector of (key, value) tuples. As far as I can tell, iov_base is always a NULL-terminated char*, and iov_len should be strlen(iov_base) + 1 (for the NULL terminator).

Unfortunately, the only hints that man 2 nmount gives us is

The following options are required by all file
     systems:
           fstype     file system type name (e.g., ``procfs'')
           fspath     mount point pathname (e.g., ``/proc'')

     Depending on the file system type, other options may be recognized or
     required; for example, most disk-based file systems require a ``from''
     option containing the pathname of a special device in addition to the
     options listed above.

So far, the only way I’ve been able to find the actual options is to dig through mount_* sources and see what they use, but it’s pretty gross. Take, for example, the following two filesystems:

  • nullfs simply layers one vnode on top of another, effectively grafting one directory over another.
  • unionfs (roughly) does the same thing, but still lets you access the grafted-over directory in read-only mode (and can be configured to do cool shit like copy-on-write).

They’re pretty close, but let’s look at the arguments that each of them take:

nullfs
  • fstype: “nullfs”
  • fspath: Path to the directory to graft over.
  • target: Path of the directory that’s being grafted onto another.

IMHO, "target" should be "from", bikesheds, et. al.

unionfs
  • fstype: “unionfs”
  • fspath: Path to the directory where the unionfs will be mounted.
  • from: Same as “target”, above.
  • below: Makes “fspath” writable, “from” read-only (swaps default behavior)
  • errmsg: …I have no fucking idea, a char[255] which presumably is used as a buffer instead of errno?
  • …anything else passed as -oyour=mom passed to mount_unionfs?!

Maybe this is more a gripe that unionfs seems to be very shitty. And maybe I just haven’t found a nice magical table of options that every filesystem takes. But FFFFFF SERIOUSLY >:(


Tagged with: , , , ,
2 comments

2 Comments so far

  1. Anonymous July 22nd, 2011 8:45 am

    Are you using go at work? Or just for personal stuff?

    If at work, why did you go with it? What do you hope to gain from it, compared to plain C?

    ( Also, what happened to that nagios-like python scheduler? )

  2. Taro July 22nd, 2011 10:28 am

    Personal stuff (that I may use at work at some point). Basically writing the hooks into the kernel that I need to expose a web interface for creating/administrating jails (similar to ESX, I guess).

    I could have written it in raw C, but then I’d be dicking around with JSON and HTTP instead (which Go provides out-of-the-box). Also it’s a personal project, so I tend to dick around with weird languages.

    Uhh, the nagios-compatible Python system is running on one of my machines; it’s pretty gritty but it works. When I have some more time to polish it (or do anything with it) I’ll probably rant some more about it.

Leave a comment