kernel/vfs: Replace the mount mutex with a rw_lock.
Since the entry_cache operations go through the mount lock, this may considerably speed up parallel entry cache operations. Change-Id: Ib2f841e288eb593ee3f795922103459c77764c22 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2362 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
dba1e7423b
commit
cbb517abfd
@@ -214,7 +214,7 @@ struct advisory_locking {
|
|||||||
Manipulation of the fs_mount structures themselves
|
Manipulation of the fs_mount structures themselves
|
||||||
(and their destruction) requires different locks though.
|
(and their destruction) requires different locks though.
|
||||||
*/
|
*/
|
||||||
static mutex sMountMutex = MUTEX_INITIALIZER("vfs_mount_lock");
|
static rw_lock sMountLock = RW_LOCK_INITIALIZER("vfs_mount_lock");
|
||||||
|
|
||||||
/*! \brief Guards mount/unmount operations.
|
/*! \brief Guards mount/unmount operations.
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ static mutex sMountMutex = MUTEX_INITIALIZER("vfs_mount_lock");
|
|||||||
sMountsTable will not be modified,
|
sMountsTable will not be modified,
|
||||||
|
|
||||||
The thread trying to lock the lock must not hold sVnodeLock or
|
The thread trying to lock the lock must not hold sVnodeLock or
|
||||||
sMountMutex.
|
sMountLock.
|
||||||
*/
|
*/
|
||||||
static recursive_lock sMountOpLock;
|
static recursive_lock sMountOpLock;
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ static recursive_lock sMountOpLock;
|
|||||||
locked. Write access to covered_by and covers requires to write lock
|
locked. Write access to covered_by and covers requires to write lock
|
||||||
sVnodeLock.
|
sVnodeLock.
|
||||||
|
|
||||||
The thread trying to acquire the lock must not hold sMountMutex.
|
The thread trying to acquire the lock must not hold sMountLock.
|
||||||
You must not hold this lock when calling create_sem(), as this might call
|
You must not hold this lock when calling create_sem(), as this might call
|
||||||
vfs_free_unused_vnodes() and thus cause a deadlock.
|
vfs_free_unused_vnodes() and thus cause a deadlock.
|
||||||
*/
|
*/
|
||||||
@@ -732,12 +732,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*! Finds the mounted device (the fs_mount structure) with the given ID.
|
/*! Finds the mounted device (the fs_mount structure) with the given ID.
|
||||||
Note, you must hold the gMountMutex lock when you call this function.
|
Note, you must hold the sMountLock lock when you call this function.
|
||||||
*/
|
*/
|
||||||
static struct fs_mount*
|
static struct fs_mount*
|
||||||
find_mount(dev_t id)
|
find_mount(dev_t id)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED_MUTEX(&sMountMutex);
|
ASSERT_READ_LOCKED_RW_LOCK(&sMountLock);
|
||||||
|
|
||||||
return sMountsTable->Lookup(id);
|
return sMountsTable->Lookup(id);
|
||||||
}
|
}
|
||||||
@@ -749,7 +749,7 @@ get_mount(dev_t id, struct fs_mount** _mount)
|
|||||||
struct fs_mount* mount;
|
struct fs_mount* mount;
|
||||||
|
|
||||||
ReadLocker nodeLocker(sVnodeLock);
|
ReadLocker nodeLocker(sVnodeLock);
|
||||||
MutexLocker mountLocker(sMountMutex);
|
ReadLocker mountLocker(sMountLock);
|
||||||
|
|
||||||
mount = find_mount(id);
|
mount = find_mount(id);
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
@@ -971,10 +971,10 @@ create_new_vnode_and_lock(dev_t mountID, ino_t vnodeID, struct vnode*& _vnode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the mount structure
|
// get the mount structure
|
||||||
mutex_lock(&sMountMutex);
|
rw_lock_read_lock(&sMountLock);
|
||||||
vnode->mount = find_mount(mountID);
|
vnode->mount = find_mount(mountID);
|
||||||
if (!vnode->mount || vnode->mount->unmounting) {
|
if (!vnode->mount || vnode->mount->unmounting) {
|
||||||
mutex_unlock(&sMountMutex);
|
rw_lock_read_unlock(&sMountLock);
|
||||||
rw_lock_write_unlock(&sVnodeLock);
|
rw_lock_write_unlock(&sVnodeLock);
|
||||||
free(vnode);
|
free(vnode);
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
@@ -984,7 +984,7 @@ create_new_vnode_and_lock(dev_t mountID, ino_t vnodeID, struct vnode*& _vnode,
|
|||||||
sVnodeTable->Insert(vnode);
|
sVnodeTable->Insert(vnode);
|
||||||
add_vnode_to_mount_list(vnode, vnode->mount);
|
add_vnode_to_mount_list(vnode, vnode->mount);
|
||||||
|
|
||||||
mutex_unlock(&sMountMutex);
|
rw_lock_read_unlock(&sMountLock);
|
||||||
|
|
||||||
_vnode = vnode;
|
_vnode = vnode;
|
||||||
_nodeCreated = true;
|
_nodeCreated = true;
|
||||||
@@ -1062,7 +1062,7 @@ free_vnode(struct vnode* vnode, bool reenter)
|
|||||||
|
|
||||||
The caller must, of course, own a reference to the vnode to call this
|
The caller must, of course, own a reference to the vnode to call this
|
||||||
function.
|
function.
|
||||||
The caller must not hold the sVnodeLock or the sMountMutex.
|
The caller must not hold the sVnodeLock or the sMountLock.
|
||||||
|
|
||||||
\param vnode the vnode.
|
\param vnode the vnode.
|
||||||
\param alwaysFree don't move this vnode into the unused list, but really
|
\param alwaysFree don't move this vnode into the unused list, but really
|
||||||
@@ -1161,7 +1161,7 @@ create_special_sub_node(struct vnode* vnode, uint32 flags)
|
|||||||
|
|
||||||
If the node is not yet in memory, it will be loaded.
|
If the node is not yet in memory, it will be loaded.
|
||||||
|
|
||||||
The caller must not hold the sVnodeLock or the sMountMutex.
|
The caller must not hold the sVnodeLock or the sMountLock.
|
||||||
|
|
||||||
\param mountID the mount ID.
|
\param mountID the mount ID.
|
||||||
\param vnodeID the node ID.
|
\param vnodeID the node ID.
|
||||||
@@ -1284,7 +1284,7 @@ restart:
|
|||||||
|
|
||||||
The caller must, of course, own a reference to the vnode to call this
|
The caller must, of course, own a reference to the vnode to call this
|
||||||
function.
|
function.
|
||||||
The caller must not hold the sVnodeLock or the sMountMutex.
|
The caller must not hold the sVnodeLock or the sMountLock.
|
||||||
|
|
||||||
\param vnode the vnode.
|
\param vnode the vnode.
|
||||||
*/
|
*/
|
||||||
@@ -4163,7 +4163,7 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID)
|
|||||||
{
|
{
|
||||||
// lookup mount -- the caller is required to make sure that the mount
|
// lookup mount -- the caller is required to make sure that the mount
|
||||||
// won't go away
|
// won't go away
|
||||||
MutexLocker locker(sMountMutex);
|
ReadLocker locker(sMountLock);
|
||||||
struct fs_mount* mount = find_mount(mountID);
|
struct fs_mount* mount = find_mount(mountID);
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -4178,7 +4178,7 @@ entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name)
|
|||||||
{
|
{
|
||||||
// lookup mount -- the caller is required to make sure that the mount
|
// lookup mount -- the caller is required to make sure that the mount
|
||||||
// won't go away
|
// won't go away
|
||||||
MutexLocker locker(sMountMutex);
|
ReadLocker locker(sMountLock);
|
||||||
struct fs_mount* mount = find_mount(mountID);
|
struct fs_mount* mount = find_mount(mountID);
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -4193,7 +4193,7 @@ entry_cache_remove(dev_t mountID, ino_t dirID, const char* name)
|
|||||||
{
|
{
|
||||||
// lookup mount -- the caller is required to make sure that the mount
|
// lookup mount -- the caller is required to make sure that the mount
|
||||||
// won't go away
|
// won't go away
|
||||||
MutexLocker locker(sMountMutex);
|
ReadLocker locker(sMountLock);
|
||||||
struct fs_mount* mount = find_mount(mountID);
|
struct fs_mount* mount = find_mount(mountID);
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -5236,7 +5236,7 @@ vfs_get_mount_point(dev_t mountID, dev_t* _mountPointMountID,
|
|||||||
ino_t* _mountPointNodeID)
|
ino_t* _mountPointNodeID)
|
||||||
{
|
{
|
||||||
ReadLocker nodeLocker(sVnodeLock);
|
ReadLocker nodeLocker(sVnodeLock);
|
||||||
MutexLocker mountLocker(sMountMutex);
|
ReadLocker mountLocker(sMountLock);
|
||||||
|
|
||||||
struct fs_mount* mount = find_mount(mountID);
|
struct fs_mount* mount = find_mount(mountID);
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
@@ -7574,9 +7574,9 @@ fs_mount(char* path, const char* device, const char* fsName, uint32 flags,
|
|||||||
|
|
||||||
// insert mount struct into list before we call FS's mount() function
|
// insert mount struct into list before we call FS's mount() function
|
||||||
// so that vnodes can be created for this mount
|
// so that vnodes can be created for this mount
|
||||||
mutex_lock(&sMountMutex);
|
rw_lock_write_lock(&sMountLock);
|
||||||
sMountsTable->Insert(mount);
|
sMountsTable->Insert(mount);
|
||||||
mutex_unlock(&sMountMutex);
|
rw_lock_write_unlock(&sMountLock);
|
||||||
|
|
||||||
ino_t rootID;
|
ino_t rootID;
|
||||||
|
|
||||||
@@ -7693,9 +7693,9 @@ err3:
|
|||||||
if (coveredNode != NULL)
|
if (coveredNode != NULL)
|
||||||
put_vnode(coveredNode);
|
put_vnode(coveredNode);
|
||||||
err2:
|
err2:
|
||||||
mutex_lock(&sMountMutex);
|
rw_lock_write_lock(&sMountLock);
|
||||||
sMountsTable->Remove(mount);
|
sMountsTable->Remove(mount);
|
||||||
mutex_unlock(&sMountMutex);
|
rw_lock_write_unlock(&sMountLock);
|
||||||
err1:
|
err1:
|
||||||
delete mount;
|
delete mount;
|
||||||
|
|
||||||
@@ -7720,17 +7720,16 @@ fs_unmount(char* path, dev_t mountID, uint32 flags, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecursiveLocker mountOpLocker(sMountOpLock);
|
RecursiveLocker mountOpLocker(sMountOpLock);
|
||||||
|
ReadLocker mountLocker(sMountLock);
|
||||||
|
|
||||||
// this lock is not strictly necessary, but here in case of KDEBUG
|
|
||||||
// to keep the ASSERT in find_mount() working.
|
|
||||||
KDEBUG_ONLY(mutex_lock(&sMountMutex));
|
|
||||||
mount = find_mount(path != NULL ? pathVnode->device : mountID);
|
mount = find_mount(path != NULL ? pathVnode->device : mountID);
|
||||||
KDEBUG_ONLY(mutex_unlock(&sMountMutex));
|
|
||||||
if (mount == NULL) {
|
if (mount == NULL) {
|
||||||
panic("fs_unmount: find_mount() failed on root vnode @%p of mount\n",
|
panic("fs_unmount: find_mount() failed on root vnode @%p of mount\n",
|
||||||
pathVnode);
|
pathVnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mountLocker.Unlock();
|
||||||
|
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
put_vnode(pathVnode);
|
put_vnode(pathVnode);
|
||||||
|
|
||||||
@@ -7901,9 +7900,9 @@ fs_unmount(char* path, dev_t mountID, uint32 flags, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove the mount structure from the hash table
|
// remove the mount structure from the hash table
|
||||||
mutex_lock(&sMountMutex);
|
rw_lock_write_lock(&sMountLock);
|
||||||
sMountsTable->Remove(mount);
|
sMountsTable->Remove(mount);
|
||||||
mutex_unlock(&sMountMutex);
|
rw_lock_write_unlock(&sMountLock);
|
||||||
|
|
||||||
mountOpLocker.Unlock();
|
mountOpLocker.Unlock();
|
||||||
|
|
||||||
@@ -8071,7 +8070,7 @@ fs_next_device(int32* _cookie)
|
|||||||
struct fs_mount* mount = NULL;
|
struct fs_mount* mount = NULL;
|
||||||
dev_t device = *_cookie;
|
dev_t device = *_cookie;
|
||||||
|
|
||||||
mutex_lock(&sMountMutex);
|
rw_lock_read_lock(&sMountLock);
|
||||||
|
|
||||||
// Since device IDs are assigned sequentially, this algorithm
|
// Since device IDs are assigned sequentially, this algorithm
|
||||||
// does work good enough. It makes sure that the device list
|
// does work good enough. It makes sure that the device list
|
||||||
@@ -8091,7 +8090,7 @@ fs_next_device(int32* _cookie)
|
|||||||
else
|
else
|
||||||
device = B_BAD_VALUE;
|
device = B_BAD_VALUE;
|
||||||
|
|
||||||
mutex_unlock(&sMountMutex);
|
rw_lock_read_unlock(&sMountLock);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user