BTRFS: Implement btrfs_create_dir that can create directories in most case.

We need to handle a case when node is full, the solution should be split or push data to another node.

Signed-off-by: Augustin Cavalier <[email protected]>
This commit is contained in:
hyche
2017-12-10 11:03:03 -05:00
committed by Augustin Cavalier
parent a9e85cb62f
commit 166917c9cd
3 changed files with 60 additions and 1 deletions
@@ -388,6 +388,17 @@ Volume::Mount(const char* deviceName, uint32 flags)
fChecksumTree->SetRoot(root->LogicalAddress(), NULL);
free(root);
search_key.SetObjectID(-1);
search_key.SetType(0);
status = fFSTree->FindPrevious(&path, search_key, NULL);
if (status != B_OK) {
ERROR("Volume::Mount() Couldn't find any inode!!\n");
return status;
}
fLargestInodeID = search_key.ObjectID();
TRACE("Volume::Mount() Find larget inode id % " B_PRIu64 "\n",
fLargestInodeID);
// Initialize Journal
fJournal = new(std::nothrow) Journal(this);
if (fJournal == NULL)
@@ -49,6 +49,7 @@ public:
uint32 MaxInlineSize() const
{ return fSectorSize / 2; }
uint32 BlockSize() const { return fBlockSize; }
ino_t GetNextInodeID() { return ++fLargestInodeID; }
Chunk* SystemChunk() const { return fChunk; }
Journal* GetJournal() const { return fJournal; }
ExtentAllocator* GetAllocator() const { return fExtentAllocator; }
@@ -72,6 +73,7 @@ private:
mutex fLock;
fs_volume* fFSVolume;
int fDevice;
ino_t fLargestInodeID;
btrfs_super_block fSuperBlock;
char fName[32];
@@ -482,6 +482,52 @@ btrfs_read_link(fs_volume* _volume, fs_vnode* _node, char* buffer,
// #pragma mark - Directory functions
static status_t
btrfs_create_dir(fs_volume* _volume, fs_vnode* _directory, const char* name,
int mode)
{
Volume* volume = (Volume*)_volume->private_volume;
Inode* directory = (Inode*)_directory->private_node;
BTree::Path path(volume->FSTree());
if (volume->IsReadOnly())
return B_READ_ONLY_DEVICE;
if (!directory->IsDirectory())
return B_NOT_A_DIRECTORY;
status_t status = directory->CheckPermissions(W_OK);
if (status < B_OK)
return status;
Transaction transaction(volume);
ino_t id = volume->GetNextInodeID();
mode = S_DIRECTORY | (mode & S_IUMSK);
Inode* inode = Inode::Create(transaction, id, directory, mode);
if (inode == NULL)
return B_NO_MEMORY;
status = inode->Insert(transaction, &path);
if (status != B_OK)
return status;
status = inode->MakeReference(transaction, &path, directory, name, mode);
if (status != B_OK)
return status;
put_vnode(volume->FSVolume(), inode->ID());
entry_cache_add(volume->ID(), directory->ID(), name, inode->ID());
status = transaction.Done();
if (status == B_OK)
notify_entry_created(volume->ID(), directory->ID(), name, inode->ID());
else
entry_cache_remove(volume->ID(), directory->ID(), name);
return status;
}
static status_t
btrfs_open_dir(fs_volume* /*_volume*/, fs_vnode* _node, void** _cookie)
{
@@ -814,7 +860,7 @@ fs_vnode_ops gBtrfsVnodeOps = {
NULL, // fs_write,
/* directory operations */
NULL, // fs_create_dir,
&btrfs_create_dir,
NULL, // fs_remove_dir,
&btrfs_open_dir,
&btrfs_close_dir,