diff --git a/headers/os/drivers/fs_interface.h b/headers/os/drivers/fs_interface.h index 96b69fab04..9296e1c049 100644 --- a/headers/os/drivers/fs_interface.h +++ b/headers/os/drivers/fs_interface.h @@ -330,6 +330,8 @@ extern status_t remove_vnode(fs_volume* volume, ino_t vnodeID); extern status_t unremove_vnode(fs_volume* volume, ino_t vnodeID); extern status_t get_vnode_removed(fs_volume* volume, ino_t vnodeID, bool* _removed); +extern status_t mark_vnode_busy(fs_volume* volume, ino_t vnodeID, bool busy); +extern status_t change_vnode_id(fs_volume* volume, ino_t vnodeID, ino_t newID); extern fs_volume* volume_for_vnode(fs_vnode* vnode); extern status_t check_access_permissions(int accessMode, mode_t mode, gid_t nodeGroupID, uid_t nodeUserID); diff --git a/headers/private/fs_shell/fssh_api_wrapper.h b/headers/private/fs_shell/fssh_api_wrapper.h index 88a1441e20..bbe883ca34 100644 --- a/headers/private/fs_shell/fssh_api_wrapper.h +++ b/headers/private/fs_shell/fssh_api_wrapper.h @@ -944,6 +944,8 @@ #define remove_vnode fssh_remove_vnode #define unremove_vnode fssh_unremove_vnode #define get_vnode_removed fssh_get_vnode_removed +#define mark_vnode_busy fssh_mark_vnode_busy +#define change_vnode_id fssh_change_vnode_id #define volume_for_vnode fssh_volume_for_vnode #define check_access_permissions fssh_check_access_permissions #define read_pages fssh_read_pages diff --git a/headers/private/fs_shell/fssh_fs_interface.h b/headers/private/fs_shell/fssh_fs_interface.h index 7d2d6fcc58..350a16aaf9 100644 --- a/headers/private/fs_shell/fssh_fs_interface.h +++ b/headers/private/fs_shell/fssh_fs_interface.h @@ -360,6 +360,10 @@ extern fssh_status_t fssh_unremove_vnode(fssh_fs_volume *volume, fssh_vnode_id vnodeID); extern fssh_status_t fssh_get_vnode_removed(fssh_fs_volume *volume, fssh_vnode_id vnodeID, bool* removed); +extern fssh_status_t fssh_mark_vnode_busy(fssh_fs_volume* volume, + fssh_vnode_id vnodeID, bool busy); +extern fssh_status_t fssh_change_vnode_id(fssh_fs_volume* volume, + fssh_vnode_id vnodeID, fssh_vnode_id newID); extern fssh_fs_volume* fssh_volume_for_vnode(fssh_fs_vnode *vnode); extern fssh_status_t fssh_check_access_permissions(int accessMode, fssh_mode_t mode, fssh_gid_t nodeGroupID, diff --git a/src/system/kernel/cache/vnode_store.h b/src/system/kernel/cache/vnode_store.h index 8f3b3ed4e2..d99060dfaa 100644 --- a/src/system/kernel/cache/vnode_store.h +++ b/src/system/kernel/cache/vnode_store.h @@ -52,6 +52,8 @@ public: { return fDevice; } ino_t InodeId() const { return fInode; } + void SetVnodeID(ino_t id) + { fInode = id; } protected: virtual void DeleteObject(); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 9a34c4a678..71657ae439 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -3981,6 +3981,47 @@ get_vnode_removed(fs_volume* volume, ino_t vnodeID, bool* _removed) } +extern "C" status_t +mark_vnode_busy(fs_volume* volume, ino_t vnodeID, bool busy) +{ + ReadLocker locker(sVnodeLock); + + struct vnode* vnode = lookup_vnode(volume->id, vnodeID); + if (vnode == NULL) + return B_ENTRY_NOT_FOUND; + + // are we trying to mark an already busy node busy again? + if (busy && vnode->IsBusy()) + return B_BUSY; + + vnode->Lock(); + vnode->SetBusy(busy); + vnode->Unlock(); + + return B_OK; +} + + +extern "C" status_t +change_vnode_id(fs_volume* volume, ino_t vnodeID, ino_t newID) +{ + WriteLocker locker(sVnodeLock); + + struct vnode* vnode = lookup_vnode(volume->id, vnodeID); + if (vnode == NULL) + return B_ENTRY_NOT_FOUND; + + sVnodeTable->Remove(vnode); + vnode->id = newID; + sVnodeTable->Insert(vnode); + + if (vnode->cache != NULL) + ((VMVnodeCache*)vnode->cache)->SetVnodeID(newID); + + return B_OK; +} + + extern "C" fs_volume* volume_for_vnode(fs_vnode* _vnode) { diff --git a/src/tools/fs_shell/vfs.cpp b/src/tools/fs_shell/vfs.cpp index 5137ddd364..27e73b8569 100644 --- a/src/tools/fs_shell/vfs.cpp +++ b/src/tools/fs_shell/vfs.cpp @@ -2117,6 +2117,51 @@ fssh_get_vnode_removed(fssh_fs_volume *volume, fssh_vnode_id vnodeID, bool* remo } +extern "C" fssh_status_t +fssh_mark_vnode_busy(fssh_fs_volume* volume, fssh_vnode_id vnodeID, bool busy) +{ + fssh_mutex_lock(&sVnodeMutex); + + struct vnode* vnode = lookup_vnode(volume->id, vnodeID); + if (vnode == NULL) { + fssh_mutex_unlock(&sVnodeMutex); + return FSSH_B_ENTRY_NOT_FOUND; + } + + // are we trying to mark an already busy node busy again? + if (busy && vnode->busy) { + fssh_mutex_unlock(&sVnodeMutex); + return FSSH_B_BUSY; + } + + vnode->busy = busy; + + fssh_mutex_unlock(&sVnodeMutex); + return FSSH_B_OK; +} + + +extern "C" fssh_status_t +fssh_change_vnode_id(fssh_fs_volume* volume, fssh_vnode_id vnodeID, + fssh_vnode_id newID) +{ + fssh_mutex_lock(&sVnodeMutex); + + struct vnode* vnode = lookup_vnode(volume->id, vnodeID); + if (vnode == NULL) { + fssh_mutex_unlock(&sVnodeMutex); + return FSSH_B_ENTRY_NOT_FOUND; + } + + hash_remove(sVnodeTable, vnode); + vnode->id = newID; + hash_insert(sVnodeTable, vnode); + + fssh_mutex_unlock(&sVnodeMutex); + return FSSH_B_OK; +} + + extern "C" fssh_fs_volume* fssh_volume_for_vnode(fssh_fs_vnode *_vnode) {