* Replaced the specialized inode in transaction mechanism with a generic one.

That costs 12 more bytes per inode on 32 bit platforms, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35491 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-02-16 11:30:15 +00:00
parent 2a8ae7fb92
commit fd91cf4d18
7 changed files with 322 additions and 261 deletions

View File

@ -3,6 +3,7 @@
* This file may be used under the terms of the MIT License.
*/
//! block bitmap handling and allocation policies

View File

@ -3,7 +3,8 @@
* This file may be used under the terms of the MIT License.
*/
//! inode access functions
//! Inode access functions
#include "Debug.h"
@ -175,7 +176,7 @@ InodeAllocator::~InodeAllocator()
fInode->Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_USE);
// this unblocks any pending bfs_read_vnode() calls
fInode->Free(*fTransaction);
fTransaction->RemoveInode(fInode);
fTransaction->RemoveListener(fInode);
remove_vnode(volume->FSVolume(), fInode->ID());
} else
@ -291,7 +292,7 @@ InodeAllocator::_TransactionListener(int32 id, int32 event, void* _inode)
status_t
bfs_inode::InitCheck(Volume* volume)
bfs_inode::InitCheck(Volume* volume) const
{
if (Magic1() != INODE_MAGIC1
|| !(Flags() & INODE_IN_USE)
@ -403,7 +404,7 @@ Inode::~Inode()
status_t
Inode::InitCheck(bool checkNode)
Inode::InitCheck(bool checkNode) const
{
// test inode magic and flags
if (checkNode) {
@ -437,6 +438,33 @@ Inode::InitCheck(bool checkNode)
}
/*! Adds this inode to the specified transaction. This means that the inode will
be write locked until the transaction ended.
To ensure that the inode will stay valid until that point, an extra reference
is acquired to it as long as this transaction stays active.
*/
void
Inode::WriteLockInTransaction(Transaction& transaction)
{
// These flags can only change while holding the transaction lock
if ((Flags() & INODE_IN_TRANSACTION) != 0)
return;
// We share the same list link with the removed list, so we have to remove
// the inode from that list here (and add it back when we no longer need it)
if ((Flags() & INODE_DELETED) != 0)
fVolume->RemovedInodes().Remove(this);
if (!fVolume->IsInitializing())
acquire_vnode(fVolume->FSVolume(), ID());
rw_lock_write_lock(&Lock());
Node().flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
transaction.AddListener(this);
}
status_t
Inode::WriteBack(Transaction& transaction)
{
@ -2379,6 +2407,35 @@ Inode::Sync()
}
// #pragma mark - TransactionListener implementation
void
Inode::TransactionDone(bool success)
{
if (!success) {
// revert any changes made to the cached bfs_inode
UpdateNodeFromDisk();
}
}
void
Inode::RemovedFromTransaction()
{
Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
// See AddInode() why we do this here
if ((Flags() & INODE_DELETED) != 0)
fVolume->RemovedInodes().Add(this);
rw_lock_write_unlock(&Lock());
if (!fVolume->IsInitializing())
put_vnode(fVolume->FSVolume(), ID());
}
// #pragma mark - creation/deletion

View File

@ -23,241 +23,245 @@ class NodeGetter;
class Transaction;
class Inode {
class Inode : public TransactionListener {
typedef DoublyLinkedListLink<Inode> Link;
public:
Inode(Volume* volume, ino_t id);
Inode(Volume* volume, Transaction& transaction,
ino_t id, mode_t mode, block_run& run);
~Inode();
Inode(Volume* volume, ino_t id);
Inode(Volume* volume, Transaction& transaction,
ino_t id, mode_t mode, block_run& run);
~Inode();
ino_t ID() const { return fID; }
off_t BlockNumber() const
{ return fVolume->VnodeToBlock(fID); }
status_t InitCheck(bool checkNode = true) const;
rw_lock& Lock() { return fLock; }
ReadLocker ReadLock() { return ReadLocker(fLock); }
void WriteLockInTransaction(Transaction& transaction)
{ transaction.AddInode(this); }
ino_t ID() const { return fID; }
off_t BlockNumber() const
{ return fVolume->VnodeToBlock(fID); }
recursive_lock& SmallDataLock() { return fSmallDataLock; }
rw_lock& Lock() { return fLock; }
ReadLocker ReadLock() { return ReadLocker(fLock); }
void WriteLockInTransaction(Transaction& transaction);
status_t WriteBack(Transaction& transaction);
void UpdateNodeFromDisk();
recursive_lock& SmallDataLock() { return fSmallDataLock; }
bool IsContainer() const
{ return S_ISDIR(Mode()); }
bool IsDirectory() const
{ return is_directory(Mode()); }
bool IsIndex() const
{ return is_index(Mode()); }
status_t WriteBack(Transaction& transaction);
void UpdateNodeFromDisk();
bool IsAttributeDirectory() const
{ return (Mode() & S_EXTENDED_TYPES)
== S_ATTR_DIR; }
bool IsAttribute() const
{ return (Mode() & S_EXTENDED_TYPES)
== S_ATTR; }
bool IsFile() const
{ return (Mode()
& (S_IFMT | S_EXTENDED_TYPES)) == S_FILE; }
bool IsRegularNode() const
{ return (Mode() & S_EXTENDED_TYPES) == 0; }
// a regular node in the standard namespace
// (i.e. not an index or attribute)
bool IsSymLink() const { return S_ISLNK(Mode()); }
bool IsLongSymLink() const
{ return (Flags() & INODE_LONG_SYMLINK) != 0; }
bool IsContainer() const
{ return S_ISDIR(Mode()); }
bool IsDirectory() const
{ return is_directory(Mode()); }
bool IsIndex() const
{ return is_index(Mode()); }
bool HasUserAccessableStream() const { return IsFile(); }
// currently only files can be accessed with
// bfs_read()/bfs_write()
bool NeedsFileCache() const
{ return IsFile() || IsAttribute()
|| IsLongSymLink(); }
bool IsAttributeDirectory() const
{ return (Mode() & S_EXTENDED_TYPES)
== S_ATTR_DIR; }
bool IsAttribute() const
{ return (Mode() & S_EXTENDED_TYPES)
== S_ATTR; }
bool IsFile() const
{ return (Mode() & (S_IFMT
| S_EXTENDED_TYPES)) == S_FILE; }
bool IsRegularNode() const
{ return (Mode() & S_EXTENDED_TYPES) == 0; }
// a regular node in the standard namespace
// (i.e. not an index or attribute)
bool IsSymLink() const { return S_ISLNK(Mode()); }
bool IsLongSymLink() const
{ return (Flags() & INODE_LONG_SYMLINK)
!= 0; }
bool IsDeleted() const
{ return (Flags() & INODE_DELETED) != 0; }
bool HasUserAccessableStream() const
{ return IsFile(); }
// currently only files can be accessed with
// bfs_read()/bfs_write()
bool NeedsFileCache() const
{ return IsFile() || IsAttribute()
|| IsLongSymLink(); }
mode_t Mode() const { return fNode.Mode(); }
uint32 Type() const { return fNode.Type(); }
int32 Flags() const { return fNode.Flags(); }
bool IsDeleted() const
{ return (Flags() & INODE_DELETED) != 0; }
off_t Size() const { return fNode.data.Size(); }
off_t AllocatedSize() const;
off_t LastModified() const
{ return fNode.LastModifiedTime(); }
mode_t Mode() const { return fNode.Mode(); }
uint32 Type() const { return fNode.Type(); }
int32 Flags() const { return fNode.Flags(); }
const block_run& BlockRun() const
{ return fNode.inode_num; }
block_run& Parent() { return fNode.parent; }
block_run& Attributes() { return fNode.attributes; }
off_t Size() const { return fNode.data.Size(); }
off_t AllocatedSize() const;
off_t LastModified() const
{ return fNode.LastModifiedTime(); }
Volume* GetVolume() const { return fVolume; }
const block_run& BlockRun() const
{ return fNode.inode_num; }
block_run& Parent() { return fNode.parent; }
block_run& Attributes() { return fNode.attributes; }
status_t InitCheck(bool checkNode = true);
Volume* GetVolume() const { return fVolume; }
status_t CheckPermissions(int accessMode) const;
status_t CheckPermissions(int accessMode) const;
// small_data access methods
small_data* FindSmallData(const bfs_inode* node,
const char* name) const;
const char* Name(const bfs_inode* node) const;
status_t GetName(char* buffer,
size_t bufferSize = B_FILE_NAME_LENGTH) const;
status_t SetName(Transaction& transaction, const char* name);
small_data* FindSmallData(const bfs_inode* node,
const char* name) const;
const char* Name(const bfs_inode* node) const;
status_t GetName(char* buffer, size_t bufferSize
= B_FILE_NAME_LENGTH) const;
status_t SetName(Transaction& transaction,
const char* name);
// high-level attribute methods
status_t ReadAttribute(const char* name, int32 type,
off_t pos, uint8* buffer, size_t* _length);
status_t WriteAttribute(Transaction& transaction,
const char* name, int32 type, off_t pos,
const uint8* buffer, size_t* _length,
bool* _created);
status_t RemoveAttribute(Transaction& transaction,
const char* name);
status_t ReadAttribute(const char* name, int32 type,
off_t pos, uint8* buffer, size_t* _length);
status_t WriteAttribute(Transaction& transaction,
const char* name, int32 type, off_t pos,
const uint8* buffer, size_t* _length,
bool* _created);
status_t RemoveAttribute(Transaction& transaction,
const char* name);
// attribute methods
status_t GetAttribute(const char* name, Inode** attribute);
void ReleaseAttribute(Inode* attribute);
status_t CreateAttribute(Transaction& transaction,
const char* name, uint32 type,
Inode** attribute);
status_t GetAttribute(const char* name,
Inode** _attribute);
void ReleaseAttribute(Inode* attribute);
status_t CreateAttribute(Transaction& transaction,
const char* name, uint32 type,
Inode** attribute);
// for directories only:
BPlusTree* Tree() const { return fTree; }
bool IsEmpty();
status_t ContainerContentsChanged(Transaction& transaction);
BPlusTree* Tree() const { return fTree; }
bool IsEmpty();
status_t ContainerContentsChanged(
Transaction& transaction);
// manipulating the data stream
status_t FindBlockRun(off_t pos, block_run& run,
off_t& offset);
status_t FindBlockRun(off_t pos, block_run& run,
off_t& offset);
status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
status_t WriteAt(Transaction& transaction, off_t pos,
const uint8* buffer, size_t* length);
status_t FillGapWithZeros(off_t oldSize, off_t newSize);
status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
status_t WriteAt(Transaction& transaction, off_t pos,
const uint8* buffer, size_t* length);
status_t FillGapWithZeros(off_t oldSize, off_t newSize);
status_t SetFileSize(Transaction& transaction, off_t size);
status_t Append(Transaction& transaction, off_t bytes);
status_t TrimPreallocation(Transaction& transaction);
bool NeedsTrimming() const;
status_t SetFileSize(Transaction& transaction,
off_t size);
status_t Append(Transaction& transaction, off_t bytes);
status_t TrimPreallocation(Transaction& transaction);
bool NeedsTrimming() const;
status_t Free(Transaction& transaction);
status_t Sync();
status_t Free(Transaction& transaction);
status_t Sync();
bfs_inode& Node() { return fNode; }
const bfs_inode& Node() const { return fNode; }
bfs_inode& Node() { return fNode; }
const bfs_inode& Node() const { return fNode; }
// create/remove inodes
status_t Remove(Transaction& transaction, const char* name,
ino_t* _id = NULL, bool isDirectory = false,
bool force = false);
static status_t Create(Transaction& transaction, Inode* parent,
const char* name, int32 mode, int openMode,
uint32 type, bool* _created = NULL,
ino_t* _id = NULL, Inode** _inode = NULL,
fs_vnode_ops* vnodeOps = NULL,
uint32 publishFlags = 0);
status_t Remove(Transaction& transaction,
const char* name, ino_t* _id = NULL,
bool isDirectory = false,
bool force = false);
static status_t Create(Transaction& transaction, Inode* parent,
const char* name, int32 mode, int openMode,
uint32 type, bool* _created = NULL,
ino_t* _id = NULL, Inode** _inode = NULL,
fs_vnode_ops* vnodeOps = NULL,
uint32 publishFlags = 0);
// index maintaining helper
void UpdateOldSize() { fOldSize = Size(); }
void UpdateOldLastModified()
{ fOldLastModified
= Node().LastModifiedTime(); }
off_t OldSize() { return fOldSize; }
off_t OldLastModified() { return fOldLastModified; }
void UpdateOldSize() { fOldSize = Size(); }
void UpdateOldLastModified()
{ fOldLastModified
= Node().LastModifiedTime(); }
off_t OldSize() { return fOldSize; }
off_t OldLastModified() { return fOldLastModified; }
bool InNameIndex() const;
bool InSizeIndex() const;
bool InLastModifiedIndex() const;
bool InNameIndex() const;
bool InSizeIndex() const;
bool InLastModifiedIndex() const;
// file cache
void* FileCache() const { return fCache; }
void SetFileCache(void* cache) { fCache = cache; }
void* Map() const { return fMap; }
void SetMap(void* map) { fMap = map; }
void* FileCache() const { return fCache; }
void SetFileCache(void* cache) { fCache = cache; }
void* Map() const { return fMap; }
void SetMap(void* map) { fMap = map; }
#if _KERNEL_MODE && KDEBUG
void AssertReadLocked()
{ ASSERT_READ_LOCKED_RW_LOCK(&fLock); }
void AssertWriteLocked()
{ ASSERT_WRITE_LOCKED_RW_LOCK(&fLock); }
void AssertReadLocked()
{ ASSERT_READ_LOCKED_RW_LOCK(&fLock); }
void AssertWriteLocked()
{ ASSERT_WRITE_LOCKED_RW_LOCK(&fLock); }
#endif
#ifdef B_HAIKU_64_BIT
Link* GetDoublyLinkedListLink()
{ return &fListLink; }
const Link* GetDoublyLinkedListLink() const
{ return &fListLink; }
#else
Link* GetDoublyLinkedListLink()
{ return (Link*)&fNode.pad[0]; }
const Link* GetDoublyLinkedListLink() const
{ return (Link*)&fNode.pad[0]; }
#endif
Link* GetDoublyLinkedListLink()
{ return (Link*)TransactionListener
::GetDoublyLinkedListLink(); }
const Link* GetDoublyLinkedListLink() const
{ return (Link*)TransactionListener
::GetDoublyLinkedListLink(); }
protected:
virtual void TransactionDone(bool success);
virtual void RemovedFromTransaction();
private:
Inode(const Inode& other);
Inode& operator=(const Inode& other);
// no implementation
Inode(const Inode& other);
Inode& operator=(const Inode& other);
// no implementation
friend class AttributeIterator;
friend class InodeAllocator;
// small_data access methods
status_t _MakeSpaceForSmallData(Transaction& transaction,
bfs_inode* node, const char* name,
int32 length);
status_t _RemoveSmallData(Transaction& transaction,
NodeGetter& node, const char* name);
status_t _AddSmallData(Transaction& transaction,
NodeGetter& node, const char* name, uint32 type,
off_t pos, const uint8* data, size_t length,
bool force = false);
status_t _GetNextSmallData(bfs_inode* node,
small_data** _smallData) const;
status_t _RemoveSmallData(bfs_inode* node, small_data* item,
int32 index);
status_t _RemoveAttribute(Transaction& transaction,
const char* name, bool hasIndex, Index* index);
status_t _MakeSpaceForSmallData(Transaction& transaction,
bfs_inode* node, const char* name,
int32 length);
status_t _RemoveSmallData(Transaction& transaction,
NodeGetter& node, const char* name);
status_t _AddSmallData(Transaction& transaction,
NodeGetter& node, const char* name,
uint32 type, off_t pos, const uint8* data,
size_t length, bool force = false);
status_t _GetNextSmallData(bfs_inode* node,
small_data** _smallData) const;
status_t _RemoveSmallData(bfs_inode* node,
small_data* item, int32 index);
status_t _RemoveAttribute(Transaction& transaction,
const char* name, bool hasIndex,
Index* index);
void _AddIterator(AttributeIterator* iterator);
void _RemoveIterator(AttributeIterator* iterator);
void _AddIterator(AttributeIterator* iterator);
void _RemoveIterator(AttributeIterator* iterator);
size_t _DoubleIndirectBlockLength() const;
status_t _FreeStaticStreamArray(Transaction& transaction,
int32 level, block_run run, off_t size,
off_t offset, off_t& max);
status_t _FreeStreamArray(Transaction& transaction,
block_run* array, uint32 arrayLength,
off_t size, off_t& offset, off_t& max);
status_t _AllocateBlockArray(Transaction& transaction,
block_run& run, size_t length,
bool variableSize = false);
status_t _GrowStream(Transaction& transaction, off_t size);
status_t _ShrinkStream(Transaction& transaction, off_t size);
size_t _DoubleIndirectBlockLength() const;
status_t _FreeStaticStreamArray(Transaction& transaction,
int32 level, block_run run, off_t size,
off_t offset, off_t& max);
status_t _FreeStreamArray(Transaction& transaction,
block_run* array, uint32 arrayLength,
off_t size, off_t& offset, off_t& max);
status_t _AllocateBlockArray(Transaction& transaction,
block_run& run, size_t length,
bool variableSize = false);
status_t _GrowStream(Transaction& transaction,
off_t size);
status_t _ShrinkStream(Transaction& transaction,
off_t size);
private:
rw_lock fLock;
Volume* fVolume;
ino_t fID;
BPlusTree* fTree;
Inode* fAttributes;
void* fCache;
void* fMap;
bfs_inode fNode;
rw_lock fLock;
Volume* fVolume;
ino_t fID;
BPlusTree* fTree;
Inode* fAttributes;
void* fCache;
void* fMap;
bfs_inode fNode;
off_t fOldSize;
off_t fOldLastModified;
off_t fOldSize;
off_t fOldLastModified;
// we need those values to ensure we will remove
// the correct keys from the indices
#ifdef B_HAIKU_64_BIT
Link fListLink;
#endif
mutable recursive_lock fSmallDataLock;
SinglyLinkedList<AttributeIterator> fIterators;
};

View File

@ -1,8 +1,9 @@
/*
* Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
//! Transaction and logging
@ -1005,7 +1006,7 @@ Journal::Unlock(Transaction* owner, bool success)
// closed.
bool separateSubTransactions = fSeparateSubTransactions;
fSeparateSubTransactions = true;
owner->UnlockInodes(success);
owner->NotifyListeners(success);
fSeparateSubTransactions = separateSubTransactions;
fOwner = owner->Parent();
@ -1018,7 +1019,7 @@ Journal::Unlock(Transaction* owner, bool success)
&& recursive_lock_get_recursion(&fLock) == 1)
fSeparateSubTransactions = false;
} else
owner->MoveInodesTo(fOwner);
owner->MoveListenersTo(fOwner);
recursive_lock_unlock(&fLock);
return B_OK;
@ -1077,6 +1078,7 @@ Journal::_TransactionDone(bool success)
#ifdef BFS_DEBUGGER_COMMANDS
void
Journal::Dump()
{
@ -1121,9 +1123,23 @@ dump_journal(int argc, char** argv)
return 0;
}
#endif // BFS_DEBUGGER_COMMANDS
// #pragma mark - TransactionListener
TransactionListener::TransactionListener()
{
}
TransactionListener::~TransactionListener()
{
}
// #pragma mark - Transaction
@ -1143,74 +1159,33 @@ Transaction::Start(Volume* volume, off_t refBlock)
}
/*! Adds an inode to this transaction. This means that the inode will be write
locked until the transaction ended.
To ensure that the inode will stay valid until that point, an extra reference
is acquired to it as long as this transaction stays active.
*/
void
Transaction::AddInode(Inode* inode)
Transaction::AddListener(TransactionListener* listener)
{
if (fJournal == NULL)
panic("Transaction is not running!");
// These flags can only change while holding the transaction lock
if ((inode->Flags() & INODE_IN_TRANSACTION) != 0)
return;
// We share the same list link with the removed list, so we have to remove
// the inode from that list here (and add it back when we no longer need it)
if ((inode->Flags() & INODE_DELETED) != 0)
GetVolume()->RemovedInodes().Remove(inode);
if (!GetVolume()->IsInitializing())
acquire_vnode(GetVolume()->FSVolume(), inode->ID());
rw_lock_write_lock(&inode->Lock());
fLockedInodes.Add(inode);
inode->Node().flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
fListeners.Add(listener);
}
void
Transaction::RemoveInode(Inode* inode)
Transaction::RemoveListener(TransactionListener* listener)
{
if (fJournal == NULL)
panic("Transaction is not running!");
inode->Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
fLockedInodes.Remove(inode);
rw_lock_write_unlock(&inode->Lock());
// See AddInode() why we do this here
if ((inode->Flags() & INODE_DELETED) != 0)
GetVolume()->RemovedInodes().Add(inode);
if (!GetVolume()->IsInitializing())
put_vnode(GetVolume()->FSVolume(), inode->ID());
fListeners.Remove(listener);
listener->RemovedFromTransaction();
}
void
Transaction::UnlockInodes(bool success)
Transaction::NotifyListeners(bool success)
{
while (Inode* inode = fLockedInodes.RemoveHead()) {
if (success) {
inode->Node().flags
&= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
} else {
// revert any changes made to the cached bfs_inode
inode->UpdateNodeFromDisk();
}
rw_lock_write_unlock(&inode->Lock());
// See AddInode() why we do this here
if ((inode->Flags() & INODE_DELETED) != 0)
GetVolume()->RemovedInodes().Add(inode);
if (!GetVolume()->IsInitializing())
put_vnode(GetVolume()->FSVolume(), inode->ID());
while (TransactionListener* listener = fListeners.RemoveHead()) {
listener->TransactionDone(success);
listener->RemovedFromTransaction();
}
}
@ -1219,9 +1194,9 @@ Transaction::UnlockInodes(bool success)
sure they will still be reverted in case the transaction is aborted.
*/
void
Transaction::MoveInodesTo(Transaction* transaction)
Transaction::MoveListenersTo(Transaction* transaction)
{
while (Inode* inode = fLockedInodes.RemoveHead()) {
transaction->fLockedInodes.Add(inode);
while (TransactionListener* listener = fListeners.RemoveHead()) {
transaction->fListeners.Add(listener);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#ifndef JOURNAL_H
@ -86,6 +86,19 @@ Journal::FreeLogBlocks() const
}
class TransactionListener
: public DoublyLinkedListLinkImpl<TransactionListener> {
public:
TransactionListener();
virtual ~TransactionListener();
virtual void TransactionDone(bool success) = 0;
virtual void RemovedFromTransaction() = 0;
};
typedef DoublyLinkedList<TransactionListener> TransactionListeners;
class Transaction {
public:
Transaction(Volume* volume, off_t refBlock)
@ -176,11 +189,11 @@ public:
int32 ID() const
{ return fJournal->TransactionID(); }
void AddInode(Inode* inode);
void RemoveInode(Inode* inode);
void AddListener(TransactionListener* listener);
void RemoveListener(TransactionListener* listener);
void UnlockInodes(bool success);
void MoveInodesTo(Transaction* transaction);
void NotifyListeners(bool success);
void MoveListenersTo(Transaction* transaction);
void SetParent(Transaction* parent)
{ fParent = parent; }
@ -192,13 +205,15 @@ private:
Transaction& operator=(const Transaction& other);
// no implementation
Journal* fJournal;
InodeList fLockedInodes;
Transaction* fParent;
Journal* fJournal;
TransactionListeners fListeners;
Transaction* fParent;
};
#ifdef BFS_DEBUGGER_COMMANDS
int dump_journal(int argc, char** argv);
#endif
#endif // JOURNAL_H

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#ifndef VOLUME_H
@ -11,10 +11,12 @@
#include "bfs.h"
#include "BlockAllocator.h"
class Journal;
class Inode;
class Query;
enum volume_flags {
VOLUME_READ_ONLY = 0x0001
};
@ -25,6 +27,7 @@ enum volume_initialize_flags {
typedef DoublyLinkedList<Inode> InodeList;
class Volume {
public:
Volume(fs_volume* volume);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de.
* Parts of this code is based on work previously done by Marcus Overhagen.
*
* This file may be used under the terms of the MIT License.
@ -7,6 +7,7 @@
#ifndef BFS_H
#define BFS_H
//! BFS definitions and helper functions
@ -144,20 +145,25 @@ struct data_stream {
struct bfs_inode;
struct small_data {
uint32 type;
uint16 name_size;
uint16 data_size;
char name[0]; // name_size long, followed by data
uint32 type;
uint16 name_size;
uint16 data_size;
char name[0]; // name_size long, followed by data
uint32 Type() const { return BFS_ENDIAN_TO_HOST_INT32(type); }
uint16 NameSize() const { return BFS_ENDIAN_TO_HOST_INT16(name_size); }
uint16 DataSize() const { return BFS_ENDIAN_TO_HOST_INT16(data_size); }
uint32 Type() const
{ return BFS_ENDIAN_TO_HOST_INT32(type); }
uint16 NameSize() const
{ return BFS_ENDIAN_TO_HOST_INT16(
name_size); }
uint16 DataSize() const
{ return BFS_ENDIAN_TO_HOST_INT16(
data_size); }
inline char *Name() const;
inline uint8 *Data() const;
inline uint32 Size() const;
inline small_data *Next() const;
inline bool IsLast(const bfs_inode *inode) const;
inline char* Name() const;
inline uint8* Data() const;
inline uint32 Size() const;
inline small_data* Next() const;
inline bool IsLast(const bfs_inode* inode) const;
} _PACKED;
// the file name is part of the small_data structure
@ -222,7 +228,7 @@ struct bfs_inode {
{ return BFS_ENDIAN_TO_HOST_INT64(status_change_time); }
small_data* SmallDataStart() { return small_data_start; }
status_t InitCheck(Volume *volume);
status_t InitCheck(Volume* volume) const;
// defined in Inode.cpp
static int64 ToInode(bigtime_t time)