* 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:
Axel Dörfler 2007-10-08 16:06:32 +00:00
parent a16571b404
commit 0710d59c1c
4 changed files with 29 additions and 25 deletions

View File

@ -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);
status_t vfs_get_vnode_from_path(const char *path, bool kernel,
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,
const char *name, struct vnode **_vnode);
void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID,

View File

@ -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
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,
int32 pageOffset, addr_t buffer, size_t bufferSize,
size_t lastReservedPages, size_t reservePages)
{
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));
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.
The same restrictions apply.
*/
static inline status_t
static status_t
write_to_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
int32 pageOffset, addr_t buffer, size_t bufferSize,
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
struct vnode *vnode;
if (vfs_get_vnode(mountID, vnodeID, &vnode) != B_OK)
if (vfs_get_vnode(mountID, vnodeID, true, &vnode) != B_OK)
return;
cache_prefetch_vnode(vnode, offset, size);

View File

@ -88,7 +88,7 @@ store_acquire_unreferenced_ref(struct vm_store *_store)
{
vnode_store *store = (vnode_store *)_store;
struct vnode *vnode;
return vfs_get_vnode(store->device, store->inode, &vnode);
return vfs_get_vnode(store->device, store->inode, false, &vnode);
}

View File

@ -825,21 +825,22 @@ lookup_vnode(dev_t mountID, ino_t vnodeID)
\return \c B_OK, if everything when fine, an error code otherwise.
*/
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));
mutex_lock(&sVnodeMutex);
int32 tries = 300;
// try for 3 secs
int32 tries = 1000;
// try for 10 secs
restart:
struct vnode *vnode = lookup_vnode(mountID, vnodeID);
if (vnode && vnode->busy) {
mutex_unlock(&sVnodeMutex);
if (--tries < 0) {
if (!canWait || --tries < 0) {
// 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;
}
snooze(10000); // 10 ms
@ -867,7 +868,8 @@ restart:
vnode->busy = true;
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)
status = B_BAD_VALUE;
@ -1422,7 +1424,7 @@ resolve_mount_point_to_volume_root(dev_t mountID, ino_t nodeID,
{
// get the 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)
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
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)
return status;
@ -2532,7 +2534,7 @@ dump_vnode_usage(int argc, char **argv)
#endif // ADD_DEBUGGER_COMMANDS
// #pragma mark - public VFS API
// #pragma mark - public API for file systems
extern "C" status_t
@ -2603,7 +2605,7 @@ get_vnode(dev_t mountID, ino_t vnodeID, fs_vnode *_fsNode)
{
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)
return status;
@ -2771,11 +2773,11 @@ vfs_get_vnode_from_path(const char *path, bool kernel, struct vnode **_vnode)
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;
status_t status = get_vnode(mountID, vnodeID, &vnode, false);
status_t status = get_vnode(mountID, vnodeID, &vnode, canWait, false);
if (status < B_OK)
return status;
@ -3068,7 +3070,7 @@ vfs_disconnect_vnode(dev_t mountID, ino_t vnodeID)
{
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)
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));
// 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)
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));
status = get_vnode(mountID, parentID, &vnode, kernel);
status = get_vnode(mountID, parentID, &vnode, true, false);
if (status < B_OK)
return status;
@ -3991,7 +3993,7 @@ dir_open_entry_ref(dev_t mountID, ino_t parentID, const char *name, bool kernel)
if (name)
status = entry_ref_to_vnode(mountID, parentID, name, &vnode);
else
status = get_vnode(mountID, parentID, &vnode, false);
status = get_vnode(mountID, parentID, &vnode, true, false);
if (status < B_OK)
return status;
@ -4088,7 +4090,8 @@ fix_dirent(struct vnode *parent, struct dirent *entry)
} else {
// resolve mount points
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)
return;
@ -5725,7 +5728,7 @@ fs_sync(dev_t device)
// 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)
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);
leaf = NULL;
} else
status = get_vnode(device, inode, &vnode, false);
status = get_vnode(device, inode, &vnode, true, false);
if (status < B_OK)
return status;