* Added missing `flags' parameter for the mount functions.
* fs_mount() and fs_unmount() are now aware of partitions. A device to be mounted is looked up by the DDM and the mount state and mount cookie of the corresponding KPartition are updated accordingly. Still missing is support for mounting files. Moreover the device path needs to be normalized. * Added RecursiveLockAutoLocker class to ease the `goto errN' pain a bit. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9555 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5de8542789
commit
f3604f65e7
@ -13,7 +13,9 @@
|
||||
#include <fs_info.h>
|
||||
#include <fs_interface.h>
|
||||
|
||||
#include <disk_device_manager/KDiskDevice.h>
|
||||
#include <disk_device_manager/KDiskDeviceManager.h>
|
||||
#include <disk_device_manager/KDiskDeviceUtils.h>
|
||||
#include <syscalls.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <vfs.h>
|
||||
@ -91,10 +93,31 @@ struct fs_mount {
|
||||
recursive_lock rlock; // guards the vnodes list
|
||||
struct vnode *root_vnode;
|
||||
struct vnode *covers_vnode;
|
||||
KPartition *partition;
|
||||
struct list vnodes;
|
||||
bool unmounting;
|
||||
};
|
||||
|
||||
// RecursiveLockAutoLocking
|
||||
class RecursiveLockAutoLocking {
|
||||
public:
|
||||
inline bool Lock(recursive_lock *lockable)
|
||||
{
|
||||
recursive_lock_lock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(recursive_lock *lockable)
|
||||
{
|
||||
recursive_lock_unlock(lockable);
|
||||
}
|
||||
};
|
||||
|
||||
// RecursiveLockAutoLocker
|
||||
typedef AutoLocker<recursive_lock, RecursiveLockAutoLocking >
|
||||
RecursiveLockAutoLocker;
|
||||
|
||||
|
||||
static mutex sFileSystemsMutex;
|
||||
|
||||
/** \brief Guards sMountsTable.
|
||||
@ -2033,7 +2056,7 @@ vfs_bootstrap_file_systems(void)
|
||||
status_t status;
|
||||
|
||||
// bootstrap the root filesystem
|
||||
status = _kern_mount("/", NULL, "rootfs", NULL);
|
||||
status = _kern_mount("/", NULL, "rootfs", B_MOUNT_READ_ONLY, NULL);
|
||||
if (status < B_OK)
|
||||
panic("error mounting rootfs!\n");
|
||||
|
||||
@ -2041,19 +2064,19 @@ vfs_bootstrap_file_systems(void)
|
||||
|
||||
// bootstrap the devfs
|
||||
_kern_create_dir(-1, "/dev", 0755);
|
||||
status = _kern_mount("/dev", NULL, "devfs", NULL);
|
||||
status = _kern_mount("/dev", NULL, "devfs", B_MOUNT_READ_ONLY, NULL);
|
||||
if (status < B_OK)
|
||||
panic("error mounting devfs\n");
|
||||
|
||||
// bootstrap the pipefs
|
||||
_kern_create_dir(-1, "/pipe", 0755);
|
||||
status = _kern_mount("/pipe", NULL, "pipefs", NULL);
|
||||
status = _kern_mount("/pipe", NULL, "pipefs", B_MOUNT_READ_ONLY, NULL);
|
||||
if (status < B_OK)
|
||||
panic("error mounting pipefs\n");
|
||||
|
||||
// bootstrap the bootfs (if possible)
|
||||
_kern_create_dir(-1, "/boot", 0755);
|
||||
status = _kern_mount("/boot", NULL, "bootfs", NULL);
|
||||
status = _kern_mount("/boot", NULL, "bootfs", B_MOUNT_READ_ONLY, NULL);
|
||||
if (status < B_OK) {
|
||||
// this is no fatal exception at this point, as we may mount
|
||||
// a real on disk file system later
|
||||
@ -2079,7 +2102,6 @@ vfs_mount_boot_file_system()
|
||||
KDiskDeviceManager::CreateDefault();
|
||||
|
||||
status_t status;
|
||||
#if 0
|
||||
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
||||
|
||||
status = manager->InitialDeviceScan();
|
||||
@ -2092,14 +2114,14 @@ vfs_mount_boot_file_system()
|
||||
}
|
||||
} else
|
||||
dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n", strerror(status));
|
||||
#endif
|
||||
|
||||
file_system_info *bootfs;
|
||||
if ((bootfs = get_file_system("bootfs")) == NULL) {
|
||||
// no bootfs there, yet
|
||||
|
||||
// ToDo: do this for real!
|
||||
status_t status = _kern_mount("/boot", "/dev/disk/scsi/0/0/0/raw", "bfs", NULL);
|
||||
status_t status = _kern_mount("/boot", "/dev/disk/scsi/0/0/0/raw",
|
||||
"bfs", B_MOUNT_READ_ONLY, NULL);
|
||||
if (status < B_OK)
|
||||
panic("could not get boot device: %s!\n", strerror(status));
|
||||
} else
|
||||
@ -3617,7 +3639,8 @@ out:
|
||||
|
||||
|
||||
static status_t
|
||||
fs_mount(char *path, const char *device, const char *fsName, void *args, bool kernel)
|
||||
fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
|
||||
void *args, bool kernel)
|
||||
{
|
||||
struct fs_mount *mount;
|
||||
struct vnode *covered_vnode = NULL;
|
||||
@ -3627,18 +3650,54 @@ fs_mount(char *path, const char *device, const char *fsName, void *args, bool ke
|
||||
FUNCTION(("fs_mount: entry. path = '%s', fs_name = '%s'\n", path, fsName));
|
||||
|
||||
// The path is always safe, we just have to make sure that fsName is
|
||||
// almost valid - we can't make any assumptions about device and args,
|
||||
// though.
|
||||
// almost valid - we can't make any assumptions about args, though.
|
||||
if (fsName == NULL || fsName[0] == '\0')
|
||||
return B_BAD_VALUE;
|
||||
|
||||
recursive_lock_lock(&sMountOpLock);
|
||||
RecursiveLockAutoLocker mountOpLocker(sMountOpLock);
|
||||
|
||||
// If the file system is not a "virtual" one, the device argument should
|
||||
// point to a real file/device (if given at all).
|
||||
// get the partition
|
||||
KDiskDeviceManager* ddm = KDiskDeviceManager::Default();
|
||||
KPartition* partition = NULL;
|
||||
if (!(flags & B_MOUNT_VIRTUAL_DEVICE) && device) {
|
||||
// get a corresponding partition from the DDM
|
||||
partition = ddm->RegisterPartition(device, true);
|
||||
// TODO: Normalize the path!
|
||||
// TODO: Support for mounting images!
|
||||
if (!partition) {
|
||||
PRINT(("fs_mount(): Partition `%s' not found.\n", device));
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
PartitionRegistrar partitionRegistrar(partition, true);
|
||||
|
||||
// Write lock the partition's device. For the time being, we keep the lock
|
||||
// until we're done mounting -- not nice, but ensure, that no-one is
|
||||
// interfering.
|
||||
// TODO: Find a better solution.
|
||||
KDiskDevice* diskDevice = NULL;
|
||||
if (partition) {
|
||||
diskDevice = ddm->WriteLockDevice(partition->Device()->ID());
|
||||
if (!diskDevice) {
|
||||
PRINT(("fs_mount(): Failed to lock disk device!\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
DeviceWriteLocker writeLocker(diskDevice, true);
|
||||
|
||||
// make sure, that the partition is not busy
|
||||
if (partition) {
|
||||
if (partition->IsBusy() || partition->IsDescendantBusy()) {
|
||||
PRINT(("fs_mount(): Partition is busy.\n"));
|
||||
return B_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
mount = (struct fs_mount *)malloc(sizeof(struct fs_mount));
|
||||
if (mount == NULL) {
|
||||
err = B_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
if (mount == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
list_init_etc(&mount->vnodes, offsetof(struct vnode, mount_link));
|
||||
|
||||
@ -3663,6 +3722,7 @@ fs_mount(char *path, const char *device, const char *fsName, void *args, bool ke
|
||||
|
||||
mount->id = sNextMountID++;
|
||||
mount->unmounting = false;
|
||||
mount->partition = NULL;
|
||||
|
||||
mutex_lock(&sMountMutex);
|
||||
|
||||
@ -3733,7 +3793,15 @@ fs_mount(char *path, const char *device, const char *fsName, void *args, bool ke
|
||||
if (!sRoot)
|
||||
sRoot = mount->root_vnode;
|
||||
|
||||
recursive_lock_unlock(&sMountOpLock);
|
||||
// supply the partition (if any) with the mount cookie and mark it mounted
|
||||
if (partition) {
|
||||
partition->SetMountCookie(mount->cookie);
|
||||
partition->AddFlags(B_PARTITION_MOUNTED);
|
||||
|
||||
// keep a partition reference as long as the partition is mounted
|
||||
partitionRegistrar.Detach();
|
||||
mount->partition = partition;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
@ -3755,8 +3823,6 @@ err3:
|
||||
free(mount->fs_name);
|
||||
err1:
|
||||
free(mount);
|
||||
err:
|
||||
recursive_lock_unlock(&sMountOpLock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -3775,7 +3841,7 @@ fs_unmount(char *path, bool kernel)
|
||||
if (err < 0)
|
||||
return ERR_VFS_PATH_NOT_FOUND;
|
||||
|
||||
recursive_lock_lock(&sMountOpLock);
|
||||
RecursiveLockAutoLocker mountOpLocker(sMountOpLock);
|
||||
|
||||
mount = find_mount(vnode->device);
|
||||
if (!mount)
|
||||
@ -3784,8 +3850,29 @@ fs_unmount(char *path, bool kernel)
|
||||
if (mount->root_vnode != vnode) {
|
||||
// not mountpoint
|
||||
put_vnode(vnode);
|
||||
err = ERR_VFS_NOT_MOUNTPOINT;
|
||||
goto err;
|
||||
return ERR_VFS_NOT_MOUNTPOINT;
|
||||
}
|
||||
|
||||
// if the volume is associated with a partition, lock the device of the
|
||||
// partition as long as we are unmounting
|
||||
KDiskDeviceManager* ddm = KDiskDeviceManager::Default();
|
||||
KPartition *partition = mount->partition;
|
||||
KDiskDevice *diskDevice = NULL;
|
||||
if (partition) {
|
||||
diskDevice = ddm->WriteLockDevice(partition->Device()->ID());
|
||||
if (!diskDevice) {
|
||||
PRINT(("fs_unmount(): Failed to lock disk device!\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
DeviceWriteLocker writeLocker(diskDevice, true);
|
||||
|
||||
// make sure, that the partition is not busy
|
||||
if (partition) {
|
||||
if (partition->IsBusy() || partition->IsDescendantBusy()) {
|
||||
PRINT(("fs_unmount(): Partition is busy.\n"));
|
||||
return B_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* grab the vnode master mutex to keep someone from creating
|
||||
@ -3805,8 +3892,7 @@ fs_unmount(char *path, bool kernel)
|
||||
mutex_unlock(&sVnodeMutex);
|
||||
put_vnode(mount->root_vnode);
|
||||
|
||||
err = EBUSY;
|
||||
goto err;
|
||||
return EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3839,7 +3925,7 @@ fs_unmount(char *path, bool kernel)
|
||||
hash_remove(sMountsTable, mount);
|
||||
mutex_unlock(&sMountMutex);
|
||||
|
||||
recursive_lock_unlock(&sMountOpLock);
|
||||
mountOpLocker.Unlock();
|
||||
|
||||
FS_MOUNT_CALL(mount, unmount)(mount->cookie);
|
||||
|
||||
@ -3850,11 +3936,11 @@ fs_unmount(char *path, bool kernel)
|
||||
free(mount->fs_name);
|
||||
free(mount);
|
||||
|
||||
return 0;
|
||||
// dereference the partition
|
||||
if (partition)
|
||||
partition->Unregister();
|
||||
|
||||
err:
|
||||
recursive_lock_unlock(&sMountOpLock);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -4048,12 +4134,13 @@ err:
|
||||
|
||||
|
||||
status_t
|
||||
_kern_mount(const char *path, const char *device, const char *fs_name, void *args)
|
||||
_kern_mount(const char *path, const char *device, const char *fs_name,
|
||||
uint32 flags, void *args)
|
||||
{
|
||||
char pathBuffer[SYS_MAX_PATH_LEN + 1];
|
||||
strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN);
|
||||
|
||||
return fs_mount(pathBuffer, device, fs_name, args, true);
|
||||
return fs_mount(pathBuffer, device, fs_name, flags, args, true);
|
||||
}
|
||||
|
||||
|
||||
@ -4662,7 +4749,8 @@ _kern_setcwd(int fd, const char *path)
|
||||
|
||||
|
||||
status_t
|
||||
_user_mount(const char *upath, const char *udevice, const char *ufs_name, void *args)
|
||||
_user_mount(const char *upath, const char *udevice, const char *ufs_name,
|
||||
uint32 flags, void *args)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
char fs_name[B_OS_NAME_LENGTH + 1];
|
||||
@ -4689,7 +4777,7 @@ _user_mount(const char *upath, const char *udevice, const char *ufs_name, void *
|
||||
} else
|
||||
device[0] = '\0';
|
||||
|
||||
return fs_mount(path, device, fs_name, args, false);
|
||||
return fs_mount(path, device, fs_name, flags, args, false);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user