From 52fafe627e0439ce36f8715d9c00a9e3bab3adfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 20 Nov 2002 01:50:03 +0000 Subject: [PATCH] Changed the parameter logic from Inode::Create() - it now also keeps the inode locked if the _inode parameter is passed. Makes some more use of the new type identificators. Symlinks are no longer added to the "size" index (compatibility with BFS, and it also makes much more sense). Now sets S_STR_INDEX for directories, if no index type was set (again, compatibility issue with BFS). Fixed a bug in the Inode::GrowStream() method in the double indirect region. Some style updates. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2030 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/file_systems/bfs/Inode.cpp | 95 +++++++++++-------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index 3ee2cadd12..2d7c799dc3 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -770,7 +770,7 @@ Inode::CreateAttribute(Transaction *transaction,const char *name,uint32 type,Ino { // do we need to create the attribute directory first? if (Attributes().IsZero()) { - status_t status = Inode::Create(transaction,this,NULL,S_ATTR_DIR | 0666,0,0,NULL); + status_t status = Inode::Create(transaction, this, NULL, S_ATTR_DIR | 0666, 0, 0, NULL); if (status < B_OK) RETURN_ERROR(status); } @@ -779,9 +779,8 @@ Inode::CreateAttribute(Transaction *transaction,const char *name,uint32 type,Ino if (vnode.Get(&attributes) < B_OK) return B_ERROR; - // Inode::Create() locks the inode if we provide the "id" parameter - vnode_id id; - return Inode::Create(transaction,attributes,name,S_ATTR | 0666,0,type,&id,attribute); + // Inode::Create() locks the inode for us + return Inode::Create(transaction, attributes, name, S_ATTR | 0666, 0, type, NULL, attribute); } @@ -801,7 +800,7 @@ Inode::GetTree(BPlusTree **tree) return B_OK; } - if (IsDirectory()) { + if (IsContainer()) { fTree = new BPlusTree(this); if (!fTree) RETURN_ERROR(B_NO_MEMORY); @@ -1284,8 +1283,10 @@ Inode::GrowStream(Transaction *transaction, off_t size) return B_IO_ERROR; } while ((index % runsPerArray) != 0 && run.length); - if (++indirectIndex % runsPerBlock == 0) + if (++indirectIndex % runsPerBlock == 0) { array = NULL; + index = 0; + } } data->max_double_indirect_range += runLength << fVolume->BlockShift(); @@ -1623,13 +1624,13 @@ Inode::Remove(Transaction *transaction, const char *name, off_t *_id, bool isDir if (inode->Flags() & INODE_NO_CACHE) return B_NOT_ALLOWED; - // Inode::IsDirectory() is true also for indices (furthermore, the S_IFDIR + // Inode::IsContainer() is true also for indices (furthermore, the S_IFDIR // bit is set for indices in BFS, not for attribute directories) - but you // should really be able to do whatever you want with your indices // without having to remove all files first :) if (!inode->IsIndex()) { // if it's not of the correct type, don't delete it! - if (inode->IsDirectory() != isDirectory) + if (inode->IsContainer() != isDirectory) return isDirectory ? B_NOT_A_DIRECTORY : B_IS_A_DIRECTORY; // only delete empty directories @@ -1653,7 +1654,7 @@ Inode::Remove(Transaction *transaction, const char *name, off_t *_id, bool isDir // are updated here (name, size, & last_modified) Index index(fVolume); - if ((inode->Mode() & (S_ATTR_DIR | S_ATTR | S_INDEX_DIR)) == 0) { + if (inode->IsRegularNode()) { index.RemoveName(transaction, name, inode); // If removing from the index fails, it is not regarded as a // fatal error and will not be reported back! @@ -1661,7 +1662,8 @@ Inode::Remove(Transaction *transaction, const char *name, off_t *_id, bool isDir } if ((inode->Mode() & (S_FILE | S_SYMLINK)) != 0) { - index.RemoveSize(transaction, inode); + if (inode->IsFile()) + index.RemoveSize(transaction, inode); index.RemoveLastModified(transaction, inode); } @@ -1679,31 +1681,32 @@ Inode::Remove(Transaction *transaction, const char *name, off_t *_id, bool isDir * to the super block. * It will also create the initial B+tree for the inode if it's a directory * of any kind. - * If the "id" variable is given to store the inode's ID, the inode stays - * locked - you have to call put_vnode() if you don't use it anymore. + * If the "_id" or "_inode" variable is given and non-NULL to store the inode's + * ID, the inode stays locked - you have to call put_vnode() if you don't use it + * anymore. */ status_t Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 mode, int omode, uint32 type, off_t *_id, Inode **_inode) { - block_run parentRun = parent ? parent->BlockRun() : block_run::Run(0,0,0); + block_run parentRun = parent ? parent->BlockRun() : block_run::Run(0, 0, 0); Volume *volume = transaction->GetVolume(); BPlusTree *tree = NULL; - if (parent && (mode & S_ATTR_DIR) == 0 && parent->IsDirectory()) { + if (parent && (mode & S_ATTR_DIR) == 0 && parent->IsContainer()) { // check if the file already exists in the directory if (parent->GetTree(&tree) != B_OK) RETURN_ERROR(B_BAD_VALUE); // does the file already exist? off_t offset; - if (tree->Find((uint8 *)name,(uint16)strlen(name),&offset) == B_OK) { + if (tree->Find((uint8 *)name, (uint16)strlen(name), &offset) == B_OK) { // return if the file should be a directory or opened in exclusive mode if (mode & S_DIRECTORY || omode & O_EXCL) return B_FILE_EXISTS; - Vnode vnode(volume,offset); + Vnode vnode(volume, offset); Inode *inode; status_t status = vnode.Get(&inode); if (status < B_OK) { @@ -1724,19 +1727,20 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m if (omode & O_TRUNC) { WriteLocked locked(inode->Lock()); - status_t status = inode->SetFileSize(transaction,0); + status_t status = inode->SetFileSize(transaction, 0); if (status < B_OK) return status; } - // only keep the vnode in memory if the vnode_id pointer is provided - if (_id) { + if (_id) *_id = offset; - vnode.Keep(); - } if (_inode) *_inode = inode; + // only keep the vnode in memory if the _id or _inode pointer is provided + if (_id == NULL && _inode == NULL) + vnode.Keep(); + return B_OK; } } else if (parent && (mode & S_ATTR_DIR) == 0) @@ -1746,7 +1750,7 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m InodeAllocator allocator(transaction); block_run run; Inode *inode; - status_t status = allocator.New(&parentRun,mode,run,&inode); + status_t status = allocator.New(&parentRun, mode, run, &inode); if (status < B_OK) return status; @@ -1774,28 +1778,33 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m // only add the name to regular files, directories, or symlinks // don't add it to attributes, or indices - if (tree && (mode & (S_INDEX_DIR | S_ATTR_DIR | S_ATTR)) == 0 - && inode->SetName(transaction,name) < B_OK) + if (tree && inode->IsRegularNode() && inode->SetName(transaction, name) < B_OK) return B_ERROR; // initialize b+tree if it's a directory (and add "." & ".." if it's // a standard directory for files - not for attributes or indices) - if (mode & (S_DIRECTORY | S_ATTR_DIR | S_INDEX_DIR)) { - BPlusTree *tree = inode->fTree = new BPlusTree(transaction,inode); + if (inode->IsContainer()) { + // force S_STR_INDEX to be set, if no type is set + if ((mode & S_INDEX_TYPES) == 0) + node->mode |= S_STR_INDEX; + + BPlusTree *tree = inode->fTree = new BPlusTree(transaction, inode); if (tree == NULL || tree->InitCheck() < B_OK) return B_ERROR; - if ((mode & (S_INDEX_DIR | S_ATTR_DIR)) == 0) { - if (tree->Insert(transaction,".",inode->BlockNumber()) < B_OK - || tree->Insert(transaction,"..",volume->ToBlock(inode->Parent())) < B_OK) + if (inode->IsRegularNode()) { + if (tree->Insert(transaction, ".", inode->BlockNumber()) < B_OK + || tree->Insert(transaction, "..", volume->ToBlock(inode->Parent())) < B_OK) return B_ERROR; } } // update the main indices (name, size & last_modified) + Index index(volume); - if ((mode & (S_ATTR_DIR | S_ATTR | S_INDEX_DIR)) == 0) { - status = index.InsertName(transaction,name,inode); + if (inode->IsRegularNode()) { + // the name index only contains regular files + status = index.InsertName(transaction, name, inode); if (status < B_OK && status != B_BAD_INDEX) return status; } @@ -1804,36 +1813,40 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m // The "size" & "last_modified" indices don't contain directories if ((mode & (S_FILE | S_SYMLINK)) != 0) { - // if adding to these indices fails, the inode creation will not be harmed - index.InsertSize(transaction,inode); - index.InsertLastModified(transaction,inode); + // if adding to these indices fails, the inode creation will not be harmed; + // they are considered less important than the "name" index + if (inode->IsFile()) + index.InsertSize(transaction, inode); + index.InsertLastModified(transaction, inode); } if ((status = inode->WriteBack(transaction)) < B_OK) return status; - if (new_vnode(volume->ID(),inode->ID(),inode) != B_OK) + if (new_vnode(volume->ID(), inode->ID(), inode) != B_OK) return B_ERROR; // add a link to the inode from the parent, depending on its type - if (tree && tree->Insert(transaction,name,volume->ToBlock(run)) < B_OK) { - put_vnode(volume->ID(),inode->ID()); + if (tree && tree->Insert(transaction, name, volume->ToBlock(run)) < B_OK) { + put_vnode(volume->ID(), inode->ID()); RETURN_ERROR(B_ERROR); } else if (parent && mode & S_ATTR_DIR) { parent->Attributes() = run; parent->WriteBack(transaction); } + // everything worked well, so we want to keep the inode allocator.Keep(); if (_id != NULL) *_id = inode->ID(); - else - put_vnode(volume->ID(),inode->ID()); - if (_inode != NULL) *_inode = inode; + // if either _id or _inode is passed, we will keep the inode locked + if (_id == NULL && _inode == NULL) + put_vnode(volume->ID(), inode->ID()); + return B_OK; } @@ -1856,7 +1869,7 @@ AttributeIterator::AttributeIterator(Inode *inode) AttributeIterator::~AttributeIterator() { if (fAttributes) - put_vnode(fAttributes->GetVolume()->ID(),fAttributes->ID()); + put_vnode(fAttributes->GetVolume()->ID(), fAttributes->ID()); delete fIterator; fInode->RemoveIterator(this);