The c_mount() function

The last function we'll look at is the one that handles mount requests. Handling a mount request can be fairly tricky (there are lots of options), so we've just stuck with a simple version that does everything we need for the RAM disk.

When the RAM-disk resource manager starts up, there is no mounted RAM disk, so you must use the command-line mount command to mount one:

mount -Tramdisk /dev/ramdisk /ramdisk

The above command creates a RAM disk at the mount point /ramdisk.

The code is:

int
cfs_c_mount (resmgr_context_t *ctp, io_mount_t *msg,
             RESMGR_HANDLE_T *handle, io_mount_extra_t *extra)
{
  char        *mnt_point;
  char        *mnt_type;
  int         ret;
  cfs_attr_t  *cfs_attr;

  // 1) shortcuts
  mnt_point = msg -> connect.path;
  mnt_type = extra -> extra.srv.type;

  // 2) Verify that it is a mount request, not something else
  if (extra -> flags &
     (_MOUNT_ENUMERATE | _MOUNT_UNMOUNT | _MOUNT_REMOUNT)) {
    return (ENOTSUP);
  }

  // 3) decide if we should handle this request or not
  if (!mnt_type || strcmp (mnt_type, "ramdisk")) {
    return (ENOSYS);
  }

  // 4) create a new attributes structure and fill it
  if (!(cfs_attr = malloc (sizeof (*cfs_attr)))) {
    return (ENOMEM);
  }
  iofunc_attr_init (&cfs_attr -> attr, S_IFDIR | 0777,
                    NULL, NULL);

  // 5) initializes extended attribute structure
  cfs_attr_init (cfs_attr);

  // set up the inode
  cfs_attr -> attr.inode = (int) cfs_attr;

  // create "." and ".."
  cfs_a_mknod (cfs_attr, ".", S_IFDIR | 0755, NULL);
  cfs_a_mknod (cfs_attr, "..", S_IFDIR | 0755, NULL);

  // 6) attach the new pathname with the new value
  ret = resmgr_attach (dpp, &resmgr_attr, mnt_point,
                       _FTYPE_ANY, _RESMGR_FLAG_DIR,
                       &connect_func, &io_func,
                       &cfs_attr -> attr);
  if (ret == -1) {
    free (cfs_attr);
    return (errno);
  }

  return (EOK);
}

The code walkthrough is:

  1. We create some shortcuts into the msg and extra fields. The mnt_point indicates where we would like to mount the RAM disk.. mnt_type indicates what kind of resource we are mounting, in this case we expect the string "ramdisk."
  2. We don't support any of the other mounting methods, like enumeration, unmounting, or remounting, so we just fail if we detect them.
  3. We ensure that the type of mount request matches the type of our device (ramdisk).
  4. We create a new attributes structure that represents the root directory of the new RAM disk, and we initialize it.
  5. We also initialize the extended portion of the attributes structure, set up the inode member (see below), and create the . and .. directories.
  6. Finally, we call resmgr_attach() to create the new mount point in the pathname space.

The inode needs to be unique on a per-device basis, so the easiest way of doing that is to give it the address of the attributes structure.