BTRFS: Implement MakeReference() in Inode that will link file name to inode.
Signed-off-by: Augustin Cavalier <waddlesplash@gmail.com>
This commit is contained in:
parent
371935de18
commit
b44d924df4
@ -8,6 +8,7 @@
|
||||
|
||||
#include "Inode.h"
|
||||
#include "CachedBlock.h"
|
||||
#include "CRCTable.h"
|
||||
#include "Utility.h"
|
||||
|
||||
|
||||
@ -372,6 +373,21 @@ Inode::FindParent(ino_t* id)
|
||||
}
|
||||
|
||||
|
||||
uint64
|
||||
Inode::FindNextIndex(BTree::Path* path) const
|
||||
{
|
||||
btrfs_key key;
|
||||
key.SetObjectID(fID);
|
||||
key.SetType(BTRFS_KEY_TYPE_DIR_INDEX);
|
||||
key.SetOffset(-1);
|
||||
|
||||
if (fVolume->FSTree()->FindPrevious(path, key, NULL))
|
||||
return 2; // not found any dir index item
|
||||
|
||||
return key.Offset() + 1;
|
||||
}
|
||||
|
||||
|
||||
/* Insert inode_item
|
||||
*/
|
||||
status_t
|
||||
@ -391,6 +407,68 @@ Inode::Insert(Transaction& transaction, BTree::Path* path)
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Insert 3 items: inode_ref, dir_item, dir_index
|
||||
* Basically, make a link between name and its node (location)
|
||||
*/
|
||||
status_t
|
||||
Inode::MakeReference(Transaction& transaction, BTree::Path* path,
|
||||
Inode* parent, const char* name, int32 mode)
|
||||
{
|
||||
BTree* tree = fVolume->FSTree();
|
||||
uint16 nameLength = strlen(name);
|
||||
uint64 index = parent->FindNextIndex(path);
|
||||
void* data[1];
|
||||
|
||||
// insert inode_ref
|
||||
btrfs_entry entry;
|
||||
btrfs_inode_ref inodeRef;
|
||||
|
||||
inodeRef.index = index;
|
||||
inodeRef.SetName(name, nameLength);
|
||||
data[0] = (void*)&inodeRef;
|
||||
|
||||
entry.key.SetObjectID(fID);
|
||||
entry.key.SetType(BTRFS_KEY_TYPE_INODE_REF);
|
||||
entry.key.SetOffset(parent->ID());
|
||||
entry.SetSize(inodeRef.Length());
|
||||
|
||||
status_t status = tree->InsertEntries(transaction, path, &entry, data, 1);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// insert dir_entry
|
||||
uint32 hash = calculate_crc((uint32)~1, (uint8*)name, nameLength);
|
||||
btrfs_dir_entry directoryEntry;
|
||||
directoryEntry.location.SetObjectID(fID);
|
||||
directoryEntry.location.SetType(BTRFS_KEY_TYPE_INODE_ITEM);
|
||||
directoryEntry.location.SetOffset(0);
|
||||
directoryEntry.SetTransactionID(transaction.SystemID());
|
||||
// TODO: xattribute, 0 for standard directory
|
||||
directoryEntry.SetAttributeData(NULL, 0);
|
||||
directoryEntry.SetName(name, nameLength);
|
||||
directoryEntry.type = get_filetype(mode);
|
||||
data[0] = (void*)&directoryEntry;
|
||||
|
||||
entry.key.SetObjectID(parent->ID());
|
||||
entry.key.SetType(BTRFS_KEY_TYPE_DIR_ITEM);
|
||||
entry.key.SetOffset(hash);
|
||||
entry.SetSize(directoryEntry.Length());
|
||||
|
||||
status = tree->InsertEntries(transaction, path, &entry, data, 1);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// insert dir_index (has same data with dir_entry)
|
||||
entry.key.SetType(BTRFS_KEY_TYPE_DIR_INDEX);
|
||||
entry.key.SetOffset(index);
|
||||
|
||||
status = tree->InsertEntries(transaction, path, &entry, data, 1);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -68,10 +68,13 @@ public:
|
||||
void* Map() const { return fMap; }
|
||||
|
||||
status_t FindParent(ino_t* id);
|
||||
uint64 FindNextIndex(BTree::Path* path) const;
|
||||
static Inode* Create(Transaction& transaction, ino_t id,
|
||||
Inode* parent, int32 mode, uint64 size = 0,
|
||||
uint64 flags = 0);
|
||||
status_t Insert(Transaction& transaction, BTree::Path* path);
|
||||
status_t MakeReference(Transaction& transaction, BTree::Path* path,
|
||||
Inode* parent, const char* name, int32 mode);
|
||||
private:
|
||||
Inode(Volume* volume);
|
||||
Inode(const Inode&);
|
||||
|
@ -319,6 +319,13 @@ struct btrfs_inode_ref {
|
||||
|
||||
uint64 Index() const { return index; }
|
||||
uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); }
|
||||
uint16 Length() const
|
||||
{ return sizeof(btrfs_inode_ref) + NameLength(); }
|
||||
void SetName(const char* name, uint16 nameLength)
|
||||
{
|
||||
name_length = B_HOST_TO_LENDIAN_INT16(nameLength);
|
||||
memcpy(this->name, name, nameLength);
|
||||
}
|
||||
} _PACKED;
|
||||
|
||||
|
||||
@ -348,11 +355,26 @@ struct btrfs_dir_entry {
|
||||
uint16 data_length;
|
||||
uint16 name_length;
|
||||
uint8 type;
|
||||
uint8 name[];
|
||||
uint8 data[]; // attribute data
|
||||
uint16 DataLength() const { return B_LENDIAN_TO_HOST_INT16(data_length); }
|
||||
uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); }
|
||||
ino_t InodeID() const { return location.ObjectID(); }
|
||||
uint16 Length() const
|
||||
{ return sizeof(*this) + NameLength() + DataLength(); }
|
||||
void SetTransactionID(uint64 id)
|
||||
{ transaction_id = B_HOST_TO_LENDIAN_INT64(id); }
|
||||
void SetAttributeData(void* data, uint16 dataLength)
|
||||
{
|
||||
data_length = B_HOST_TO_LENDIAN_INT16(dataLength);
|
||||
if (data != NULL)
|
||||
memcpy(this->data, data, dataLength);
|
||||
}
|
||||
void SetName(const char* name, uint16 nameLength)
|
||||
{
|
||||
name_length = B_HOST_TO_LENDIAN_INT16(nameLength);
|
||||
memcpy(this->name, name, nameLength);
|
||||
}
|
||||
} _PACKED;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user