From d11e733fee81b682160c03a5d1cacb77b3a2faff Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 25 Apr 2008 01:04:48 +0000 Subject: [PATCH] * Allow passing sub vnode ops and publish flags to Inode::Create(). * Implemented create_special_node() hook. * Fixed Inode::IsContainer()/IsDirectory(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25140 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/file_systems/bfs/Inode.cpp | 19 +++---- src/add-ons/kernel/file_systems/bfs/Inode.h | 10 ++-- .../file_systems/bfs/kernel_interface.cpp | 52 ++++++++++++++++++- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index b693627039..fe65e22dda 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -139,9 +139,9 @@ class InodeAllocator { ~InodeAllocator(); status_t New(block_run *parentRun, mode_t mode, block_run &run, - Inode **_inode); + fs_vnode_ops *vnodeOps, Inode **_inode); status_t CreateTree(); - status_t Keep(); + status_t Keep(fs_vnode_ops *vnodeOps, uint32 publishFlags); private: static void _TransactionListener(int32 id, int32 event, void *_inode); @@ -180,7 +180,7 @@ InodeAllocator::~InodeAllocator() status_t InodeAllocator::New(block_run *parentRun, mode_t mode, block_run &run, - Inode **_inode) + fs_vnode_ops *vnodeOps, Inode **_inode) { Volume *volume = fTransaction->GetVolume(); @@ -200,7 +200,7 @@ InodeAllocator::New(block_run *parentRun, mode_t mode, block_run &run, if (volume->ID() >= 0) { status = new_vnode(volume->FSVolume(), fInode->ID(), fInode, - &gBFSVnodeOps); + vnodeOps != NULL ? vnodeOps : &gBFSVnodeOps); if (status < B_OK) { delete fInode; fInode = NULL; @@ -237,7 +237,7 @@ InodeAllocator::CreateTree() status_t -InodeAllocator::Keep() +InodeAllocator::Keep(fs_vnode_ops *vnodeOps, uint32 publishFlags) { ASSERT(fInode != NULL && fTransaction != NULL); Volume *volume = fTransaction->GetVolume(); @@ -250,7 +250,8 @@ InodeAllocator::Keep() if (!fInode->IsSymLink() && volume->ID() >= 0) { status = publish_vnode(volume->FSVolume(), fInode->ID(), fInode, - &gBFSVnodeOps, fInode->Mode(), 0); + vnodeOps != NULL ? vnodeOps : &gBFSVnodeOps, fInode->Mode(), + publishFlags); } if (status == B_OK) { @@ -2302,7 +2303,7 @@ Inode::Remove(Transaction &transaction, const char *name, ino_t *_id, status_t Inode::Create(Transaction &transaction, Inode *parent, const char *name, int32 mode, int openMode, uint32 type, bool *_created, ino_t *_id, - Inode **_inode) + Inode **_inode, fs_vnode_ops *vnodeOps, uint32 publishFlags) { FUNCTION_START(("name = %s, mode = %ld\n", name, mode)); @@ -2388,7 +2389,7 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name, InodeAllocator allocator(transaction); block_run run; Inode *inode; - status = allocator.New(&parentRun, mode, run, &inode); + status = allocator.New(&parentRun, mode, run, vnodeOps, &inode); if (status < B_OK) return status; @@ -2481,7 +2482,7 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name, // Everything worked well until this point, we have a fully // initialized inode, and we want to keep it - allocator.Keep(); + allocator.Keep(vnodeOps, publishFlags); if (inode->IsFile() || inode->IsAttribute()) { inode->SetFileCache(file_cache_create(volume->ID(), inode->ID(), diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.h b/src/add-ons/kernel/file_systems/bfs/Inode.h index 36e7d5e84f..c0d7c80f10 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.h +++ b/src/add-ons/kernel/file_systems/bfs/Inode.h @@ -50,12 +50,9 @@ class Inode { status_t WriteBack(Transaction &transaction); bool IsContainer() const - { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); } - // note, that this test will also be true for S_IFBLK - // (not that it's used in the fs :) + { return (Mode() & (S_INDEX_DIR | S_ATTR_DIR)) || S_ISDIR(Mode()); } bool IsDirectory() const - { return (Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) - == S_DIRECTORY; } + { return S_ISDIR(Mode()); } bool IsIndex() const { return (Mode() & (S_INDEX_DIR | 0777)) == S_INDEX_DIR; } // that's a stupid check, but AFAIK the only possible method... @@ -141,7 +138,8 @@ class Inode { ino_t *_id = NULL, bool isDirectory = false); static status_t Create(Transaction &transaction, Inode *parent, const char *name, int32 mode, int openMode, uint32 type, - bool *_created = NULL, ino_t *_id = NULL, Inode **_inode = NULL); + bool *_created = NULL, ino_t *_id = NULL, Inode **_inode = NULL, + fs_vnode_ops *vnodeOps = NULL, uint32 publishFlags = 0); // index maintaining helper void UpdateOldSize() diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 84be89828b..4c6f15798e 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -1770,6 +1770,53 @@ bfs_remove_attr(fs_volume *_volume, fs_vnode *_node, const char *name) } +// #pragma mark - Special Nodes + + +status_t +bfs_create_special_node(fs_volume *_volume, fs_vnode *_directory, + const char *name, fs_vnode *subVnode, mode_t mode, uint32 flags, + fs_vnode *_superVnode, ino_t *_nodeID) +{ + // no need to support entry-less nodes + if (name == NULL) + return B_UNSUPPORTED; + + FUNCTION_START(("name = \"%s\", mode = %d, flags = 0x%lx, subVnode: %p\n", + name, mode, flags, subVnode)); + + Volume *volume = (Volume *)_volume->private_volume; + Inode *directory = (Inode *)_directory->private_node; + + if (volume->IsReadOnly()) + return B_READ_ONLY_DEVICE; + + if (!directory->IsDirectory()) + RETURN_ERROR(B_BAD_TYPE); + + status_t status = directory->CheckPermissions(W_OK); + if (status < B_OK) + RETURN_ERROR(status); + + Transaction transaction(volume, directory->BlockNumber()); + + off_t id; + Inode *inode; + status = Inode::Create(transaction, directory, name, mode, O_EXCL, 0, NULL, + &id, &inode, subVnode ? subVnode->ops : NULL, flags); + if (status == B_OK) { + _superVnode->private_node = inode; + _superVnode->ops = &gBFSVnodeOps; + *_nodeID = id; + transaction.Done(); + + notify_entry_created(volume->ID(), directory->ID(), name, id); + } + + return status; +} + + // #pragma mark - // Index functions @@ -2224,7 +2271,10 @@ fs_vnode_ops gBFSVnodeOps = { &bfs_read_attr_stat, &bfs_write_attr_stat, &bfs_rename_attr, - &bfs_remove_attr + &bfs_remove_attr, + + /* special nodes */ + &bfs_create_special_node }; static file_system_module_info sBeFileSystem = {