From c40fe37f0b9ed23d499abfbb4dbc51ae282bba1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 30 Aug 2006 23:09:04 +0000 Subject: [PATCH] * Reverted the changes r17693 made to vfs_get_vnode_cache(); instead, vm_create_vnode_cache() will now grab a reference to the vnode as well if successful. This way, vfs_get_vnode_cache() now actually works how it should: it will now always grab a reference to the cache and its underlying vnode. This removes an extra reference to the vnode (and vm_cache) that got ignored before and prevented volumes to be unmounted (or file caches to be removed). Thanks to Korli for pointing this out. * file_cache_create() is now aware of that extra vnode reference and releases it; unmounting volumes is now working again as it should. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18716 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/cache/file_cache.cpp | 16 ++++++++++++---- src/system/kernel/fs/vfs.cpp | 10 ++++------ src/system/kernel/vm/vm.cpp | 8 ++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 215ead6ebe..a96a4301dc 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -1176,7 +1176,7 @@ file_cache_create(mount_id mountID, vnode_id vnodeID, off_t size, int fd) if (ref == NULL) return NULL; - // ToDo: delay vm_cache/vm_cache_ref creation until data is + // TODO: delay vm_cache/vm_cache_ref creation until data is // requested/written for the first time? Listing lots of // files in Tracker (and elsewhere) could be slowed down. // Since the file_cache_ref itself doesn't have a lock, @@ -1186,21 +1186,29 @@ file_cache_create(mount_id mountID, vnode_id vnodeID, off_t size, int fd) // use atomic_test_and_set(), and free the resources again // when that fails... - // get the vnode of the underlying device + // Get the vnode of the underlying device if (vfs_get_vnode_from_fd(fd, true, &ref->device) != B_OK) goto err1; - // we also need the cookie of the underlying device to properly access it + // We also need the cookie of the underlying device to properly access it if (vfs_get_cookie_from_fd(fd, &ref->cookie) != B_OK) goto err2; - // get the vnode for the object (note, this does not grab a reference to the node) + // Get the vnode for the object (note, this does not grab a reference to the node) if (vfs_lookup_vnode(mountID, vnodeID, &ref->vnode) != B_OK) goto err2; + // Gets (usually creates) the cache for the node - note, this does grab a + // reference to the node... if (vfs_get_vnode_cache(ref->vnode, &ref->cache, true) != B_OK) goto err2; + // ... that we don't need, and therefore release it again. + // Our caller already holds a reference to the vnode; it will destroy us + // when the last one goes away (which, of course, can only ever happen if + // we don't grab an extra reference). + vfs_put_vnode(ref->vnode); + ref->cache->cache->virtual_size = size; ((vnode_store *)ref->cache->cache->store)->file_cache_ref = ref; return ref; diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6236faf104..2eb254aac6 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -3063,7 +3063,7 @@ vfs_write_pages(void *_vnode, void *cookie, off_t pos, const iovec *vecs, size_t /** Gets the vnode's vm_cache object. If it didn't have one, it will be * created if \a allocate is \c true. * In case it's successful, it will also grab a reference to the cache - * it returns. + * it returns (and therefore, one from the \a vnode in question as well). */ extern "C" status_t @@ -3096,12 +3096,11 @@ vfs_get_vnode_cache(void *_vnode, vm_cache_ref **_cache, bool allocate) vnode->busy = wasBusy; } else status = B_BAD_VALUE; - } - - if (status == B_OK) { + } else vm_cache_acquire_ref(vnode->cache); + + if (status == B_OK) *_cache = vnode->cache; - } mutex_unlock(&sVnodeMutex); return status; @@ -5468,7 +5467,6 @@ fs_unmount(char *path, uint32 flags, bool kernel) // a vnode while we're figuring out if we can continue mutex_lock(&sVnodeMutex); - bool disconnectedDescriptors = false; while (true) { diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 5b0333b525..d1365de922 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -1101,6 +1101,13 @@ err1: } +/** Creates the vnode cache for the specified \a vnode. + * The vnode has to be marked busy when calling this function. + * If successful, it will also acquire an extra reference to + * the vnode (as the vnode store itself can't do this + * automatically). + */ + status_t vm_create_vnode_cache(void *vnode, struct vm_cache_ref **_cacheRef) { @@ -1121,6 +1128,7 @@ vm_create_vnode_cache(void *vnode, struct vm_cache_ref **_cacheRef) goto err2; *_cacheRef = cache->ref; + vfs_acquire_vnode(vnode); return B_OK; err2: