Moved vfs_bootstrap_file_systems() and vfs_mount_boot_file_system() out of vfs.cpp
and into its own file vfs_boot.cpp. Added basic support for booting from CD - it doesn't give CDs a higher priority, so you could end up booting from HD when you didn't explicetly select "CD-ROM" in the boot loader. Eventually, it should only boot from HD in this case, if booting from CD failed (because of a missing boot partition or whatever). fs_mount(), _kern_mount(), and _user_mount() will now return the dev_t of the mounted device, and not just B_OK. Maybe we should have fs_unmount() work on a dev_t instead of a path as well... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14403 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -115,7 +115,7 @@ extern status_t _kern_get_image_info(image_id id, image_info *info, size_t size
|
||||
extern status_t _kern_get_next_image_info(team_id team, int32 *cookie, image_info *info, size_t size);
|
||||
|
||||
// VFS functions
|
||||
extern status_t _kern_mount(const char *path, const char *device,
|
||||
extern dev_t _kern_mount(const char *path, const char *device,
|
||||
const char *fs_name, uint32 flags, const char *args);
|
||||
extern status_t _kern_unmount(const char *path, uint32 flags);
|
||||
extern status_t _kern_read_fs_info(dev_t device, struct fs_info *info);
|
||||
|
||||
@@ -104,7 +104,7 @@ status_t resolve_mount_point_to_volume_root(mount_id mountID, vnode_id nodeID,
|
||||
mount_id *resolvedMountID, vnode_id *resolvedNodeID);
|
||||
|
||||
/* calls the syscall dispatcher should use for user file I/O */
|
||||
status_t _user_mount(const char *path, const char *device, const char *fs_name,
|
||||
dev_t _user_mount(const char *path, const char *device, const char *fs_name,
|
||||
uint32 flags, const char *args);
|
||||
status_t _user_unmount(const char *path, uint32 flags);
|
||||
status_t _user_read_fs_info(dev_t device, struct fs_info *info);
|
||||
|
||||
@@ -12,6 +12,7 @@ KernelMergeObject kernel_fs.o :
|
||||
pipefs.cpp
|
||||
fd.c
|
||||
vfs.cpp
|
||||
vfs_boot.cpp
|
||||
vfs_select.cpp
|
||||
message.c
|
||||
node_monitor.cpp
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <disk_device_manager/KDiskDevice.h>
|
||||
#include <disk_device_manager/KDiskDeviceManager.h>
|
||||
#include <disk_device_manager/KDiskDeviceUtils.h>
|
||||
#include <disk_device_manager/KPartitionVisitor.h>
|
||||
#include <disk_device_manager/KDiskSystem.h>
|
||||
#include <KPath.h>
|
||||
#include <syscalls.h>
|
||||
@@ -62,18 +61,6 @@ const static uint32 kMaxUnusedVnodes = 8192;
|
||||
// It may be chosen with respect to the available memory or enhanced
|
||||
// by some timestamp/frequency heurism.
|
||||
|
||||
static struct {
|
||||
const char *path;
|
||||
const char *target;
|
||||
} sPredefinedLinks[] = {
|
||||
{"/system", "/boot/beos/system"},
|
||||
{"/bin", "/boot/beos/bin"},
|
||||
{"/etc", "/boot/beos/etc"},
|
||||
{"/var", "/boot/var"},
|
||||
{"/tmp", "/boot/var/tmp"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
struct vnode {
|
||||
struct vnode *next;
|
||||
vm_cache_ref *cache;
|
||||
@@ -178,10 +165,6 @@ static mount_id sNextMountID = 1;
|
||||
|
||||
mode_t __gUmask = 022;
|
||||
|
||||
// This can be used by other code to see if there is a boot file system already
|
||||
dev_t gBootDevice = -1;
|
||||
|
||||
|
||||
/* function declarations */
|
||||
|
||||
// file descriptor operation prototypes
|
||||
@@ -3074,123 +3057,6 @@ vfs_setrlimit(int resource, const struct rlimit * rlp)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vfs_bootstrap_file_systems(void)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
// bootstrap the root filesystem
|
||||
status = _kern_mount("/", NULL, "rootfs", 0, NULL);
|
||||
if (status < B_OK)
|
||||
panic("error mounting rootfs!\n");
|
||||
|
||||
_kern_setcwd(-1, "/");
|
||||
|
||||
// bootstrap the devfs
|
||||
_kern_create_dir(-1, "/dev", 0755);
|
||||
status = _kern_mount("/dev", NULL, "devfs", 0, 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", 0, 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", 0, NULL);
|
||||
if (status < B_OK) {
|
||||
// this is no fatal exception at this point, as we may mount
|
||||
// a real on disk file system later
|
||||
dprintf("Can't mount bootfs (will try disk file system later)\n");
|
||||
}
|
||||
|
||||
// create some standard links on the rootfs
|
||||
|
||||
for (int32 i = 0; sPredefinedLinks[i].path != NULL; i++) {
|
||||
_kern_create_symlink(-1, sPredefinedLinks[i].path,
|
||||
sPredefinedLinks[i].target, 0);
|
||||
// we don't care if it will succeed or not
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vfs_mount_boot_file_system(kernel_args *args)
|
||||
{
|
||||
// make the boot partition (and probably others) available
|
||||
KDiskDeviceManager::CreateDefault();
|
||||
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
||||
|
||||
status_t status = manager->InitialDeviceScan();
|
||||
if (status == B_OK) {
|
||||
// ToDo: do this for real... (no hacks allowed :))
|
||||
for (;;) {
|
||||
snooze(500000);
|
||||
if (manager->CountJobs() == 0)
|
||||
break;
|
||||
}
|
||||
} else
|
||||
dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n", strerror(status));
|
||||
|
||||
file_system_module_info *bootfs;
|
||||
if ((bootfs = get_file_system("bootfs")) == NULL) {
|
||||
// no bootfs there, yet
|
||||
|
||||
// ToDo: do this for real! It will currently only use the partition offset;
|
||||
// it does not yet use the disk_identifier information.
|
||||
|
||||
KPartition *bootPartition = NULL;
|
||||
|
||||
struct BootPartitionVisitor : KPartitionVisitor {
|
||||
BootPartitionVisitor(off_t offset) : fOffset(offset) {}
|
||||
|
||||
virtual bool VisitPre(KPartition *partition)
|
||||
{
|
||||
return (partition->ContainsFileSystem()
|
||||
&& partition->Offset() == fOffset);
|
||||
}
|
||||
private:
|
||||
off_t fOffset;
|
||||
} visitor(args->boot_disk.partition_offset);
|
||||
|
||||
KDiskDevice *device;
|
||||
int32 cookie = 0;
|
||||
while ((device = manager->NextDevice(&cookie)) != NULL) {
|
||||
bootPartition = device->VisitEachDescendant(&visitor);
|
||||
if (bootPartition)
|
||||
break;
|
||||
}
|
||||
|
||||
KPath path;
|
||||
if (bootPartition == NULL
|
||||
|| bootPartition->GetPath(&path) != B_OK
|
||||
|| _kern_mount("/boot", path.Path(), "bfs", 0, NULL) < B_OK)
|
||||
panic("could not get boot device!\n");
|
||||
} else
|
||||
put_file_system(bootfs);
|
||||
|
||||
gBootDevice = sNextMountID - 1;
|
||||
|
||||
// create link for the name of the boot device
|
||||
|
||||
fs_info info;
|
||||
if (_kern_read_fs_info(gBootDevice, &info) == B_OK) {
|
||||
char path[B_FILE_NAME_LENGTH + 1];
|
||||
snprintf(path, sizeof(path), "/%s", info.volume_name);
|
||||
|
||||
_kern_create_symlink(-1, path, "/boot", 0);
|
||||
}
|
||||
|
||||
file_cache_init_post_boot_device();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vfs_init(kernel_args *args)
|
||||
{
|
||||
@@ -4891,7 +4757,7 @@ query_rewind(struct file_descriptor *descriptor)
|
||||
// General File System functions
|
||||
|
||||
|
||||
static status_t
|
||||
static dev_t
|
||||
fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
|
||||
const char *args, bool kernel)
|
||||
{
|
||||
@@ -5121,7 +4987,7 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
|
||||
fileDeviceDeleter.id = -1;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
return mount->id;
|
||||
|
||||
err7:
|
||||
FS_MOUNT_CALL(mount, unmount)(mount->cookie);
|
||||
@@ -5446,7 +5312,7 @@ err:
|
||||
// Calls from within the kernel
|
||||
|
||||
|
||||
status_t
|
||||
dev_t
|
||||
_kern_mount(const char *path, const char *device, const char *fsName,
|
||||
uint32 flags, const char *args)
|
||||
{
|
||||
@@ -6076,7 +5942,7 @@ _kern_setcwd(int fd, const char *path)
|
||||
// Calls from userland (with extra address checks)
|
||||
|
||||
|
||||
status_t
|
||||
dev_t
|
||||
_user_mount(const char *userPath, const char *userDevice, const char *userFileSystem,
|
||||
uint32 flags, const char *userArgs)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <fs_info.h>
|
||||
|
||||
#include <disk_device_manager/KDiskDevice.h>
|
||||
#include <disk_device_manager/KDiskDeviceManager.h>
|
||||
#include <disk_device_manager/KPartitionVisitor.h>
|
||||
#include <DiskDeviceTypes.h>
|
||||
|
||||
#include <vfs.h>
|
||||
#include <file_cache.h>
|
||||
#include <KPath.h>
|
||||
#include <syscalls.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <util/Stack.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
//#define TRACE_VFS
|
||||
#ifdef TRACE_VFS
|
||||
# define PRINT(x) dprintf x
|
||||
# define FUNCTION(x) dprintf x
|
||||
#else
|
||||
# define PRINT(x) ;
|
||||
# define FUNCTION(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
typedef Stack<KPartition *> PartitionStack;
|
||||
|
||||
static struct {
|
||||
const char *path;
|
||||
const char *target;
|
||||
} sPredefinedLinks[] = {
|
||||
{"/system", "/boot/beos/system"},
|
||||
{"/bin", "/boot/beos/bin"},
|
||||
{"/etc", "/boot/beos/etc"},
|
||||
{"/var", "/boot/var"},
|
||||
{"/tmp", "/boot/var/tmp"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
// This can be used by other code to see if there is a boot file system already
|
||||
dev_t gBootDevice = -1;
|
||||
|
||||
|
||||
static status_t
|
||||
get_boot_partitions(kernel_args *args, PartitionStack &partitions)
|
||||
{
|
||||
// make the boot partition (and probably others) available
|
||||
KDiskDeviceManager::CreateDefault();
|
||||
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
||||
|
||||
status_t status = manager->InitialDeviceScan();
|
||||
if (status == B_OK) {
|
||||
// ToDo: do this for real... (no hacks allowed :))
|
||||
for (;;) {
|
||||
snooze(500000);
|
||||
if (manager->CountJobs() == 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n", strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
// ToDo: do this for real! It will currently only use the partition offset;
|
||||
// it does not yet use the disk_identifier information.
|
||||
|
||||
struct BootPartitionVisitor : KPartitionVisitor {
|
||||
BootPartitionVisitor(kernel_args &args, PartitionStack &stack)
|
||||
: fArgs(args), fPartitions(stack) {}
|
||||
|
||||
virtual bool VisitPre(KPartition *partition)
|
||||
{
|
||||
if (!partition->ContainsFileSystem())
|
||||
return false;
|
||||
|
||||
if (!fArgs.boot_disk.booted_from_image) {
|
||||
// the simple case: we can just boot from the selected boot device
|
||||
if (partition->Offset() == fArgs.boot_disk.partition_offset) {
|
||||
fPartitions.Push(partition);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// for now, we will just collect all BFS volumes
|
||||
if (fArgs.boot_disk.cd && fArgs.boot_disk.user_selected
|
||||
&& partition->Type() != NULL
|
||||
&& strcmp(partition->Type(), kPartitionTypeDataSession))
|
||||
return false;
|
||||
|
||||
if (partition->ContentType() != NULL
|
||||
&& !strcmp(partition->ContentType(), "Be File System"))
|
||||
fPartitions.Push(partition);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
kernel_args &fArgs;
|
||||
PartitionStack &fPartitions;
|
||||
} visitor(*args, partitions);
|
||||
|
||||
KDiskDevice *device;
|
||||
int32 cookie = 0;
|
||||
while ((device = manager->NextDevice(&cookie)) != NULL) {
|
||||
if (device->VisitEachDescendant(&visitor) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
// ToDo: sort partition list (ie. when booting from CD, CDs should come first in the list)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
vfs_bootstrap_file_systems(void)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
// bootstrap the root filesystem
|
||||
status = _kern_mount("/", NULL, "rootfs", 0, NULL);
|
||||
if (status < B_OK)
|
||||
panic("error mounting rootfs!\n");
|
||||
|
||||
_kern_setcwd(-1, "/");
|
||||
|
||||
// bootstrap the devfs
|
||||
_kern_create_dir(-1, "/dev", 0755);
|
||||
status = _kern_mount("/dev", NULL, "devfs", 0, 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", 0, 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", 0, NULL);
|
||||
if (status < B_OK) {
|
||||
// this is no fatal exception at this point, as we may mount
|
||||
// a real on disk file system later
|
||||
dprintf("Can't mount bootfs (will try disk file system later)\n");
|
||||
}
|
||||
|
||||
// create some standard links on the rootfs
|
||||
|
||||
for (int32 i = 0; sPredefinedLinks[i].path != NULL; i++) {
|
||||
_kern_create_symlink(-1, sPredefinedLinks[i].path,
|
||||
sPredefinedLinks[i].target, 0);
|
||||
// we don't care if it will succeed or not
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vfs_mount_boot_file_system(kernel_args *args)
|
||||
{
|
||||
PartitionStack partitions;
|
||||
status_t status = get_boot_partitions(args, partitions);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
KPartition *bootPartition;
|
||||
while (partitions.Pop(&bootPartition)) {
|
||||
KPath path;
|
||||
if (bootPartition->GetPath(&path) != B_OK)
|
||||
panic("could not get boot device!\n");
|
||||
|
||||
gBootDevice = _kern_mount("/boot", path.Path(), NULL, 0, NULL);
|
||||
if (gBootDevice >= B_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gBootDevice < B_OK)
|
||||
panic("could not mount boot device!\n");
|
||||
|
||||
// create link for the name of the boot device
|
||||
|
||||
fs_info info;
|
||||
if (_kern_read_fs_info(gBootDevice, &info) == B_OK) {
|
||||
char path[B_FILE_NAME_LENGTH + 1];
|
||||
snprintf(path, sizeof(path), "/%s", info.volume_name);
|
||||
|
||||
_kern_create_symlink(-1, path, "/boot", 0);
|
||||
}
|
||||
|
||||
file_cache_init_post_boot_device();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user