From d764d148b10b8b0f84bbf344ccc9cf35fdb2c99d Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Wed, 27 Jun 2012 18:36:07 +0200 Subject: [PATCH] Allow file systems to manage file locks Haiku implements file locking at vfs level. That would not work for remote and shared file systems, since they need to negotiate locks with peers. This patch introduces three additional hooks in fs_interface that allow file system module to take over the management of file locks. --- headers/os/drivers/fs_interface.h | 8 ++++++++ src/system/kernel/fs/vfs.cpp | 26 +++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/headers/os/drivers/fs_interface.h b/headers/os/drivers/fs_interface.h index 03d867b131..1b3f0be8f7 100644 --- a/headers/os/drivers/fs_interface.h +++ b/headers/os/drivers/fs_interface.h @@ -242,6 +242,14 @@ struct fs_vnode_ops { fs_vnode* _superVnode, ino_t* _nodeID); status_t (*get_super_vnode)(fs_volume* volume, fs_vnode* vnode, fs_volume* superVolume, fs_vnode* superVnode); + + /* lock operations */ + status_t (*test_lock)(fs_volume* volume, fs_vnode* vnode, void* cookie, + struct flock* lock); + status_t (*acquire_lock)(fs_volume* volume, fs_vnode* vnode, void* cookie, + const struct flock* lock, bool wait); + status_t (*release_lock)(fs_volume* volume, fs_vnode* vnode, void* cookie, + const struct flock* lock); }; struct file_system_module_info { diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6737a3046c..3d7628e7ca 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5475,7 +5475,10 @@ file_close(struct file_descriptor* descriptor) if (status == B_OK) { // remove all outstanding locks for this team - release_advisory_lock(vnode, NULL); + if (HAS_FS_CALL(vnode, release_lock)) + status = FS_CALL(vnode, release_lock, descriptor->cookie, NULL); + else + status = release_advisory_lock(vnode, NULL); } return status; } @@ -6006,7 +6009,11 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) case F_GETLK: if (vnode != NULL) { - status = get_advisory_lock(vnode, &flock); + if (HAS_FS_CALL(vnode, test_lock)) { + status = FS_CALL(vnode, test_lock, descriptor->cookie, + &flock); + } else + status = get_advisory_lock(vnode, &flock); if (status == B_OK) { // copy back flock structure status = user_memcpy((struct flock*)argument, &flock, @@ -6025,7 +6032,11 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) if (vnode == NULL) { status = B_BAD_VALUE; } else if (flock.l_type == F_UNLCK) { - status = release_advisory_lock(vnode, &flock); + if (HAS_FS_CALL(vnode, release_lock)) { + status = FS_CALL(vnode, release_lock, descriptor->cookie, + &flock); + } else + status = release_advisory_lock(vnode, &flock); } else { // the open mode must match the lock type if (((descriptor->open_mode & O_RWMASK) == O_RDONLY @@ -6034,8 +6045,13 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) && flock.l_type == F_RDLCK)) status = B_FILE_ERROR; else { - status = acquire_advisory_lock(vnode, -1, - &flock, op == F_SETLKW); + if (HAS_FS_CALL(vnode, acquire_lock)) { + status = FS_CALL(vnode, acquire_lock, + descriptor->cookie, &flock, op == F_SETLKW); + } else { + status = acquire_advisory_lock(vnode, -1, + &flock, op == F_SETLKW); + } } } break;