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:
@@ -388,6 +388,17 @@ Volume::Mount(const char* deviceName, uint32 flags)
|
|||||||
fChecksumTree->SetRoot(root->LogicalAddress(), NULL);
|
fChecksumTree->SetRoot(root->LogicalAddress(), NULL);
|
||||||
free(root);
|
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
|
// Initialize Journal
|
||||||
fJournal = new(std::nothrow) Journal(this);
|
fJournal = new(std::nothrow) Journal(this);
|
||||||
if (fJournal == NULL)
|
if (fJournal == NULL)
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public:
|
|||||||
uint32 MaxInlineSize() const
|
uint32 MaxInlineSize() const
|
||||||
{ return fSectorSize / 2; }
|
{ return fSectorSize / 2; }
|
||||||
uint32 BlockSize() const { return fBlockSize; }
|
uint32 BlockSize() const { return fBlockSize; }
|
||||||
|
ino_t GetNextInodeID() { return ++fLargestInodeID; }
|
||||||
Chunk* SystemChunk() const { return fChunk; }
|
Chunk* SystemChunk() const { return fChunk; }
|
||||||
Journal* GetJournal() const { return fJournal; }
|
Journal* GetJournal() const { return fJournal; }
|
||||||
ExtentAllocator* GetAllocator() const { return fExtentAllocator; }
|
ExtentAllocator* GetAllocator() const { return fExtentAllocator; }
|
||||||
@@ -72,6 +73,7 @@ private:
|
|||||||
mutex fLock;
|
mutex fLock;
|
||||||
fs_volume* fFSVolume;
|
fs_volume* fFSVolume;
|
||||||
int fDevice;
|
int fDevice;
|
||||||
|
ino_t fLargestInodeID;
|
||||||
btrfs_super_block fSuperBlock;
|
btrfs_super_block fSuperBlock;
|
||||||
char fName[32];
|
char fName[32];
|
||||||
|
|
||||||
|
|||||||
@@ -482,6 +482,52 @@ btrfs_read_link(fs_volume* _volume, fs_vnode* _node, char* buffer,
|
|||||||
// #pragma mark - Directory functions
|
// #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
|
static status_t
|
||||||
btrfs_open_dir(fs_volume* /*_volume*/, fs_vnode* _node, void** _cookie)
|
btrfs_open_dir(fs_volume* /*_volume*/, fs_vnode* _node, void** _cookie)
|
||||||
{
|
{
|
||||||
@@ -814,7 +860,7 @@ fs_vnode_ops gBtrfsVnodeOps = {
|
|||||||
NULL, // fs_write,
|
NULL, // fs_write,
|
||||||
|
|
||||||
/* directory operations */
|
/* directory operations */
|
||||||
NULL, // fs_create_dir,
|
&btrfs_create_dir,
|
||||||
NULL, // fs_remove_dir,
|
NULL, // fs_remove_dir,
|
||||||
&btrfs_open_dir,
|
&btrfs_open_dir,
|
||||||
&btrfs_close_dir,
|
&btrfs_close_dir,
|
||||||
|
|||||||
Reference in New Issue
Block a user