mirror of
https://review.haiku-os.org/haiku
synced 2025-01-19 21:11:28 +01:00
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:
parent
67fa10dcde
commit
52fafe627e
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user