* 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:
Axel Dörfler 2007-12-08 14:23:35 +00:00
parent 477d25de35
commit 21885de266
7 changed files with 71 additions and 48 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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();

View File

@ -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); }

View File

@ -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
*/

View File

@ -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:
{

View File

@ -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)