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
This commit is contained in:
Axel Dörfler 2002-11-20 01:50:03 +00:00
parent 67fa10dcde
commit 52fafe627e

View File

@ -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);