bfs: Always check if NodeGetter succeeded.
* There were quite a few cases that just assumed that the disk access would succeed. * This also fixes bug #12962.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
* Copyright 2004-2017, Axel Dörfler, [email protected].
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -83,6 +83,9 @@ Attribute::Get(const char* name)
|
|||||||
// try to find it in the small data region
|
// try to find it in the small data region
|
||||||
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
||||||
fNodeGetter.SetToNode(fInode);
|
fNodeGetter.SetToNode(fInode);
|
||||||
|
if (fNodeGetter.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char*)name);
|
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char*)name);
|
||||||
if (fSmall != NULL)
|
if (fSmall != NULL)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2014, Axel Dörfler, [email protected].
|
* Copyright 2001-2017, Axel Dörfler, [email protected].
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1546,6 +1546,11 @@ BlockAllocator::CheckNextNode(check_control* control)
|
|||||||
&& inode->IsRegularNode()) {
|
&& inode->IsRegularNode()) {
|
||||||
RecursiveLocker locker(inode->SmallDataLock());
|
RecursiveLocker locker(inode->SmallDataLock());
|
||||||
NodeGetter node(fVolume, inode);
|
NodeGetter node(fVolume, inode);
|
||||||
|
if (node.Node() == NULL) {
|
||||||
|
fCheckCookie->control.errors |= BFS_COULD_NOT_OPEN;
|
||||||
|
fCheckCookie->control.status = B_IO_ERROR;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
const char* localName = inode->Name(node.Node());
|
const char* localName = inode->Name(node.Node());
|
||||||
if (localName == NULL || strcmp(localName, name)) {
|
if (localName == NULL || strcmp(localName, name)) {
|
||||||
|
|||||||
@@ -346,11 +346,14 @@ Inode::Inode(Volume* volume, ino_t id)
|
|||||||
{
|
{
|
||||||
PRINT(("Inode::Inode(volume = %p, id = %Ld) @ %p\n", volume, id, this));
|
PRINT(("Inode::Inode(volume = %p, id = %Ld) @ %p\n", volume, id, this));
|
||||||
|
|
||||||
UpdateNodeFromDisk();
|
|
||||||
|
|
||||||
rw_lock_init(&fLock, "bfs inode");
|
rw_lock_init(&fLock, "bfs inode");
|
||||||
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||||
|
|
||||||
|
if (UpdateNodeFromDisk() != B_OK) {
|
||||||
|
// TODO: the error code gets eaten
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// these two will help to maintain the indices
|
// these two will help to maintain the indices
|
||||||
fOldSize = Size();
|
fOldSize = Size();
|
||||||
fOldLastModified = LastModified();
|
fOldLastModified = LastModified();
|
||||||
@@ -381,6 +384,11 @@ Inode::Inode(Volume* volume, Transaction& transaction, ino_t id, mode_t mode,
|
|||||||
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||||
|
|
||||||
NodeGetter node(volume, transaction, this, true);
|
NodeGetter node(volume, transaction, this, true);
|
||||||
|
if (node.Node() == NULL) {
|
||||||
|
FATAL(("Could not read inode block %" B_PRId64 "!\n", BlockNumber()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&fNode, 0, sizeof(bfs_inode));
|
memset(&fNode, 0, sizeof(bfs_inode));
|
||||||
|
|
||||||
// Initialize the bfs_inode structure -- it's not written back to disk
|
// Initialize the bfs_inode structure -- it's not written back to disk
|
||||||
@@ -490,12 +498,19 @@ Inode::WriteBack(Transaction& transaction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
Inode::UpdateNodeFromDisk()
|
Inode::UpdateNodeFromDisk()
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume, this);
|
||||||
|
if (node.Node() == NULL) {
|
||||||
|
FATAL(("Failed to read block %" B_PRId64 " from disk!\n",
|
||||||
|
BlockNumber()));
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&fNode, node.Node(), sizeof(bfs_inode));
|
memcpy(&fNode, node.Node(), sizeof(bfs_inode));
|
||||||
fNode.flags &= HOST_ENDIAN_TO_BFS_INT32(INODE_PERMANENT_FLAGS);
|
fNode.flags &= HOST_ENDIAN_TO_BFS_INT32(INODE_PERMANENT_FLAGS);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -916,6 +931,9 @@ status_t
|
|||||||
Inode::GetName(char* buffer, size_t size) const
|
Inode::GetName(char* buffer, size_t size) const
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume, this);
|
||||||
|
if (node.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
RecursiveLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
const char* name = Name(node.Node());
|
const char* name = Name(node.Node());
|
||||||
@@ -940,6 +958,9 @@ Inode::SetName(Transaction& transaction, const char* name)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume, transaction, this);
|
||||||
|
if (node.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
const char nameTag[2] = {FILE_NAME_NAME, 0};
|
const char nameTag[2] = {FILE_NAME_NAME, 0};
|
||||||
|
|
||||||
return _AddSmallData(transaction, node, nameTag, FILE_NAME_TYPE, 0,
|
return _AddSmallData(transaction, node, nameTag, FILE_NAME_TYPE, 0,
|
||||||
@@ -1013,6 +1034,9 @@ Inode::ReadAttribute(const char* name, int32 type, off_t pos, uint8* buffer,
|
|||||||
// search in the small_data section (which has to be locked first)
|
// search in the small_data section (which has to be locked first)
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume, this);
|
||||||
|
if (node.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
RecursiveLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
small_data* smallData = FindSmallData(node.Node(), name);
|
small_data* smallData = FindSmallData(node.Node(), name);
|
||||||
@@ -1079,6 +1103,9 @@ Inode::WriteAttribute(Transaction& transaction, const char* name, int32 type,
|
|||||||
|
|
||||||
// save the old attribute data
|
// save the old attribute data
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume, transaction, this);
|
||||||
|
if (node.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
recursive_lock_lock(&fSmallDataLock);
|
recursive_lock_lock(&fSmallDataLock);
|
||||||
|
|
||||||
small_data* smallData = FindSmallData(node.Node(), name);
|
small_data* smallData = FindSmallData(node.Node(), name);
|
||||||
@@ -1148,6 +1175,9 @@ Inode::WriteAttribute(Transaction& transaction, const char* name, int32 type,
|
|||||||
|
|
||||||
// check if the data fits into the small_data section again
|
// check if the data fits into the small_data section again
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume, transaction, this);
|
||||||
|
if (node.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
status = _AddSmallData(transaction, node, name, type, pos, buffer,
|
status = _AddSmallData(transaction, node, name, type, pos, buffer,
|
||||||
*_length);
|
*_length);
|
||||||
|
|
||||||
@@ -1214,6 +1244,8 @@ Inode::RemoveAttribute(Transaction& transaction, const char* name)
|
|||||||
Index index(fVolume);
|
Index index(fVolume);
|
||||||
bool hasIndex = index.SetTo(name) == B_OK;
|
bool hasIndex = index.SetTo(name) == B_OK;
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume, this);
|
||||||
|
if (node.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
// update index for attributes in the small_data section
|
// update index for attributes in the small_data section
|
||||||
{
|
{
|
||||||
@@ -2431,7 +2463,8 @@ void
|
|||||||
Inode::TransactionDone(bool success)
|
Inode::TransactionDone(bool success)
|
||||||
{
|
{
|
||||||
if (!success) {
|
if (!success) {
|
||||||
// revert any changes made to the cached bfs_inode
|
// Revert any changes made to the cached bfs_inode
|
||||||
|
// TODO: return code gets eaten
|
||||||
UpdateNodeFromDisk();
|
UpdateNodeFromDisk();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2822,6 +2855,9 @@ AttributeIterator::GetNext(char* name, size_t* _length, uint32* _type,
|
|||||||
|
|
||||||
if (fCurrentSmallData >= 0) {
|
if (fCurrentSmallData >= 0) {
|
||||||
NodeGetter nodeGetter(fInode->GetVolume(), fInode);
|
NodeGetter nodeGetter(fInode->GetVolume(), fInode);
|
||||||
|
if (nodeGetter.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
const bfs_inode* node = nodeGetter.Node();
|
const bfs_inode* node = nodeGetter.Node();
|
||||||
const small_data* item = ((bfs_inode*)node)->SmallDataStart();
|
const small_data* item = ((bfs_inode*)node)->SmallDataStart();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2016, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef INODE_H
|
#ifndef INODE_H
|
||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
recursive_lock& SmallDataLock() { return fSmallDataLock; }
|
recursive_lock& SmallDataLock() { return fSmallDataLock; }
|
||||||
|
|
||||||
status_t WriteBack(Transaction& transaction);
|
status_t WriteBack(Transaction& transaction);
|
||||||
void UpdateNodeFromDisk();
|
status_t UpdateNodeFromDisk();
|
||||||
|
|
||||||
bool IsContainer() const
|
bool IsContainer() const
|
||||||
{ return S_ISDIR(Mode()); }
|
{ return S_ISDIR(Mode()); }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2014, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
|
* Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -558,6 +558,8 @@ Equation::Match(Inode* inode, const char* attributeName, int32 type,
|
|||||||
} else if (!strcmp(fAttribute, "name")) {
|
} else if (!strcmp(fAttribute, "name")) {
|
||||||
// we need to lock before accessing Inode::Name()
|
// we need to lock before accessing Inode::Name()
|
||||||
nodeGetter.SetToNode(inode);
|
nodeGetter.SetToNode(inode);
|
||||||
|
if (nodeGetter.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
recursive_lock_lock(&inode->SmallDataLock());
|
recursive_lock_lock(&inode->SmallDataLock());
|
||||||
locked = true;
|
locked = true;
|
||||||
@@ -589,6 +591,9 @@ Equation::Match(Inode* inode, const char* attributeName, int32 type,
|
|||||||
// then for attributes in the small_data section, and finally for the
|
// then for attributes in the small_data section, and finally for the
|
||||||
// real attributes
|
// real attributes
|
||||||
nodeGetter.SetToNode(inode);
|
nodeGetter.SetToNode(inode);
|
||||||
|
if (nodeGetter.Node() == NULL)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
Inode* attribute;
|
Inode* attribute;
|
||||||
|
|
||||||
recursive_lock_lock(&inode->SmallDataLock());
|
recursive_lock_lock(&inode->SmallDataLock());
|
||||||
|
|||||||
Reference in New Issue
Block a user