* Added a "canWait" argument to vfs_get_vnode() - you can use this to ignore
busy vnodes. * dir_create_entry_ref() used get_vnode() incorrectly (and could therefore potentially prevent a file system from doing proper locking when called from the kernel). * The vnode_store now uses this for its acquire_unreferenced_ref() implementation (and therefore for the page writer). * read_into_cache() and write_to_cache() were still marked inline. * The system will now wait 10 secs for a busy vnode before returning an error. * It will also no longer panic in that case. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22485 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a16571b404
commit
0710d59c1c
|
@ -81,7 +81,8 @@ int vfs_setrlimit(int resource, const struct rlimit * rlp);
|
||||||
int vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode **_vnode);
|
int vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode **_vnode);
|
||||||
status_t vfs_get_vnode_from_path(const char *path, bool kernel,
|
status_t vfs_get_vnode_from_path(const char *path, bool kernel,
|
||||||
struct vnode **_vnode);
|
struct vnode **_vnode);
|
||||||
status_t vfs_get_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode);
|
status_t vfs_get_vnode(dev_t mountID, ino_t vnodeID, bool canWait,
|
||||||
|
struct vnode **_vnode);
|
||||||
status_t vfs_entry_ref_to_vnode(dev_t mountID, ino_t directoryID,
|
status_t vfs_entry_ref_to_vnode(dev_t mountID, ino_t directoryID,
|
||||||
const char *name, struct vnode **_vnode);
|
const char *name, struct vnode **_vnode);
|
||||||
void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID,
|
void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID,
|
||||||
|
|
|
@ -518,13 +518,13 @@ pages_io(file_cache_ref *ref, off_t offset, const iovec *vecs, size_t count,
|
||||||
The cache_ref lock must be hold when calling this function; during
|
The cache_ref lock must be hold when calling this function; during
|
||||||
operation it will unlock the cache, though.
|
operation it will unlock the cache, though.
|
||||||
*/
|
*/
|
||||||
static inline status_t
|
static status_t
|
||||||
read_into_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
|
read_into_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
|
||||||
int32 pageOffset, addr_t buffer, size_t bufferSize,
|
int32 pageOffset, addr_t buffer, size_t bufferSize,
|
||||||
size_t lastReservedPages, size_t reservePages)
|
size_t lastReservedPages, size_t reservePages)
|
||||||
{
|
{
|
||||||
TRACE(("read_into_cache(offset = %Ld, size = %lu, pageOffset = %ld, buffer "
|
TRACE(("read_into_cache(offset = %Ld, size = %lu, pageOffset = %ld, buffer "
|
||||||
"= %#lx, bufferSize = %lu\n", offset, size, pageOffset, buffer,
|
"= %#lx, bufferSize = %lu\n", offset, numBytes, pageOffset, buffer,
|
||||||
bufferSize));
|
bufferSize));
|
||||||
|
|
||||||
vm_cache *cache = ref->cache;
|
vm_cache *cache = ref->cache;
|
||||||
|
@ -630,7 +630,7 @@ read_into_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
|
||||||
though, if only a partial page gets written.
|
though, if only a partial page gets written.
|
||||||
The same restrictions apply.
|
The same restrictions apply.
|
||||||
*/
|
*/
|
||||||
static inline status_t
|
static status_t
|
||||||
write_to_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
|
write_to_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
|
||||||
int32 pageOffset, addr_t buffer, size_t bufferSize,
|
int32 pageOffset, addr_t buffer, size_t bufferSize,
|
||||||
size_t lastReservedPages, size_t reservePages)
|
size_t lastReservedPages, size_t reservePages)
|
||||||
|
@ -1086,7 +1086,7 @@ cache_prefetch(dev_t mountID, ino_t vnodeID, off_t offset, size_t size)
|
||||||
|
|
||||||
// get the vnode for the object, this also grabs a ref to it
|
// get the vnode for the object, this also grabs a ref to it
|
||||||
struct vnode *vnode;
|
struct vnode *vnode;
|
||||||
if (vfs_get_vnode(mountID, vnodeID, &vnode) != B_OK)
|
if (vfs_get_vnode(mountID, vnodeID, true, &vnode) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cache_prefetch_vnode(vnode, offset, size);
|
cache_prefetch_vnode(vnode, offset, size);
|
||||||
|
|
|
@ -88,7 +88,7 @@ store_acquire_unreferenced_ref(struct vm_store *_store)
|
||||||
{
|
{
|
||||||
vnode_store *store = (vnode_store *)_store;
|
vnode_store *store = (vnode_store *)_store;
|
||||||
struct vnode *vnode;
|
struct vnode *vnode;
|
||||||
return vfs_get_vnode(store->device, store->inode, &vnode);
|
return vfs_get_vnode(store->device, store->inode, false, &vnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -825,21 +825,22 @@ lookup_vnode(dev_t mountID, ino_t vnodeID)
|
||||||
\return \c B_OK, if everything when fine, an error code otherwise.
|
\return \c B_OK, if everything when fine, an error code otherwise.
|
||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
get_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode, int reenter)
|
get_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode, bool canWait,
|
||||||
|
int reenter)
|
||||||
{
|
{
|
||||||
FUNCTION(("get_vnode: mountid %ld vnid 0x%Lx %p\n", mountID, vnodeID, _vnode));
|
FUNCTION(("get_vnode: mountid %ld vnid 0x%Lx %p\n", mountID, vnodeID, _vnode));
|
||||||
|
|
||||||
mutex_lock(&sVnodeMutex);
|
mutex_lock(&sVnodeMutex);
|
||||||
|
|
||||||
int32 tries = 300;
|
int32 tries = 1000;
|
||||||
// try for 3 secs
|
// try for 10 secs
|
||||||
restart:
|
restart:
|
||||||
struct vnode *vnode = lookup_vnode(mountID, vnodeID);
|
struct vnode *vnode = lookup_vnode(mountID, vnodeID);
|
||||||
if (vnode && vnode->busy) {
|
if (vnode && vnode->busy) {
|
||||||
mutex_unlock(&sVnodeMutex);
|
mutex_unlock(&sVnodeMutex);
|
||||||
if (--tries < 0) {
|
if (!canWait || --tries < 0) {
|
||||||
// vnode doesn't seem to become unbusy
|
// vnode doesn't seem to become unbusy
|
||||||
panic("vnode %ld:%Ld is not becoming unbusy!\n", mountID, vnodeID);
|
dprintf("vnode %ld:%Ld is not becoming unbusy!\n", mountID, vnodeID);
|
||||||
return B_BUSY;
|
return B_BUSY;
|
||||||
}
|
}
|
||||||
snooze(10000); // 10 ms
|
snooze(10000); // 10 ms
|
||||||
|
@ -867,7 +868,8 @@ restart:
|
||||||
vnode->busy = true;
|
vnode->busy = true;
|
||||||
mutex_unlock(&sVnodeMutex);
|
mutex_unlock(&sVnodeMutex);
|
||||||
|
|
||||||
status = FS_CALL(vnode, get_vnode)(vnode->mount->cookie, vnodeID, &vnode->private_node, reenter);
|
status = FS_CALL(vnode, get_vnode)(vnode->mount->cookie, vnodeID,
|
||||||
|
&vnode->private_node, reenter);
|
||||||
if (status == B_OK && vnode->private_node == NULL)
|
if (status == B_OK && vnode->private_node == NULL)
|
||||||
status = B_BAD_VALUE;
|
status = B_BAD_VALUE;
|
||||||
|
|
||||||
|
@ -1422,7 +1424,7 @@ resolve_mount_point_to_volume_root(dev_t mountID, ino_t nodeID,
|
||||||
{
|
{
|
||||||
// get the node
|
// get the node
|
||||||
struct vnode *node;
|
struct vnode *node;
|
||||||
status_t error = get_vnode(mountID, nodeID, &node, false);
|
status_t error = get_vnode(mountID, nodeID, &node, true, false);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
@ -1534,7 +1536,7 @@ entry_ref_to_vnode(dev_t mountID, ino_t directoryID, const char *name,
|
||||||
// get the directory vnode and let vnode_path_to_vnode() do the rest
|
// get the directory vnode and let vnode_path_to_vnode() do the rest
|
||||||
struct vnode *directory;
|
struct vnode *directory;
|
||||||
|
|
||||||
status_t status = get_vnode(mountID, directoryID, &directory, false);
|
status_t status = get_vnode(mountID, directoryID, &directory, true, false);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -2532,7 +2534,7 @@ dump_vnode_usage(int argc, char **argv)
|
||||||
#endif // ADD_DEBUGGER_COMMANDS
|
#endif // ADD_DEBUGGER_COMMANDS
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - public VFS API
|
// #pragma mark - public API for file systems
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
|
@ -2603,7 +2605,7 @@ get_vnode(dev_t mountID, ino_t vnodeID, fs_vnode *_fsNode)
|
||||||
{
|
{
|
||||||
struct vnode *vnode;
|
struct vnode *vnode;
|
||||||
|
|
||||||
status_t status = get_vnode(mountID, vnodeID, &vnode, true);
|
status_t status = get_vnode(mountID, vnodeID, &vnode, true, true);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -2771,11 +2773,11 @@ vfs_get_vnode_from_path(const char *path, bool kernel, struct vnode **_vnode)
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
vfs_get_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode)
|
vfs_get_vnode(dev_t mountID, ino_t vnodeID, bool canWait, struct vnode **_vnode)
|
||||||
{
|
{
|
||||||
struct vnode *vnode;
|
struct vnode *vnode;
|
||||||
|
|
||||||
status_t status = get_vnode(mountID, vnodeID, &vnode, false);
|
status_t status = get_vnode(mountID, vnodeID, &vnode, canWait, false);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -3068,7 +3070,7 @@ vfs_disconnect_vnode(dev_t mountID, ino_t vnodeID)
|
||||||
{
|
{
|
||||||
struct vnode *vnode;
|
struct vnode *vnode;
|
||||||
|
|
||||||
status_t status = get_vnode(mountID, vnodeID, &vnode, true);
|
status_t status = get_vnode(mountID, vnodeID, &vnode, true, true);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -3697,7 +3699,7 @@ file_create_entry_ref(dev_t mountID, ino_t directoryID, const char *name,
|
||||||
FUNCTION(("file_create_entry_ref: name = '%s', omode %x, perms %d, kernel %d\n", name, openMode, perms, kernel));
|
FUNCTION(("file_create_entry_ref: name = '%s', omode %x, perms %d, kernel %d\n", name, openMode, perms, kernel));
|
||||||
|
|
||||||
// get directory to put the new file in
|
// get directory to put the new file in
|
||||||
status = get_vnode(mountID, directoryID, &directory, false);
|
status = get_vnode(mountID, directoryID, &directory, true, false);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -3938,7 +3940,7 @@ dir_create_entry_ref(dev_t mountID, ino_t parentID, const char *name, int perms,
|
||||||
|
|
||||||
FUNCTION(("dir_create_entry_ref(dev = %ld, ino = %Ld, name = '%s', perms = %d)\n", mountID, parentID, name, perms));
|
FUNCTION(("dir_create_entry_ref(dev = %ld, ino = %Ld, name = '%s', perms = %d)\n", mountID, parentID, name, perms));
|
||||||
|
|
||||||
status = get_vnode(mountID, parentID, &vnode, kernel);
|
status = get_vnode(mountID, parentID, &vnode, true, false);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -3991,7 +3993,7 @@ dir_open_entry_ref(dev_t mountID, ino_t parentID, const char *name, bool kernel)
|
||||||
if (name)
|
if (name)
|
||||||
status = entry_ref_to_vnode(mountID, parentID, name, &vnode);
|
status = entry_ref_to_vnode(mountID, parentID, name, &vnode);
|
||||||
else
|
else
|
||||||
status = get_vnode(mountID, parentID, &vnode, false);
|
status = get_vnode(mountID, parentID, &vnode, true, false);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -4088,7 +4090,8 @@ fix_dirent(struct vnode *parent, struct dirent *entry)
|
||||||
} else {
|
} else {
|
||||||
// resolve mount points
|
// resolve mount points
|
||||||
struct vnode *vnode = NULL;
|
struct vnode *vnode = NULL;
|
||||||
status_t status = get_vnode(entry->d_dev, entry->d_ino, &vnode, false);
|
status_t status = get_vnode(entry->d_dev, entry->d_ino, &vnode, true,
|
||||||
|
false);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -5725,7 +5728,7 @@ fs_sync(dev_t device)
|
||||||
|
|
||||||
// acquire a reference to the vnode
|
// acquire a reference to the vnode
|
||||||
|
|
||||||
if (get_vnode(mount->id, id, &vnode, true) == B_OK) {
|
if (get_vnode(mount->id, id, &vnode, true, false) == B_OK) {
|
||||||
if (previousVnode != NULL)
|
if (previousVnode != NULL)
|
||||||
put_vnode(previousVnode);
|
put_vnode(previousVnode);
|
||||||
|
|
||||||
|
@ -6773,7 +6776,7 @@ _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf,
|
||||||
status = entry_ref_to_vnode(device, inode, leaf, &vnode);
|
status = entry_ref_to_vnode(device, inode, leaf, &vnode);
|
||||||
leaf = NULL;
|
leaf = NULL;
|
||||||
} else
|
} else
|
||||||
status = get_vnode(device, inode, &vnode, false);
|
status = get_vnode(device, inode, &vnode, true, false);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue