* BFS now always writes back the whole block when it writes the super block.
* Therefore, I've added an I/O control that let's it update the boot block part of this block, so that makebootable can use it on a mounted volume (this will probably be moved into a disk system API later). * Added user_memcpy() to the fs_shell. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23082 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
477d25de35
commit
21885de266
@ -932,9 +932,11 @@
|
||||
// #pragma mark - fssh_kernel_export.h
|
||||
|
||||
/* kernel threads */
|
||||
|
||||
#define spawn_kernel_thread fssh_spawn_kernel_thread
|
||||
|
||||
/* misc */
|
||||
#define user_memcpy fssh_user_memcpy
|
||||
|
||||
/* primitive kernel debugging facilities */
|
||||
#define dprintf fssh_dprintf
|
||||
#define kprintf fssh_kprintf
|
||||
|
@ -10,15 +10,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* kernel threads */
|
||||
|
||||
extern fssh_thread_id fssh_spawn_kernel_thread(fssh_thread_func function,
|
||||
const char *threadName, int32_t priority,
|
||||
void *arg);
|
||||
|
||||
/* misc */
|
||||
|
||||
extern fssh_status_t fssh_user_memcpy(void *dest, const void *source,
|
||||
fssh_size_t length);
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/* primitive kernel debugging facilities */
|
||||
|
||||
extern void fssh_dprintf(const char *format, ...) /* just like printf */
|
||||
|
@ -78,13 +78,13 @@ DeviceOpener::~DeviceOpener()
|
||||
int
|
||||
DeviceOpener::Open(const char *device, int mode)
|
||||
{
|
||||
fDevice = open(device, mode);
|
||||
fDevice = open(device, mode | O_NOCACHE);
|
||||
if (fDevice < 0)
|
||||
fDevice = errno;
|
||||
|
||||
if (fDevice < 0 && mode == O_RDWR) {
|
||||
// try again to open read-only (don't rely on a specific error code)
|
||||
return Open(device, O_RDONLY);
|
||||
return Open(device, O_RDONLY | O_NOCACHE);
|
||||
}
|
||||
|
||||
if (fDevice >= 0) {
|
||||
@ -97,7 +97,7 @@ DeviceOpener::Open(const char *device, int mode)
|
||||
if (geometry.read_only) {
|
||||
// reopen device read-only
|
||||
close(fDevice);
|
||||
return Open(device, O_RDONLY);
|
||||
return Open(device, O_RDONLY | O_NOCACHE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -203,7 +203,8 @@ disk_super_block::IsValid()
|
||||
|
||||
|
||||
void
|
||||
disk_super_block::Initialize(const char *diskName, off_t numBlocks, uint32 blockSize)
|
||||
disk_super_block::Initialize(const char *diskName, off_t numBlocks,
|
||||
uint32 blockSize)
|
||||
{
|
||||
memset(this, 0, sizeof(disk_super_block));
|
||||
|
||||
@ -312,7 +313,8 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
||||
flags |= B_MOUNT_READ_ONLY;
|
||||
#endif
|
||||
|
||||
DeviceOpener opener(deviceName, flags & B_MOUNT_READ_ONLY ? O_RDONLY : O_RDWR);
|
||||
DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
|
||||
? O_RDONLY : O_RDWR);
|
||||
fDevice = opener.Device();
|
||||
if (fDevice < B_OK)
|
||||
RETURN_ERROR(fDevice);
|
||||
@ -326,21 +328,6 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
||||
if (fstat(fDevice, &stat) < 0)
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
// TODO: allow turning off caching of the underlying file (once O_NOCACHE works)
|
||||
#if 0
|
||||
#ifndef NO_FILE_UNCACHED_IO
|
||||
if ((stat.st_mode & S_FILE) != 0 && ioctl(fDevice, IOCTL_FILE_UNCACHED_IO, NULL) < 0) {
|
||||
// mount read-only if the cache couldn't be disabled
|
||||
# ifdef DEBUG
|
||||
FATAL(("couldn't disable cache for image file - system may dead-lock!\n"));
|
||||
# else
|
||||
FATAL(("couldn't disable cache for image file!\n"));
|
||||
Panic();
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// read the super block
|
||||
if (Identify(fDevice, &fSuperBlock) != B_OK) {
|
||||
FATAL(("invalid super block!\n"));
|
||||
@ -383,11 +370,6 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
||||
if (status == B_OK) {
|
||||
// try to get indices root dir
|
||||
|
||||
// question: why doesn't get_vnode() work here??
|
||||
// answer: we have not yet backpropagated the pointer to the
|
||||
// volume in bfs_mount(), so bfs_read_vnode() can't get it.
|
||||
// But it's not needed to do that anyway.
|
||||
|
||||
if (!Indices().IsZero())
|
||||
fIndicesNode = new Inode(this, ToVnode(Indices()));
|
||||
|
||||
@ -397,8 +379,8 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
||||
INFORM(("bfs: volume doesn't have indices!\n"));
|
||||
|
||||
if (fIndicesNode) {
|
||||
// if this is the case, the index root node is gone bad, and
|
||||
// BFS switch to read-only mode
|
||||
// if this is the case, the index root node is gone bad,
|
||||
// and BFS switch to read-only mode
|
||||
fFlags |= VOLUME_READ_ONLY;
|
||||
delete fIndicesNode;
|
||||
fIndicesNode = NULL;
|
||||
@ -450,12 +432,14 @@ Volume::Sync()
|
||||
status_t
|
||||
Volume::ValidateBlockRun(block_run run)
|
||||
{
|
||||
if (run.AllocationGroup() < 0 || run.AllocationGroup() > (int32)AllocationGroups()
|
||||
if (run.AllocationGroup() < 0
|
||||
|| run.AllocationGroup() > (int32)AllocationGroups()
|
||||
|| run.Start() > (1UL << AllocationGroupShift())
|
||||
|| run.length == 0
|
||||
|| uint32(run.Length() + run.Start()) > (1UL << AllocationGroupShift())) {
|
||||
Panic();
|
||||
FATAL(("*** invalid run(%d,%d,%d)\n", (int)run.AllocationGroup(), run.Start(), run.Length()));
|
||||
FATAL(("*** invalid run(%d,%d,%d)\n", (int)run.AllocationGroup(),
|
||||
run.Start(), run.Length()));
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
return B_OK;
|
||||
@ -466,8 +450,10 @@ block_run
|
||||
Volume::ToBlockRun(off_t block) const
|
||||
{
|
||||
block_run run;
|
||||
run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(block >> AllocationGroupShift());
|
||||
run.start = HOST_ENDIAN_TO_BFS_INT16(block & ((1LL << AllocationGroupShift()) - 1));
|
||||
run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(
|
||||
block >> AllocationGroupShift());
|
||||
run.start = HOST_ENDIAN_TO_BFS_INT16(
|
||||
block & ((1LL << AllocationGroupShift()) - 1));
|
||||
run.length = HOST_ENDIAN_TO_BFS_INT16(1);
|
||||
return run;
|
||||
}
|
||||
@ -489,16 +475,20 @@ Volume::CreateIndicesRoot(Transaction &transaction)
|
||||
|
||||
|
||||
status_t
|
||||
Volume::AllocateForInode(Transaction &transaction, const Inode *parent, mode_t type, block_run &run)
|
||||
Volume::AllocateForInode(Transaction &transaction, const Inode *parent,
|
||||
mode_t type, block_run &run)
|
||||
{
|
||||
return fBlockAllocator.AllocateForInode(transaction, &parent->BlockRun(), type, run);
|
||||
return fBlockAllocator.AllocateForInode(transaction, &parent->BlockRun(),
|
||||
type, run);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::WriteSuperBlock()
|
||||
{
|
||||
if (write_pos(fDevice, 512, &fSuperBlock, sizeof(disk_super_block)) != sizeof(disk_super_block))
|
||||
// TODO: this assumes a block size of 512 bytes of the underlying device
|
||||
if (write_pos(fDevice, 512, &fSuperBlock, sizeof(disk_super_block))
|
||||
!= sizeof(disk_super_block))
|
||||
return B_IO_ERROR;
|
||||
|
||||
return B_OK;
|
||||
@ -506,15 +496,18 @@ Volume::WriteSuperBlock()
|
||||
|
||||
|
||||
void
|
||||
Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type, const uint8 *oldKey,
|
||||
size_t oldLength, const uint8 *newKey, size_t newLength)
|
||||
Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
|
||||
const uint8 *oldKey, size_t oldLength, const uint8 *newKey,
|
||||
size_t newLength)
|
||||
{
|
||||
if (fQueryLock.Lock() < B_OK)
|
||||
return;
|
||||
|
||||
Query *query = NULL;
|
||||
while ((query = fQueries.Next(query)) != NULL)
|
||||
query->LiveUpdate(inode, attribute, type, oldKey, oldLength, newKey, newLength);
|
||||
while ((query = fQueries.Next(query)) != NULL) {
|
||||
query->LiveUpdate(inode, attribute, type, oldKey, oldLength, newKey,
|
||||
newLength);
|
||||
}
|
||||
|
||||
fQueryLock.Unlock();
|
||||
}
|
||||
@ -568,11 +561,10 @@ Volume::Identify(int fd, disk_super_block *superBlock)
|
||||
if (read_pos(fd, 0, buffer, sizeof(buffer)) != sizeof(buffer))
|
||||
return B_IO_ERROR;
|
||||
|
||||
// Note: that does work only for x86, for PowerPC, the super block
|
||||
// may be located at offset 0!
|
||||
memcpy(superBlock, buffer + 512, sizeof(disk_super_block));
|
||||
if (!superBlock->IsValid()) {
|
||||
#ifndef BFS_LITTLE_ENDIAN_ONLY
|
||||
// For PPC, the super block might be located at offset 0
|
||||
memcpy(superBlock, buffer, sizeof(disk_super_block));
|
||||
if (!superBlock->IsValid())
|
||||
return B_BAD_VALUE;
|
||||
@ -615,7 +607,7 @@ Volume::Initialize(int fd, const char *name, uint32 blockSize,
|
||||
// create valid super block
|
||||
|
||||
fSuperBlock.Initialize(name, numBlocks, blockSize);
|
||||
|
||||
|
||||
// initialize short hands to the super block (to save byte swapping)
|
||||
fBlockSize = fSuperBlock.BlockSize();
|
||||
fBlockShift = fSuperBlock.BlockShift();
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* bfs - BFS definitions and helper functions
|
||||
*
|
||||
* Copyright 2001-2004, Axel Dörfler, axeld@pinc-software.de.
|
||||
/*
|
||||
* Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Parts of this code is based on work previously done by Marcus Overhagen.
|
||||
*
|
||||
* This file may be used under the terms of the MIT License.
|
||||
@ -8,6 +7,8 @@
|
||||
#ifndef BFS_H
|
||||
#define BFS_H
|
||||
|
||||
//! BFS definitions and helper functions
|
||||
|
||||
|
||||
#include "bfs_endian.h"
|
||||
#include "system_dependencies.h"
|
||||
@ -71,7 +72,9 @@ struct disk_super_block {
|
||||
int32 magic3;
|
||||
inode_addr root_dir;
|
||||
inode_addr indices;
|
||||
int32 pad[8];
|
||||
int32 _reserved[8];
|
||||
int32 pad_to_block[87];
|
||||
// this also contains parts of the boot block
|
||||
|
||||
int32 Magic1() const { return BFS_ENDIAN_TO_HOST_INT32(magic1); }
|
||||
int32 Magic2() const { return BFS_ENDIAN_TO_HOST_INT32(magic2); }
|
||||
|
@ -16,6 +16,8 @@
|
||||
*/
|
||||
#define BFS_IOCTL_VERSION 14200
|
||||
|
||||
#define BFS_IOCTL_UPDATE_BOOT_BLOCK 14204
|
||||
|
||||
/* ioctls to use the "chkbfs" feature from the outside
|
||||
* all calls use a struct check_result as single parameter
|
||||
*/
|
||||
|
@ -576,6 +576,17 @@ bfs_ioctl(void *_fs, void *_node, void *_cookie, ulong cmd, void *buffer,
|
||||
|
||||
return allocator.CheckNextNode(control);
|
||||
}
|
||||
case BFS_IOCTL_UPDATE_BOOT_BLOCK:
|
||||
{
|
||||
// let's makebootable (or anyone else) update the boot block
|
||||
// while BFS is mounted
|
||||
if (user_memcpy(&volume->SuperBlock().pad_to_block,
|
||||
(uint8 *)buffer + offsetof(disk_super_block, pad_to_block),
|
||||
sizeof(volume->SuperBlock().pad_to_block)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return volume->WriteSuperBlock();
|
||||
}
|
||||
#ifdef DEBUG
|
||||
case 56742:
|
||||
{
|
||||
|
@ -20,6 +20,14 @@ fssh_spawn_kernel_thread(fssh_thread_func function, const char *threadName,
|
||||
}
|
||||
|
||||
|
||||
fssh_status_t
|
||||
fssh_user_memcpy(void *dest, const void *source, fssh_size_t length)
|
||||
{
|
||||
memcpy(dest, source, length);
|
||||
return FSSH_B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fssh_dprintf(const char *format, ...)
|
||||
{
|
||||
@ -65,6 +73,7 @@ fssh_panic(const char *format, ...)
|
||||
*badAddress = 42;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fssh_kernel_debugger(const char *message)
|
||||
{
|
||||
@ -78,6 +87,7 @@ fssh_parse_expression(const char *string)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fssh_add_debugger_command(char *name, fssh_debugger_command_hook hook,
|
||||
char *help)
|
||||
|
Loading…
Reference in New Issue
Block a user