* 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:
Axel Dörfler 2009-04-17 09:51:42 +00:00
parent e50b251243
commit 24b822d843
4 changed files with 12 additions and 10 deletions

View File

@ -1498,7 +1498,7 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
if (pos + length > Size()) {
// let's grow the data stream to the size needed
status_t status = SetFileSize(transaction, pos + length);
if (status < B_OK) {
if (status != B_OK) {
*_length = 0;
WriteLockInTransaction(transaction);
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
// is closed)
status = WriteBack(transaction);
if (status < B_OK) {
if (status != B_OK) {
WriteLockInTransaction(transaction);
return status;
}

View File

@ -19,7 +19,6 @@ class TreeIterator;
class AttributeIterator;
class Index;
class InodeAllocator;
class InodeReadLocker;
class NodeGetter;
class Transaction;
@ -188,8 +187,6 @@ private:
friend class AttributeIterator;
friend class InodeAllocator;
friend class InodeReadLocker;
friend class Transaction;
// small_data access methods
status_t _MakeSpaceForSmallData(Transaction& transaction,
@ -253,7 +250,7 @@ class InodeReadLocker {
public:
InodeReadLocker(Inode* inode)
:
fLock(&inode->fLock)
fLock(&inode->Lock())
{
rw_lock_read_lock(fLock);
}

View File

@ -1103,7 +1103,7 @@ Transaction::AddInode(Inode* inode)
if (!GetVolume()->IsInitializing())
acquire_vnode(GetVolume()->FSVolume(), inode->ID());
rw_lock_write_lock(&inode->fLock);
rw_lock_write_lock(&inode->Lock());
fLockedInodes.Add(inode);
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);
fLockedInodes.Remove(inode);
rw_lock_write_unlock(&inode->fLock);
rw_lock_write_unlock(&inode->Lock());
// See AddInode() why we do this here
if ((inode->Flags() & INODE_DELETED) != 0)
@ -1133,7 +1133,7 @@ Transaction::_UnlockInodes()
{
while (Inode* inode = fLockedInodes.RemoveHead()) {
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
if ((inode->Flags() & INODE_DELETED) != 0)

View File

@ -755,8 +755,13 @@ bfs_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat* stat,
return status;
// 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());
rw_lock_write_lock(&inode->Lock());
}
if (!inode->IsDeleted()) {
Index index(volume);