* 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:
parent
e50b251243
commit
24b822d843
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue