* dec_vnode_ref_count() can now also directly free the vnode if requested
(and if it isn't used anymore). * vnode_low_memory_handler() now just calls it this way, so it doesn't have to use two passes anymore, and can always write back vnodes without having the busy flag set. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26124 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -297,7 +297,8 @@ static status_t dir_vnode_to_path(struct vnode *vnode, char *buffer,
|
|||||||
static status_t fd_and_path_to_vnode(int fd, char *path, bool traverseLeafLink,
|
static status_t fd_and_path_to_vnode(int fd, char *path, bool traverseLeafLink,
|
||||||
struct vnode **_vnode, ino_t *_parentID, bool kernel);
|
struct vnode **_vnode, ino_t *_parentID, bool kernel);
|
||||||
static void inc_vnode_ref_count(struct vnode *vnode);
|
static void inc_vnode_ref_count(struct vnode *vnode);
|
||||||
static status_t dec_vnode_ref_count(struct vnode *vnode, bool reenter);
|
static status_t dec_vnode_ref_count(struct vnode *vnode, bool alwaysFree,
|
||||||
|
bool reenter);
|
||||||
static inline void put_vnode(struct vnode *vnode);
|
static inline void put_vnode(struct vnode *vnode);
|
||||||
static status_t fs_unmount(char *path, dev_t mountID, uint32 flags,
|
static status_t fs_unmount(char *path, dev_t mountID, uint32 flags,
|
||||||
bool kernel);
|
bool kernel);
|
||||||
@@ -792,7 +793,7 @@ free_vnode(struct vnode *vnode, bool reenter)
|
|||||||
\return \c B_OK, if everything went fine, an error code otherwise.
|
\return \c B_OK, if everything went fine, an error code otherwise.
|
||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
dec_vnode_ref_count(struct vnode *vnode, bool reenter)
|
dec_vnode_ref_count(struct vnode *vnode, bool alwaysFree, bool reenter)
|
||||||
{
|
{
|
||||||
mutex_lock(&sVnodeMutex);
|
mutex_lock(&sVnodeMutex);
|
||||||
|
|
||||||
@@ -810,7 +811,7 @@ dec_vnode_ref_count(struct vnode *vnode, bool reenter)
|
|||||||
|
|
||||||
// Just insert the vnode into an unused list if we don't need
|
// Just insert the vnode into an unused list if we don't need
|
||||||
// to delete it
|
// to delete it
|
||||||
if (vnode->remove) {
|
if (vnode->remove || alwaysFree) {
|
||||||
vnode->busy = true;
|
vnode->busy = true;
|
||||||
freeNode = true;
|
freeNode = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -1012,7 +1013,7 @@ err:
|
|||||||
static inline void
|
static inline void
|
||||||
put_vnode(struct vnode *vnode)
|
put_vnode(struct vnode *vnode)
|
||||||
{
|
{
|
||||||
dec_vnode_ref_count(vnode, false);
|
dec_vnode_ref_count(vnode, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1039,7 +1040,7 @@ vnode_low_memory_handler(void */*data*/, int32 level)
|
|||||||
if (count > sUnusedVnodes)
|
if (count > sUnusedVnodes)
|
||||||
count = sUnusedVnodes;
|
count = sUnusedVnodes;
|
||||||
|
|
||||||
// first, write back the modified pages of some unused vnodes
|
// Write back the modified pages of some unused vnodes and free them
|
||||||
|
|
||||||
uint32 freeCount = count;
|
uint32 freeCount = count;
|
||||||
|
|
||||||
@@ -1060,32 +1061,8 @@ vnode_low_memory_handler(void */*data*/, int32 level)
|
|||||||
if (vnode->cache != NULL)
|
if (vnode->cache != NULL)
|
||||||
vm_cache_write_modified(vnode->cache, false);
|
vm_cache_write_modified(vnode->cache, false);
|
||||||
|
|
||||||
dec_vnode_ref_count(vnode, false);
|
dec_vnode_ref_count(vnode, true, false);
|
||||||
}
|
// this should free the vnode when it's still unused
|
||||||
|
|
||||||
// and then free them
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < freeCount; i++) {
|
|
||||||
mutex_lock(&sVnodeMutex);
|
|
||||||
|
|
||||||
// We're removing vnodes from the tail of the list - hoping it's
|
|
||||||
// one of those we have just written back; otherwise we'll write
|
|
||||||
// back the vnode with the busy flag turned on, and that might
|
|
||||||
// take some time.
|
|
||||||
struct vnode *vnode = (struct vnode *)list_remove_tail_item(
|
|
||||||
&sUnusedVnodeList);
|
|
||||||
if (vnode == NULL) {
|
|
||||||
mutex_unlock(&sVnodeMutex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
TRACE((" free vnode %ld:%Ld (%p)\n", vnode->device, vnode->id, vnode));
|
|
||||||
|
|
||||||
vnode->busy = true;
|
|
||||||
sUnusedVnodes--;
|
|
||||||
|
|
||||||
mutex_unlock(&sVnodeMutex);
|
|
||||||
|
|
||||||
free_vnode(vnode, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3236,7 +3213,7 @@ put_vnode(fs_volume *volume, ino_t vnodeID)
|
|||||||
mutex_unlock(&sVnodeMutex);
|
mutex_unlock(&sVnodeMutex);
|
||||||
|
|
||||||
if (vnode)
|
if (vnode)
|
||||||
dec_vnode_ref_count(vnode, true);
|
dec_vnode_ref_count(vnode, false, true);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -4218,10 +4195,10 @@ vfs_free_io_context(void *_ioContext)
|
|||||||
uint32 i;
|
uint32 i;
|
||||||
|
|
||||||
if (context->root)
|
if (context->root)
|
||||||
dec_vnode_ref_count(context->root, false);
|
put_vnode(context->root);
|
||||||
|
|
||||||
if (context->cwd)
|
if (context->cwd)
|
||||||
dec_vnode_ref_count(context->cwd, false);
|
put_vnode(context->cwd);
|
||||||
|
|
||||||
mutex_lock(&context->io_mutex);
|
mutex_lock(&context->io_mutex);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user