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" #include "Inode.h"
//#define TRACE_UFS2 #define TRACE_UFS2
#ifdef TRACE_UFS2 #ifdef TRACE_UFS2
# define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) # define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x)
#else #else
@@ -24,8 +24,7 @@ DirectoryIterator::DirectoryIterator(Inode* inode)
: :
fInode(inode) fInode(inode)
{ {
fOffset = fInode->GetBlockPointer() * MINBSIZE; fOffset = 0;
TRACE("DirectoryIterator::DirectoryIterator() \n");
} }
@@ -67,32 +66,30 @@ status_t
DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id) DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
{ {
dir direct; 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; return B_ERROR;
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;
} }
+132 -2
View File
@@ -5,8 +5,11 @@
*/ */
#include "Inode.h" #include "Inode.h"
#include <string.h>
#ifdef TRACE_ufs2
#define TRACE_UFS2
#ifdef TRACE_UFS2
#define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) #define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x)
#else #else
#define TRACE(x...) ; #define TRACE(x...) ;
@@ -34,7 +37,7 @@ Inode::Inode(Volume* volume, ino_t id)
ufs2_super_block* superblock = (ufs2_super_block* )&fVolume->SuperBlock(); ufs2_super_block* superblock = (ufs2_super_block* )&fVolume->SuperBlock();
int64_t fs_block = ino_to_fsba(superblock, id); int64_t fs_block = ino_to_fsba(superblock, id);
int64_t offset_in_block = ino_to_fsbo(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)) if (read_pos(fd, offset, (void*)&fNode, sizeof(fNode)) != sizeof(fNode))
ERROR("Inode::Inode(): IO Error\n"); ERROR("Inode::Inode(): IO Error\n");
@@ -85,3 +88,130 @@ Inode::InitCheck()
{ {
return fInitStatus; 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 extendedBklPtr1;
int64_t extendedBklPtr2; int64_t extendedBklPtr2;
/* 12 direct block pointers */ /* 12 direct block pointers */
int64_t directBlkPtr1; int64_t directBlkPtr[12];
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 indirectBlkPtr; /* 1 Indirect block pointer */ int64_t indirectBlkPtr; /* 1 Indirect block pointer */
int64_t doubleIndriectBlkPtr; // 1 Double Indirect block pointer int64_t doubleIndriectBlkPtr; // 1 Double Indirect block pointer
int64_t tripleIndriectBlkPtr; // 1 Triple Indirect block pointer int64_t tripleIndriectBlkPtr; // 1 Triple Indirect block pointer
@@ -118,12 +107,22 @@ class Inode {
Volume* GetVolume() const { return fVolume; } 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(); ino_t Parent();
// status_t FindBlock(off_t logical, off_t& physical, off_t FindBlock(off_t block_number, off_t block_offset);
// off_t* _length = NULL); status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
// status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
// status_t FillGapWithZeros(off_t start, off_t end); // status_t FillGapWithZeros(off_t start, off_t end);
void* FileCache() const { return fCache; } void* FileCache() const { return fCache; }
@@ -3,7 +3,6 @@
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
#include "DirectoryIterator.h" #include "DirectoryIterator.h"
#include "Inode.h" #include "Inode.h"
#include "system_dependencies.h" #include "system_dependencies.h"
@@ -26,6 +25,7 @@ struct identify_cookie
}; };
#if 0
//! ufs2_io() callback hook //! ufs2_io() callback hook
static status_t static status_t
iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset, 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; return B_NOT_SUPPORTED;
} }
#endif
// #pragma mark - Scanning // #pragma mark - Scanning
@@ -196,7 +197,6 @@ static status_t
ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
ino_t *_vnodeID) ino_t *_vnodeID)
{ {
TRACE("UFS2_LOOKUP: %p (%s)\n", name, name);
Volume* volume = (Volume*)_volume->private_volume; Volume* volume = (Volume*)_volume->private_volume;
Inode* directory = (Inode*)_directory->private_node; Inode* directory = (Inode*)_directory->private_node;
@@ -207,7 +207,6 @@ ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
return status; return status;
status = get_vnode(volume->FSVolume(), *_vnodeID, NULL); status = get_vnode(volume->FSVolume(), *_vnodeID, NULL);
TRACE("get_vnode status: %s\n", strerror(status));
return status; return status;
} }
@@ -223,11 +222,9 @@ ufs2_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd,
static status_t static status_t
ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
{ {
TRACE("Reading stat...\n");
Inode* inode = (Inode*)_node->private_node; Inode* inode = (Inode*)_node->private_node;
stat->st_dev = inode->GetVolume()->ID(); stat->st_dev = inode->GetVolume()->ID();
stat->st_ino = inode->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 // TODO handle hardlinks which will have nlink > 1. Maybe linkCount in inode
// structure may help? // structure may help?
stat->st_nlink = 1; stat->st_nlink = 1;
@@ -251,10 +248,27 @@ ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
static status_t 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) 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, ufs2_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos,
void *buffer, size_t *_length) 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, ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
struct dirent *dirent, size_t bufferSize, uint32 *_num) struct dirent *dirent, size_t bufferSize, uint32 *_num)
{ {
TRACE("read dir \n");
DirectoryIterator* iterator = (DirectoryIterator*)_cookie; DirectoryIterator* iterator = (DirectoryIterator*)_cookie;
Volume* volume = (Volume*)_volume->private_volume; Volume* volume = (Volume*)_volume->private_volume;
uint32 maxCount = *_num; uint32 maxCount = *_num;
uint32 count = 0; 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; size_t length = bufferSize - sizeof(struct dirent) + 1;
ino_t iNodeNo; ino_t iNodeNo;
@@ -371,7 +391,6 @@ ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
} }
*_num = count; *_num = count;
TRACE("count is %d\n", count);
return B_OK; return B_OK;
} }
@@ -359,6 +359,14 @@ struct ufs2_super_block {
CTASSERT(sizeof(struct fs) == 1376); CTASSERT(sizeof(struct fs) == 1376);
#endif #endif
struct file_cookie {
bigtime_t last_notification;
off_t last_size;
int open_mode;
};
/* /*
* Filesystem identification * Filesystem identification
*/ */