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:
Suhel Mehta
2020-10-11 15:57:51 +00:00
committed by waddlesplash
parent 7c095f4709
commit 057a3b389f
5 changed files with 209 additions and 56 deletions
@@ -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;
}
+132 -2
View File
@@ -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;
}
+15 -16
View File
@@ -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
*/