ufs2: Implementing read function
Attempting to read data from direct blocks and single indirect blocks even if the data stored is not in continous blocks and DirectoryIterator now uses ReadAt to iterate through directories. Change-Id: I8156aba53782da8c2bb4481db611ae26d8881b35 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3088 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
7c095f4709
commit
057a3b389f
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "Inode.h"
|
||||
|
||||
//#define TRACE_UFS2
|
||||
#define TRACE_UFS2
|
||||
#ifdef TRACE_UFS2
|
||||
# define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x)
|
||||
#else
|
||||
@@ -24,8 +24,7 @@ DirectoryIterator::DirectoryIterator(Inode* inode)
|
||||
:
|
||||
fInode(inode)
|
||||
{
|
||||
fOffset = fInode->GetBlockPointer() * MINBSIZE;
|
||||
TRACE("DirectoryIterator::DirectoryIterator() \n");
|
||||
fOffset = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,32 +66,30 @@ status_t
|
||||
DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
||||
{
|
||||
dir direct;
|
||||
int fd = fInode->GetVolume()->Device();
|
||||
size_t size = sizeof(dir);
|
||||
status_t status = fInode->ReadAt(fOffset, (uint8_t*)&direct, &size);
|
||||
if (status == B_OK) {
|
||||
int remainder = direct.namlen % 4;
|
||||
if(remainder != 0) {
|
||||
remainder = 4 - remainder;
|
||||
remainder = direct.namlen + remainder;
|
||||
} else {
|
||||
remainder = direct.namlen + 4;
|
||||
}
|
||||
|
||||
fOffset = fOffset + 8 + remainder;
|
||||
|
||||
if (direct.next_ino > 0) {
|
||||
strlcpy(name, direct.name, direct.namlen + 1);
|
||||
*_id = direct.next_ino;
|
||||
*_nameLength = direct.namlen;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
if (read_pos(fd, fOffset, &direct, sizeof(dir)) != sizeof(dir)) {
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
int remainder = direct.namlen % 4;
|
||||
if(remainder != 0) {
|
||||
remainder = 4 - remainder;
|
||||
remainder = direct.namlen + remainder;
|
||||
} else {
|
||||
remainder = direct.namlen + 4;
|
||||
}
|
||||
|
||||
fOffset = fOffset + 8 + remainder;
|
||||
|
||||
if (direct.next_ino > 0) {
|
||||
TRACE("direct.next_ino %d\n",direct.next_ino);
|
||||
|
||||
strlcpy(name, direct.name, remainder);
|
||||
*_id = direct.next_ino;
|
||||
*_nameLength = direct.namlen;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
*/
|
||||
|
||||
#include "Inode.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef TRACE_ufs2
|
||||
|
||||
#define TRACE_UFS2
|
||||
#ifdef TRACE_UFS2
|
||||
#define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x)
|
||||
#else
|
||||
#define TRACE(x...) ;
|
||||
@@ -34,7 +37,7 @@ Inode::Inode(Volume* volume, ino_t id)
|
||||
ufs2_super_block* superblock = (ufs2_super_block* )&fVolume->SuperBlock();
|
||||
int64_t fs_block = ino_to_fsba(superblock, id);
|
||||
int64_t offset_in_block = ino_to_fsbo(superblock, id);
|
||||
int64_t offset = fs_block * MINBSIZE + offset_in_block * 256;
|
||||
int64_t offset = fs_block * MINBSIZE + offset_in_block * sizeof(fNode);
|
||||
|
||||
if (read_pos(fd, offset, (void*)&fNode, sizeof(fNode)) != sizeof(fNode))
|
||||
ERROR("Inode::Inode(): IO Error\n");
|
||||
@@ -85,3 +88,130 @@ Inode::InitCheck()
|
||||
{
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::ReadAt(off_t file_offset, uint8* buffer, size_t* _length)
|
||||
{
|
||||
int fd = fVolume->Device();
|
||||
ufs2_super_block super_block = fVolume->SuperBlock();
|
||||
int32_t blockSize = super_block.fs_bsize;
|
||||
off_t pos;
|
||||
int64_t size = Size();
|
||||
off_t startBlockNumber = file_offset / blockSize;
|
||||
off_t endBlockNumber = (file_offset + *_length) / blockSize;
|
||||
off_t blockOffset = file_offset % blockSize;
|
||||
ssize_t length = 0;
|
||||
if (startBlockNumber != endBlockNumber) {
|
||||
ssize_t remainingLength = blockSize - blockOffset;
|
||||
for (; startBlockNumber <= endBlockNumber; startBlockNumber++) {
|
||||
//code for reading multiple blocks
|
||||
pos = FindBlock(startBlockNumber, blockOffset);
|
||||
length += read_pos(fd, pos, buffer, remainingLength);
|
||||
blockOffset = 0;
|
||||
remainingLength = *_length - length;
|
||||
if (remainingLength > blockSize)
|
||||
remainingLength = blockSize;
|
||||
}
|
||||
*_length = length;
|
||||
return B_OK;
|
||||
}
|
||||
pos = FindBlock(startBlockNumber, blockOffset);
|
||||
length = read_pos(fd, pos, buffer, *_length);
|
||||
*_length = length;
|
||||
return B_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
off_t
|
||||
Inode::FindBlock(off_t blockNumber, off_t blockOffset)
|
||||
{
|
||||
int fd = fVolume->Device();
|
||||
ufs2_super_block super_block = fVolume->SuperBlock();
|
||||
int32_t blockSize = super_block.fs_bsize;
|
||||
int32_t fragmentSize = super_block.fs_fsize;
|
||||
off_t indirectOffset;
|
||||
int64_t directBlock;
|
||||
off_t numberOfBlockPointers = blockSize / 8;
|
||||
const off_t numberOfIndirectBlocks = numberOfBlockPointers;
|
||||
const off_t numberOfDoubleIndirectBlocks = numberOfBlockPointers
|
||||
* numberOfBlockPointers;
|
||||
if (blockNumber < 12) {
|
||||
// read from direct block
|
||||
return GetBlockPointer(blockNumber) * fragmentSize + blockOffset;
|
||||
|
||||
} else if (blockNumber < numberOfIndirectBlocks + 12) {
|
||||
//read from indirect block
|
||||
blockNumber = blockNumber - 12;
|
||||
indirectOffset = GetIndirectBlockPointer() *
|
||||
fragmentSize + (8 * blockNumber);
|
||||
read_pos(fd, indirectOffset,
|
||||
(void*)&directBlock, sizeof(directBlock));
|
||||
|
||||
return directBlock * fragmentSize + blockOffset;
|
||||
|
||||
} else if (blockNumber < numberOfDoubleIndirectBlocks
|
||||
+ numberOfIndirectBlocks + 12) {
|
||||
// Data is in double indirect block
|
||||
// Subract the already read blocks
|
||||
blockNumber = blockNumber - numberOfBlockPointers - 12;
|
||||
// Calculate indirect block inside double indirect block
|
||||
off_t indirectBlockNumber = blockNumber / numberOfBlockPointers;
|
||||
indirectOffset = GetDoubleIndirectBlockPtr() *
|
||||
fragmentSize + (8 * indirectBlockNumber);
|
||||
|
||||
int64_t indirectPointer;
|
||||
read_pos(fd, indirectOffset,
|
||||
(void*)&indirectPointer, sizeof(directBlock));
|
||||
|
||||
indirectOffset = indirectPointer * fragmentSize
|
||||
+ (8 * (blockNumber % numberOfBlockPointers));
|
||||
|
||||
read_pos(fd, indirectOffset,
|
||||
(void*)&directBlock, sizeof(directBlock));
|
||||
|
||||
return directBlock * fragmentSize + blockOffset;
|
||||
|
||||
} else if (blockNumber < (numberOfIndirectBlocks
|
||||
* numberOfDoubleIndirectBlocks)
|
||||
+ (numberOfDoubleIndirectBlocks + numberOfBlockPointers + 12)) {
|
||||
// Reading from triple indirect block
|
||||
blockNumber = blockNumber - numberOfDoubleIndirectBlocks
|
||||
- numberOfBlockPointers - 12;
|
||||
|
||||
// Get double indirect block
|
||||
// Double indirect block no
|
||||
off_t indirectBlockNumber = blockNumber / numberOfDoubleIndirectBlocks;
|
||||
|
||||
// offset to double indirect block ptr
|
||||
indirectOffset = GetTripleIndirectBlockPtr() *
|
||||
fragmentSize + (8 * indirectBlockNumber);
|
||||
|
||||
int64_t indirectPointer;
|
||||
// Get the double indirect block ptr
|
||||
read_pos(fd, indirectOffset,
|
||||
(void*)&indirectPointer, sizeof(directBlock));
|
||||
|
||||
// Get the indirect block
|
||||
// number of indirect block ptr
|
||||
indirectBlockNumber = blockNumber / numberOfBlockPointers;
|
||||
// Indirect block ptr offset
|
||||
indirectOffset = indirectPointer * fragmentSize
|
||||
+ (8 * indirectBlockNumber);
|
||||
|
||||
read_pos(fd, indirectOffset,
|
||||
(void*)&indirectPointer, sizeof(directBlock));
|
||||
|
||||
// Get direct block pointer
|
||||
indirectOffset = indirectPointer * fragmentSize
|
||||
+ (8 * (blockNumber % numberOfBlockPointers));
|
||||
|
||||
read_pos(fd, indirectOffset,
|
||||
(void*)&directBlock, sizeof(directBlock));
|
||||
|
||||
return directBlock * fragmentSize + blockOffset;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
@@ -44,18 +44,7 @@ struct ufs2_inode {
|
||||
int64_t extendedBklPtr1;
|
||||
int64_t extendedBklPtr2;
|
||||
/* 12 direct block pointers */
|
||||
int64_t directBlkPtr1;
|
||||
int64_t directBlkPtr2;
|
||||
int64_t directBlkPtr3;
|
||||
int64_t directBlkPtr4;
|
||||
int64_t directBlkPtr5;
|
||||
int64_t directBlkPtr6;
|
||||
int64_t directBlkPtr7;
|
||||
int64_t directBlkPtr8;
|
||||
int64_t directBlkPtr9;
|
||||
int64_t directBlkPtr10;
|
||||
int64_t directBlkPtr11;
|
||||
int64_t directBlkPtr12;
|
||||
int64_t directBlkPtr[12];
|
||||
int64_t indirectBlkPtr; /* 1 Indirect block pointer */
|
||||
int64_t doubleIndriectBlkPtr; // 1 Double Indirect block pointer
|
||||
int64_t tripleIndriectBlkPtr; // 1 Triple Indirect block pointer
|
||||
@@ -118,12 +107,22 @@ class Inode {
|
||||
|
||||
Volume* GetVolume() const { return fVolume; }
|
||||
|
||||
int64_t GetBlockPointer() { return fNode.directBlkPtr1; }
|
||||
int64_t GetBlockPointer(int ptrNumber)
|
||||
{ return fNode.directBlkPtr[ptrNumber]; }
|
||||
|
||||
int64_t GetIndirectBlockPointer()
|
||||
{ return fNode.indirectBlkPtr; }
|
||||
|
||||
int64_t GetDoubleIndirectBlockPtr()
|
||||
{ return fNode.doubleIndriectBlkPtr; }
|
||||
|
||||
int64_t GetTripleIndirectBlockPtr()
|
||||
{ return fNode.tripleIndriectBlkPtr; }
|
||||
|
||||
ino_t Parent();
|
||||
|
||||
// status_t FindBlock(off_t logical, off_t& physical,
|
||||
// off_t* _length = NULL);
|
||||
// status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
|
||||
off_t FindBlock(off_t block_number, off_t block_offset);
|
||||
status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
|
||||
// status_t FillGapWithZeros(off_t start, off_t end);
|
||||
|
||||
void* FileCache() const { return fCache; }
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "DirectoryIterator.h"
|
||||
#include "Inode.h"
|
||||
#include "system_dependencies.h"
|
||||
@@ -26,6 +25,7 @@ struct identify_cookie
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
//! ufs2_io() callback hook
|
||||
static status_t
|
||||
iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset,
|
||||
@@ -42,6 +42,7 @@ iterative_io_finished_hook(void *cookie, io_request *request, status_t status,
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// #pragma mark - Scanning
|
||||
@@ -196,7 +197,6 @@ static status_t
|
||||
ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
|
||||
ino_t *_vnodeID)
|
||||
{
|
||||
TRACE("UFS2_LOOKUP: %p (%s)\n", name, name);
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
Inode* directory = (Inode*)_directory->private_node;
|
||||
|
||||
@@ -207,7 +207,6 @@ ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
|
||||
return status;
|
||||
|
||||
status = get_vnode(volume->FSVolume(), *_vnodeID, NULL);
|
||||
TRACE("get_vnode status: %s\n", strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -223,11 +222,9 @@ ufs2_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd,
|
||||
static status_t
|
||||
ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
|
||||
{
|
||||
TRACE("Reading stat...\n");
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
stat->st_dev = inode->GetVolume()->ID();
|
||||
stat->st_ino = inode->ID();
|
||||
TRACE("stat->st_ino %ld\n",stat->st_ino);
|
||||
// TODO handle hardlinks which will have nlink > 1. Maybe linkCount in inode
|
||||
// structure may help?
|
||||
stat->st_nlink = 1;
|
||||
@@ -251,10 +248,27 @@ ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
|
||||
|
||||
|
||||
static status_t
|
||||
ufs2_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode,
|
||||
ufs2_open(fs_volume * _volume, fs_vnode *_node, int openMode,
|
||||
void **_cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
//Volume* volume = (Volume*)_volume->private_volume;
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
TRACE("in open %d \n", openMode);
|
||||
if (inode->IsDirectory())
|
||||
return B_IS_A_DIRECTORY;
|
||||
|
||||
file_cookie* cookie = new(std::nothrow) file_cookie;
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<file_cookie> cookieDeleter(cookie);
|
||||
|
||||
cookie->last_size = inode->Size();
|
||||
cookie->last_notification = system_time();
|
||||
|
||||
// fileCacheEnabler.Detach();
|
||||
cookieDeleter.Detach();
|
||||
*_cookie = cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -262,7 +276,14 @@ static status_t
|
||||
ufs2_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos,
|
||||
void *buffer, size_t *_length)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
|
||||
if (!inode->IsFile()) {
|
||||
*_length = 0;
|
||||
return inode->IsDirectory() ? B_IS_A_DIRECTORY : B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return inode->ReadAt(pos, (uint8*)buffer, _length);
|
||||
}
|
||||
|
||||
|
||||
@@ -340,14 +361,13 @@ static status_t
|
||||
ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
||||
{
|
||||
TRACE("read dir \n");
|
||||
DirectoryIterator* iterator = (DirectoryIterator*)_cookie;
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
|
||||
uint32 maxCount = *_num;
|
||||
uint32 count = 0;
|
||||
|
||||
while (count < maxCount and (bufferSize > sizeof(struct dirent))) {
|
||||
while (count < maxCount && (bufferSize > sizeof(struct dirent))) {
|
||||
size_t length = bufferSize - sizeof(struct dirent) + 1;
|
||||
ino_t iNodeNo;
|
||||
|
||||
@@ -371,7 +391,6 @@ ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
}
|
||||
|
||||
*_num = count;
|
||||
TRACE("count is %d\n", count);
|
||||
return B_OK;
|
||||
|
||||
}
|
||||
|
||||
@@ -359,6 +359,14 @@ struct ufs2_super_block {
|
||||
CTASSERT(sizeof(struct fs) == 1376);
|
||||
#endif
|
||||
|
||||
|
||||
struct file_cookie {
|
||||
bigtime_t last_notification;
|
||||
off_t last_size;
|
||||
int open_mode;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Filesystem identification
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user