* Coding style cleanups, no functional changes.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26728 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,13 +10,14 @@
|
|||||||
|
|
||||||
|
|
||||||
// TODO: clean this up, find a better separation between Inode and this class
|
// TODO: clean this up, find a better separation between Inode and this class
|
||||||
// TODO: even after Create(), the attribute cannot be stat() for until the first write
|
// TODO: even after Create(), the attribute cannot be stat() for until the
|
||||||
|
// first write
|
||||||
|
|
||||||
|
|
||||||
extern void fill_stat_buffer(Inode *inode, struct stat &stat);
|
extern void fill_stat_buffer(Inode* inode, struct stat& stat);
|
||||||
|
|
||||||
|
|
||||||
Attribute::Attribute(Inode *inode)
|
Attribute::Attribute(Inode* inode)
|
||||||
:
|
:
|
||||||
fNodeGetter(inode->GetVolume()),
|
fNodeGetter(inode->GetVolume()),
|
||||||
fInode(inode),
|
fInode(inode),
|
||||||
@@ -27,7 +28,7 @@ Attribute::Attribute(Inode *inode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Attribute::Attribute(Inode *inode, attr_cookie *cookie)
|
Attribute::Attribute(Inode* inode, attr_cookie* cookie)
|
||||||
:
|
:
|
||||||
fNodeGetter(inode->GetVolume()),
|
fNodeGetter(inode->GetVolume()),
|
||||||
fInode(inode),
|
fInode(inode),
|
||||||
@@ -53,7 +54,7 @@ Attribute::InitCheck()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::CheckAccess(const char *name, int openMode)
|
Attribute::CheckAccess(const char* name, int openMode)
|
||||||
{
|
{
|
||||||
// Opening the name attribute using this function is not allowed,
|
// Opening the name attribute using this function is not allowed,
|
||||||
// also using the reserved indices name, last_modified, and size
|
// also using the reserved indices name, last_modified, and size
|
||||||
@@ -73,7 +74,7 @@ Attribute::CheckAccess(const char *name, int openMode)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::Get(const char *name)
|
Attribute::Get(const char* name)
|
||||||
{
|
{
|
||||||
Put();
|
Put();
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ Attribute::Get(const char *name)
|
|||||||
// try to find it in the small data region
|
// try to find it in the small data region
|
||||||
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
||||||
fNodeGetter.SetToNode(fInode);
|
fNodeGetter.SetToNode(fInode);
|
||||||
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char *)name);
|
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char*)name);
|
||||||
if (fSmall != NULL)
|
if (fSmall != NULL)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@@ -112,14 +113,14 @@ Attribute::Put()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::Create(const char *name, type_code type, int openMode,
|
Attribute::Create(const char* name, type_code type, int openMode,
|
||||||
attr_cookie **_cookie)
|
attr_cookie** _cookie)
|
||||||
{
|
{
|
||||||
status_t status = CheckAccess(name, openMode);
|
status_t status = CheckAccess(name, openMode);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
attr_cookie *cookie = new(std::nothrow) attr_cookie;
|
attr_cookie* cookie = new(std::nothrow) attr_cookie;
|
||||||
if (cookie == NULL)
|
if (cookie == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
@@ -142,7 +143,7 @@ Attribute::Create(const char *name, type_code type, int openMode,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::Open(const char *name, int openMode, attr_cookie **_cookie)
|
Attribute::Open(const char* name, int openMode, attr_cookie** _cookie)
|
||||||
{
|
{
|
||||||
status_t status = CheckAccess(name, openMode);
|
status_t status = CheckAccess(name, openMode);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
@@ -152,7 +153,7 @@ Attribute::Open(const char *name, int openMode, attr_cookie **_cookie)
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
attr_cookie *cookie = new(std::nothrow) attr_cookie;
|
attr_cookie* cookie = new(std::nothrow) attr_cookie;
|
||||||
if (cookie == NULL)
|
if (cookie == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
@@ -171,7 +172,7 @@ Attribute::Open(const char *name, int openMode, attr_cookie **_cookie)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::Stat(struct stat &stat)
|
Attribute::Stat(struct stat& stat)
|
||||||
{
|
{
|
||||||
if (fSmall == NULL && fAttribute == NULL)
|
if (fSmall == NULL && fAttribute == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
@@ -192,7 +193,7 @@ Attribute::Stat(struct stat &stat)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length)
|
Attribute::Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* _length)
|
||||||
{
|
{
|
||||||
if (fSmall == NULL && fAttribute == NULL)
|
if (fSmall == NULL && fAttribute == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
@@ -203,8 +204,8 @@ Attribute::Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Attribute::Write(Transaction &transaction, attr_cookie *cookie,
|
Attribute::Write(Transaction& transaction, attr_cookie* cookie, off_t pos,
|
||||||
off_t pos, const uint8 *buffer, size_t *_length)
|
const uint8* buffer, size_t* _length)
|
||||||
{
|
{
|
||||||
if (!cookie->create && fSmall == NULL && fAttribute == NULL)
|
if (!cookie->create && fSmall == NULL && fAttribute == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/* Attribute - connection between pure inode and kernel_interface attributes
|
/*
|
||||||
*
|
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
||||||
* Copyright 2004, Axel Dörfler, [email protected].
|
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef ATTRIBUTE_H
|
#ifndef ATTRIBUTE_H
|
||||||
@@ -19,35 +18,38 @@ struct attr_cookie {
|
|||||||
|
|
||||||
|
|
||||||
class Attribute {
|
class Attribute {
|
||||||
public:
|
public:
|
||||||
Attribute(Inode *inode);
|
Attribute(Inode* inode);
|
||||||
Attribute(Inode *inode, attr_cookie *cookie);
|
Attribute(Inode* inode, attr_cookie* cookie);
|
||||||
~Attribute();
|
~Attribute();
|
||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
status_t CheckAccess(const char *name, int openMode);
|
status_t CheckAccess(const char* name, int openMode);
|
||||||
|
|
||||||
status_t Get(const char *name);
|
status_t Get(const char* name);
|
||||||
void Put();
|
void Put();
|
||||||
|
|
||||||
status_t Create(const char *name, type_code type, int openMode,
|
status_t Create(const char* name, type_code type,
|
||||||
attr_cookie **_cookie);
|
int openMode, attr_cookie** _cookie);
|
||||||
status_t Open(const char *name, int openMode, attr_cookie **_cookie);
|
status_t Open(const char* name, int openMode,
|
||||||
|
attr_cookie** _cookie);
|
||||||
|
|
||||||
status_t Stat(struct stat &stat);
|
status_t Stat(struct stat& stat);
|
||||||
|
|
||||||
status_t Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length);
|
status_t Read(attr_cookie* cookie, off_t pos, uint8* buffer,
|
||||||
status_t Write(Transaction &transaction, attr_cookie *cookie,
|
size_t* _length);
|
||||||
off_t pos, const uint8 *buffer, size_t *_length);
|
status_t Write(Transaction& transaction, attr_cookie* cookie,
|
||||||
|
off_t pos, const uint8* buffer,
|
||||||
|
size_t* _length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _Truncate();
|
status_t _Truncate();
|
||||||
|
|
||||||
NodeGetter fNodeGetter;
|
NodeGetter fNodeGetter;
|
||||||
Inode *fInode;
|
Inode* fInode;
|
||||||
small_data *fSmall;
|
small_data* fSmall;
|
||||||
Inode *fAttribute;
|
Inode* fAttribute;
|
||||||
const char *fName;
|
const char* fName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ATTRIBUTE_H */
|
#endif // ATTRIBUTE_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,56 +20,63 @@ struct check_cookie;
|
|||||||
|
|
||||||
|
|
||||||
class BlockAllocator {
|
class BlockAllocator {
|
||||||
public:
|
public:
|
||||||
BlockAllocator(Volume *volume);
|
BlockAllocator(Volume* volume);
|
||||||
~BlockAllocator();
|
~BlockAllocator();
|
||||||
|
|
||||||
status_t Initialize(bool full = true);
|
status_t Initialize(bool full = true);
|
||||||
status_t InitializeAndClearBitmap(Transaction &transaction);
|
status_t InitializeAndClearBitmap(Transaction& transaction);
|
||||||
|
|
||||||
void Uninitialize();
|
void Uninitialize();
|
||||||
|
|
||||||
status_t AllocateForInode(Transaction &transaction, const block_run *parent,
|
status_t AllocateForInode(Transaction& transaction,
|
||||||
mode_t type, block_run &run);
|
const block_run* parent, mode_t type,
|
||||||
status_t Allocate(Transaction &transaction, Inode *inode, off_t numBlocks,
|
block_run& run);
|
||||||
block_run &run, uint16 minimum = 1);
|
status_t Allocate(Transaction& transaction, Inode* inode,
|
||||||
status_t Free(Transaction &transaction, block_run run);
|
off_t numBlocks, block_run& run,
|
||||||
|
uint16 minimum = 1);
|
||||||
|
status_t Free(Transaction& transaction, block_run run);
|
||||||
|
|
||||||
status_t AllocateBlocks(Transaction &transaction, int32 group, uint16 start,
|
status_t AllocateBlocks(Transaction& transaction,
|
||||||
uint16 numBlocks, uint16 minimum, block_run &run);
|
int32 group, uint16 start, uint16 numBlocks,
|
||||||
|
uint16 minimum, block_run& run);
|
||||||
|
|
||||||
status_t StartChecking(check_control *control);
|
status_t StartChecking(check_control* control);
|
||||||
status_t StopChecking(check_control *control);
|
status_t StopChecking(check_control* control);
|
||||||
status_t CheckNextNode(check_control *control);
|
status_t CheckNextNode(check_control* control);
|
||||||
|
|
||||||
status_t CheckBlockRun(block_run run, const char *type = NULL, check_control *control = NULL, bool allocated = true);
|
status_t CheckBlockRun(block_run run,
|
||||||
status_t CheckInode(Inode *inode, check_control *control = NULL);
|
const char* type = NULL,
|
||||||
|
check_control* control = NULL,
|
||||||
|
bool allocated = true);
|
||||||
|
status_t CheckInode(Inode* inode,
|
||||||
|
check_control* control = NULL);
|
||||||
|
|
||||||
size_t BitmapSize() const;
|
size_t BitmapSize() const;
|
||||||
|
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
void Dump(int32 index);
|
void Dump(int32 index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _IsValidCheckControl(check_control *control);
|
bool _IsValidCheckControl(check_control* control);
|
||||||
bool _CheckBitmapIsUsedAt(off_t block) const;
|
bool _CheckBitmapIsUsedAt(off_t block) const;
|
||||||
void _SetCheckBitmapAt(off_t block);
|
void _SetCheckBitmapAt(off_t block);
|
||||||
|
|
||||||
static status_t _Initialize(BlockAllocator *);
|
static status_t _Initialize(BlockAllocator* self);
|
||||||
|
|
||||||
Volume *fVolume;
|
Volume* fVolume;
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
AllocationGroup *fGroups;
|
AllocationGroup* fGroups;
|
||||||
int32 fNumGroups;
|
int32 fNumGroups;
|
||||||
uint32 fBlocksPerGroup;
|
uint32 fBlocksPerGroup;
|
||||||
|
|
||||||
uint32 *fCheckBitmap;
|
uint32* fCheckBitmap;
|
||||||
check_cookie *fCheckCookie;
|
check_cookie* fCheckCookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
int dump_block_allocator(int argc, char **argv);
|
int dump_block_allocator(int argc, char** argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* BLOCK_ALLOCATOR_H */
|
#endif // BLOCK_ALLOCATOR_H
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Index::Index(Volume *volume)
|
Index::Index(Volume* volume)
|
||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
fNode(NULL)
|
fNode(NULL)
|
||||||
@@ -51,15 +51,14 @@ Index::Unset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Sets the index to specified one. Returns an error if the index could
|
||||||
Sets the index to specified one. Returns an error if the index could
|
|
||||||
not be found or initialized.
|
not be found or initialized.
|
||||||
Note, Index::Update() may be called on the object even if this method
|
Note, Index::Update() may be called on the object even if this method
|
||||||
failed previously. In this case, it will only update live queries for
|
failed previously. In this case, it will only update live queries for
|
||||||
the updated attribute.
|
the updated attribute.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Index::SetTo(const char *name)
|
Index::SetTo(const char* name)
|
||||||
{
|
{
|
||||||
// remove the old node, if the index is set for the second time
|
// remove the old node, if the index is set for the second time
|
||||||
Unset();
|
Unset();
|
||||||
@@ -71,18 +70,18 @@ Index::SetTo(const char *name)
|
|||||||
// Note, the name is saved even if the index couldn't be initialized!
|
// Note, the name is saved even if the index couldn't be initialized!
|
||||||
// This is used to optimize Index::Update() in case there is no index
|
// This is used to optimize Index::Update() in case there is no index
|
||||||
|
|
||||||
Inode *indices = fVolume->IndicesNode();
|
Inode* indices = fVolume->IndicesNode();
|
||||||
if (indices == NULL)
|
if (indices == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
InodeReadLocker locker(indices);
|
InodeReadLocker locker(indices);
|
||||||
|
|
||||||
BPlusTree *tree;
|
BPlusTree* tree;
|
||||||
if (indices->GetTree(&tree) != B_OK)
|
if (indices->GetTree(&tree) != B_OK)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
ino_t id;
|
ino_t id;
|
||||||
status_t status = tree->Find((uint8 *)name, (uint16)strlen(name), &id);
|
status_t status = tree->Find((uint8*)name, (uint16)strlen(name), &id);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -167,7 +166,7 @@ Index::KeySize()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::Create(Transaction &transaction, const char *name, uint32 type)
|
Index::Create(Transaction &transaction, const char* name, uint32 type)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
|
|
||||||
@@ -222,9 +221,9 @@ Index::Create(Transaction &transaction, const char *name, uint32 type)
|
|||||||
You may not want to let the whole transaction fail because of that.
|
You may not want to let the whole transaction fail because of that.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Index::Update(Transaction &transaction, const char *name, int32 type,
|
Index::Update(Transaction &transaction, const char* name, int32 type,
|
||||||
const uint8 *oldKey, uint16 oldLength, const uint8 *newKey,
|
const uint8* oldKey, uint16 oldLength, const uint8* newKey,
|
||||||
uint16 newLength, Inode *inode)
|
uint16 newLength, Inode* inode)
|
||||||
{
|
{
|
||||||
if (name == NULL
|
if (name == NULL
|
||||||
|| (oldKey == NULL && newKey == NULL)
|
|| (oldKey == NULL && newKey == NULL)
|
||||||
@@ -262,7 +261,7 @@ Index::Update(Transaction &transaction, const char *name, int32 type,
|
|||||||
newKey, newLength);
|
newKey, newLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
BPlusTree *tree;
|
BPlusTree* tree;
|
||||||
status_t status = Node()->GetTree(&tree);
|
status_t status = Node()->GetTree(&tree);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
@@ -272,7 +271,7 @@ Index::Update(Transaction &transaction, const char *name, int32 type,
|
|||||||
Node()->WriteLockInTransaction(transaction);
|
Node()->WriteLockInTransaction(transaction);
|
||||||
|
|
||||||
if (oldKey != NULL) {
|
if (oldKey != NULL) {
|
||||||
status = tree->Remove(transaction, (const uint8 *)oldKey, oldLength,
|
status = tree->Remove(transaction, (const uint8*)oldKey, oldLength,
|
||||||
inode->ID());
|
inode->ID());
|
||||||
if (status == B_ENTRY_NOT_FOUND) {
|
if (status == B_ENTRY_NOT_FOUND) {
|
||||||
// That's not nice, but no reason to let the whole thing fail
|
// That's not nice, but no reason to let the whole thing fail
|
||||||
@@ -284,7 +283,7 @@ Index::Update(Transaction &transaction, const char *name, int32 type,
|
|||||||
// add the new key to the tree
|
// add the new key to the tree
|
||||||
|
|
||||||
if (newKey != NULL) {
|
if (newKey != NULL) {
|
||||||
status = tree->Insert(transaction, (const uint8 *)newKey, newLength,
|
status = tree->Insert(transaction, (const uint8*)newKey, newLength,
|
||||||
inode->ID());
|
inode->ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,57 +292,57 @@ Index::Update(Transaction &transaction, const char *name, int32 type,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::InsertName(Transaction &transaction, const char *name, Inode *inode)
|
Index::InsertName(Transaction &transaction, const char* name, Inode* inode)
|
||||||
{
|
{
|
||||||
return UpdateName(transaction, NULL, name, inode);
|
return UpdateName(transaction, NULL, name, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::RemoveName(Transaction &transaction, const char *name, Inode *inode)
|
Index::RemoveName(Transaction &transaction, const char* name, Inode* inode)
|
||||||
{
|
{
|
||||||
return UpdateName(transaction, name, NULL, inode);
|
return UpdateName(transaction, name, NULL, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::UpdateName(Transaction &transaction, const char *oldName,
|
Index::UpdateName(Transaction &transaction, const char* oldName,
|
||||||
const char *newName, Inode *inode)
|
const char* newName, Inode* inode)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsRegularNode());
|
ASSERT(inode->IsRegularNode());
|
||||||
|
|
||||||
uint16 oldLength = oldName != NULL ? strlen(oldName) : 0;
|
uint16 oldLength = oldName != NULL ? strlen(oldName) : 0;
|
||||||
uint16 newLength = newName != NULL ? strlen(newName) : 0;
|
uint16 newLength = newName != NULL ? strlen(newName) : 0;
|
||||||
return Update(transaction, "name", B_STRING_TYPE, (uint8 *)oldName,
|
return Update(transaction, "name", B_STRING_TYPE, (uint8*)oldName,
|
||||||
oldLength, (uint8 *)newName, newLength, inode);
|
oldLength, (uint8*)newName, newLength, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::InsertSize(Transaction &transaction, Inode *inode)
|
Index::InsertSize(Transaction &transaction, Inode* inode)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsFile());
|
ASSERT(inode->IsFile());
|
||||||
|
|
||||||
off_t size = inode->Size();
|
off_t size = inode->Size();
|
||||||
return Update(transaction, "size", B_INT64_TYPE, NULL, 0, (uint8 *)&size,
|
return Update(transaction, "size", B_INT64_TYPE, NULL, 0, (uint8*)&size,
|
||||||
sizeof(int64), inode);
|
sizeof(int64), inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::RemoveSize(Transaction &transaction, Inode *inode)
|
Index::RemoveSize(Transaction &transaction, Inode* inode)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsFile());
|
ASSERT(inode->IsFile());
|
||||||
|
|
||||||
// Inode::OldSize() is the size that's in the index
|
// Inode::OldSize() is the size that's in the index
|
||||||
off_t size = inode->OldSize();
|
off_t size = inode->OldSize();
|
||||||
return Update(transaction, "size", B_INT64_TYPE, (uint8 *)&size,
|
return Update(transaction, "size", B_INT64_TYPE, (uint8*)&size,
|
||||||
sizeof(int64), NULL, 0, inode);
|
sizeof(int64), NULL, 0, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::UpdateSize(Transaction &transaction, Inode *inode)
|
Index::UpdateSize(Transaction &transaction, Inode* inode)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsFile());
|
ASSERT(inode->IsFile());
|
||||||
|
|
||||||
@@ -351,7 +350,7 @@ Index::UpdateSize(Transaction &transaction, Inode *inode)
|
|||||||
off_t newSize = inode->Size();
|
off_t newSize = inode->Size();
|
||||||
|
|
||||||
status_t status = Update(transaction, "size", B_INT64_TYPE,
|
status_t status = Update(transaction, "size", B_INT64_TYPE,
|
||||||
(uint8 *)&oldSize, sizeof(int64), (uint8 *)&newSize, sizeof(int64),
|
(uint8*)&oldSize, sizeof(int64), (uint8*)&newSize, sizeof(int64),
|
||||||
inode);
|
inode);
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
inode->UpdateOldSize();
|
inode->UpdateOldSize();
|
||||||
@@ -361,30 +360,30 @@ Index::UpdateSize(Transaction &transaction, Inode *inode)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::InsertLastModified(Transaction &transaction, Inode *inode)
|
Index::InsertLastModified(Transaction &transaction, Inode* inode)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsFile() || inode->IsSymLink());
|
ASSERT(inode->IsFile() || inode->IsSymLink());
|
||||||
|
|
||||||
off_t modified = inode->LastModified();
|
off_t modified = inode->LastModified();
|
||||||
return Update(transaction, "last_modified", B_INT64_TYPE, NULL, 0,
|
return Update(transaction, "last_modified", B_INT64_TYPE, NULL, 0,
|
||||||
(uint8 *)&modified, sizeof(int64), inode);
|
(uint8*)&modified, sizeof(int64), inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::RemoveLastModified(Transaction &transaction, Inode *inode)
|
Index::RemoveLastModified(Transaction &transaction, Inode* inode)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsFile() || inode->IsSymLink());
|
ASSERT(inode->IsFile() || inode->IsSymLink());
|
||||||
|
|
||||||
// Inode::OldLastModified() is the value which is in the index
|
// Inode::OldLastModified() is the value which is in the index
|
||||||
off_t modified = inode->OldLastModified();
|
off_t modified = inode->OldLastModified();
|
||||||
return Update(transaction, "last_modified", B_INT64_TYPE,
|
return Update(transaction, "last_modified", B_INT64_TYPE,
|
||||||
(uint8 *)&modified, sizeof(int64), NULL, 0, inode);
|
(uint8*)&modified, sizeof(int64), NULL, 0, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Index::UpdateLastModified(Transaction &transaction, Inode *inode,
|
Index::UpdateLastModified(Transaction &transaction, Inode* inode,
|
||||||
off_t modified)
|
off_t modified)
|
||||||
{
|
{
|
||||||
ASSERT(inode->IsFile() || inode->IsSymLink());
|
ASSERT(inode->IsFile() || inode->IsSymLink());
|
||||||
@@ -395,7 +394,7 @@ Index::UpdateLastModified(Transaction &transaction, Inode *inode,
|
|||||||
modified |= fVolume->GetUniqueID() & INODE_TIME_MASK;
|
modified |= fVolume->GetUniqueID() & INODE_TIME_MASK;
|
||||||
|
|
||||||
status_t status = Update(transaction, "last_modified", B_INT64_TYPE,
|
status_t status = Update(transaction, "last_modified", B_INT64_TYPE,
|
||||||
(uint8 *)&oldModified, sizeof(int64), (uint8 *)&modified,
|
(uint8*)&oldModified, sizeof(int64), (uint8*)&modified,
|
||||||
sizeof(int64), inode);
|
sizeof(int64), inode);
|
||||||
|
|
||||||
inode->Node().last_modified_time = HOST_ENDIAN_TO_BFS_INT64(modified);
|
inode->Node().last_modified_time = HOST_ENDIAN_TO_BFS_INT64(modified);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/* Index - index access functions
|
/*
|
||||||
*
|
* Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Copyright 2001-2004, Axel Dörfler, axeld@pinc-software.de.
|
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef INDEX_H
|
#ifndef INDEX_H
|
||||||
@@ -9,49 +8,59 @@
|
|||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
|
|
||||||
class Transaction;
|
class Transaction;
|
||||||
class Volume;
|
class Volume;
|
||||||
class Inode;
|
class Inode;
|
||||||
|
|
||||||
|
|
||||||
class Index {
|
class Index {
|
||||||
public:
|
public:
|
||||||
Index(Volume *volume);
|
Index(Volume* volume);
|
||||||
~Index();
|
~Index();
|
||||||
|
|
||||||
status_t SetTo(const char *name);
|
status_t SetTo(const char* name);
|
||||||
void Unset();
|
void Unset();
|
||||||
|
|
||||||
Inode *Node() const { return fNode; };
|
Inode* Node() const { return fNode; };
|
||||||
uint32 Type();
|
uint32 Type();
|
||||||
size_t KeySize();
|
size_t KeySize();
|
||||||
|
|
||||||
status_t Create(Transaction &transaction, const char *name, uint32 type);
|
status_t Create(Transaction& transaction, const char* name,
|
||||||
|
uint32 type);
|
||||||
|
|
||||||
status_t Update(Transaction &transaction, const char *name, int32 type, const uint8 *oldKey,
|
status_t Update(Transaction& transaction, const char* name,
|
||||||
uint16 oldLength, const uint8 *newKey, uint16 newLength, Inode *inode);
|
int32 type, const uint8* oldKey,
|
||||||
|
uint16 oldLength, const uint8* newKey,
|
||||||
|
uint16 newLength, Inode* inode);
|
||||||
|
|
||||||
status_t InsertName(Transaction &transaction, const char *name, Inode *inode);
|
status_t InsertName(Transaction& transaction,
|
||||||
status_t RemoveName(Transaction &transaction, const char *name, Inode *inode);
|
const char* name, Inode* inode);
|
||||||
status_t UpdateName(Transaction &transaction, const char *oldName, const char *newName,
|
status_t RemoveName(Transaction& transaction,
|
||||||
Inode *inode);
|
const char* name, Inode* inode);
|
||||||
|
status_t UpdateName(Transaction& transaction,
|
||||||
|
const char* oldName, const char* newName,
|
||||||
|
Inode* inode);
|
||||||
|
|
||||||
status_t InsertSize(Transaction &transaction, Inode *inode);
|
status_t InsertSize(Transaction& transaction, Inode* inode);
|
||||||
status_t RemoveSize(Transaction &transaction, Inode *inode);
|
status_t RemoveSize(Transaction& transaction, Inode* inode);
|
||||||
status_t UpdateSize(Transaction &transaction, Inode *inode);
|
status_t UpdateSize(Transaction& transaction, Inode* inode);
|
||||||
|
|
||||||
status_t InsertLastModified(Transaction &transaction, Inode *inode);
|
status_t InsertLastModified(Transaction& transaction,
|
||||||
status_t RemoveLastModified(Transaction &transaction, Inode *inode);
|
Inode* inode);
|
||||||
status_t UpdateLastModified(Transaction &transaction, Inode *inode, off_t modified = -1);
|
status_t RemoveLastModified(Transaction& transaction,
|
||||||
|
Inode* inode);
|
||||||
|
status_t UpdateLastModified(Transaction& transaction,
|
||||||
|
Inode* inode, off_t modified = -1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Index(const Index &);
|
Index(const Index& other);
|
||||||
Index &operator=(const Index &);
|
Index& operator=(const Index& other);
|
||||||
// no implementation
|
// no implementation
|
||||||
|
|
||||||
Volume *fVolume;
|
Volume* fVolume;
|
||||||
Inode *fNode;
|
Inode* fNode;
|
||||||
const char *fName;
|
const char* fName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INDEX_H */
|
#endif // INDEX_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,67 +18,69 @@ struct run_array {
|
|||||||
block_run runs[0];
|
block_run runs[0];
|
||||||
|
|
||||||
void Init(int32 blockSize);
|
void Init(int32 blockSize);
|
||||||
void Insert(block_run &run);
|
void Insert(block_run& run);
|
||||||
|
|
||||||
int32 CountRuns() const { return BFS_ENDIAN_TO_HOST_INT32(count); }
|
int32 CountRuns() const { return BFS_ENDIAN_TO_HOST_INT32(count); }
|
||||||
int32 MaxRuns() const { return BFS_ENDIAN_TO_HOST_INT32(max_runs) - 1; }
|
int32 MaxRuns() const { return BFS_ENDIAN_TO_HOST_INT32(max_runs) - 1; }
|
||||||
// that -1 accounts for an off-by-one error in Be's BFS implementation
|
// that -1 accounts for an off-by-one error in Be's BFS implementation
|
||||||
const block_run &RunAt(int32 i) const { return runs[i]; }
|
const block_run& RunAt(int32 i) const { return runs[i]; }
|
||||||
|
|
||||||
static int32 MaxRuns(int32 blockSize);
|
static int32 MaxRuns(int32 blockSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int _Compare(block_run &a, block_run &b);
|
static int _Compare(block_run& a, block_run& b);
|
||||||
int32 _FindInsertionIndex(block_run &run);
|
int32 _FindInsertionIndex(block_run& run);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RunArrays {
|
class RunArrays {
|
||||||
public:
|
public:
|
||||||
RunArrays(Journal *journal);
|
RunArrays(Journal* journal);
|
||||||
~RunArrays();
|
~RunArrays();
|
||||||
|
|
||||||
status_t Insert(off_t blockNumber);
|
status_t Insert(off_t blockNumber);
|
||||||
|
|
||||||
run_array *ArrayAt(int32 i) { return fArrays.Array()[i]; }
|
run_array* ArrayAt(int32 i) { return fArrays.Array()[i]; }
|
||||||
int32 CountArrays() const { return fArrays.CountItems(); }
|
int32 CountArrays() const { return fArrays.CountItems(); }
|
||||||
|
|
||||||
uint32 CountBlocks() const { return fBlockCount; }
|
uint32 CountBlocks() const { return fBlockCount; }
|
||||||
uint32 LogEntryLength() const { return CountBlocks() + CountArrays(); }
|
uint32 LogEntryLength() const
|
||||||
|
{ return CountBlocks() + CountArrays(); }
|
||||||
|
|
||||||
int32 MaxArrayLength();
|
int32 MaxArrayLength();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _AddArray();
|
status_t _AddArray();
|
||||||
bool _ContainsRun(block_run &run);
|
bool _ContainsRun(block_run& run);
|
||||||
bool _AddRun(block_run &run);
|
bool _AddRun(block_run& run);
|
||||||
|
|
||||||
Journal *fJournal;
|
Journal* fJournal;
|
||||||
uint32 fBlockCount;
|
uint32 fBlockCount;
|
||||||
Stack<run_array *> fArrays;
|
Stack<run_array*> fArrays;
|
||||||
run_array *fLastArray;
|
run_array* fLastArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LogEntry : public DoublyLinkedListLinkImpl<LogEntry> {
|
class LogEntry : public DoublyLinkedListLinkImpl<LogEntry> {
|
||||||
public:
|
public:
|
||||||
LogEntry(Journal *journal, uint32 logStart, uint32 length);
|
LogEntry(Journal* journal, uint32 logStart,
|
||||||
~LogEntry();
|
uint32 length);
|
||||||
|
~LogEntry();
|
||||||
|
|
||||||
uint32 Start() const { return fStart; }
|
uint32 Start() const { return fStart; }
|
||||||
uint32 Length() const { return fLength; }
|
uint32 Length() const { return fLength; }
|
||||||
|
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
void SetTransactionID(int32 id) { fTransactionID = id; }
|
void SetTransactionID(int32 id) { fTransactionID = id; }
|
||||||
int32 TransactionID() const { return fTransactionID; }
|
int32 TransactionID() const { return fTransactionID; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Journal *GetJournal() { return fJournal; }
|
Journal* GetJournal() { return fJournal; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Journal *fJournal;
|
Journal* fJournal;
|
||||||
uint32 fStart;
|
uint32 fStart;
|
||||||
uint32 fLength;
|
uint32 fLength;
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
int32 fTransactionID;
|
int32 fTransactionID;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -87,44 +89,44 @@ class LogEntry : public DoublyLinkedListLinkImpl<LogEntry> {
|
|||||||
namespace BFSJournalTracing {
|
namespace BFSJournalTracing {
|
||||||
|
|
||||||
class LogEntry : public AbstractTraceEntry {
|
class LogEntry : public AbstractTraceEntry {
|
||||||
public:
|
public:
|
||||||
LogEntry(::LogEntry* entry, off_t logPosition, bool started)
|
LogEntry(::LogEntry* entry, off_t logPosition, bool started)
|
||||||
:
|
:
|
||||||
fEntry(entry),
|
fEntry(entry),
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
fTransactionID(entry->TransactionID()),
|
fTransactionID(entry->TransactionID()),
|
||||||
#endif
|
#endif
|
||||||
fStart(entry->Start()),
|
fStart(entry->Start()),
|
||||||
fLength(entry->Length()),
|
fLength(entry->Length()),
|
||||||
fLogPosition(logPosition),
|
fLogPosition(logPosition),
|
||||||
fStarted(started)
|
fStarted(started)
|
||||||
{
|
{
|
||||||
Initialized();
|
Initialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AddDump(TraceOutput& out)
|
virtual void AddDump(TraceOutput& out)
|
||||||
{
|
{
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
out.Print("bfs:j:%s entry %p id %ld, start %lu, length %lu, log %s "
|
out.Print("bfs:j:%s entry %p id %ld, start %lu, length %lu, log %s "
|
||||||
"%lu\n", fStarted ? "Started" : "Written", fEntry,
|
"%lu\n", fStarted ? "Started" : "Written", fEntry,
|
||||||
fTransactionID, fStart, fLength,
|
fTransactionID, fStart, fLength,
|
||||||
fStarted ? "end" : "start", fLogPosition);
|
fStarted ? "end" : "start", fLogPosition);
|
||||||
#else
|
#else
|
||||||
out.Print("bfs:j:%s entry %p start %lu, length %lu, log %s %lu\n",
|
out.Print("bfs:j:%s entry %p start %lu, length %lu, log %s %lu\n",
|
||||||
fStarted ? "Started" : "Written", fEntry, fStart, fLength,
|
fStarted ? "Started" : "Written", fEntry, fStart, fLength,
|
||||||
fStarted ? "end" : "start", fLogPosition);
|
fStarted ? "end" : "start", fLogPosition);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::LogEntry* fEntry;
|
::LogEntry* fEntry;
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
int32 fTransactionID;
|
int32 fTransactionID;
|
||||||
#endif
|
#endif
|
||||||
uint32 fStart;
|
uint32 fStart;
|
||||||
uint32 fLength;
|
uint32 fLength;
|
||||||
uint32 fLogPosition;
|
uint32 fLogPosition;
|
||||||
bool fStarted;
|
bool fStarted;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BFSJournalTracing
|
} // namespace BFSJournalTracing
|
||||||
@@ -139,7 +141,7 @@ class LogEntry : public AbstractTraceEntry {
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_to_iovec(iovec *vecs, int32 &index, int32 max, const void *address,
|
add_to_iovec(iovec* vecs, int32& index, int32 max, const void* address,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
if (index > 0 && (addr_t)vecs[index - 1].iov_base
|
if (index > 0 && (addr_t)vecs[index - 1].iov_base
|
||||||
@@ -153,7 +155,7 @@ add_to_iovec(iovec *vecs, int32 &index, int32 max, const void *address,
|
|||||||
panic("no more space for iovecs!");
|
panic("no more space for iovecs!");
|
||||||
|
|
||||||
// we need to start a new iovec
|
// we need to start a new iovec
|
||||||
vecs[index].iov_base = const_cast<void *>(address);
|
vecs[index].iov_base = const_cast<void*>(address);
|
||||||
vecs[index].iov_len = size;
|
vecs[index].iov_len = size;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -162,7 +164,7 @@ add_to_iovec(iovec *vecs, int32 &index, int32 max, const void *address,
|
|||||||
// #pragma mark - LogEntry
|
// #pragma mark - LogEntry
|
||||||
|
|
||||||
|
|
||||||
LogEntry::LogEntry(Journal *journal, uint32 start, uint32 length)
|
LogEntry::LogEntry(Journal* journal, uint32 start, uint32 length)
|
||||||
:
|
:
|
||||||
fJournal(journal),
|
fJournal(journal),
|
||||||
fStart(start),
|
fStart(start),
|
||||||
@@ -196,7 +198,7 @@ run_array::Init(int32 blockSize)
|
|||||||
array is large enough to contain the entry before calling this function.
|
array is large enough to contain the entry before calling this function.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
run_array::Insert(block_run &run)
|
run_array::Insert(block_run& run)
|
||||||
{
|
{
|
||||||
int32 index = _FindInsertionIndex(run);
|
int32 index = _FindInsertionIndex(run);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
@@ -226,7 +228,7 @@ run_array::MaxRuns(int32 blockSize)
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ int
|
/*static*/ int
|
||||||
run_array::_Compare(block_run &a, block_run &b)
|
run_array::_Compare(block_run& a, block_run& b)
|
||||||
{
|
{
|
||||||
int cmp = a.AllocationGroup() - b.AllocationGroup();
|
int cmp = a.AllocationGroup() - b.AllocationGroup();
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
@@ -237,7 +239,7 @@ run_array::_Compare(block_run &a, block_run &b)
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
run_array::_FindInsertionIndex(block_run &run)
|
run_array::_FindInsertionIndex(block_run& run)
|
||||||
{
|
{
|
||||||
int32 min = 0, max = CountRuns() - 1;
|
int32 min = 0, max = CountRuns() - 1;
|
||||||
int32 i = 0;
|
int32 i = 0;
|
||||||
@@ -272,7 +274,7 @@ run_array::_FindInsertionIndex(block_run &run)
|
|||||||
// #pragma mark - RunArrays
|
// #pragma mark - RunArrays
|
||||||
|
|
||||||
|
|
||||||
RunArrays::RunArrays(Journal *journal)
|
RunArrays::RunArrays(Journal* journal)
|
||||||
:
|
:
|
||||||
fJournal(journal),
|
fJournal(journal),
|
||||||
fBlockCount(0),
|
fBlockCount(0),
|
||||||
@@ -284,20 +286,20 @@ RunArrays::RunArrays(Journal *journal)
|
|||||||
|
|
||||||
RunArrays::~RunArrays()
|
RunArrays::~RunArrays()
|
||||||
{
|
{
|
||||||
run_array *array;
|
run_array* array;
|
||||||
while (fArrays.Pop(&array))
|
while (fArrays.Pop(&array))
|
||||||
free(array);
|
free(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RunArrays::_ContainsRun(block_run &run)
|
RunArrays::_ContainsRun(block_run& run)
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < CountArrays(); i++) {
|
for (int32 i = 0; i < CountArrays(); i++) {
|
||||||
run_array *array = ArrayAt(i);
|
run_array* array = ArrayAt(i);
|
||||||
|
|
||||||
for (int32 j = 0; j < array->CountRuns(); j++) {
|
for (int32 j = 0; j < array->CountRuns(); j++) {
|
||||||
block_run &arrayRun = array->runs[j];
|
block_run& arrayRun = array->runs[j];
|
||||||
if (run.AllocationGroup() != arrayRun.AllocationGroup())
|
if (run.AllocationGroup() != arrayRun.AllocationGroup())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -317,7 +319,7 @@ RunArrays::_ContainsRun(block_run &run)
|
|||||||
with block_runs of length 1!
|
with block_runs of length 1!
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
RunArrays::_AddRun(block_run &run)
|
RunArrays::_AddRun(block_run& run)
|
||||||
{
|
{
|
||||||
ASSERT(run.length == 1);
|
ASSERT(run.length == 1);
|
||||||
|
|
||||||
@@ -338,7 +340,7 @@ RunArrays::_AddArray()
|
|||||||
{
|
{
|
||||||
int32 blockSize = fJournal->GetVolume()->BlockSize();
|
int32 blockSize = fJournal->GetVolume()->BlockSize();
|
||||||
|
|
||||||
run_array *array = (run_array *)malloc(blockSize);
|
run_array* array = (run_array*)malloc(blockSize);
|
||||||
if (array == NULL)
|
if (array == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -356,7 +358,7 @@ RunArrays::_AddArray()
|
|||||||
status_t
|
status_t
|
||||||
RunArrays::Insert(off_t blockNumber)
|
RunArrays::Insert(off_t blockNumber)
|
||||||
{
|
{
|
||||||
Volume *volume = fJournal->GetVolume();
|
Volume* volume = fJournal->GetVolume();
|
||||||
block_run run = volume->ToBlockRun(blockNumber);
|
block_run run = volume->ToBlockRun(blockNumber);
|
||||||
|
|
||||||
if (fLastArray != NULL) {
|
if (fLastArray != NULL) {
|
||||||
@@ -393,7 +395,7 @@ RunArrays::MaxArrayLength()
|
|||||||
// #pragma mark - Journal
|
// #pragma mark - Journal
|
||||||
|
|
||||||
|
|
||||||
Journal::Journal(Volume *volume)
|
Journal::Journal(Volume* volume)
|
||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
fOwner(NULL),
|
fOwner(NULL),
|
||||||
@@ -429,7 +431,7 @@ Journal::InitCheck()
|
|||||||
within a the volume.
|
within a the volume.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Journal::_CheckRunArray(const run_array *array)
|
Journal::_CheckRunArray(const run_array* array)
|
||||||
{
|
{
|
||||||
int32 maxRuns = run_array::MaxRuns(fVolume->BlockSize()) - 1;
|
int32 maxRuns = run_array::MaxRuns(fVolume->BlockSize()) - 1;
|
||||||
// the -1 works around an off-by-one bug in Be's BFS implementation,
|
// the -1 works around an off-by-one bug in Be's BFS implementation,
|
||||||
@@ -458,7 +460,7 @@ Journal::_CheckRunArray(const run_array *array)
|
|||||||
one if replaying succeeded.
|
one if replaying succeeded.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Journal::_ReplayRunArray(int32 *_start)
|
Journal::_ReplayRunArray(int32* _start)
|
||||||
{
|
{
|
||||||
PRINT(("ReplayRunArray(start = %ld)\n", *_start));
|
PRINT(("ReplayRunArray(start = %ld)\n", *_start));
|
||||||
|
|
||||||
@@ -467,7 +469,7 @@ Journal::_ReplayRunArray(int32 *_start)
|
|||||||
|
|
||||||
CachedBlock cachedArray(fVolume);
|
CachedBlock cachedArray(fVolume);
|
||||||
|
|
||||||
const run_array *array = (const run_array *)cachedArray.SetTo(logOffset
|
const run_array* array = (const run_array*)cachedArray.SetTo(logOffset
|
||||||
+ firstBlockNumber);
|
+ firstBlockNumber);
|
||||||
if (array == NULL)
|
if (array == NULL)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
@@ -484,11 +486,11 @@ Journal::_ReplayRunArray(int32 *_start)
|
|||||||
int32 blockSize = fVolume->BlockSize();
|
int32 blockSize = fVolume->BlockSize();
|
||||||
|
|
||||||
for (int32 index = 0; index < array->CountRuns(); index++) {
|
for (int32 index = 0; index < array->CountRuns(); index++) {
|
||||||
const block_run &run = array->RunAt(index);
|
const block_run& run = array->RunAt(index);
|
||||||
|
|
||||||
off_t offset = fVolume->ToOffset(run);
|
off_t offset = fVolume->ToOffset(run);
|
||||||
for (int32 i = 0; i < run.Length(); i++) {
|
for (int32 i = 0; i < run.Length(); i++) {
|
||||||
const uint8 *data = cached.SetTo(logOffset + blockNumber);
|
const uint8* data = cached.SetTo(logOffset + blockNumber);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
RETURN_ERROR(B_IO_ERROR);
|
||||||
|
|
||||||
@@ -514,13 +516,13 @@ Journal::_ReplayRunArray(int32 *_start)
|
|||||||
int32 count = 1;
|
int32 count = 1;
|
||||||
|
|
||||||
for (int32 index = 0; index < array->CountRuns(); index++) {
|
for (int32 index = 0; index < array->CountRuns(); index++) {
|
||||||
const block_run &run = array->RunAt(index);
|
const block_run& run = array->RunAt(index);
|
||||||
INFORM(("replay block run %u:%u:%u in log at %Ld!\n",
|
INFORM(("replay block run %u:%u:%u in log at %Ld!\n",
|
||||||
(int)run.AllocationGroup(), run.Start(), run.Length(), blockNumber));
|
(int)run.AllocationGroup(), run.Start(), run.Length(), blockNumber));
|
||||||
|
|
||||||
off_t offset = fVolume->ToOffset(run);
|
off_t offset = fVolume->ToOffset(run);
|
||||||
for (int32 i = 0; i < run.Length(); i++) {
|
for (int32 i = 0; i < run.Length(); i++) {
|
||||||
const uint8 *data = cached.SetTo(logOffset + blockNumber);
|
const uint8* data = cached.SetTo(logOffset + blockNumber);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
RETURN_ERROR(B_IO_ERROR);
|
RETURN_ERROR(B_IO_ERROR);
|
||||||
|
|
||||||
@@ -597,15 +599,15 @@ Journal::ReplayLog()
|
|||||||
completed in the order they were written.
|
completed in the order they were written.
|
||||||
*/
|
*/
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
|
Journal::_TransactionWritten(int32 transactionID, int32 event, void* _logEntry)
|
||||||
{
|
{
|
||||||
LogEntry *logEntry = (LogEntry *)_logEntry;
|
LogEntry* logEntry = (LogEntry*)_logEntry;
|
||||||
|
|
||||||
PRINT(("Log entry %p has been finished, transaction ID = %ld\n", logEntry,
|
PRINT(("Log entry %p has been finished, transaction ID = %ld\n", logEntry,
|
||||||
transactionID));
|
transactionID));
|
||||||
|
|
||||||
Journal *journal = logEntry->GetJournal();
|
Journal* journal = logEntry->GetJournal();
|
||||||
disk_super_block &superBlock = journal->fVolume->SuperBlock();
|
disk_super_block& superBlock = journal->fVolume->SuperBlock();
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
|
||||||
// Set log_start pointer if possible...
|
// Set log_start pointer if possible...
|
||||||
@@ -613,7 +615,7 @@ Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
|
|||||||
mutex_lock(&journal->fEntriesLock);
|
mutex_lock(&journal->fEntriesLock);
|
||||||
|
|
||||||
if (logEntry == journal->fEntries.First()) {
|
if (logEntry == journal->fEntries.First()) {
|
||||||
LogEntry *next = journal->fEntries.GetNext(logEntry);
|
LogEntry* next = journal->fEntries.GetNext(logEntry);
|
||||||
if (next != NULL) {
|
if (next != NULL) {
|
||||||
superBlock.log_start = HOST_ENDIAN_TO_BFS_INT64(next->Start()
|
superBlock.log_start = HOST_ENDIAN_TO_BFS_INT64(next->Start()
|
||||||
% journal->fLogSize);
|
% journal->fLogSize);
|
||||||
@@ -652,11 +654,11 @@ Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
|
|||||||
|
|
||||||
/*! Listens to TRANSACTION_IDLE events, and flushes the log when that happens */
|
/*! Listens to TRANSACTION_IDLE events, and flushes the log when that happens */
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
Journal::_TransactionIdle(int32 transactionID, int32 event, void *_journal)
|
Journal::_TransactionIdle(int32 transactionID, int32 event, void* _journal)
|
||||||
{
|
{
|
||||||
// The current transaction seems to be idle - flush it
|
// The current transaction seems to be idle - flush it
|
||||||
|
|
||||||
Journal *journal = (Journal *)_journal;
|
Journal* journal = (Journal*)_journal;
|
||||||
journal->_FlushLog(false, false);
|
journal->_FlushLog(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -745,23 +747,23 @@ Journal::_WriteTransactionToLog()
|
|||||||
int32 maxVecs = runArrays.MaxArrayLength() + 1;
|
int32 maxVecs = runArrays.MaxArrayLength() + 1;
|
||||||
// one extra for the index block
|
// one extra for the index block
|
||||||
|
|
||||||
iovec *vecs = (iovec *)malloc(sizeof(iovec) * maxVecs);
|
iovec* vecs = (iovec*)malloc(sizeof(iovec) * maxVecs);
|
||||||
if (vecs == NULL) {
|
if (vecs == NULL) {
|
||||||
// TODO: write back log entries directly?
|
// TODO: write back log entries directly?
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 k = 0; k < runArrays.CountArrays(); k++) {
|
for (int32 k = 0; k < runArrays.CountArrays(); k++) {
|
||||||
run_array *array = runArrays.ArrayAt(k);
|
run_array* array = runArrays.ArrayAt(k);
|
||||||
int32 index = 0, count = 1;
|
int32 index = 0, count = 1;
|
||||||
int32 wrap = fLogSize - logStart;
|
int32 wrap = fLogSize - logStart;
|
||||||
|
|
||||||
add_to_iovec(vecs, index, maxVecs, (void *)array, fVolume->BlockSize());
|
add_to_iovec(vecs, index, maxVecs, (void*)array, fVolume->BlockSize());
|
||||||
|
|
||||||
// add block runs
|
// add block runs
|
||||||
|
|
||||||
for (int32 i = 0; i < array->CountRuns(); i++) {
|
for (int32 i = 0; i < array->CountRuns(); i++) {
|
||||||
const block_run &run = array->RunAt(i);
|
const block_run& run = array->RunAt(i);
|
||||||
off_t blockNumber = fVolume->ToBlock(run);
|
off_t blockNumber = fVolume->ToBlock(run);
|
||||||
|
|
||||||
for (int32 j = 0; j < run.Length(); j++) {
|
for (int32 j = 0; j < run.Length(); j++) {
|
||||||
@@ -780,7 +782,7 @@ Journal::_WriteTransactionToLog()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make blocks available in the cache
|
// make blocks available in the cache
|
||||||
const void *data = block_cache_get(fVolume->BlockCache(),
|
const void* data = block_cache_get(fVolume->BlockCache(),
|
||||||
blockNumber + j);
|
blockNumber + j);
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
free(vecs);
|
free(vecs);
|
||||||
@@ -802,7 +804,7 @@ Journal::_WriteTransactionToLog()
|
|||||||
|
|
||||||
// release blocks again
|
// release blocks again
|
||||||
for (int32 i = 0; i < array->CountRuns(); i++) {
|
for (int32 i = 0; i < array->CountRuns(); i++) {
|
||||||
const block_run &run = array->RunAt(i);
|
const block_run& run = array->RunAt(i);
|
||||||
off_t blockNumber = fVolume->ToBlock(run);
|
off_t blockNumber = fVolume->ToBlock(run);
|
||||||
|
|
||||||
for (int32 j = 0; j < run.Length(); j++) {
|
for (int32 j = 0; j < run.Length(); j++) {
|
||||||
@@ -815,7 +817,7 @@ Journal::_WriteTransactionToLog()
|
|||||||
|
|
||||||
free(vecs);
|
free(vecs);
|
||||||
|
|
||||||
LogEntry *logEntry = new LogEntry(this, fVolume->LogEnd(),
|
LogEntry* logEntry = new LogEntry(this, fVolume->LogEnd(),
|
||||||
runArrays.LogEntryLength());
|
runArrays.LogEntryLength());
|
||||||
if (logEntry == NULL) {
|
if (logEntry == NULL) {
|
||||||
FATAL(("no memory to allocate log entries!"));
|
FATAL(("no memory to allocate log entries!"));
|
||||||
@@ -907,7 +909,7 @@ Journal::FlushLogAndBlocks()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Journal::Lock(Transaction *owner)
|
Journal::Lock(Transaction* owner)
|
||||||
{
|
{
|
||||||
status_t status = recursive_lock_lock(&fLock);
|
status_t status = recursive_lock_lock(&fLock);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
@@ -947,7 +949,7 @@ Journal::Lock(Transaction *owner)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Journal::Unlock(Transaction *owner, bool success)
|
Journal::Unlock(Transaction* owner, bool success)
|
||||||
{
|
{
|
||||||
if (recursive_lock_get_recursion(&fLock) == 1) {
|
if (recursive_lock_get_recursion(&fLock) == 1) {
|
||||||
// we only end the transaction if we would really unlock it
|
// we only end the transaction if we would really unlock it
|
||||||
@@ -1022,7 +1024,7 @@ Journal::Dump()
|
|||||||
LogEntryList::Iterator iterator = fEntries.GetIterator();
|
LogEntryList::Iterator iterator = fEntries.GetIterator();
|
||||||
|
|
||||||
while (iterator.HasNext()) {
|
while (iterator.HasNext()) {
|
||||||
LogEntry *entry = iterator.Next();
|
LogEntry* entry = iterator.Next();
|
||||||
|
|
||||||
kprintf(" %p %6ld %6lu %6lu\n", entry, entry->TransactionID(),
|
kprintf(" %p %6ld %6lu %6lu\n", entry, entry->TransactionID(),
|
||||||
entry->Start(), entry->Length());
|
entry->Start(), entry->Length());
|
||||||
@@ -1031,15 +1033,15 @@ Journal::Dump()
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dump_journal(int argc, char **argv)
|
dump_journal(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc != 2 || !strcmp(argv[1], "--help")) {
|
if (argc != 2 || !strcmp(argv[1], "--help")) {
|
||||||
kprintf("usage: %s <ptr-to-volume>\n", argv[0]);
|
kprintf("usage: %s <ptr-to-volume>\n", argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Volume *volume = (Volume *)parse_expression(argv[1]);
|
Volume* volume = (Volume*)parse_expression(argv[1]);
|
||||||
Journal *journal = volume->GetJournal(0);
|
Journal* journal = volume->GetJournal(0);
|
||||||
|
|
||||||
journal->Dump();
|
journal->Dump();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1052,7 +1054,7 @@ dump_journal(int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Transaction::Start(Volume *volume, off_t refBlock)
|
Transaction::Start(Volume* volume, off_t refBlock)
|
||||||
{
|
{
|
||||||
// has it already been started?
|
// has it already been started?
|
||||||
if (fJournal != NULL)
|
if (fJournal != NULL)
|
||||||
|
|||||||
@@ -8,10 +8,6 @@
|
|||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
#ifndef _IMPEXP_KERNEL
|
|
||||||
# define _IMPEXP_KERNEL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
|
|
||||||
@@ -23,62 +19,56 @@ typedef DoublyLinkedList<LogEntry> LogEntryList;
|
|||||||
typedef SinglyLinkedList<Inode> InodeList;
|
typedef SinglyLinkedList<Inode> InodeList;
|
||||||
|
|
||||||
|
|
||||||
// Locking policy in BFS: if you need both, the volume lock and the
|
|
||||||
// journal lock, you must lock the volume first - or else you will
|
|
||||||
// end up in a deadlock.
|
|
||||||
// That is, if you start a transaction, and will need to lock the
|
|
||||||
// volume while the transaction is in progress (for the unsafe
|
|
||||||
// get_vnode() call, for example), you must lock the volume before
|
|
||||||
// starting the transaction.
|
|
||||||
|
|
||||||
class Journal {
|
class Journal {
|
||||||
public:
|
public:
|
||||||
Journal(Volume *);
|
Journal(Volume* volume);
|
||||||
~Journal();
|
~Journal();
|
||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
status_t Lock(Transaction *owner);
|
status_t Lock(Transaction* owner);
|
||||||
void Unlock(Transaction *owner, bool success);
|
void Unlock(Transaction* owner, bool success);
|
||||||
|
|
||||||
status_t ReplayLog();
|
status_t ReplayLog();
|
||||||
|
|
||||||
Transaction *CurrentTransaction() const { return fOwner; }
|
Transaction* CurrentTransaction() const { return fOwner; }
|
||||||
|
|
||||||
status_t FlushLogAndBlocks();
|
status_t FlushLogAndBlocks();
|
||||||
Volume *GetVolume() const { return fVolume; }
|
Volume* GetVolume() const { return fVolume; }
|
||||||
int32 TransactionID() const { return fTransactionID; }
|
int32 TransactionID() const { return fTransactionID; }
|
||||||
|
|
||||||
inline uint32 FreeLogBlocks() const;
|
inline uint32 FreeLogBlocks() const;
|
||||||
|
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
void Dump();
|
void Dump();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _HasSubTransaction() { return fHasSubtransaction; }
|
bool _HasSubTransaction() { return fHasSubtransaction; }
|
||||||
status_t _FlushLog(bool canWait, bool flushBlocks);
|
status_t _FlushLog(bool canWait, bool flushBlocks);
|
||||||
uint32 _TransactionSize() const;
|
uint32 _TransactionSize() const;
|
||||||
status_t _WriteTransactionToLog();
|
status_t _WriteTransactionToLog();
|
||||||
status_t _CheckRunArray(const run_array *array);
|
status_t _CheckRunArray(const run_array* array);
|
||||||
status_t _ReplayRunArray(int32 *start);
|
status_t _ReplayRunArray(int32* start);
|
||||||
status_t _TransactionDone(bool success);
|
status_t _TransactionDone(bool success);
|
||||||
|
|
||||||
static void _TransactionWritten(int32 transactionID, int32 event,
|
static void _TransactionWritten(int32 transactionID,
|
||||||
void *_logEntry);
|
int32 event, void* _logEntry);
|
||||||
static void _TransactionIdle(int32 transactionID, int32 event,
|
static void _TransactionIdle(int32 transactionID, int32 event,
|
||||||
void *_journal);
|
void* _journal);
|
||||||
|
|
||||||
Volume *fVolume;
|
Volume* fVolume;
|
||||||
recursive_lock fLock;
|
recursive_lock fLock;
|
||||||
Transaction *fOwner;
|
Transaction* fOwner;
|
||||||
uint32 fLogSize, fMaxTransactionSize, fUsed;
|
uint32 fLogSize;
|
||||||
int32 fUnwrittenTransactions;
|
uint32 fMaxTransactionSize;
|
||||||
mutex fEntriesLock;
|
uint32 fUsed;
|
||||||
LogEntryList fEntries;
|
int32 fUnwrittenTransactions;
|
||||||
bigtime_t fTimestamp;
|
mutex fEntriesLock;
|
||||||
int32 fTransactionID;
|
LogEntryList fEntries;
|
||||||
bool fHasSubtransaction;
|
bigtime_t fTimestamp;
|
||||||
|
int32 fTransactionID;
|
||||||
|
bool fHasSubtransaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -96,99 +86,99 @@ Journal::FreeLogBlocks() const
|
|||||||
// It doesn't yet use logging.
|
// It doesn't yet use logging.
|
||||||
|
|
||||||
class Transaction {
|
class Transaction {
|
||||||
public:
|
public:
|
||||||
Transaction(Volume *volume, off_t refBlock)
|
Transaction(Volume* volume, off_t refBlock)
|
||||||
:
|
:
|
||||||
fJournal(NULL)
|
fJournal(NULL)
|
||||||
{
|
{
|
||||||
Start(volume, refBlock);
|
Start(volume, refBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction(Volume* volume, block_run refRun)
|
||||||
|
:
|
||||||
|
fJournal(NULL)
|
||||||
|
{
|
||||||
|
Start(volume, volume->ToBlock(refRun));
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction()
|
||||||
|
:
|
||||||
|
fJournal(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Transaction()
|
||||||
|
{
|
||||||
|
if (fJournal != NULL) {
|
||||||
|
fJournal->Unlock(this, false);
|
||||||
|
_UnlockInodes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Start(Volume* volume, off_t refBlock);
|
||||||
|
bool IsStarted() const { return fJournal != NULL; }
|
||||||
|
|
||||||
|
void Done()
|
||||||
|
{
|
||||||
|
if (fJournal != NULL) {
|
||||||
|
fJournal->Unlock(this, true);
|
||||||
|
_UnlockInodes();
|
||||||
|
}
|
||||||
|
fJournal = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasParent()
|
||||||
|
{
|
||||||
|
if (fJournal != NULL)
|
||||||
|
return fJournal->CurrentTransaction() == this;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t WriteBlocks(off_t blockNumber, const uint8* buffer,
|
||||||
|
size_t numBlocks = 1)
|
||||||
|
{
|
||||||
|
if (fJournal == NULL)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
void* cache = GetVolume()->BlockCache();
|
||||||
|
size_t blockSize = GetVolume()->BlockSize();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numBlocks; i++) {
|
||||||
|
void* block = block_cache_get_empty(cache, blockNumber + i,
|
||||||
|
ID());
|
||||||
|
if (block == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
memcpy(block, buffer, blockSize);
|
||||||
|
buffer += blockSize;
|
||||||
|
|
||||||
|
block_cache_put(cache, blockNumber + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction(Volume *volume, block_run refRun)
|
return B_OK;
|
||||||
:
|
}
|
||||||
fJournal(NULL)
|
|
||||||
{
|
|
||||||
Start(volume, volume->ToBlock(refRun));
|
|
||||||
}
|
|
||||||
|
|
||||||
Transaction()
|
Volume *GetVolume()
|
||||||
:
|
{ return fJournal != NULL ? fJournal->GetVolume() : NULL; }
|
||||||
fJournal(NULL)
|
int32 ID() const
|
||||||
{
|
{ return fJournal->TransactionID(); }
|
||||||
}
|
|
||||||
|
|
||||||
~Transaction()
|
void AddInode(Inode* inode);
|
||||||
{
|
|
||||||
if (fJournal != NULL) {
|
|
||||||
fJournal->Unlock(this, false);
|
|
||||||
_UnlockInodes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Start(Volume *volume, off_t refBlock);
|
private:
|
||||||
bool IsStarted() const { return fJournal != NULL; }
|
Transaction(const Transaction& other);
|
||||||
|
Transaction& operator=(const Transaction& other);
|
||||||
|
// no implementation
|
||||||
|
|
||||||
void Done()
|
void _UnlockInodes();
|
||||||
{
|
|
||||||
if (fJournal != NULL) {
|
|
||||||
fJournal->Unlock(this, true);
|
|
||||||
_UnlockInodes();
|
|
||||||
}
|
|
||||||
fJournal = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasParent()
|
Journal* fJournal;
|
||||||
{
|
InodeList fLockedInodes;
|
||||||
if (fJournal != NULL)
|
|
||||||
return fJournal->CurrentTransaction() == this;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t WriteBlocks(off_t blockNumber, const uint8 *buffer,
|
|
||||||
size_t numBlocks = 1)
|
|
||||||
{
|
|
||||||
if (fJournal == NULL)
|
|
||||||
return B_NO_INIT;
|
|
||||||
|
|
||||||
void *cache = GetVolume()->BlockCache();
|
|
||||||
size_t blockSize = GetVolume()->BlockSize();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numBlocks; i++) {
|
|
||||||
void *block = block_cache_get_empty(cache, blockNumber + i,
|
|
||||||
ID());
|
|
||||||
if (block == NULL)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
memcpy(block, buffer, blockSize);
|
|
||||||
buffer += blockSize;
|
|
||||||
|
|
||||||
block_cache_put(cache, blockNumber + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Volume *GetVolume()
|
|
||||||
{ return fJournal != NULL ? fJournal->GetVolume() : NULL; }
|
|
||||||
int32 ID() const
|
|
||||||
{ return fJournal->TransactionID(); }
|
|
||||||
|
|
||||||
void AddInode(Inode* inode);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Transaction(const Transaction &);
|
|
||||||
Transaction &operator=(const Transaction &);
|
|
||||||
// no implementation
|
|
||||||
|
|
||||||
void _UnlockInodes();
|
|
||||||
|
|
||||||
Journal* fJournal;
|
|
||||||
InodeList fLockedInodes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BFS_DEBUGGER_COMMANDS
|
#ifdef BFS_DEBUGGER_COMMANDS
|
||||||
int dump_journal(int argc, char **argv);
|
int dump_journal(int argc, char** argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* JOURNAL_H */
|
#endif // JOURNAL_H
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sorted_array::_FindInternal(off_t value, int32 &index) const
|
sorted_array::_FindInternal(off_t value, int32& index) const
|
||||||
{
|
{
|
||||||
int32 min = 0, max = count - 1;
|
int32 min = 0, max = count - 1;
|
||||||
off_t cmp;
|
off_t cmp;
|
||||||
@@ -61,7 +61,8 @@ sorted_array::Remove(off_t value)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
count--;
|
count--;
|
||||||
memmove(&values[index], &values[index + 1], (count - index) * sizeof(off_t));
|
memmove(&values[index], &values[index + 1],
|
||||||
|
(count - index) * sizeof(off_t));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,15 @@
|
|||||||
// TODO: this is not endian safe!!!
|
// TODO: this is not endian safe!!!
|
||||||
|
|
||||||
struct sorted_array {
|
struct sorted_array {
|
||||||
public:
|
off_t count;
|
||||||
off_t count;
|
off_t values[0];
|
||||||
off_t values[0];
|
|
||||||
|
|
||||||
inline int32 Find(off_t value) const;
|
inline int32 Find(off_t value) const;
|
||||||
void Insert(off_t value);
|
void Insert(off_t value);
|
||||||
bool Remove(off_t value);
|
bool Remove(off_t value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _FindInternal(off_t value, int32 &index) const;
|
bool _FindInternal(off_t value, int32& index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,116 +24,132 @@ enum volume_initialize_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Volume {
|
class Volume {
|
||||||
public:
|
public:
|
||||||
Volume(fs_volume *volume);
|
Volume(fs_volume* volume);
|
||||||
~Volume();
|
~Volume();
|
||||||
|
|
||||||
status_t Mount(const char *device, uint32 flags);
|
status_t Mount(const char* device, uint32 flags);
|
||||||
status_t Unmount();
|
status_t Unmount();
|
||||||
status_t Initialize(int fd, const char *name,
|
status_t Initialize(int fd, const char* name,
|
||||||
uint32 blockSize, uint32 flags);
|
uint32 blockSize, uint32 flags);
|
||||||
|
|
||||||
bool IsInitializing() const { return fVolume == NULL; }
|
bool IsInitializing() const { return fVolume == NULL; }
|
||||||
|
|
||||||
bool IsValidSuperBlock();
|
bool IsValidSuperBlock();
|
||||||
bool IsReadOnly() const;
|
bool IsReadOnly() const;
|
||||||
void Panic();
|
void Panic();
|
||||||
mutex &Lock();
|
mutex& Lock();
|
||||||
|
|
||||||
block_run Root() const { return fSuperBlock.root_dir; }
|
block_run Root() const { return fSuperBlock.root_dir; }
|
||||||
Inode *RootNode() const { return fRootNode; }
|
Inode* RootNode() const { return fRootNode; }
|
||||||
block_run Indices() const { return fSuperBlock.indices; }
|
block_run Indices() const { return fSuperBlock.indices; }
|
||||||
Inode *IndicesNode() const { return fIndicesNode; }
|
Inode* IndicesNode() const { return fIndicesNode; }
|
||||||
block_run Log() const { return fSuperBlock.log_blocks; }
|
block_run Log() const { return fSuperBlock.log_blocks; }
|
||||||
vint32 &LogStart() { return fLogStart; }
|
vint32& LogStart() { return fLogStart; }
|
||||||
vint32 &LogEnd() { return fLogEnd; }
|
vint32& LogEnd() { return fLogEnd; }
|
||||||
int Device() const { return fDevice; }
|
int Device() const { return fDevice; }
|
||||||
|
|
||||||
dev_t ID() const { return fVolume ? fVolume->id : -1; }
|
dev_t ID() const { return fVolume ? fVolume->id : -1; }
|
||||||
fs_volume *FSVolume() const { return fVolume; }
|
fs_volume* FSVolume() const { return fVolume; }
|
||||||
const char *Name() const { return fSuperBlock.name; }
|
const char* Name() const { return fSuperBlock.name; }
|
||||||
|
|
||||||
off_t NumBlocks() const { return fSuperBlock.NumBlocks(); }
|
off_t NumBlocks() const
|
||||||
off_t UsedBlocks() const { return fSuperBlock.UsedBlocks(); }
|
{ return fSuperBlock.NumBlocks(); }
|
||||||
off_t FreeBlocks() const { return NumBlocks() - UsedBlocks(); }
|
off_t UsedBlocks() const
|
||||||
|
{ return fSuperBlock.UsedBlocks(); }
|
||||||
|
off_t FreeBlocks() const
|
||||||
|
{ return NumBlocks() - UsedBlocks(); }
|
||||||
|
|
||||||
uint32 BlockSize() const { return fBlockSize; }
|
uint32 BlockSize() const { return fBlockSize; }
|
||||||
uint32 BlockShift() const { return fBlockShift; }
|
uint32 BlockShift() const { return fBlockShift; }
|
||||||
uint32 InodeSize() const { return fSuperBlock.InodeSize(); }
|
uint32 InodeSize() const
|
||||||
uint32 AllocationGroups() const { return fSuperBlock.AllocationGroups(); }
|
{ return fSuperBlock.InodeSize(); }
|
||||||
uint32 AllocationGroupShift() const { return fAllocationGroupShift; }
|
uint32 AllocationGroups() const
|
||||||
disk_super_block &SuperBlock() { return fSuperBlock; }
|
{ return fSuperBlock.AllocationGroups(); }
|
||||||
|
uint32 AllocationGroupShift() const
|
||||||
|
{ return fAllocationGroupShift; }
|
||||||
|
disk_super_block& SuperBlock() { return fSuperBlock; }
|
||||||
|
|
||||||
off_t ToOffset(block_run run) const { return ToBlock(run) << BlockShift(); }
|
off_t ToOffset(block_run run) const
|
||||||
off_t ToBlock(block_run run) const { return ((((off_t)run.AllocationGroup()) << AllocationGroupShift()) | (off_t)run.Start()); }
|
{ return ToBlock(run) << BlockShift(); }
|
||||||
block_run ToBlockRun(off_t block) const;
|
off_t ToBlock(block_run run) const
|
||||||
status_t ValidateBlockRun(block_run run);
|
{ return ((((off_t)run.AllocationGroup())
|
||||||
|
<< AllocationGroupShift())
|
||||||
|
| (off_t)run.Start()); }
|
||||||
|
block_run ToBlockRun(off_t block) const;
|
||||||
|
status_t ValidateBlockRun(block_run run);
|
||||||
|
|
||||||
off_t ToVnode(block_run run) const { return ToBlock(run); }
|
off_t ToVnode(block_run run) const
|
||||||
off_t ToVnode(off_t block) const { return block; }
|
{ return ToBlock(run); }
|
||||||
off_t VnodeToBlock(ino_t id) const { return (off_t)id; }
|
off_t ToVnode(off_t block) const { return block; }
|
||||||
|
off_t VnodeToBlock(ino_t id) const { return (off_t)id; }
|
||||||
|
|
||||||
status_t CreateIndicesRoot(Transaction &transaction);
|
status_t CreateIndicesRoot(Transaction& transaction);
|
||||||
|
|
||||||
// block bitmap
|
// block bitmap
|
||||||
BlockAllocator &Allocator();
|
BlockAllocator& Allocator();
|
||||||
status_t AllocateForInode(Transaction &transaction, const Inode *parent,
|
status_t AllocateForInode(Transaction& transaction,
|
||||||
mode_t type, block_run &run);
|
const Inode* parent, mode_t type,
|
||||||
status_t AllocateForInode(Transaction &transaction, const block_run *parent,
|
block_run& run);
|
||||||
mode_t type, block_run &run);
|
status_t AllocateForInode(Transaction& transaction,
|
||||||
status_t Allocate(Transaction &transaction, Inode *inode,
|
const block_run* parent, mode_t type,
|
||||||
off_t numBlocks, block_run &run, uint16 minimum = 1);
|
block_run& run);
|
||||||
status_t Free(Transaction &transaction, block_run run);
|
status_t Allocate(Transaction& transaction, Inode* inode,
|
||||||
|
off_t numBlocks, block_run& run,
|
||||||
|
uint16 minimum = 1);
|
||||||
|
status_t Free(Transaction& transaction, block_run run);
|
||||||
|
|
||||||
// cache access
|
// cache access
|
||||||
status_t WriteSuperBlock();
|
status_t WriteSuperBlock();
|
||||||
status_t FlushDevice();
|
status_t FlushDevice();
|
||||||
|
|
||||||
// queries
|
// queries
|
||||||
void UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
|
void UpdateLiveQueries(Inode* inode,
|
||||||
const uint8 *oldKey, size_t oldLength,
|
const char* attribute, int32 type,
|
||||||
const uint8 *newKey, size_t newLength);
|
const uint8* oldKey, size_t oldLength,
|
||||||
bool CheckForLiveQuery(const char *attribute);
|
const uint8* newKey, size_t newLength);
|
||||||
void AddQuery(Query *query);
|
bool CheckForLiveQuery(const char* attribute);
|
||||||
void RemoveQuery(Query *query);
|
void AddQuery(Query* query);
|
||||||
|
void RemoveQuery(Query* query);
|
||||||
|
|
||||||
status_t Sync();
|
status_t Sync();
|
||||||
Journal *GetJournal(off_t refBlock) const;
|
Journal* GetJournal(off_t refBlock) const;
|
||||||
|
|
||||||
void *BlockCache() { return fBlockCache; }
|
void* BlockCache() { return fBlockCache; }
|
||||||
|
|
||||||
uint32 GetUniqueID();
|
uint32 GetUniqueID();
|
||||||
|
|
||||||
static status_t CheckSuperBlock(const uint8* data,
|
static status_t CheckSuperBlock(const uint8* data,
|
||||||
uint32* _offset = NULL);
|
uint32* _offset = NULL);
|
||||||
static status_t Identify(int fd, disk_super_block *superBlock);
|
static status_t Identify(int fd, disk_super_block* superBlock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
fs_volume *fVolume;
|
fs_volume* fVolume;
|
||||||
int fDevice;
|
int fDevice;
|
||||||
disk_super_block fSuperBlock;
|
disk_super_block fSuperBlock;
|
||||||
|
|
||||||
uint32 fBlockSize;
|
uint32 fBlockSize;
|
||||||
uint32 fBlockShift;
|
uint32 fBlockShift;
|
||||||
uint32 fAllocationGroupShift;
|
uint32 fAllocationGroupShift;
|
||||||
|
|
||||||
BlockAllocator fBlockAllocator;
|
BlockAllocator fBlockAllocator;
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
Journal *fJournal;
|
Journal* fJournal;
|
||||||
vint32 fLogStart, fLogEnd;
|
vint32 fLogStart;
|
||||||
|
vint32 fLogEnd;
|
||||||
|
|
||||||
Inode *fRootNode;
|
Inode* fRootNode;
|
||||||
Inode *fIndicesNode;
|
Inode* fIndicesNode;
|
||||||
|
|
||||||
vint32 fDirtyCachedBlocks;
|
vint32 fDirtyCachedBlocks;
|
||||||
|
|
||||||
mutex fQueryLock;
|
mutex fQueryLock;
|
||||||
SinglyLinkedList<Query> fQueries;
|
SinglyLinkedList<Query> fQueries;
|
||||||
|
|
||||||
int32 fUniqueID;
|
int32 fUniqueID;
|
||||||
uint32 fFlags;
|
uint32 fFlags;
|
||||||
|
|
||||||
void *fBlockCache;
|
void* fBlockCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -146,14 +162,14 @@ Volume::IsReadOnly() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline mutex &
|
inline mutex&
|
||||||
Volume::Lock()
|
Volume::Lock()
|
||||||
{
|
{
|
||||||
return fLock;
|
return fLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline BlockAllocator &
|
inline BlockAllocator&
|
||||||
Volume::Allocator()
|
Volume::Allocator()
|
||||||
{
|
{
|
||||||
return fBlockAllocator;
|
return fBlockAllocator;
|
||||||
@@ -161,21 +177,24 @@ Volume::Allocator()
|
|||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
Volume::AllocateForInode(Transaction &transaction, const block_run *parent, mode_t type, block_run &run)
|
Volume::AllocateForInode(Transaction& transaction, const block_run* parent,
|
||||||
|
mode_t type, block_run& run)
|
||||||
{
|
{
|
||||||
return fBlockAllocator.AllocateForInode(transaction, parent, type, run);
|
return fBlockAllocator.AllocateForInode(transaction, parent, type, run);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
Volume::Allocate(Transaction &transaction, Inode *inode, off_t numBlocks, block_run &run, uint16 minimum)
|
Volume::Allocate(Transaction& transaction, Inode* inode, off_t numBlocks,
|
||||||
|
block_run& run, uint16 minimum)
|
||||||
{
|
{
|
||||||
return fBlockAllocator.Allocate(transaction, inode, numBlocks, run, minimum);
|
return fBlockAllocator.Allocate(transaction, inode, numBlocks, run,
|
||||||
|
minimum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
Volume::Free(Transaction &transaction, block_run run)
|
Volume::Free(Transaction& transaction, block_run run)
|
||||||
{
|
{
|
||||||
return fBlockAllocator.Free(transaction, run);
|
return fBlockAllocator.Free(transaction, run);
|
||||||
}
|
}
|
||||||
@@ -188,7 +207,7 @@ Volume::FlushDevice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Journal *
|
inline Journal*
|
||||||
Volume::GetJournal(off_t /*refBlock*/) const
|
Volume::GetJournal(off_t /*refBlock*/) const
|
||||||
{
|
{
|
||||||
return fJournal;
|
return fJournal;
|
||||||
@@ -201,4 +220,4 @@ Volume::GetUniqueID()
|
|||||||
return atomic_add(&fUniqueID, 1);
|
return atomic_add(&fUniqueID, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* VOLUME_H */
|
#endif // VOLUME_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user