* Replaced BFS's ReadWriteLock implementation with the kernel's rw_lock.
* The BlockAllocator now uses the new mutex_transfer_lock() function instead of clobbering the mutex directly. * Removed Lock.h - it's no longer needed. * Minor white space cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26317 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2007, Axel Dörfler, [email protected].
|
||||
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -71,7 +71,7 @@ Attribute::CheckAccess(const char *name, int openMode)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
status_t
|
||||
Attribute::Get(const char *name)
|
||||
{
|
||||
Put();
|
||||
@@ -119,7 +119,7 @@ Attribute::Create(const char *name, type_code type, int openMode, attr_cookie **
|
||||
|
||||
attr_cookie *cookie = (attr_cookie *)malloc(sizeof(attr_cookie));
|
||||
if (cookie == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
fName = name;
|
||||
|
||||
@@ -152,7 +152,7 @@ Attribute::Open(const char *name, int openMode, attr_cookie **_cookie)
|
||||
|
||||
attr_cookie *cookie = (attr_cookie *)malloc(sizeof(attr_cookie));
|
||||
if (cookie == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
// initialize the cookie
|
||||
strlcpy(cookie->name, fName, B_ATTR_NAME_LENGTH);
|
||||
@@ -222,7 +222,7 @@ Attribute::_Truncate()
|
||||
}
|
||||
|
||||
if (fAttribute != NULL) {
|
||||
WriteLocked locked(fAttribute->Lock());
|
||||
WriteLocker locker(fAttribute->Lock());
|
||||
Transaction transaction(fAttribute->GetVolume(), fAttribute->BlockNumber());
|
||||
|
||||
status_t status = fAttribute->SetFileSize(transaction, 0);
|
||||
|
||||
@@ -1259,7 +1259,7 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
|
||||
#endif
|
||||
|
||||
// lock access to stream
|
||||
WriteLocked locked(fStream->Lock());
|
||||
WriteLocker locker(fStream->Lock());
|
||||
|
||||
Stack<node_and_key> stack;
|
||||
if (_SeekDown(stack, key, keyLength) != B_OK)
|
||||
@@ -1653,7 +1653,7 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
// lock access to stream
|
||||
WriteLocked locked(fStream->Lock());
|
||||
WriteLocker locker(fStream->Lock());
|
||||
|
||||
Stack<node_and_key> stack;
|
||||
if (_SeekDown(stack, key, keyLength) != B_OK)
|
||||
@@ -1771,7 +1771,7 @@ BPlusTree::Replace(Transaction &transaction, const uint8 *key,
|
||||
RETURN_ERROR(B_BAD_TYPE);
|
||||
|
||||
// lock access to stream (a read lock is okay for this purpose)
|
||||
ReadLocked locked(fStream->Lock());
|
||||
ReadLocker locker(fStream->Lock());
|
||||
|
||||
off_t nodeOffset = fHeader->RootNode();
|
||||
CachedNode cached(this);
|
||||
@@ -1825,7 +1825,7 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
|
||||
RETURN_ERROR(B_BAD_TYPE);
|
||||
|
||||
// lock access to stream
|
||||
ReadLocked locked(fStream->Lock());
|
||||
ReadLocker locker(fStream->Lock());
|
||||
|
||||
off_t nodeOffset = fHeader->RootNode();
|
||||
CachedNode cached(this);
|
||||
@@ -1889,7 +1889,7 @@ TreeIterator::Goto(int8 to)
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
// lock access to stream
|
||||
ReadLocked locked(fTree->fStream->Lock());
|
||||
ReadLocker locker(fTree->fStream->Lock());
|
||||
|
||||
off_t nodeOffset = fTree->fHeader->RootNode();
|
||||
CachedNode cached(fTree);
|
||||
@@ -1959,7 +1959,7 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// lock access to stream
|
||||
ReadLocked locked(fTree->fStream->Lock());
|
||||
ReadLocker locker(fTree->fStream->Lock());
|
||||
|
||||
CachedNode cached(fTree);
|
||||
const bplustree_node *node;
|
||||
@@ -2095,7 +2095,7 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
// lock access to stream
|
||||
ReadLocked locked(fTree->fStream->Lock());
|
||||
ReadLocker locker(fTree->fStream->Lock());
|
||||
|
||||
off_t nodeOffset = fTree->fHeader->RootNode();
|
||||
|
||||
|
||||
@@ -474,10 +474,8 @@ BlockAllocator::Initialize(bool full)
|
||||
"bfs block allocator", B_LOW_PRIORITY, (void *)this);
|
||||
if (id < B_OK)
|
||||
return _Initialize(this);
|
||||
#ifdef KDEBUG
|
||||
else
|
||||
fLock.holder = id;
|
||||
#endif
|
||||
mutex_transfer_lock(&fLock, id);
|
||||
|
||||
return resume_thread(id);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include "Volume.h"
|
||||
#include "Journal.h"
|
||||
#include "Lock.h"
|
||||
#include "Chain.h"
|
||||
#include "Debug.h"
|
||||
|
||||
@@ -96,7 +95,7 @@ CachedBlock::CachedBlock(Volume *volume, block_run run)
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
inline
|
||||
CachedBlock::CachedBlock(CachedBlock *cached)
|
||||
:
|
||||
fVolume(cached->fVolume),
|
||||
@@ -161,7 +160,7 @@ CachedBlock::SetToWritable(Transaction &transaction, off_t block, off_t base,
|
||||
{
|
||||
Unset();
|
||||
fBlockNumber = block;
|
||||
|
||||
|
||||
if (empty) {
|
||||
fBlock = (uint8 *)block_cache_get_empty(fVolume->BlockCache(),
|
||||
block, transaction.ID());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de.
|
||||
/*
|
||||
* Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -63,7 +63,7 @@ Index::SetTo(const char *name)
|
||||
{
|
||||
// remove the old node, if the index is set for the second time
|
||||
Unset();
|
||||
|
||||
|
||||
fName = name;
|
||||
// only stores the pointer, so it assumes that it will stay constant
|
||||
// in further comparisons (currently only used in Index::Update())
|
||||
@@ -138,7 +138,7 @@ Index::KeySize()
|
||||
{
|
||||
if (fNode == NULL)
|
||||
return 0;
|
||||
|
||||
|
||||
int32 mode = fNode->Mode() & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX
|
||||
| S_LONG_LONG_INDEX | S_ULONG_LONG_INDEX | S_FLOAT_INDEX
|
||||
| S_DOUBLE_INDEX);
|
||||
|
||||
@@ -328,7 +328,7 @@ Inode::Inode(Volume *volume, ino_t id)
|
||||
char lockName[B_OS_NAME_LENGTH];
|
||||
snprintf(lockName, sizeof(lockName), "bfs inode %d.%d",
|
||||
(int)BlockRun().AllocationGroup(), BlockRun().Start());
|
||||
fLock.Initialize(lockName);
|
||||
rw_lock_init_etc(&fLock, lockName, RW_LOCK_FLAG_CLONE_NAME);
|
||||
|
||||
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||
|
||||
@@ -361,7 +361,7 @@ Inode::Inode(Volume *volume, Transaction &transaction, ino_t id, mode_t mode,
|
||||
char lockName[B_OS_NAME_LENGTH];
|
||||
snprintf(lockName, sizeof(lockName), "bfs inode+%d.%d",
|
||||
(int)run.AllocationGroup(), run.Start());
|
||||
fLock.Initialize(lockName);
|
||||
rw_lock_init_etc(&fLock, lockName, RW_LOCK_FLAG_CLONE_NAME);
|
||||
|
||||
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||
|
||||
@@ -399,6 +399,8 @@ Inode::~Inode()
|
||||
file_cache_delete(FileCache());
|
||||
file_map_delete(Map());
|
||||
delete fTree;
|
||||
|
||||
rw_lock_destroy(&fLock);
|
||||
}
|
||||
|
||||
|
||||
@@ -429,9 +431,7 @@ Inode::InitCheck(bool checkNode)
|
||||
}
|
||||
}
|
||||
|
||||
// it's more important to know that the inode is corrupt
|
||||
// so we check for the lock not until here
|
||||
return fLock.InitCheck();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1055,7 +1055,7 @@ Inode::WriteAttribute(Transaction &transaction, const char *name, int32 type,
|
||||
}
|
||||
|
||||
if (attribute != NULL) {
|
||||
if (attribute->Lock().LockWrite() == B_OK) {
|
||||
if (rw_lock_write_lock(&attribute->Lock()) == B_OK) {
|
||||
// Save the old attribute data (if this fails, oldLength will
|
||||
// reflect it)
|
||||
if (fVolume->CheckForLiveQuery(name) && attribute->Size() > 0) {
|
||||
@@ -1071,14 +1071,14 @@ Inode::WriteAttribute(Transaction &transaction, const char *name, int32 type,
|
||||
|
||||
if (status == B_OK) {
|
||||
// it does - remove its file
|
||||
attribute->Lock().UnlockWrite();
|
||||
rw_lock_write_unlock(&attribute->Lock());
|
||||
status = _RemoveAttribute(transaction, name, false, NULL);
|
||||
} else {
|
||||
// The attribute type might have been changed - we need to
|
||||
// adopt the new one
|
||||
attribute->Node().type = HOST_ENDIAN_TO_BFS_INT32(type);
|
||||
status = attribute->WriteBack(transaction);
|
||||
attribute->Lock().UnlockWrite();
|
||||
rw_lock_write_unlock(&attribute->Lock());
|
||||
|
||||
if (status == B_OK) {
|
||||
status = attribute->WriteAt(transaction, pos, buffer,
|
||||
@@ -1376,7 +1376,7 @@ Inode::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
|
||||
if (pos < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ReadLocked locker(Lock());
|
||||
ReadLocker locker(Lock());
|
||||
|
||||
if (pos >= Size() || length == 0) {
|
||||
*_length = 0;
|
||||
@@ -1393,8 +1393,8 @@ status_t
|
||||
Inode::WriteAt(Transaction &transaction, off_t pos, const uint8 *buffer,
|
||||
size_t *_length)
|
||||
{
|
||||
WriteLocked locker(Lock());
|
||||
if (locker.IsLocked() < B_OK)
|
||||
WriteLocker locker(Lock());
|
||||
if (!locker.IsLocked())
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
// update the last modification time in memory, it will be written
|
||||
@@ -2310,7 +2310,7 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name,
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
}
|
||||
|
||||
WriteLocked locker(parent != NULL ? &parent->Lock() : NULL);
|
||||
WriteLocker locker(parent != NULL ? &parent->Lock() : NULL);
|
||||
// the parent directory is locked during the whole inode creation
|
||||
|
||||
if (parent != NULL && parent->IsDirectory()) {
|
||||
@@ -2354,7 +2354,7 @@ Inode::Create(Transaction &transaction, Inode *parent, const char *name,
|
||||
return status;
|
||||
|
||||
// truncate the existing file
|
||||
WriteLocked locked(inode->Lock());
|
||||
WriteLocker _(inode->Lock());
|
||||
|
||||
status_t status = inode->SetFileSize(transaction, 0);
|
||||
if (status >= B_OK)
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "Volume.h"
|
||||
#include "Journal.h"
|
||||
#include "Lock.h"
|
||||
#include "Chain.h"
|
||||
#include "Debug.h"
|
||||
#include "CachedBlock.h"
|
||||
@@ -45,7 +44,7 @@ class Inode {
|
||||
ino_t ID() const { return fID; }
|
||||
off_t BlockNumber() const { return fVolume->VnodeToBlock(fID); }
|
||||
|
||||
ReadWriteLock &Lock() { return fLock; }
|
||||
rw_lock &Lock() { return fLock; }
|
||||
recursive_lock &SmallDataLock() { return fSmallDataLock; }
|
||||
status_t WriteBack(Transaction &transaction);
|
||||
|
||||
@@ -193,7 +192,7 @@ class Inode {
|
||||
status_t _ShrinkStream(Transaction &transaction, off_t size);
|
||||
|
||||
private:
|
||||
ReadWriteLock fLock;
|
||||
rw_lock fLock;
|
||||
Volume *fVolume;
|
||||
ino_t fID;
|
||||
BPlusTree *fTree;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "Volume.h"
|
||||
#include "Chain.h"
|
||||
#include "Lock.h"
|
||||
#include "Utility.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LOCK_H
|
||||
#define LOCK_H
|
||||
|
||||
/*! Simple semaphores, read/write lock implementation
|
||||
Roughly based on a Be sample code written by Nathan Schrenk.
|
||||
*/
|
||||
|
||||
#include "system_dependencies.h"
|
||||
|
||||
#include "Utility.h"
|
||||
#include "Debug.h"
|
||||
|
||||
|
||||
// Configure here if and when real benaphores should be used
|
||||
//#define USE_BENAPHORE
|
||||
// if defined, benaphores are used for the Semaphore/RecursiveLock classes
|
||||
//# define FAST_LOCK
|
||||
// the ReadWriteLock class uses a second Semaphore to
|
||||
// speed up locking - only makes sense if USE_BENAPHORE
|
||||
// is defined, too.
|
||||
#ifdef FAST_LOCK
|
||||
# error implement recursive write locking first
|
||||
#endif
|
||||
|
||||
// #pragma mark - Many Reader/Single Writer Lock
|
||||
|
||||
// This is a "fast" implementation of a single writer/many reader
|
||||
// locking scheme. It's fast because it uses the benaphore idea
|
||||
// to do lazy semaphore locking - in most cases it will only have
|
||||
// to do some simple integer arithmetic.
|
||||
// The second semaphore (fWriteLock) is needed to prevent the situation
|
||||
// that a second writer can acquire the lock when there are still readers
|
||||
// holding it.
|
||||
|
||||
#define MAX_READERS 100000
|
||||
|
||||
// Note: this code will break if you actually have 100000 readers
|
||||
// at once. With the current thread/... limits in BeOS you can't
|
||||
// touch that value, but it might be possible in the future.
|
||||
// Also, you can only have about 20000 concurrent writers until
|
||||
// the semaphore count exceeds the int32 bounds
|
||||
|
||||
// Timeouts:
|
||||
// It may be a good idea to have timeouts for the WriteLocked class,
|
||||
// in case something went wrong - we'll see if this is necessary,
|
||||
// but it would be a somewhat poor work-around for a deadlock...
|
||||
// But the only real problem with timeouts could be for things like
|
||||
// "chkbfs" - because such a tool may need to lock for some more time
|
||||
|
||||
|
||||
// define if you want to have fast locks as the foundation for the
|
||||
// ReadWriteLock class - the benefit is that acquire_sem() doesn't
|
||||
// have to be called when there is no one waiting.
|
||||
// The disadvantage is the use of 2 real semaphores which is quite
|
||||
// expensive regarding that BeOS only allows for a total of 64k
|
||||
// semaphores (since every open BFS inode has such a lock).
|
||||
|
||||
#ifdef FAST_LOCK
|
||||
class ReadWriteLock {
|
||||
public:
|
||||
ReadWriteLock(const char *name)
|
||||
:
|
||||
fWriteLock(name)
|
||||
{
|
||||
Initialize(name);
|
||||
}
|
||||
|
||||
ReadWriteLock()
|
||||
:
|
||||
fWriteLock("bfs r/w w-lock")
|
||||
{
|
||||
}
|
||||
|
||||
~ReadWriteLock()
|
||||
{
|
||||
delete_sem(fSemaphore);
|
||||
}
|
||||
|
||||
status_t Initialize(const char *name = "bfs r/w lock")
|
||||
{
|
||||
fSemaphore = create_sem(0, name);
|
||||
fCount = MAX_READERS;
|
||||
return fSemaphore;
|
||||
}
|
||||
|
||||
status_t InitCheck()
|
||||
{
|
||||
if (fSemaphore < B_OK)
|
||||
return fSemaphore;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t Lock()
|
||||
{
|
||||
if (atomic_add(&fCount, -1) <= 0)
|
||||
return acquire_sem(fSemaphore);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
if (atomic_add(&fCount, 1) < 0)
|
||||
release_sem(fSemaphore);
|
||||
}
|
||||
|
||||
status_t LockWrite()
|
||||
{
|
||||
if (fWriteLock.Lock() < B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
int32 readers = atomic_add(&fCount, -MAX_READERS);
|
||||
status_t status = B_OK;
|
||||
|
||||
if (readers < MAX_READERS) {
|
||||
// Acquire sem for all readers currently not using a semaphore.
|
||||
// But if we are not the only write lock in the queue, just get
|
||||
// the one for us
|
||||
status = acquire_sem_etc(fSemaphore, readers <= 0 ? 1 : MAX_READERS - readers, 0, 0);
|
||||
}
|
||||
fWriteLock.Unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void UnlockWrite()
|
||||
{
|
||||
int32 readers = atomic_add(&fCount, MAX_READERS);
|
||||
if (readers < 0) {
|
||||
// release sem for all readers only when we were the only writer
|
||||
release_sem_etc(fSemaphore, readers <= -MAX_READERS ? 1 : -readers, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ReadLocked;
|
||||
friend class WriteLocked;
|
||||
|
||||
sem_id fSemaphore;
|
||||
vint32 fCount;
|
||||
Semaphore fWriteLock;
|
||||
};
|
||||
#else // FAST_LOCK
|
||||
class ReadWriteLock {
|
||||
public:
|
||||
ReadWriteLock(const char *name)
|
||||
:
|
||||
fOwner(-1)
|
||||
{
|
||||
Initialize(name);
|
||||
}
|
||||
|
||||
ReadWriteLock()
|
||||
:
|
||||
fSemaphore(-1),
|
||||
fOwner(-1)
|
||||
{
|
||||
}
|
||||
|
||||
~ReadWriteLock()
|
||||
{
|
||||
delete_sem(fSemaphore);
|
||||
}
|
||||
|
||||
status_t Initialize(const char *name = "bfs r/w lock")
|
||||
{
|
||||
fSemaphore = create_sem(MAX_READERS, name);
|
||||
return fSemaphore;
|
||||
}
|
||||
|
||||
status_t InitCheck()
|
||||
{
|
||||
if (fSemaphore < B_OK)
|
||||
return fSemaphore;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t Lock()
|
||||
{
|
||||
// This allows nested locking when holding a write lock
|
||||
thread_id currentThread = find_thread(NULL);
|
||||
if (currentThread == fOwner) {
|
||||
fOwnerCount++;
|
||||
return B_OK;
|
||||
}
|
||||
return acquire_sem(fSemaphore);
|
||||
}
|
||||
|
||||
status_t TryLock()
|
||||
{
|
||||
// This allows nested locking when holding a write lock
|
||||
thread_id currentThread = find_thread(NULL);
|
||||
if (currentThread == fOwner) {
|
||||
fOwnerCount++;
|
||||
return B_OK;
|
||||
}
|
||||
return acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, 0);
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
thread_id currentThread = find_thread(NULL);
|
||||
if (fOwner == currentThread && --fOwnerCount > 0)
|
||||
return;
|
||||
|
||||
release_sem(fSemaphore);
|
||||
}
|
||||
|
||||
status_t LockWrite()
|
||||
{
|
||||
thread_id currentThread = find_thread(NULL);
|
||||
if (currentThread == fOwner) {
|
||||
fOwnerCount++;
|
||||
return B_OK;
|
||||
}
|
||||
status_t status = acquire_sem_etc(fSemaphore, MAX_READERS, 0, 0);
|
||||
if (status >= B_OK) {
|
||||
fOwner = currentThread;
|
||||
fOwnerCount = 1;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void UnlockWrite()
|
||||
{
|
||||
if (--fOwnerCount == 0) {
|
||||
fOwner = -1;
|
||||
release_sem_etc(fSemaphore, MAX_READERS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ReadLocked;
|
||||
friend class WriteLocked;
|
||||
|
||||
sem_id fSemaphore;
|
||||
thread_id fOwner;
|
||||
int32 fOwnerCount;
|
||||
};
|
||||
#endif // FAST_LOCK
|
||||
|
||||
|
||||
class ReadLocked {
|
||||
public:
|
||||
ReadLocked(ReadWriteLock &lock)
|
||||
:
|
||||
fLock(lock)
|
||||
{
|
||||
fStatus = lock.Lock();
|
||||
}
|
||||
|
||||
~ReadLocked()
|
||||
{
|
||||
if (fStatus == B_OK)
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
status_t
|
||||
IsLocked()
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
void
|
||||
Unlock()
|
||||
{
|
||||
fLock.Unlock();
|
||||
fStatus = B_NO_INIT;
|
||||
}
|
||||
|
||||
private:
|
||||
ReadWriteLock &fLock;
|
||||
status_t fStatus;
|
||||
};
|
||||
|
||||
|
||||
class WriteLocked {
|
||||
public:
|
||||
WriteLocked(ReadWriteLock &lock)
|
||||
:
|
||||
fLock(&lock)
|
||||
{
|
||||
fStatus = lock.LockWrite();
|
||||
}
|
||||
|
||||
WriteLocked(ReadWriteLock *lock)
|
||||
:
|
||||
fLock(lock)
|
||||
{
|
||||
fStatus = lock != NULL ? lock->LockWrite() : B_NO_INIT;
|
||||
}
|
||||
|
||||
~WriteLocked()
|
||||
{
|
||||
if (fStatus == B_OK)
|
||||
fLock->UnlockWrite();
|
||||
}
|
||||
|
||||
status_t
|
||||
Lock()
|
||||
{
|
||||
if (fStatus == B_OK)
|
||||
return B_ERROR;
|
||||
return fStatus = fLock->LockWrite();
|
||||
}
|
||||
|
||||
status_t
|
||||
IsLocked()
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
void
|
||||
Unlock()
|
||||
{
|
||||
if (fStatus == B_OK)
|
||||
fLock->UnlockWrite();
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
|
||||
private:
|
||||
ReadWriteLock *fLock;
|
||||
status_t fStatus;
|
||||
};
|
||||
|
||||
#endif /* LOCK_H */
|
||||
@@ -339,7 +339,7 @@ bfs_read_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
if (!reenter)
|
||||
inode->Lock().Lock();
|
||||
rw_lock_read_lock(&inode->Lock());
|
||||
|
||||
uint32 vecIndex = 0;
|
||||
size_t vecOffset = 0;
|
||||
@@ -368,7 +368,7 @@ bfs_read_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
}
|
||||
|
||||
if (!reenter)
|
||||
inode->Lock().Unlock();
|
||||
rw_lock_read_unlock(&inode->Lock());
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -388,7 +388,7 @@ bfs_write_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
if (!reenter)
|
||||
inode->Lock().Lock();
|
||||
rw_lock_read_lock(&inode->Lock());
|
||||
|
||||
uint32 vecIndex = 0;
|
||||
size_t vecOffset = 0;
|
||||
@@ -417,7 +417,7 @@ bfs_write_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
}
|
||||
|
||||
if (!reenter)
|
||||
inode->Lock().Unlock();
|
||||
rw_lock_read_unlock(&inode->Lock());
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -646,11 +646,10 @@ bfs_fsync(fs_volume *_volume, fs_vnode *_node)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
Inode *inode = (Inode *)_node->private_node;
|
||||
ReadLocked locked(inode->Lock());
|
||||
ReadLocker locker(inode->Lock());
|
||||
|
||||
status_t status = locked.IsLocked();
|
||||
if (status < B_OK)
|
||||
RETURN_ERROR(status);
|
||||
if (!locker.IsLocked())
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
return inode->Sync();
|
||||
}
|
||||
@@ -689,8 +688,8 @@ bfs_write_stat(fs_volume *_volume, fs_vnode *_node, const struct stat *stat,
|
||||
|
||||
Transaction transaction(volume, inode->BlockNumber());
|
||||
|
||||
WriteLocked locked(inode->Lock());
|
||||
if (locked.IsLocked() < B_OK)
|
||||
WriteLocker locker(inode->Lock());
|
||||
if (!locker.IsLocked())
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
bfs_inode &node = inode->Node();
|
||||
@@ -1150,7 +1149,7 @@ bfs_open(fs_volume *_volume, fs_vnode *_node, int openMode, void **_cookie)
|
||||
// Should we truncate the file?
|
||||
if (openMode & O_TRUNC) {
|
||||
Transaction transaction(volume, inode->BlockNumber());
|
||||
WriteLocked locked(inode->Lock());
|
||||
WriteLocker locker(inode->Lock());
|
||||
|
||||
status_t status = inode->SetFileSize(transaction, 0);
|
||||
if (status >= B_OK)
|
||||
@@ -1219,7 +1218,7 @@ bfs_write(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos,
|
||||
transaction.Done();
|
||||
|
||||
if (status == B_OK) {
|
||||
ReadLocked locker(inode->Lock());
|
||||
ReadLocker locker(inode->Lock());
|
||||
|
||||
// periodically notify if the file size has changed
|
||||
// TODO: should we better test for a change in the last_modified time only?
|
||||
@@ -1258,7 +1257,7 @@ bfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||
bool needsTrimming = false;
|
||||
|
||||
if (!volume->IsReadOnly()) {
|
||||
ReadLocked locker(inode->Lock());
|
||||
ReadLocker locker(inode->Lock());
|
||||
needsTrimming = inode->NeedsTrimming();
|
||||
|
||||
if ((cookie->open_mode & O_RWMASK) != 0
|
||||
@@ -1274,7 +1273,7 @@ bfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||
status_t status = transaction.IsStarted() ? B_OK : B_ERROR;
|
||||
|
||||
if (status == B_OK) {
|
||||
WriteLocked locker(inode->Lock());
|
||||
WriteLocker locker(inode->Lock());
|
||||
|
||||
// trim the preallocated blocks and update the size,
|
||||
// and last_modified indices if needed
|
||||
|
||||
Reference in New Issue
Block a user