From b44d924df453be386d656805c53efe0f0dd0fe2f Mon Sep 17 00:00:00 2001 From: hyche Date: Tue, 29 Aug 2017 06:38:42 +0700 Subject: [PATCH] BTRFS: Implement MakeReference() in Inode that will link file name to inode. Signed-off-by: Augustin Cavalier --- .../kernel/file_systems/btrfs/Inode.cpp | 78 +++++++++++++++++++ src/add-ons/kernel/file_systems/btrfs/Inode.h | 3 + src/add-ons/kernel/file_systems/btrfs/btrfs.h | 22 ++++++ 3 files changed, 103 insertions(+) diff --git a/src/add-ons/kernel/file_systems/btrfs/Inode.cpp b/src/add-ons/kernel/file_systems/btrfs/Inode.cpp index f9229ade26..7c0a72d47d 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/Inode.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/btrfs/Inode.h b/src/add-ons/kernel/file_systems/btrfs/Inode.h index 60c5aa083e..953f9ba8ad 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Inode.h +++ b/src/add-ons/kernel/file_systems/btrfs/Inode.h @@ -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&); diff --git a/src/add-ons/kernel/file_systems/btrfs/btrfs.h b/src/add-ons/kernel/file_systems/btrfs/btrfs.h index a1121f4881..d0481e0bf0 100644 --- a/src/add-ons/kernel/file_systems/btrfs/btrfs.h +++ b/src/add-ons/kernel/file_systems/btrfs/btrfs.h @@ -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;