* Fixed wrong group block offset computation: the
ext2_super_block::first_data_block must be used; the superblock offset doesn't matter if the block size is greater than 2KB. * Fixed block access beyond the 4GB limit - we need to cast the block to a 64 bit type in ext2_get_file_map() before shifting it. * Tested with various larger ext3 disks, and everything seems to work fine. * Added some optional debug output. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26213 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,6 +11,14 @@
|
|||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_EXT2
|
||||||
|
#ifdef TRACE_EXT2
|
||||||
|
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
DirectoryIterator::DirectoryIterator(Inode* inode)
|
DirectoryIterator::DirectoryIterator(Inode* inode)
|
||||||
:
|
:
|
||||||
fInode(inode),
|
fInode(inode),
|
||||||
@@ -24,7 +32,7 @@ DirectoryIterator::~DirectoryIterator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
||||||
{
|
{
|
||||||
if (fOffset + sizeof(ext2_dir_entry) >= fInode->Size())
|
if (fOffset + sizeof(ext2_dir_entry) >= fInode->Size())
|
||||||
@@ -48,6 +56,10 @@ DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
|||||||
fOffset += entry.Length();
|
fOffset += entry.Length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("offset %Ld: entry ino %lu, length %u, name length %u, type %u\n",
|
||||||
|
fOffset, entry.InodeID(), entry.Length(), entry.NameLength(),
|
||||||
|
entry.FileType());
|
||||||
|
|
||||||
// read name
|
// read name
|
||||||
|
|
||||||
size_t length = entry.NameLength();
|
size_t length = entry.NameLength();
|
||||||
|
|||||||
@@ -11,6 +11,14 @@
|
|||||||
#include "CachedBlock.h"
|
#include "CachedBlock.h"
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_EXT2
|
||||||
|
#ifdef TRACE_EXT2
|
||||||
|
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Inode::Inode(Volume* volume, ino_t id)
|
Inode::Inode(Volume* volume, ino_t id)
|
||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
@@ -23,6 +31,7 @@ Inode::Inode(Volume* volume, ino_t id)
|
|||||||
|
|
||||||
uint32 block;
|
uint32 block;
|
||||||
if (volume->GetInodeBlock(id, block) == B_OK) {
|
if (volume->GetInodeBlock(id, block) == B_OK) {
|
||||||
|
TRACE("inode %Ld at block %lu\n", ID(), block);
|
||||||
ext2_inode* inodes = (ext2_inode*)block_cache_get(volume->BlockCache(),
|
ext2_inode* inodes = (ext2_inode*)block_cache_get(volume->BlockCache(),
|
||||||
block);
|
block);
|
||||||
if (inodes != NULL)
|
if (inodes != NULL)
|
||||||
@@ -150,7 +159,7 @@ Inode::FindBlock(off_t offset, uint32& block)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//dprintf("FindBlock(offset %Ld): %lu\n", offset, block);
|
TRACE("inode %Ld: FindBlock(offset %Ld): %lu\n", ID(), offset, block);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,14 @@
|
|||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_EXT2
|
||||||
|
#ifdef TRACE_EXT2
|
||||||
|
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class DeviceOpener {
|
class DeviceOpener {
|
||||||
public:
|
public:
|
||||||
DeviceOpener(int fd, int mode);
|
DeviceOpener(int fd, int mode);
|
||||||
@@ -268,13 +276,20 @@ Volume::Mount(const char* deviceName, uint32 flags)
|
|||||||
// initialize short hands to the super block (to save byte swapping)
|
// initialize short hands to the super block (to save byte swapping)
|
||||||
fBlockShift = fSuperBlock.BlockShift();
|
fBlockShift = fSuperBlock.BlockShift();
|
||||||
fBlockSize = 1UL << fSuperBlock.BlockShift();
|
fBlockSize = 1UL << fSuperBlock.BlockShift();
|
||||||
|
fFirstDataBlock = fSuperBlock.FirstDataBlock();
|
||||||
|
|
||||||
fNumGroups = (fSuperBlock.NumBlocks() - fSuperBlock.FirstDataBlock() - 1)
|
fNumGroups = (fSuperBlock.NumBlocks() - fFirstDataBlock - 1)
|
||||||
/ fSuperBlock.BlocksPerGroup() + 1;
|
/ fSuperBlock.BlocksPerGroup() + 1;
|
||||||
fGroupsPerBlock = fBlockSize / sizeof(ext2_block_group);
|
fGroupsPerBlock = fBlockSize / sizeof(ext2_block_group);
|
||||||
|
|
||||||
|
TRACE("block size %ld, num groups %ld, groups per block %ld, first %lu\n",
|
||||||
|
fBlockSize, fNumGroups, fGroupsPerBlock, fFirstDataBlock);
|
||||||
|
TRACE("features %lx, incompatible features %lx, read-only features %lx\n",
|
||||||
|
fSuperBlock.CompatibleFeatures(), fSuperBlock.IncompatibleFeatures(),
|
||||||
|
fSuperBlock.ReadOnlyFeatures());
|
||||||
|
|
||||||
uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) / fGroupsPerBlock;
|
uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) / fGroupsPerBlock;
|
||||||
|
|
||||||
fGroupBlocks = (ext2_block_group**)malloc(blockCount * sizeof(void*));
|
fGroupBlocks = (ext2_block_group**)malloc(blockCount * sizeof(void*));
|
||||||
if (fGroupBlocks == NULL)
|
if (fGroupBlocks == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -298,8 +313,9 @@ Volume::Mount(const char* deviceName, uint32 flags)
|
|||||||
// all went fine
|
// all went fine
|
||||||
opener.Keep();
|
opener.Keep();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} else
|
} else {
|
||||||
dprintf("ext2: could not create root node: get_vnode() failed!\n");
|
TRACE("could not create root node: get_vnode() failed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -344,7 +360,7 @@ Volume::_GroupBlockOffset(uint32 blockIndex)
|
|||||||
if ((fSuperBlock.IncompatibleFeatures()
|
if ((fSuperBlock.IncompatibleFeatures()
|
||||||
& EXT2_INCOMPATIBLE_FEATURE_META_GROUP) == 0
|
& EXT2_INCOMPATIBLE_FEATURE_META_GROUP) == 0
|
||||||
|| blockIndex < fSuperBlock.FirstMetaBlockGroup())
|
|| blockIndex < fSuperBlock.FirstMetaBlockGroup())
|
||||||
return EXT2_SUPER_BLOCK_OFFSET + fBlockSize * (1 + blockIndex);
|
return (fFirstDataBlock + blockIndex + 1) << fBlockShift;
|
||||||
|
|
||||||
panic("meta block");
|
panic("meta block");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -380,6 +396,9 @@ Volume::GetBlockGroup(int32 index, ext2_block_group** _group)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fGroupBlocks[blockIndex] = groupBlock;
|
fGroupBlocks[blockIndex] = groupBlock;
|
||||||
|
|
||||||
|
TRACE("group [%ld]: inode table %ld\n", index,
|
||||||
|
(fGroupBlocks[blockIndex] + index % fGroupsPerBlock)->InodeTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
*_group = fGroupBlocks[blockIndex] + index % fGroupsPerBlock;
|
*_group = fGroupBlocks[blockIndex] + index % fGroupsPerBlock;
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ private:
|
|||||||
uint32 fFlags;
|
uint32 fFlags;
|
||||||
uint32 fBlockSize;
|
uint32 fBlockSize;
|
||||||
uint32 fBlockShift;
|
uint32 fBlockShift;
|
||||||
|
uint32 fFirstDataBlock;
|
||||||
uint32 fNumGroups;
|
uint32 fNumGroups;
|
||||||
uint32 fGroupsPerBlock;
|
uint32 fGroupsPerBlock;
|
||||||
ext2_block_group** fGroupBlocks;
|
ext2_block_group** fGroupBlocks;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ struct ext2_super_block {
|
|||||||
uint16 block_group;
|
uint16 block_group;
|
||||||
uint32 compatible_features;
|
uint32 compatible_features;
|
||||||
uint32 incompatible_features;
|
uint32 incompatible_features;
|
||||||
uint32 readonly_features;
|
uint32 read_only_features;
|
||||||
uint8 uuid[16];
|
uint8 uuid[16];
|
||||||
char name[16];
|
char name[16];
|
||||||
char last_mount_point[64];
|
char last_mount_point[64];
|
||||||
@@ -53,7 +53,7 @@ struct ext2_super_block {
|
|||||||
uint8 preallocated_blocks;
|
uint8 preallocated_blocks;
|
||||||
uint8 preallocated_directory_blocks;
|
uint8 preallocated_directory_blocks;
|
||||||
uint16 _padding;
|
uint16 _padding;
|
||||||
|
|
||||||
// journaling ext3 support
|
// journaling ext3 support
|
||||||
uint8 journal_uuid[16];
|
uint8 journal_uuid[16];
|
||||||
uint32 journal_inode;
|
uint32 journal_inode;
|
||||||
@@ -85,7 +85,7 @@ struct ext2_super_block {
|
|||||||
uint32 CompatibleFeatures() const
|
uint32 CompatibleFeatures() const
|
||||||
{ return B_LENDIAN_TO_HOST_INT32(compatible_features); }
|
{ return B_LENDIAN_TO_HOST_INT32(compatible_features); }
|
||||||
uint32 ReadOnlyFeatures() const
|
uint32 ReadOnlyFeatures() const
|
||||||
{ return B_LENDIAN_TO_HOST_INT32(readonly_features); }
|
{ return B_LENDIAN_TO_HOST_INT32(read_only_features); }
|
||||||
uint32 IncompatibleFeatures() const
|
uint32 IncompatibleFeatures() const
|
||||||
{ return B_LENDIAN_TO_HOST_INT32(incompatible_features); }
|
{ return B_LENDIAN_TO_HOST_INT32(incompatible_features); }
|
||||||
|
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ ext2_get_file_map(fs_volume* _volume, fs_vnode* _node, off_t offset,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
off_t blockOffset = block << volume->BlockShift();
|
off_t blockOffset = (off_t)block << volume->BlockShift();
|
||||||
uint32 blockLength = volume->BlockSize();
|
uint32 blockLength = volume->BlockSize();
|
||||||
|
|
||||||
if (index > 0 && vecs[index - 1].offset == blockOffset - blockLength) {
|
if (index > 0 && vecs[index - 1].offset == blockOffset - blockLength) {
|
||||||
|
|||||||
Reference in New Issue
Block a user