Mount in the resource manager

Your resource manager will be called upon to perform a mount request via the mount function callout in the resmgr_connect_funcs_t structure, defined as:

int mount( resmgr_context_t *ctp,
           io_mount_t *msg,
           RESMGR_HANDLE_T *handle,
           io_mount_extra_t *extra);

The only field here that differs from the other connect functions is the io_mount_extra_t structure. It's defined in <sys/iomsg.h> as:

typedef struct _io_mount_extra {
    uint32_t flags; /* _MOUNT_? or ST_? flags above */
    uint32_t nbytes; /* Size of entire structure */
    uint32_t datalen; /* Length of the data structure following */
    uint32_t zero[1];

    union { /* If EXTRA_MOUNT_PATHNAME these set*/
        struct { /* Sent from client to resmgr framework */
            struct _msg_info32 info; /* Special info on first mount,
                                        path info on remount */

        } cl;

        struct { /* Server receives this structure filled in */
            void * ocb; /* OCB to the special device */
            void * data; /* Server specific data of len datalen */
            char * type; /* Character string with type information */
            char * special; /* Optional special device info */
            void * zero[4]; /* Padding */
        } srv;
    } extra;
} io_mount_extra_t;

This structure is provided with all of the pointers already resolved, so you can use it without doing any extra fiddling.

The members are:

flags
Flag fields provided to the mount command containing the common mount flags defined in <sys/mount.h>.
nbytes
Size of the entire mount-extra message:
sizeof(_io_mount_extra) + datalen + strlen(type)
+ 1 + strlen(special) + 1
  
datalen
Size of the data pointer.
info
Used by the resource manager layer.
ocb
OCB of the special device if it was requested via the _MOUNT_OCB flag. NULL otherwise.
data
Pointer to the user data of length datalen.
type
Null-terminated string containing the mount type, such as nfs, cifs, or qnx6.
special
Null-terminated string containing the special device if it was requested via the _MOUNT_SPEC flag. NULL otherwise.

In order to receive mount requests, the resource manager should register a NULL path with an FTYPE of _FTYPE_MOUNT and with the flags _RESMGR_FLAG_FTYPEONLY. This would be done with code that looks something like:

mntid = resmgr_attach(
           dpp, /* Dispatch pointer */
           &resmgr_attr, /* Dispatch attributes */
           NULL, /* Attach at "/" */

           /* We are a directory and want only matching ftypes */

           _FTYPE_MOUNT,
           _RESMGR_FLAG_DIR | _RESMGR_FLAG_FTYPEONLY,
           mount_connect, /* Only mount filled in */
           NULL, /* No io handlers */
           & handle); /* Handle to pass to mount callout */

Again, we're attaching at the root of the filesystem so that we'll be able to receive the full path of the new mount requests in the msg->connect structure.

Adding the _RESMGR_FLAG_FTYPEONLY flag ensures that this request is used only when there's an _FTYPE_MOUNT-style of connection. Once this is done, the resource manager is ready to start receiving mount requests from users.

An outline of a sample mount handler would look something like this:

int io_mount( ... ) {

   Do any sanity checks that you need to do.

   Check type against our type with strcmp(), since
   there may be no name for REMOUNT/UNMOUNT flags.

   Error with ENOENT out if no match.

   If no name, check the validity of the REMOUNT/UNMOUNT request.

   Parse arguments or set up your data structure.

   Check to see if we are remounting (_MOUNT_REMOUNT)

      Change flags, etc., if you can remount.
      Return EOK.

   Check to see if we are unmounting _MOUNT_UNMOUNT

      Change flags, etc., if you can unmount.
      Return EOK.

   Create a new node and attach it at the msg->connect.path
   point (unless some other path is implied based on the
   input variables and the resource manager) with resmgr_attach().

   Return EOK.
}

What's important to notice here is that each resource manager that registers a mount handler will potentially get a chance to examine the request to see if it can handle it. This means that you have to be rigorous in your type- and error-checking to make sure that the request is indeed destined for your manager. If your manager returns anything other than ENOSYS or ENOENT, it's assumed that the request was valid for this manager, but there was some other sort of error. Only errors of ENOSYS or ENOENT cause the request to “fall through” to other resource managers.

When you unmount, you would perform any cleanup and integrity checks that you need, and then call resmgr_detach() with the ctp->id field. In general, you should support umounted calls only on the root of a mounted filesystem.