Mount in the resource manager
int mount( resmgr_context_t *ctp,
io_mount_t *msg,
RESMGR_HANDLE_T *handle,
io_mount_extra_t *extra );
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 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
, orqnx6
. - special
- Null-terminated string containing the special device if it was requested via the _MOUNT_SPEC flag. NULL otherwise.
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.
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 out with ENOENT 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 (unless it returns EOK).
Only errors of ENOSYS or ENOENT cause the
request to fall through
to other resource managers.
When you unmount, you must 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.