xfs: Attempt at reading extent based files
There are 2 issues right now. One is that I have to give cat command the entire file size for it to print the entire file. The second issue is that I am getting segmentation fault for some reason, and it doesn't even have to do with xfs_read(). For more info: https://review.haiku-os.org/c/haiku/+/3154 Change-Id: I8e3acd658730ed2339dabbd671820c409332f296 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3154 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
02a8f8b29c
commit
68c3f45dfb
@@ -9,7 +9,6 @@
|
|||||||
#ifndef _DEBUG_H_
|
#ifndef _DEBUG_H_
|
||||||
#define _DEBUG_H_
|
#define _DEBUG_H_
|
||||||
|
|
||||||
// #define TRACE_XFS
|
|
||||||
#ifdef TRACE_XFS
|
#ifdef TRACE_XFS
|
||||||
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||||
#define ASSERT(x) \
|
#define ASSERT(x) \
|
||||||
|
|||||||
@@ -82,18 +82,6 @@ struct ExtentBlockTail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ExtentMapEntry {
|
|
||||||
xfs_fileoff_t br_startoff;
|
|
||||||
// logical file block offset
|
|
||||||
xfs_fsblock_t br_startblock;
|
|
||||||
// absolute block number
|
|
||||||
xfs_filblks_t br_blockcount;
|
|
||||||
// # of blocks
|
|
||||||
uint8 br_state;
|
|
||||||
// state of the extent
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Extent
|
class Extent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -141,9 +141,10 @@ xfs_inode_t::DataExtentsCount() const
|
|||||||
Inode::Inode(Volume* volume, xfs_ino_t id)
|
Inode::Inode(Volume* volume, xfs_ino_t id)
|
||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
fId(id)
|
fId(id),
|
||||||
|
fBuffer(NULL),
|
||||||
|
fExtents(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -174,6 +175,14 @@ Inode::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Inode::~Inode()
|
||||||
|
{
|
||||||
|
delete fNode;
|
||||||
|
delete[] fBuffer;
|
||||||
|
delete[] fExtents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Inode::HasFileTypeField() const
|
Inode::HasFileTypeField() const
|
||||||
{
|
{
|
||||||
@@ -193,6 +202,138 @@ Inode::CheckPermissions(int accessMode) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Inode::UnWrapExtentFromWrappedEntry(uint64 wrappedExtent[2],
|
||||||
|
ExtentMapEntry* entry)
|
||||||
|
{
|
||||||
|
uint64 first = B_BENDIAN_TO_HOST_INT64(wrappedExtent[0]);
|
||||||
|
uint64 second = B_BENDIAN_TO_HOST_INT64(wrappedExtent[1]);
|
||||||
|
entry->br_state = first >> 63;
|
||||||
|
entry->br_startoff = (first & MASK(63)) >> 9;
|
||||||
|
entry->br_startblock = ((first & MASK(9)) << 43) | (second >> 21);
|
||||||
|
entry->br_blockcount = second & MASK(21);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Inode::ReadExtents()
|
||||||
|
{
|
||||||
|
if (Format() != XFS_DINODE_FMT_EXTENTS)
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
fExtents = new(std::nothrow) ExtentMapEntry[DataExtentsCount()];
|
||||||
|
char* dataStart = (char*) DIR_DFORK_PTR(Buffer());
|
||||||
|
uint64 wrappedExtent[2];
|
||||||
|
for (int i = 0; i < DataExtentsCount(); i++) {
|
||||||
|
wrappedExtent[0] = *(uint64*)(dataStart);
|
||||||
|
wrappedExtent[1] = *(uint64*)(dataStart + sizeof(uint64));
|
||||||
|
dataStart += 2 * sizeof(uint64);
|
||||||
|
UnWrapExtentFromWrappedEntry(wrappedExtent, &fExtents[i]);
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Inode::SearchMapInAllExtent(int blockNo)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < DataExtentsCount(); i++) {
|
||||||
|
if (fExtents[i].br_startoff <= blockNo
|
||||||
|
&& (blockNo <= fExtents[i].br_startoff
|
||||||
|
+ fExtents[i].br_blockcount - 1)) {
|
||||||
|
// Map found
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Inode::ReadAt(off_t pos, uint8* buffer, size_t* length)
|
||||||
|
{
|
||||||
|
TRACE("Inode::ReadAt: pos:(%ld), *length:(%ld)\n", pos, *length);
|
||||||
|
status_t status;
|
||||||
|
if (fExtents == NULL) {
|
||||||
|
status = ReadExtents();
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set/check boundaries for pos/length
|
||||||
|
if (pos < 0) {
|
||||||
|
ERROR("inode %" B_PRIdINO ": ReadAt failed(pos %" B_PRIdOFF
|
||||||
|
", length %lu)\n", ID(), pos, length);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos >= Size() || length == 0) {
|
||||||
|
TRACE("inode %" B_PRIdINO ": ReadAt 0 (pos %" B_PRIdOFF
|
||||||
|
", length %lu)\n", ID(), pos, length);
|
||||||
|
*length = 0;
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 blockNo = BLOCKNO_FROM_POSITION(pos, GetVolume());
|
||||||
|
uint32 offsetIntoBlock = BLOCKOFFSET_FROM_POSITION(pos, this);
|
||||||
|
|
||||||
|
size_t lengthOfBlock = BlockSize();
|
||||||
|
char* block = new(std::nothrow) char[lengthOfBlock];
|
||||||
|
if (block == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
ArrayDeleter<char> blockDeleter(block);
|
||||||
|
|
||||||
|
size_t lengthRead = 0;
|
||||||
|
size_t lengthLeftInFile;
|
||||||
|
size_t lengthLeftInBlock;
|
||||||
|
size_t lengthToRead;
|
||||||
|
TRACE("What is blockLen:(%d)\n", lengthOfBlock);
|
||||||
|
while (*length > 0) {
|
||||||
|
TRACE("Inode::ReadAt: pos:(%ld), *length:(%ld)\n", pos, *length);
|
||||||
|
// As long as you can read full blocks, read.
|
||||||
|
lengthLeftInFile = Size() - pos;
|
||||||
|
lengthLeftInBlock = lengthOfBlock - offsetIntoBlock;
|
||||||
|
|
||||||
|
// We could be almost at the end of the file
|
||||||
|
if (lengthLeftInFile <= lengthLeftInBlock)
|
||||||
|
lengthToRead = lengthLeftInFile;
|
||||||
|
else lengthToRead = lengthLeftInBlock;
|
||||||
|
|
||||||
|
// But we might not be able to read all of the
|
||||||
|
// data because of less buffer length
|
||||||
|
if (lengthToRead > *length)
|
||||||
|
lengthToRead = *length;
|
||||||
|
|
||||||
|
int indexForMap = SearchMapInAllExtent(blockNo);
|
||||||
|
if (indexForMap == -1)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
xfs_daddr_t readPos
|
||||||
|
= FileSystemBlockToAddr(fExtents[indexForMap].br_startblock
|
||||||
|
+ blockNo - fExtents[indexForMap].br_startoff);
|
||||||
|
|
||||||
|
if (read_pos(GetVolume()->Device(), readPos, block, lengthOfBlock)
|
||||||
|
!= lengthOfBlock) {
|
||||||
|
ERROR("TreeDirectory::FillBlockBuffer(): IO Error");
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memcpy((void*) (buffer + lengthRead),
|
||||||
|
(void*)(block + offsetIntoBlock), lengthToRead);
|
||||||
|
|
||||||
|
pos += lengthToRead;
|
||||||
|
*length -= lengthToRead;
|
||||||
|
lengthRead += lengthToRead;
|
||||||
|
blockNo = BLOCKNO_FROM_POSITION(pos, GetVolume());
|
||||||
|
offsetIntoBlock = BLOCKOFFSET_FROM_POSITION(pos, this);
|
||||||
|
}
|
||||||
|
TRACE("lengthRead:(%d)\n", lengthRead);
|
||||||
|
*length = lengthRead;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::GetFromDisk()
|
Inode::GetFromDisk()
|
||||||
{
|
{
|
||||||
@@ -253,13 +394,6 @@ Inode::FileSystemBlockToAddr(uint64 block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Inode::~Inode()
|
|
||||||
{
|
|
||||||
delete fBuffer;
|
|
||||||
delete fNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Basically take 4 characters at a time as long as you can, and xor with
|
* Basically take 4 characters at a time as long as you can, and xor with
|
||||||
* previous hashVal after rotating 4 bits of hashVal. Likewise, continue
|
* previous hashVal after rotating 4 bits of hashVal. Likewise, continue
|
||||||
@@ -272,22 +406,22 @@ hashfunction(const char* name, int length)
|
|||||||
int lengthCovered = 0;
|
int lengthCovered = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (length >= 4) {
|
if (length >= 4) {
|
||||||
for (;index < length && (length - index) >= 4; index += 4)
|
for (; index < length && (length - index) >= 4; index += 4)
|
||||||
{
|
{
|
||||||
lengthCovered += 4;
|
lengthCovered += 4;
|
||||||
hashVal = (name[index] << 21) ^ (name[index+1] << 14)
|
hashVal = (name[index] << 21) ^ (name[index + 1] << 14)
|
||||||
^ (name[index+2] << 7) ^ (name[index+3] << 0)
|
^ (name[index + 2] << 7) ^ (name[index + 3] << 0)
|
||||||
^ ((hashVal << 28) | (hashVal >> (4)));
|
^ ((hashVal << 28) | (hashVal >> 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int leftToCover = length - lengthCovered;
|
int leftToCover = length - lengthCovered;
|
||||||
if (leftToCover == 3) {
|
if (leftToCover == 3) {
|
||||||
hashVal = (name[index] << 14) ^ (name[index+1] << 7)
|
hashVal = (name[index] << 14) ^ (name[index + 1] << 7)
|
||||||
^ (name[index+2] << 0) ^ ((hashVal << 21) | (hashVal >> (11)));
|
^ (name[index + 2] << 0) ^ ((hashVal << 21) | (hashVal >> 11));
|
||||||
}
|
}
|
||||||
if (leftToCover == 2) {
|
if (leftToCover == 2) {
|
||||||
hashVal = (name[index] << 7) ^ (name[index+1] << 0)
|
hashVal = (name[index] << 7) ^ (name[index + 1] << 0)
|
||||||
^ ((hashVal << 14) | (hashVal >> (32 - 14)));
|
^ ((hashVal << 14) | (hashVal >> (32 - 14)));
|
||||||
}
|
}
|
||||||
if (leftToCover == 1) {
|
if (leftToCover == 1) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#ifndef _INODE_H_
|
#ifndef _INODE_H_
|
||||||
#define _INODE_H_
|
#define _INODE_H_
|
||||||
|
|
||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "xfs_types.h"
|
#include "xfs_types.h"
|
||||||
@@ -39,6 +40,9 @@
|
|||||||
#define MASK(n) ((1UL << n) - 1)
|
#define MASK(n) ((1UL << n) - 1)
|
||||||
#define FSBLOCKS_TO_AGNO(n, volume) ((n) >> volume->AgBlocksLog())
|
#define FSBLOCKS_TO_AGNO(n, volume) ((n) >> volume->AgBlocksLog())
|
||||||
#define FSBLOCKS_TO_AGBLOCKNO(n, volume) ((n) & MASK(volume->AgBlocksLog()))
|
#define FSBLOCKS_TO_AGBLOCKNO(n, volume) ((n) & MASK(volume->AgBlocksLog()))
|
||||||
|
#define BLOCKNO_FROM_POSITION(n, volume) \
|
||||||
|
((n) >> (volume->BlockLog()))
|
||||||
|
#define BLOCKOFFSET_FROM_POSITION(n, inode) ((n) & (inode->BlockSize() - 1))
|
||||||
|
|
||||||
|
|
||||||
// xfs_da_blkinfo_t
|
// xfs_da_blkinfo_t
|
||||||
@@ -50,6 +54,18 @@ struct BlockInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ExtentMapEntry {
|
||||||
|
xfs_fileoff_t br_startoff;
|
||||||
|
// logical file block offset
|
||||||
|
xfs_fsblock_t br_startblock;
|
||||||
|
// absolute block number
|
||||||
|
xfs_filblks_t br_blockcount;
|
||||||
|
// # of blocks
|
||||||
|
uint8 br_state;
|
||||||
|
// state of the extent
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
hashfunction(const char* name, int length);
|
hashfunction(const char* name, int length);
|
||||||
|
|
||||||
@@ -80,7 +96,6 @@ enum xfs_dinode_fmt_t {
|
|||||||
struct xfs_inode_t {
|
struct xfs_inode_t {
|
||||||
void SwapEndian();
|
void SwapEndian();
|
||||||
int8 Version() const;
|
int8 Version() const;
|
||||||
//TODO: Check
|
|
||||||
mode_t Mode() const;
|
mode_t Mode() const;
|
||||||
void GetModificationTime(struct timespec&
|
void GetModificationTime(struct timespec&
|
||||||
timestamp);
|
timestamp);
|
||||||
@@ -179,6 +194,9 @@ public:
|
|||||||
uint32 DirBlockSize() const
|
uint32 DirBlockSize() const
|
||||||
{ return fVolume->DirBlockSize(); }
|
{ return fVolume->DirBlockSize(); }
|
||||||
|
|
||||||
|
uint32 BlockSize() const
|
||||||
|
{ return fVolume->BlockSize(); }
|
||||||
|
|
||||||
void GetChangeTime(struct timespec& timestamp) const
|
void GetChangeTime(struct timespec& timestamp) const
|
||||||
{ fNode->GetChangeTime(timestamp); }
|
{ fNode->GetChangeTime(timestamp); }
|
||||||
|
|
||||||
@@ -198,7 +216,11 @@ public:
|
|||||||
uint64 FileSystemBlockToAddr(uint64 block);
|
uint64 FileSystemBlockToAddr(uint64 block);
|
||||||
uint8 ForkOffset() const
|
uint8 ForkOffset() const
|
||||||
{ return fNode->ForkOffset(); }
|
{ return fNode->ForkOffset(); }
|
||||||
|
status_t ReadExtents();
|
||||||
|
status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
|
||||||
|
int SearchMapInAllExtent(int blockNo);
|
||||||
|
void UnWrapExtentFromWrappedEntry(
|
||||||
|
uint64 wrappedExtent[2], ExtentMapEntry* entry);
|
||||||
private:
|
private:
|
||||||
status_t GetFromDisk();
|
status_t GetFromDisk();
|
||||||
xfs_inode_t* fNode;
|
xfs_inode_t* fNode;
|
||||||
@@ -206,6 +228,7 @@ private:
|
|||||||
Volume* fVolume;
|
Volume* fVolume;
|
||||||
char* fBuffer;
|
char* fBuffer;
|
||||||
// Contains the disk inode in BE format
|
// Contains the disk inode in BE format
|
||||||
|
ExtentMapEntry* fExtents;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2001-2009, Axel Dörfler, [email protected].
|
||||||
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
|
* This file may be used under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef UTILITY_H
|
||||||
|
#define UTILITY_H
|
||||||
|
|
||||||
|
|
||||||
|
/*! Converts the open mode, the open flags given to xfs_open(), into
|
||||||
|
access modes, e.g. since O_RDONLY requires read access to the
|
||||||
|
file, it will be converted to R_OK.
|
||||||
|
*/
|
||||||
|
inline int
|
||||||
|
open_mode_to_access(int openMode)
|
||||||
|
{
|
||||||
|
openMode &= O_RWMASK;
|
||||||
|
if (openMode == O_RDONLY)
|
||||||
|
return R_OK;
|
||||||
|
if (openMode == O_WRONLY)
|
||||||
|
return W_OK;
|
||||||
|
|
||||||
|
return R_OK | W_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // UTILITY_H
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
#include "Utility.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -281,7 +282,33 @@ static status_t
|
|||||||
xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode,
|
xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode,
|
||||||
void **_cookie)
|
void **_cookie)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
TRACE("XFS_OPEN:\n");
|
||||||
|
Inode* inode = (Inode*)_node->private_node;
|
||||||
|
|
||||||
|
// opening a directory read-only is allowed, although you can't read
|
||||||
|
// any data from it.
|
||||||
|
if (inode->IsDirectory() && (openMode & O_RWMASK) != 0)
|
||||||
|
return B_IS_A_DIRECTORY;
|
||||||
|
|
||||||
|
status_t status = inode->CheckPermissions(open_mode_to_access(openMode)
|
||||||
|
| (openMode & O_TRUNC ? W_OK : 0));
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// Prepare the cookie
|
||||||
|
file_cookie* cookie = new(std::nothrow) file_cookie;
|
||||||
|
if (cookie == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<file_cookie> cookieDeleter(cookie);
|
||||||
|
|
||||||
|
cookie->open_mode = openMode & XFS_OPEN_MODE_USER_MASK;
|
||||||
|
cookie->last_size = inode->Size();
|
||||||
|
cookie->last_notification = system_time();
|
||||||
|
|
||||||
|
cookieDeleter.Detach();
|
||||||
|
*_cookie = cookie;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -289,21 +316,38 @@ static status_t
|
|||||||
xfs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos,
|
xfs_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;
|
TRACE("Inode::ReadAt: pos:(%ld), *length:(%ld)\n", pos, *_length);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
xfs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
xfs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
TRACE("XFS_FREE_COOKIE:\n");
|
||||||
|
file_cookie* cookie = (file_cookie*)_cookie;
|
||||||
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
|
Inode* inode = (Inode*)_node->private_node;
|
||||||
|
|
||||||
|
if (inode->Size() != cookie->last_size)
|
||||||
|
notify_stat_changed(volume->ID(), -1, inode->ID(), B_STAT_SIZE);
|
||||||
|
|
||||||
|
delete cookie;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -423,13 +467,14 @@ static status_t
|
|||||||
xfs_close_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/,
|
xfs_close_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/,
|
||||||
void * /*_cookie*/)
|
void * /*_cookie*/)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
xfs_free_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
xfs_free_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||||
{
|
{
|
||||||
|
delete (DirectoryIterator*)_cookie;
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2001-2017, Axel Dörfler, [email protected].
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -29,6 +30,14 @@ extern fs_volume_ops gxfsVolumeOps;
|
|||||||
// Log of block size should be 9
|
// Log of block size should be 9
|
||||||
#define BASICBLOCKSIZE (1 << BASICBLOCKLOG)
|
#define BASICBLOCKSIZE (1 << BASICBLOCKLOG)
|
||||||
// The size of a basic block should be 512
|
// The size of a basic block should be 512
|
||||||
|
#define XFS_OPEN_MODE_USER_MASK 0x7fffffff
|
||||||
|
|
||||||
|
|
||||||
|
struct file_cookie {
|
||||||
|
bigtime_t last_notification;
|
||||||
|
off_t last_size;
|
||||||
|
int open_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Version 4 superblock definition */
|
/* Version 4 superblock definition */
|
||||||
|
|||||||
Reference in New Issue
Block a user