added 4 changesets to branch 'refs/remotes/ahenriksson-github/production' old head: e919807126410d625f5de66d29414f21c0dd6782 new head: 52950f29f5a1636da6bc94d8b7220c7ee25d5891 ---------------------------------------------------------------------------- 72b03a1: Don't put vnode before we're done with it 720c75d: Bugfixes in resize code 5dd9a9b: Add sscanf and vsscanf to fs_shell 52950f2: 'resizefs'-command added to bfs_shell [ ahenriksson <sausageboy@xxxxxxxxx> ] ---------------------------------------------------------------------------- 9 files changed, 286 insertions(+), 20 deletions(-) .../kernel/file_systems/bfs/FileSystemVisitor.cpp | 5 +- .../kernel/file_systems/bfs/ResizeVisitor.cpp | 24 +- .../kernel/file_systems/bfs/ResizeVisitor.h | 4 +- .../kernel/file_systems/bfs/kernel_interface.cpp | 18 +- src/tools/bfs_shell/Jamfile | 1 + src/tools/bfs_shell/additional_commands.cpp | 3 + src/tools/bfs_shell/command_resizefs.cpp | 209 ++++++++++++++++ src/tools/bfs_shell/command_resizefs.h | 21 ++ src/tools/fs_shell/stdio.cpp | 21 ++ ############################################################################ Commit: 72b03a1603def4baae17379b744f0954914fec16 Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Fri Jul 13 16:12:45 2012 UTC Don't put vnode before we're done with it ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/FileSystemVisitor.cpp b/src/add-ons/kernel/file_systems/bfs/FileSystemVisitor.cpp index a6173438..eba462b 100644 --- a/src/add-ons/kernel/file_systems/bfs/FileSystemVisitor.cpp +++ b/src/add-ons/kernel/file_systems/bfs/FileSystemVisitor.cpp @@ -48,6 +48,7 @@ FileSystemVisitor::Next() while (true) { const char* name = NULL; Inode* inode; + Vnode vnode; if (fIterator == NULL) { if (!fStack.Pop(&fCurrent)) { @@ -56,7 +57,7 @@ FileSystemVisitor::Next() } // open inode - Vnode vnode(fVolume, fCurrent); + vnode.SetTo(fVolume, fCurrent); status = vnode.Get(&inode); if (status != B_OK) { status = OpenInodeFailed(status, fVolume->ToBlock(fCurrent), @@ -121,7 +122,7 @@ FileSystemVisitor::Next() if (!strcmp(treeName, ".") || !strcmp(treeName, "..")) continue; - Vnode vnode(fVolume, id); + vnode.SetTo(fVolume, id); status = vnode.Get(&inode); if (status != B_OK) { status = OpenInodeFailed(status, id, fParent, treeName, ############################################################################ Commit: 720c75db5f21f78744d7c2db560c949185e5631a Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Fri Jul 13 16:13:49 2012 UTC Bugfixes in resize code ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp index db05613..2a5de33 100644 --- a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp +++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp @@ -38,16 +38,16 @@ ResizeVisitor::StartResize() Control().stats.block_size = GetVolume()->BlockSize(); // calculate new values for the log and number of bitmap blocks - off_t numBlocks = (Control().new_size + blockSize - 1) >> blockShift; + fNumBlocks = (Control().new_size + blockSize - 1) >> blockShift; // round up to a whole block uint16 logLength = 2048; - if (numBlocks <= 20480) + if (fNumBlocks <= 20480) logLength = 512; if (Control().new_size > 1LL * 1024 * 1024 * 1024) logLength = 4096; - fBitmapBlocks = (numBlocks + blockSize * 8 - 1) / (blockSize * 8); + fBitmapBlocks = (fNumBlocks + blockSize * 8 - 1) / (blockSize * 8); fNewLog.SetTo(0, 1 + fBitmapBlocks, logLength); off_t reservedLength = 1 + fBitmapBlocks + logLength; @@ -74,12 +74,12 @@ ResizeVisitor::StartResize() return; } - if (diskSize < (numBlocks << blockShift)) { + if (diskSize < (fNumBlocks << blockShift)) { _SetError(B_BAD_VALUE, BFS_DISK_TOO_SMALL); return; } - if (GetVolume()->UsedBlocks() > numBlocks) { + if (GetVolume()->UsedBlocks() > fNumBlocks) { _SetError(B_BAD_VALUE, BFS_NO_SPACE); return; } @@ -98,9 +98,9 @@ ResizeVisitor::StartResize() fBeginBlock = reservedLength; - if (numBlocks < GetVolume()->NumBlocks()) { + if (fNumBlocks < GetVolume()->NumBlocks()) { fShrinking = true; - fEndBlock = numBlocks; + fEndBlock = fNumBlocks; } else { fShrinking = false; fEndBlock = GetVolume()->NumBlocks(); @@ -259,9 +259,9 @@ ResizeVisitor::_ResizeVolume() BlockAllocator& allocator = GetVolume()->Allocator(); // check that the end blocks are free - if (fEndBlock < GetVolume()->NumBlocks()) { - status = allocator.CheckBlocks(fEndBlock, - GetVolume()->NumBlocks() - fEndBlock, false); + if (fNumBlocks < GetVolume()->NumBlocks()) { + status = allocator.CheckBlocks(fNumBlocks, + GetVolume()->NumBlocks() - fNumBlocks, false); if (status != B_OK) return status; } @@ -299,9 +299,9 @@ ResizeVisitor::_ResizeVolume() int64 oldNumBlocks = superBlock.num_blocks; int32 oldNumAgs = superBlock.num_ags; - superBlock.num_blocks = HOST_ENDIAN_TO_BFS_INT64(fEndBlock); + superBlock.num_blocks = HOST_ENDIAN_TO_BFS_INT64(fNumBlocks); superBlock.num_ags = HOST_ENDIAN_TO_BFS_INT32( - (fBitmapBlocks + blocksPerGroup - 1) >> groupShift); + (fNumBlocks + blocksPerGroup - 1) >> groupShift); status = GetVolume()->WriteSuperBlock(); if (status != B_OK) { diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h index 353d94e..0a95b34 100644 --- a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h +++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h @@ -57,14 +57,14 @@ private: resize_control fControl; bool fShrinking; + off_t fNumBlocks; + off_t fBeginBlock; off_t fEndBlock; off_t fBitmapBlocks; block_run fNewLog; - - //bool fForce; }; diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 3215c8c..12a9d15 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -740,8 +740,15 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, resizer->StartResize(); - return user_memcpy(buffer, &resizer->Control(), + status = user_memcpy(buffer, &resizer->Control(), sizeof(resize_control)); + + if (resizer->Control().status != B_OK + || (resizer->Control().flags & BFS_CHECK_RESIZE)) { + volume->DeleteResizeVisitor(); + } + + return status; } case BFS_IOCTL_FINISH_RESIZE: { @@ -754,7 +761,7 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, status_t status = user_memcpy(buffer, &resizer->Control(), sizeof(resize_control)); - delete resizer; + volume->DeleteResizeVisitor(); return status; } case BFS_IOCTL_MOVE_NEXT_NODE: @@ -763,8 +770,11 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, if (resizer == NULL) return B_NO_INIT; - resizer->Next(); - // the return value has been saved away in the resize_control + if (resizer->Next() == B_ENTRY_NOT_FOUND) { + // other return values will be saved away in the + // resize_control + return B_ENTRY_NOT_FOUND; + } return user_memcpy(buffer, &resizer->Control(), sizeof(resize_control)); ############################################################################ Commit: 5dd9a9b3e723d50043cc10b66d7161ec58d60e6f Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Fri Jul 13 16:15:18 2012 UTC Add sscanf and vsscanf to fs_shell ---------------------------------------------------------------------------- diff --git a/src/tools/fs_shell/stdio.cpp b/src/tools/fs_shell/stdio.cpp index 3ae5718..6e99223 100644 --- a/src/tools/fs_shell/stdio.cpp +++ b/src/tools/fs_shell/stdio.cpp @@ -49,3 +49,24 @@ fssh_vsnprintf(char *string, fssh_size_t size, char const *format, va_list ap) { return vsnprintf(string, size, format, ap); } + + +int +fssh_sscanf(char const *str, char const *format, ...) +{ + va_list args; + va_start(args, format); + + int result = vsscanf(str, format, args); + + va_end(args); + + return result; +} + + +int +fssh_vsscanf(char const *str, char const *format, va_list ap) +{ + return vsscanf(str, format, ap); +} ############################################################################ Commit: 52950f29f5a1636da6bc94d8b7220c7ee25d5891 Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Fri Jul 13 16:17:53 2012 UTC 'resizefs'-command added to bfs_shell ---------------------------------------------------------------------------- diff --git a/src/tools/bfs_shell/Jamfile b/src/tools/bfs_shell/Jamfile index 8ff483e..41d932a 100644 --- a/src/tools/bfs_shell/Jamfile +++ b/src/tools/bfs_shell/Jamfile @@ -68,6 +68,7 @@ BuildPlatformMain <build>bfs_shell : additional_commands.cpp command_checkfs.cpp + command_resizefs.cpp : <build>bfs.o <build>fs_shell.a $(libHaikuCompat) $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) diff --git a/src/tools/bfs_shell/additional_commands.cpp b/src/tools/bfs_shell/additional_commands.cpp index be876d1..f5dbe8f 100644 --- a/src/tools/bfs_shell/additional_commands.cpp +++ b/src/tools/bfs_shell/additional_commands.cpp @@ -7,6 +7,7 @@ #include "fssh.h" #include "command_checkfs.h" +#include "command_resizefs.h" namespace FSShell { @@ -17,6 +18,8 @@ register_additional_commands() { CommandManager::Default()->AddCommand(command_checkfs, "checkfs", "check file system"); + CommandManager::Default()->AddCommand(command_resizefs, "resizefs", + "resize file system"); } diff --git a/src/tools/bfs_shell/command_resizefs.cpp b/src/tools/bfs_shell/command_resizefs.cpp new file mode 100644 index 0000000..f533f8d --- /dev/null +++ b/src/tools/bfs_shell/command_resizefs.cpp @@ -0,0 +1,209 @@ +/* + * Copyright 2012, Andreas Henriksson, sausageboy@xxxxxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include "fssh_stdio.h" +#include "syscalls.h" + +#include "bfs.h" +#include "bfs_control.h" + + +namespace FSShell { + + +void Usage(const char* name); + +void PrintInformation(const resize_control& result); +void PrintError(const resize_control& result); +void PrintStats(const resize_control& result); +const char* FailureToString(uint32 failurePoint); + + +fssh_status_t +command_resizefs(int argc, const char* const* argv) +{ + // get command line options + bool hasNewSize = false; + uint64 newSize = 0; + + bool check = false; + + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--check")) + check = true; + else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + Usage(argv[0]); + return B_OK; + } else { + if (fssh_sscanf(argv[i], "%" B_SCNu64, &newSize) < 1) { + fssh_dprintf("Unknown argument or invalid size\n\n"); + Usage(argv[0]); + return B_ERROR; + } + hasNewSize = true; + } + } + + if (!hasNewSize) { + fssh_dprintf("No size specified\n\n"); + Usage(argv[0]); + return B_ERROR; + } + + int rootDir = _kern_open_dir(-1, "/myfs"); + if (rootDir < 0) { + fssh_dprintf("Error: Couldn't open root directory\n"); + return rootDir; + } + + struct resize_control result; + memset(&result, 0, sizeof(result)); + result.magic = BFS_IOCTL_RESIZE_MAGIC; + + if (check) + result.flags |= BFS_CHECK_RESIZE; + + result.new_size = newSize; + + // start resizing + fssh_status_t status = _kern_ioctl(rootDir, BFS_IOCTL_START_RESIZE, + &result, sizeof(result)); + + if (status != B_OK) { + fssh_dprintf("Error: Couldn't perform 'start' ioctl\n"); + return status; + } + + PrintInformation(result); + if (result.status != B_OK) { + PrintError(result); + _kern_close(rootDir); + return result.status; + } + + if (check) { + _kern_close(rootDir); + fssh_dprintf("Resizing appears to be possible.\n"); + return B_OK; + } + + // move all files out of the way + while (true) { + status = _kern_ioctl(rootDir, BFS_IOCTL_MOVE_NEXT_NODE, &result, + sizeof(result)); + if (status == B_ENTRY_NOT_FOUND) + break; + + // we couldn't return the resizefs_control struct + if (status != B_OK) { + fssh_dprintf("Error: Couldn't perform 'next' ioctl\n"); + break; + } + + if (result.status != B_OK) { + PrintError(result); + status = result.status; + break; + } + } + + // finish the resize + if (_kern_ioctl(rootDir, BFS_IOCTL_FINISH_RESIZE, &result, sizeof(result)) + != B_OK) { + _kern_close(rootDir); + fssh_dprintf("Error: Couldn't perform 'finish' ioctl\n"); + return errno; + } + + _kern_close(rootDir); + + PrintStats(result); + + if (result.status != B_OK) + PrintError(result); + else + fssh_dprintf("File system successfully resized!\n"); + + return result.status; +} + + +void +Usage(const char* name) +{ + fssh_dprintf("Usage: %s <new size> [options]\n" + "\t-c, --check Don't resize, just check if it would be possible\n" + "\t-h, --help Print this message\n", name); +} + + +void +PrintInformation(const resize_control& result) +{ + fssh_dprintf("New file system information:\n"); + fssh_dprintf("\tBitmap: %" B_PRIu16 " blocks (was %" B_PRIu16 ")\n", + result.stats.bitmap_blocks_new, result.stats.bitmap_blocks_old); + fssh_dprintf("\tLog start: block %" B_PRIu16 " (was %" B_PRIu16 ")\n", + result.stats.log_start_new, result.stats.log_start_old); + fssh_dprintf("\tLog length: %" B_PRIu16 " blocks (was %" B_PRIu16 ")\n", + result.stats.log_length_new, result.stats.log_length_old); + fssh_dprintf("\tBlock size: %" B_PRIu16 " bytes\n\n", + result.stats.block_size); +} + + +void +PrintError(const resize_control& result) +{ + fssh_dprintf("Error: %s.\n", FailureToString(result.failure_point)); + fssh_dprintf("Status: %s\n", fssh_strerror(result.status)); + + if ((result.failure_point == BFS_MOVE_INODE_FAILED) + || (result.failure_point == BFS_MOVE_STREAM_FAILED)) { + fssh_dprintf("\tIn inode %" B_PRIdINO ", \"%s\"\n", result.inode, + result.name); + } + + fssh_dprintf("\n"); +} + + +void +PrintStats(const resize_control& result) +{ + fssh_dprintf("\tInodes moved: %" B_PRIu64 "\n", + result.stats.inodes_moved); + fssh_dprintf("\tData streams moved: %" B_PRIu64 "\n\n", + result.stats.streams_moved); +} + + +const char* +FailureToString(uint32 failurePoint) +{ + switch (failurePoint) { + case BFS_OTHER_ERROR: + return "Other error"; + case BFS_SIZE_TOO_LARGE: + return "Can't grow disk this much"; + case BFS_DISK_TOO_SMALL: + return "Not enough room on device to grow file system"; + case BFS_NO_SPACE: + return "Not enough space left"; + case BFS_MOVE_LOG_FAILED: + return "Failed to move the file system log"; + case BFS_MOVE_INODE_FAILED: + return "Failed to move inode"; + case BFS_MOVE_STREAM_FAILED: + return "Failed to move file data"; + case BFS_CHANGE_SIZE_FAILED: + return "Failed to update file system size"; + } + return "(Can't get type of failure)"; +} + + +} // namespace FSShell diff --git a/src/tools/bfs_shell/command_resizefs.h b/src/tools/bfs_shell/command_resizefs.h new file mode 100644 index 0000000..6bcb693 --- /dev/null +++ b/src/tools/bfs_shell/command_resizefs.h @@ -0,0 +1,21 @@ +/* + * Copyright 2012, Andreas Henriksson, sausageboy@xxxxxxxxxx + * Distributed under the terms of the MIT License. + */ +#ifndef RESIZEFS_H +#define RESIZEFS_H + + +#include "fssh_types.h" + + +namespace FSShell { + + +fssh_status_t command_resizefs(int argc, const char* const* argv); + + +} // namespace FSShell + + +#endif // RESIZEFS_H