* Corrected sMountMutex comment.

* Turned sMountOpMutex into a recursive lock.
* Re-inserted sMountOpLock locking in vnode_path_to_vnode(). It doesn't
  deadlock on mounting anymore. :-P
* Added a check in fs_mount(), whether the mount point is a directory. If
  it wasn't, in general it wouldn't be possible to get its parent
  directory.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8993 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2004-09-17 12:29:27 +00:00
parent 421f4885ed
commit 3b554981d3
+32 -21
View File
@@ -102,27 +102,26 @@ static mutex sFileSystemsMutex;
/** \brief Guards sMountsTable. /** \brief Guards sMountsTable.
The holder is allowed to read access the sMountsTable. Write access The holder is allowed to read/write access the sMountsTable.
additionally requires the sMountOpMutex (which has to be locked before Manipulation of the fs_mount structures themselves
acquiring sMountMutex). Manipulation of the fs_mount structures themselves
(and their destruction) requires different locks though. (and their destruction) requires different locks though.
*/ */
static mutex sMountMutex; static mutex sMountMutex;
/** \brief Guards mount/unmount operations. /** \brief Guards mount/unmount operations.
The fs_mount() and fs_unmount() hold the mutex during their whole operation. The fs_mount() and fs_unmount() hold the lock during their whole operation.
That is locking the mutex ensures that no FS is mounted/unmounted. In That is locking the lock ensures that no FS is mounted/unmounted. In
particular this means that particular this means that
- sMountsTable will not be modified, - sMountsTable will not be modified,
- the fields immutable after initialization of the fs_mount structures in - the fields immutable after initialization of the fs_mount structures in
sMountsTable will not be modified, sMountsTable will not be modified,
- vnode::covered_by of any vnode in sVnodeTable will not be modified, - vnode::covered_by of any vnode in sVnodeTable will not be modified,
The thread trying to lock the mutex must not hold sVnodeMutex or The thread trying to lock the lock must not hold sVnodeMutex or
sMountMutex. sMountMutex.
*/ */
static mutex sMountOpMutex; static recursive_lock sMountOpLock;
/** \brief Guards sVnodeTable. /** \brief Guards sVnodeTable.
@@ -130,7 +129,7 @@ static mutex sMountOpMutex;
to any unbusy vnode in that table, save to any unbusy vnode in that table, save
to the immutable fields (device, id, private_node, mount) to which to the immutable fields (device, id, private_node, mount) to which
only read-only access is allowed, and to the field covered_by, which is only read-only access is allowed, and to the field covered_by, which is
guarded by sMountOpMutex. guarded by sMountOpLock.
The thread trying to lock the mutex must not hold sMountMutex. The thread trying to lock the mutex must not hold sMountMutex.
*/ */
@@ -934,12 +933,14 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink,
vnode = nextVnode; vnode = nextVnode;
// see if we hit a mount point // see if we hit a mount point
recursive_lock_lock(&sMountOpLock);
if (vnode->covered_by) { if (vnode->covered_by) {
nextVnode = vnode->covered_by; nextVnode = vnode->covered_by;
inc_vnode_ref_count(nextVnode); inc_vnode_ref_count(nextVnode);
put_vnode(vnode); put_vnode(vnode);
vnode = nextVnode; vnode = nextVnode;
} }
recursive_lock_unlock(&sMountOpLock);
} }
*_vnode = vnode; *_vnode = vnode;
@@ -2044,7 +2045,7 @@ vfs_init(kernel_args *ka)
if (mutex_init(&sFileSystemsMutex, "vfs_lock") < 0) if (mutex_init(&sFileSystemsMutex, "vfs_lock") < 0)
panic("vfs_init: error allocating file systems lock\n"); panic("vfs_init: error allocating file systems lock\n");
if (mutex_init(&sMountOpMutex, "vfs_mount_op_lock") < 0) if (recursive_lock_init(&sMountOpLock, "vfs_mount_op_lock") < 0)
panic("vfs_init: error allocating mount op lock\n"); panic("vfs_init: error allocating mount op lock\n");
if (mutex_init(&sMountMutex, "vfs_mount_lock") < 0) if (mutex_init(&sMountMutex, "vfs_mount_lock") < 0)
@@ -2523,12 +2524,12 @@ fix_dirent(struct vnode *parent, struct dirent *entry)
if (status != B_OK) if (status != B_OK)
return; return;
mutex_lock(&sMountOpMutex); recursive_lock_lock(&sMountOpLock);
if (vnode->covered_by) { if (vnode->covered_by) {
entry->d_dev = vnode->covered_by->device; entry->d_dev = vnode->covered_by->device;
entry->d_ino = vnode->covered_by->id; entry->d_ino = vnode->covered_by->id;
} }
mutex_unlock(&sMountOpMutex); recursive_lock_unlock(&sMountOpLock);
put_vnode(vnode); put_vnode(vnode);
} }
@@ -3465,7 +3466,7 @@ fs_mount(char *path, const char *device, const char *fsName, void *args, bool ke
if (fsName == NULL || fsName[0] == '\0') if (fsName == NULL || fsName[0] == '\0')
return B_BAD_VALUE; return B_BAD_VALUE;
mutex_lock(&sMountOpMutex); recursive_lock_lock(&sMountOpLock);
mount = (struct fs_mount *)malloc(sizeof(struct fs_mount)); mount = (struct fs_mount *)malloc(sizeof(struct fs_mount));
if (mount == NULL) { if (mount == NULL) {
@@ -3535,7 +3536,17 @@ fs_mount(char *path, const char *device, const char *fsName, void *args, bool ke
goto err5; goto err5;
} }
// ToDo: insert check to make sure covered_vnode is a DIR, or maybe it's okay for it not to be // make sure covered_vnode is a DIR
struct stat coveredNodeStat;
err = FS_CALL(covered_vnode, read_stat)(covered_vnode->mount->cookie,
covered_vnode->private_node, &coveredNodeStat);
if (err < 0)
goto err5;
if (!S_ISDIR(coveredNodeStat.st_mode)) {
err = B_NOT_A_DIRECTORY;
goto err5;
}
if (covered_vnode->mount->root_vnode == covered_vnode) { if (covered_vnode->mount->root_vnode == covered_vnode) {
err = ERR_VFS_ALREADY_MOUNTPOINT; err = ERR_VFS_ALREADY_MOUNTPOINT;
@@ -3555,14 +3566,14 @@ fs_mount(char *path, const char *device, const char *fsName, void *args, bool ke
goto err7; goto err7;
// No race here, since fs_mount() is the only function changing // No race here, since fs_mount() is the only function changing
// covers_vnode (and holds sMountOpMutex at that time). // covers_vnode (and holds sMountOpLock at that time).
if (mount->covers_vnode) if (mount->covers_vnode)
mount->covers_vnode->covered_by = mount->root_vnode; mount->covers_vnode->covered_by = mount->root_vnode;
if (!sRoot) if (!sRoot)
sRoot = mount->root_vnode; sRoot = mount->root_vnode;
mutex_unlock(&sMountOpMutex); recursive_lock_unlock(&sMountOpLock);
return B_OK; return B_OK;
@@ -3587,7 +3598,7 @@ err2:
err1: err1:
free(mount); free(mount);
err: err:
mutex_unlock(&sMountOpMutex); recursive_lock_unlock(&sMountOpLock);
return err; return err;
} }
@@ -3606,7 +3617,7 @@ fs_unmount(char *path, bool kernel)
if (err < 0) if (err < 0)
return ERR_VFS_PATH_NOT_FOUND; return ERR_VFS_PATH_NOT_FOUND;
mutex_lock(&sMountOpMutex); recursive_lock_lock(&sMountOpLock);
mount = find_mount(vnode->device); mount = find_mount(vnode->device);
if (!mount) if (!mount)
@@ -3670,7 +3681,7 @@ fs_unmount(char *path, bool kernel)
hash_remove(sMountsTable, mount); hash_remove(sMountsTable, mount);
mutex_unlock(&sMountMutex); mutex_unlock(&sMountMutex);
mutex_unlock(&sMountOpMutex); recursive_lock_unlock(&sMountOpLock);
FS_MOUNT_CALL(mount, unmount)(mount->cookie); FS_MOUNT_CALL(mount, unmount)(mount->cookie);
@@ -3685,7 +3696,7 @@ fs_unmount(char *path, bool kernel)
return 0; return 0;
err: err:
mutex_unlock(&sMountOpMutex); recursive_lock_unlock(&sMountOpLock);
return err; return err;
} }
@@ -3699,7 +3710,7 @@ fs_sync(void)
FUNCTION(("vfs_sync: entry.\n")); FUNCTION(("vfs_sync: entry.\n"));
/* cycle through and call sync on each mounted fs */ /* cycle through and call sync on each mounted fs */
mutex_lock(&sMountOpMutex); recursive_lock_lock(&sMountOpLock);
mutex_lock(&sMountMutex); mutex_lock(&sMountMutex);
hash_open(sMountsTable, &iter); hash_open(sMountsTable, &iter);
@@ -3710,7 +3721,7 @@ fs_sync(void)
hash_close(sMountsTable, &iter, false); hash_close(sMountsTable, &iter, false);
mutex_unlock(&sMountMutex); mutex_unlock(&sMountMutex);
mutex_unlock(&sMountOpMutex); recursive_lock_unlock(&sMountOpLock);
return 0; return 0;
} }