fat: Fix potential double lock
* Unlock the volume once the directories are locked in dosfs_rename. At that point locking the volume has served its purpose. * If the volume lock is retained throughout dosfs_rename, a double lock can occur in dosfs_read_vnode, in the event that one of the involved file nodes has not already been constructed prior to the rename. * Fixes #19614. Change-Id: Ib679a6f3ba3dc8f87fb0c6263eb82d2d06cb6064 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10166 Tested-by: Commit checker robot <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
@@ -1376,15 +1376,15 @@ dosfs_rename(fs_volume* volume, fs_vnode* fromDir, const char* fromName, fs_vnod
|
|||||||
ComponentName fromBsdName(ISLASTCN, NOCRED, RENAME, 0, fromName);
|
ComponentName fromBsdName(ISLASTCN, NOCRED, RENAME, 0, fromName);
|
||||||
ComponentName toBsdName(ISLASTCN, NOCRED, RENAME, 0, toName);
|
ComponentName toBsdName(ISLASTCN, NOCRED, RENAME, 0, toName);
|
||||||
|
|
||||||
// Don't do 2 renames at the same time on the same volume. If moving to a new directory,
|
// Eliminate the possibility that two move operations could deadlock, if they are
|
||||||
// and the destination directory of one thread is the origin directory of the other,
|
// locking the same two directories in the reverse order.
|
||||||
// and vice versa, a deadlock can occur.
|
|
||||||
MutexLocker volumeLocker(bsdVolume->mnt_mtx.haikuMutex);
|
MutexLocker volumeLocker(bsdVolume->mnt_mtx.haikuMutex);
|
||||||
|
|
||||||
WriteLocker fromDirLocker(fromDirBsdNode->v_vnlock->haikuRW);
|
WriteLocker fromDirLocker(fromDirBsdNode->v_vnlock->haikuRW);
|
||||||
WriteLocker toDirLocker;
|
WriteLocker toDirLocker;
|
||||||
if (fromDirBsdNode != toDirBsdNode)
|
if (fromDirBsdNode != toDirBsdNode)
|
||||||
toDirLocker.SetTo(toDirBsdNode->v_vnlock->haikuRW, false);
|
toDirLocker.SetTo(toDirBsdNode->v_vnlock->haikuRW, false);
|
||||||
|
volumeLocker.Unlock();
|
||||||
|
|
||||||
status_t status = _dosfs_access(bsdVolume, fromDirBsdNode, W_OK);
|
status_t status = _dosfs_access(bsdVolume, fromDirBsdNode, W_OK);
|
||||||
if (status == B_OK && fromDirBsdNode != toDirBsdNode)
|
if (status == B_OK && fromDirBsdNode != toDirBsdNode)
|
||||||
|
|||||||
Reference in New Issue
Block a user