Implemented mandatory file locking, BeOS style. BNode::Lock() and BNode::Unlock()

are now working as expected.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17697 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-06-02 14:16:13 +00:00
parent ab8e333337
commit 8265e1210c
3 changed files with 57 additions and 7 deletions

View File

@ -98,6 +98,7 @@ status_t vfs_get_fs_node_from_path(mount_id mountID, const char *path,
status_t vfs_stat_vnode(void *_vnode, struct stat *stat);
status_t vfs_get_vnode_name(void *vnode, char *name, size_t nameSize);
status_t vfs_get_cwd(mount_id *_mountID, vnode_id *_vnodeID);
void vfs_unlock_vnode_if_locked(struct file_descriptor *descriptor);
status_t vfs_disconnect_vnode(mount_id mountID, vnode_id vnodeID);
void vfs_free_unused_vnodes(int32 level);

View File

@ -168,6 +168,8 @@ void
close_fd(struct file_descriptor *descriptor)
{
if (atomic_add(&descriptor->open_count, -1) == 1) {
vfs_unlock_vnode_if_locked(descriptor);
if (descriptor->ops->fd_close)
descriptor->ops->fd_close(descriptor);
}

View File

@ -59,7 +59,8 @@
const static uint32 kMaxUnusedVnodes = 8192;
// This is the maximum number of unused vnodes that the system
// will keep around.
// will keep around (weak limit, if there is enough memory left,
// they won't get flushed even when hitting that limit).
// It may be chosen with respect to the available memory or enhanced
// by some timestamp/frequency heurism.
@ -78,6 +79,7 @@ struct vnode {
uint8 busy : 1;
uint8 unpublished : 1;
struct advisory_locking *advisory_locking;
struct file_descriptor *mandatory_locked_by;
};
struct vnode_hash_key {
@ -2139,6 +2141,10 @@ get_new_fd(int type, struct fs_mount *mount, struct vnode *vnode,
struct file_descriptor *descriptor;
int fd;
// if the vnode is locked, we don't allow creating a new file descriptor for it
if (vnode && vnode->mandatory_locked_by != NULL)
return B_BUSY;
descriptor = alloc_fd();
if (!descriptor)
return B_NO_MEMORY;
@ -3133,6 +3139,19 @@ vfs_get_vnode_name(void *_vnode, char *name, size_t nameSize)
}
/** If the given descriptor locked its vnode, that lock will be released.
*/
void
vfs_unlock_vnode_if_locked(struct file_descriptor *descriptor)
{
struct vnode *vnode = fd_vnode(descriptor);
if (vnode != NULL && vnode->mandatory_locked_by == descriptor)
vnode->mandatory_locked_by = NULL;
}
/** Closes all file descriptors of the specified I/O context that
* don't have the O_CLOEXEC flag set.
*/
@ -4191,18 +4210,46 @@ common_sync(int fd, bool kernel)
static status_t
common_lock_node(int fd, bool kernel)
{
// TODO: Implement!
//return EOPNOTSUPP;
return B_OK;
struct file_descriptor *descriptor;
struct vnode *vnode;
descriptor = get_fd_and_vnode(fd, &vnode, kernel);
if (descriptor == NULL)
return B_FILE_ERROR;
status_t status = B_OK;
// We need to set the locking atomically - someone
// else might set one at the same time
if (atomic_test_and_set((vint32 *)&vnode->mandatory_locked_by,
(addr_t)descriptor, NULL) != NULL)
status = B_BUSY;
put_fd(descriptor);
return status;
}
static status_t
common_unlock_node(int fd, bool kernel)
{
// TODO: Implement!
//return EOPNOTSUPP;
return B_OK;
struct file_descriptor *descriptor;
struct vnode *vnode;
descriptor = get_fd_and_vnode(fd, &vnode, kernel);
if (descriptor == NULL)
return B_FILE_ERROR;
status_t status = B_OK;
// We need to set the locking atomically - someone
// else might set one at the same time
if (atomic_test_and_set((vint32 *)&vnode->mandatory_locked_by,
NULL, (addr_t)descriptor) != (int32)descriptor)
status = B_BAD_VALUE;
put_fd(descriptor);
return status;
}