www.pudn.com > efs.rar > fs_mount.c
/***********************************************************************
* fs_mount.c
*
* EFS2 mountpoint handling.
* Copyright (C) 2005, 2006 QUALCOMM, Inc.
*
* Implements handling generally for all mountpoints.
*
***********************************************************************/
/*===========================================================================
EDIT HISTORY FOR MODULE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header: //depot/asic/MSMSHARED/services/efs/MSM_EFS.01.02/fs_mount.c#6 $ $DateTime: 2006/06/08 10:00:24 $ $Author: davidb $
when who what, where, why
---------- --- ---------------------------------------------------------
2006-06-07 sh Aegis requires me to touch this file. No change.
2006-06-02 dlb Fix partial mount on mount error.
2006-05-10 dlb Track mountpoint generations.
2006-03-29 nrs Check for null function pointers in unmount
2006-02-16 dlb Add mountpoint debugging.
2005-08-03 dlb Add umount support, properly.
2005-07-13 dlb Create
===========================================================================*/
#include "msg.h"
#include "fs_err.h"
#include "fs_mount.h"
struct fs_mount *fs_root_mpoint;
fs_dev_t fs_root_dev;
struct fs_vnode *fs_root_vnode;
struct fs_mpoint fs_mpoints[FS_MAX_MOUNTS];
static int mtable_count = 0;
#ifdef FS_DEBUG_MOUNTS
#include "fs_rmtefs.h"
static void
fs_dump_mpoint_table (void)
{
unsigned i;
printf ("%s Mountpoint table\n", MSG_RPC_END);
printf (" ind dev ino rdv rin kind\n");
printf (" --- --- --- --- --- ----\n");
for (i = 0; i < FS_MAX_MOUNTS; i++) {
if (fs_mpoints[i].dev != FS_INVALID_DEV) {
printf (" [%2u] %3u %3u %3u %3u %s",
i,
fs_mpoints[i].dev,
fs_mpoints[i].inode,
fs_mpoints[i].root_node->dev,
fs_mpoints[i].root_node->inum,
fs_mpoints[i].fstype);
if (strcmp (fs_mpoints[i].fstype, "rmtefs") == 0) {
printf (" remote_dev=%d",
((struct fs_mount_rmtefs *)fs_mpoints[i].mp)->remote_dev);
}
printf ("\n");
}
}
}
#else
#define fs_dump_mpoint_table() (void) 0
#endif /* FS_DEBUG_MOUNTS */
void
fs_mount_init (void)
{
int i;
/* Clean out the mountpoint table. */
for (i = 0; i < FS_MAX_MOUNTS; i++) {
fs_mpoints[i].mount_at_dev = FS_INVALID_DEV;
fs_mpoints[i].root_node = NULL;
fs_mpoints[i].fstype = NULL;
fs_mpoints[i].mp = NULL;
}
mtable_count = 0;
}
void
fs_mount_register (const char *fstype, fs_mount_t mp)
{
if (mtable_count >= FS_MAX_MOUNTS) {
FS_ERR_FATAL ("To many internal FS types, edit FS_MAX_MOUNTS", 0, 0, 0);
}
fs_mpoints[mtable_count].fstype = fstype;
fs_mpoints[mtable_count].mp = mp;
/* XXX: If opposite ends of the remote API can be rebooted
* independently, then this needs to be set to something random. */
fs_mpoints[mtable_count].mp->mount_generation = 1;
mtable_count++;
}
static int
fs_mount_common (const char *fstype, const char *arg,
struct fs_mpoint **mpoint)
{
int i;
int found_kind = 0;
int result = 0;
for (i = 0; i < mtable_count; i++) {
if (strcmp (fstype, fs_mpoints[i].fstype) == 0) {
found_kind = 1;
if (fs_mpoints[i].root_node == NULL)
break;
}
}
if (i == mtable_count) {
if (found_kind) {
MSG_HIGH ("mountpoint table full", 0, 0, 0);
result = -EMFILE;
} else {
MSG_HIGH ("Invalid filesystem type", 0, 0, 0);
result = -ENODEV;
}
}
if (result == 0) {
/* The device number doesn't have that much meaning here, but it does
* need to be unique. Using the table index gives us the uniqueness.
* Some mpoints may require that the dev be initialized before calling
* their 'start'. */
fs_mpoints[i].mp->dev = i;
result = fs_mpoints[i].mp->ops->start (fs_mpoints[i].mp, arg);
}
if (result == 0) {
result = fs_mpoints[i].mp->ops->get_root (fs_mpoints[i].mp,
&fs_mpoints[i].root_node);
/* The root should always be available. If this doesn't work, the
* mountpoint is in error. */
if (result != 0)
FS_ERR_FATAL ("Unable to get root of file filesystem", 0, 0, 0);
}
if (result == 0) {
*mpoint = &fs_mpoints[i];
fs_mpoints[i].mp->mount_generation++;
}
return result;
}
int
fs_mount_root (const char *fstype, const char *arg)
{
int result;
struct fs_mpoint *mpoint;
result = fs_mount_common (fstype, arg, &mpoint);
if (result == 0) {
#ifdef FS_DEBUG_MOUNTS
MSG_HIGH ("root mount: %s, dev=%d, inum=%d",
fstype, mpoint->dev, mpoint->root_node->inum);
#endif
fs_root_mpoint = mpoint->mp;
fs_root_dev = mpoint->mp->dev;
fs_root_vnode = mpoint->root_node;
}
fs_dump_mpoint_table ();
return result;
}
int
fs_mount_mount (struct fs_vnode *mount_at, const char *fstype, const char *arg)
{
int result;
struct fs_mpoint *mpoint;
result = fs_mount_common (fstype, arg, &mpoint);
if (result == 0) {
#ifdef FS_DEBUG_MOUNTS
MSG_HIGH ("sub mount: %s, dev=%d, inum=%d",
fstype, mount_at->dev, mount_at->inum);
MSG_HIGH (" sub dev=%d, inum=%d",
mpoint->root_node->dev, mpoint->root_node->inum, 0);
#endif
mpoint->mount_at_dev = mount_at->dev;
mpoint->mount_at_inode = mount_at->inum;
}
fs_dump_mpoint_table ();
return result;
}
int
fs_mount_umount (struct fs_vnode *mpoint)
{
int result = 0;
int i;
for (i = 0; i < FS_MAX_MOUNTS; i++) {
if (fs_mpoints[i].root_node == mpoint)
break;
}
if (i == FS_MAX_MOUNTS) {
MSG_MED ("Attempt to umount non-mountpoint", 0, 0, 0);
return -EINVAL;
}
if (i == 0) {
MSG_MED ("Attempt to umount root", 0, 0, 0);
return -EINVAL;
}
/* Call the FS specific umount code. */
/* Check to make sure the function pointer actually exists */
if (fs_mpoints[i].mp->ops->stop != NULL)
result = fs_mpoints[i].mp->ops->stop (fs_mpoints[i].mp);
if (result == 0) {
fs_vnode_unref (fs_mpoints[i].root_node);
/* The higher level common code will clean up all open descriptors on
* this mountpoint, we just have to clean the mountpoint itself up. */
fs_mpoints[i].mount_at_dev = FS_INVALID_DEV;
fs_mpoints[i].root_node = NULL;
}
return result;
}
int
fs_mount_remount (struct fs_vnode *oldvp, struct fs_vnode *newvp)
{
int i;
for (i = 0; i < FS_MAX_MOUNTS; i++) {
if (fs_mpoints[i].root_node == oldvp)
break;
}
if (i == FS_MAX_MOUNTS) {
MSG_MED ("Attempt to remount non-mountpoint", 0, 0, 0);
return -EINVAL;
}
if (i == 0) {
MSG_MED ("Attempt to remount root", 0, 0, 0);
return -EINVAL;
}
/* Replace where the mountpoint occurs, future namei scans will find this
* mountpoint at the new location. */
fs_mpoints[i].mount_at_dev = newvp->dev;
fs_mpoints[i].mount_at_inode = newvp->inum;
return 0;
}