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? // do we need to create the attribute directory first?
if (Attributes().IsZero()) { 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) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
} }
@ -779,9 +779,8 @@ Inode::CreateAttribute(Transaction *transaction,const char *name,uint32 type,Ino
if (vnode.Get(&attributes) < B_OK) if (vnode.Get(&attributes) < B_OK)
return B_ERROR; return B_ERROR;
// Inode::Create() locks the inode if we provide the "id" parameter // Inode::Create() locks the inode for us
vnode_id id; return Inode::Create(transaction, attributes, name, S_ATTR | 0666, 0, type, NULL, attribute);
return Inode::Create(transaction,attributes,name,S_ATTR | 0666,0,type,&id,attribute);
} }
@ -801,7 +800,7 @@ Inode::GetTree(BPlusTree **tree)
return B_OK; return B_OK;
} }
if (IsDirectory()) { if (IsContainer()) {
fTree = new BPlusTree(this); fTree = new BPlusTree(this);
if (!fTree) if (!fTree)
RETURN_ERROR(B_NO_MEMORY); RETURN_ERROR(B_NO_MEMORY);
@ -1284,8 +1283,10 @@ Inode::GrowStream(Transaction *transaction, off_t size)
return B_IO_ERROR; return B_IO_ERROR;
} while ((index % runsPerArray) != 0 && run.length); } while ((index % runsPerArray) != 0 && run.length);
if (++indirectIndex % runsPerBlock == 0) if (++indirectIndex % runsPerBlock == 0) {
array = NULL; array = NULL;
index = 0;
}
} }
data->max_double_indirect_range += runLength << fVolume->BlockShift(); 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) if (inode->Flags() & INODE_NO_CACHE)
return B_NOT_ALLOWED; 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 // 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 // should really be able to do whatever you want with your indices
// without having to remove all files first :) // without having to remove all files first :)
if (!inode->IsIndex()) { if (!inode->IsIndex()) {
// if it's not of the correct type, don't delete it! // 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; return isDirectory ? B_NOT_A_DIRECTORY : B_IS_A_DIRECTORY;
// only delete empty directories // 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) // are updated here (name, size, & last_modified)
Index index(fVolume); Index index(fVolume);
if ((inode->Mode() & (S_ATTR_DIR | S_ATTR | S_INDEX_DIR)) == 0) { if (inode->IsRegularNode()) {
index.RemoveName(transaction, name, inode); index.RemoveName(transaction, name, inode);
// If removing from the index fails, it is not regarded as a // If removing from the index fails, it is not regarded as a
// fatal error and will not be reported back! // 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) { if ((inode->Mode() & (S_FILE | S_SYMLINK)) != 0) {
index.RemoveSize(transaction, inode); if (inode->IsFile())
index.RemoveSize(transaction, inode);
index.RemoveLastModified(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. * to the super block.
* It will also create the initial B+tree for the inode if it's a directory * It will also create the initial B+tree for the inode if it's a directory
* of any kind. * of any kind.
* If the "id" variable is given to store the inode's ID, the inode stays * If the "_id" or "_inode" variable is given and non-NULL to store the inode's
* locked - you have to call put_vnode() if you don't use it anymore. * ID, the inode stays locked - you have to call put_vnode() if you don't use it
* anymore.
*/ */
status_t status_t
Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 mode, Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 mode,
int omode, uint32 type, off_t *_id, Inode **_inode) 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(); Volume *volume = transaction->GetVolume();
BPlusTree *tree = NULL; 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 // check if the file already exists in the directory
if (parent->GetTree(&tree) != B_OK) if (parent->GetTree(&tree) != B_OK)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
// does the file already exist? // does the file already exist?
off_t offset; 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 // return if the file should be a directory or opened in exclusive mode
if (mode & S_DIRECTORY || omode & O_EXCL) if (mode & S_DIRECTORY || omode & O_EXCL)
return B_FILE_EXISTS; return B_FILE_EXISTS;
Vnode vnode(volume,offset); Vnode vnode(volume, offset);
Inode *inode; Inode *inode;
status_t status = vnode.Get(&inode); status_t status = vnode.Get(&inode);
if (status < B_OK) { if (status < B_OK) {
@ -1724,19 +1727,20 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m
if (omode & O_TRUNC) { if (omode & O_TRUNC) {
WriteLocked locked(inode->Lock()); WriteLocked locked(inode->Lock());
status_t status = inode->SetFileSize(transaction,0); status_t status = inode->SetFileSize(transaction, 0);
if (status < B_OK) if (status < B_OK)
return status; return status;
} }
// only keep the vnode in memory if the vnode_id pointer is provided if (_id)
if (_id) {
*_id = offset; *_id = offset;
vnode.Keep();
}
if (_inode) if (_inode)
*_inode = 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; return B_OK;
} }
} else if (parent && (mode & S_ATTR_DIR) == 0) } 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); InodeAllocator allocator(transaction);
block_run run; block_run run;
Inode *inode; Inode *inode;
status_t status = allocator.New(&parentRun,mode,run,&inode); status_t status = allocator.New(&parentRun, mode, run, &inode);
if (status < B_OK) if (status < B_OK)
return status; 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 // only add the name to regular files, directories, or symlinks
// don't add it to attributes, or indices // don't add it to attributes, or indices
if (tree && (mode & (S_INDEX_DIR | S_ATTR_DIR | S_ATTR)) == 0 if (tree && inode->IsRegularNode() && inode->SetName(transaction, name) < B_OK)
&& inode->SetName(transaction,name) < B_OK)
return B_ERROR; return B_ERROR;
// initialize b+tree if it's a directory (and add "." & ".." if it's // initialize b+tree if it's a directory (and add "." & ".." if it's
// a standard directory for files - not for attributes or indices) // a standard directory for files - not for attributes or indices)
if (mode & (S_DIRECTORY | S_ATTR_DIR | S_INDEX_DIR)) { if (inode->IsContainer()) {
BPlusTree *tree = inode->fTree = new BPlusTree(transaction,inode); // 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) if (tree == NULL || tree->InitCheck() < B_OK)
return B_ERROR; return B_ERROR;
if ((mode & (S_INDEX_DIR | S_ATTR_DIR)) == 0) { if (inode->IsRegularNode()) {
if (tree->Insert(transaction,".",inode->BlockNumber()) < B_OK if (tree->Insert(transaction, ".", inode->BlockNumber()) < B_OK
|| tree->Insert(transaction,"..",volume->ToBlock(inode->Parent())) < B_OK) || tree->Insert(transaction, "..", volume->ToBlock(inode->Parent())) < B_OK)
return B_ERROR; return B_ERROR;
} }
} }
// update the main indices (name, size & last_modified) // update the main indices (name, size & last_modified)
Index index(volume); Index index(volume);
if ((mode & (S_ATTR_DIR | S_ATTR | S_INDEX_DIR)) == 0) { if (inode->IsRegularNode()) {
status = index.InsertName(transaction,name,inode); // the name index only contains regular files
status = index.InsertName(transaction, name, inode);
if (status < B_OK && status != B_BAD_INDEX) if (status < B_OK && status != B_BAD_INDEX)
return status; 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 // The "size" & "last_modified" indices don't contain directories
if ((mode & (S_FILE | S_SYMLINK)) != 0) { if ((mode & (S_FILE | S_SYMLINK)) != 0) {
// if adding to these indices fails, the inode creation will not be harmed // if adding to these indices fails, the inode creation will not be harmed;
index.InsertSize(transaction,inode); // they are considered less important than the "name" index
index.InsertLastModified(transaction,inode); if (inode->IsFile())
index.InsertSize(transaction, inode);
index.InsertLastModified(transaction, inode);
} }
if ((status = inode->WriteBack(transaction)) < B_OK) if ((status = inode->WriteBack(transaction)) < B_OK)
return status; 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; return B_ERROR;
// add a link to the inode from the parent, depending on its type // add a link to the inode from the parent, depending on its type
if (tree && tree->Insert(transaction,name,volume->ToBlock(run)) < B_OK) { if (tree && tree->Insert(transaction, name, volume->ToBlock(run)) < B_OK) {
put_vnode(volume->ID(),inode->ID()); put_vnode(volume->ID(), inode->ID());
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
} else if (parent && mode & S_ATTR_DIR) { } else if (parent && mode & S_ATTR_DIR) {
parent->Attributes() = run; parent->Attributes() = run;
parent->WriteBack(transaction); parent->WriteBack(transaction);
} }
// everything worked well, so we want to keep the inode
allocator.Keep(); allocator.Keep();
if (_id != NULL) if (_id != NULL)
*_id = inode->ID(); *_id = inode->ID();
else
put_vnode(volume->ID(),inode->ID());
if (_inode != NULL) if (_inode != NULL)
*_inode = inode; *_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; return B_OK;
} }
@ -1856,7 +1869,7 @@ AttributeIterator::AttributeIterator(Inode *inode)
AttributeIterator::~AttributeIterator() AttributeIterator::~AttributeIterator()
{ {
if (fAttributes) if (fAttributes)
put_vnode(fAttributes->GetVolume()->ID(),fAttributes->ID()); put_vnode(fAttributes->GetVolume()->ID(), fAttributes->ID());
delete fIterator; delete fIterator;
fInode->RemoveIterator(this); fInode->RemoveIterator(this);