* No longer hold the write lock when calling Inode::FillGapWithZeros(), as this
potentially deadlocks as described in bug #3768. The system is still completely unresponsive, but gets back to a working state after some time now. * Since the rw_lock is public, Transaction and InodeReadLocker no longer need to be friends with Inode. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30221 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1498,7 +1498,7 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
|
|||||||
if (pos + length > Size()) {
|
if (pos + length > Size()) {
|
||||||
// let's grow the data stream to the size needed
|
// let's grow the data stream to the size needed
|
||||||
status_t status = SetFileSize(transaction, pos + length);
|
status_t status = SetFileSize(transaction, pos + length);
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
*_length = 0;
|
*_length = 0;
|
||||||
WriteLockInTransaction(transaction);
|
WriteLockInTransaction(transaction);
|
||||||
RETURN_ERROR(status);
|
RETURN_ERROR(status);
|
||||||
@@ -1511,7 +1511,7 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
|
|||||||
// go into this transaction (we cannot wait until the file
|
// go into this transaction (we cannot wait until the file
|
||||||
// is closed)
|
// is closed)
|
||||||
status = WriteBack(transaction);
|
status = WriteBack(transaction);
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
WriteLockInTransaction(transaction);
|
WriteLockInTransaction(transaction);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class TreeIterator;
|
|||||||
class AttributeIterator;
|
class AttributeIterator;
|
||||||
class Index;
|
class Index;
|
||||||
class InodeAllocator;
|
class InodeAllocator;
|
||||||
class InodeReadLocker;
|
|
||||||
class NodeGetter;
|
class NodeGetter;
|
||||||
class Transaction;
|
class Transaction;
|
||||||
|
|
||||||
@@ -188,8 +187,6 @@ private:
|
|||||||
|
|
||||||
friend class AttributeIterator;
|
friend class AttributeIterator;
|
||||||
friend class InodeAllocator;
|
friend class InodeAllocator;
|
||||||
friend class InodeReadLocker;
|
|
||||||
friend class Transaction;
|
|
||||||
|
|
||||||
// small_data access methods
|
// small_data access methods
|
||||||
status_t _MakeSpaceForSmallData(Transaction& transaction,
|
status_t _MakeSpaceForSmallData(Transaction& transaction,
|
||||||
@@ -253,7 +250,7 @@ class InodeReadLocker {
|
|||||||
public:
|
public:
|
||||||
InodeReadLocker(Inode* inode)
|
InodeReadLocker(Inode* inode)
|
||||||
:
|
:
|
||||||
fLock(&inode->fLock)
|
fLock(&inode->Lock())
|
||||||
{
|
{
|
||||||
rw_lock_read_lock(fLock);
|
rw_lock_read_lock(fLock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1103,7 +1103,7 @@ Transaction::AddInode(Inode* inode)
|
|||||||
if (!GetVolume()->IsInitializing())
|
if (!GetVolume()->IsInitializing())
|
||||||
acquire_vnode(GetVolume()->FSVolume(), inode->ID());
|
acquire_vnode(GetVolume()->FSVolume(), inode->ID());
|
||||||
|
|
||||||
rw_lock_write_lock(&inode->fLock);
|
rw_lock_write_lock(&inode->Lock());
|
||||||
fLockedInodes.Add(inode);
|
fLockedInodes.Add(inode);
|
||||||
inode->Node().flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
|
inode->Node().flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
|
||||||
}
|
}
|
||||||
@@ -1117,7 +1117,7 @@ Transaction::RemoveInode(Inode* inode)
|
|||||||
|
|
||||||
inode->Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
|
inode->Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
|
||||||
fLockedInodes.Remove(inode);
|
fLockedInodes.Remove(inode);
|
||||||
rw_lock_write_unlock(&inode->fLock);
|
rw_lock_write_unlock(&inode->Lock());
|
||||||
|
|
||||||
// See AddInode() why we do this here
|
// See AddInode() why we do this here
|
||||||
if ((inode->Flags() & INODE_DELETED) != 0)
|
if ((inode->Flags() & INODE_DELETED) != 0)
|
||||||
@@ -1133,7 +1133,7 @@ Transaction::_UnlockInodes()
|
|||||||
{
|
{
|
||||||
while (Inode* inode = fLockedInodes.RemoveHead()) {
|
while (Inode* inode = fLockedInodes.RemoveHead()) {
|
||||||
inode->Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
|
inode->Node().flags &= ~HOST_ENDIAN_TO_BFS_INT32(INODE_IN_TRANSACTION);
|
||||||
rw_lock_write_unlock(&inode->fLock);
|
rw_lock_write_unlock(&inode->Lock());
|
||||||
|
|
||||||
// See AddInode() why we do this here
|
// See AddInode() why we do this here
|
||||||
if ((inode->Flags() & INODE_DELETED) != 0)
|
if ((inode->Flags() & INODE_DELETED) != 0)
|
||||||
|
|||||||
@@ -755,8 +755,13 @@ bfs_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat* stat,
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
// fill the new blocks (if any) with zeros
|
// fill the new blocks (if any) with zeros
|
||||||
if ((mask & B_STAT_SIZE_INSECURE) == 0)
|
if ((mask & B_STAT_SIZE_INSECURE) == 0) {
|
||||||
|
// We must not keep the inode locked during a write operation,
|
||||||
|
// or else we might deadlock.
|
||||||
|
rw_lock_write_unlock(&inode->Lock());
|
||||||
inode->FillGapWithZeros(oldSize, inode->Size());
|
inode->FillGapWithZeros(oldSize, inode->Size());
|
||||||
|
rw_lock_write_lock(&inode->Lock());
|
||||||
|
}
|
||||||
|
|
||||||
if (!inode->IsDeleted()) {
|
if (!inode->IsDeleted()) {
|
||||||
Index index(volume);
|
Index index(volume);
|
||||||
|
|||||||
Reference in New Issue
Block a user