diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index 97060dc5ff..f01fde61ae 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -3,6 +3,7 @@ * This file may be used under the terms of the MIT License. */ + //! block bitmap handling and allocation policies diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index db5d7738ba..ca1f6b2c93 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -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 diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.h b/src/add-ons/kernel/file_systems/bfs/Inode.h index b9676b2ac1..c3f1b9c23a 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.h +++ b/src/add-ons/kernel/file_systems/bfs/Inode.h @@ -23,241 +23,245 @@ class NodeGetter; class Transaction; -class Inode { +class Inode : public TransactionListener { typedef DoublyLinkedListLink 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 fIterators; }; diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index 9212eedd77..f1a1f74a2a 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -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); } } diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.h b/src/add-ons/kernel/file_systems/bfs/Journal.h index 210b9193e8..848817c399 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.h +++ b/src/add-ons/kernel/file_systems/bfs/Journal.h @@ -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 { +public: + TransactionListener(); + virtual ~TransactionListener(); + + virtual void TransactionDone(bool success) = 0; + virtual void RemovedFromTransaction() = 0; +}; + +typedef DoublyLinkedList 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 diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.h b/src/add-ons/kernel/file_systems/bfs/Volume.h index c8c1ec5cb6..55426a68ef 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.h +++ b/src/add-ons/kernel/file_systems/bfs/Volume.h @@ -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 InodeList; + class Volume { public: Volume(fs_volume* volume); diff --git a/src/add-ons/kernel/file_systems/bfs/bfs.h b/src/add-ons/kernel/file_systems/bfs/bfs.h index 8fbf4781bc..2bba107560 100644 --- a/src/add-ons/kernel/file_systems/bfs/bfs.h +++ b/src/add-ons/kernel/file_systems/bfs/bfs.h @@ -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)