From 552c8edcd1a23c7106bd3976af7f2034078f995a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 17 Oct 2008 09:55:34 +0000 Subject: [PATCH] * fs_sync() now holds the sVnodeMutex while iterating over the mount list. * This has the advantage that we no longer need to call get_vnode(), and instead can use lookup_vnode(). * This means at least most of the "corrupted BFS inode" messages should be gone; they were produced when fs_sync() tried to get already deleted vnodes. This was actually harmless, but doesn't really help in trusting your system :-) * Also, it no longer tries to write back removed vnodes. * And finally, it now uses a marker vnode when iterating over the list, so that it doesn't need to break out of the loop anymore, and can always sync all willing vnodes. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28212 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/fs/vfs.cpp | 62 +++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index d40c85f743..1e87ca8cf7 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -7142,50 +7142,62 @@ fs_sync(dev_t device) if (status < B_OK) return status; + struct vnode marker; + marker.remove = true; + // First, synchronize all file caches - struct vnode *previousVnode = NULL; while (true) { + MutexLocker locker(sVnodeMutex); + // synchronize access to vnode list recursive_lock_lock(&mount->rlock); - struct vnode *vnode = previousVnode; - do { + struct vnode *vnode; + if (!marker.remove) { + vnode = (struct vnode *)list_get_next_item(&mount->vnodes, &marker); + list_remove_item(&mount->vnodes, &marker); + marker.remove = true; + } else + vnode = (struct vnode *)list_get_first_item(&mount->vnodes); + + while (vnode != NULL && (vnode->cache == NULL + || vnode->remove || vnode->busy)) { // TODO: we could track writes (and writable mapped vnodes) // and have a simple flag that we could test for here vnode = (struct vnode *)list_get_next_item(&mount->vnodes, vnode); - } while (vnode != NULL && vnode->cache == NULL); + } - ino_t id = -1; - if (vnode != NULL) - id = vnode->id; + if (vnode != NULL) { + // insert marker vnode again + list_insert_item_before(&mount->vnodes, + list_get_next_item(&mount->vnodes, vnode), &marker); + marker.remove = false; + } recursive_lock_unlock(&mount->rlock); if (vnode == NULL) break; - // acquire a reference to the vnode + vnode = lookup_vnode(mount->id, vnode->id); + if (vnode == NULL || vnode->busy) + continue; - if (get_vnode(mount->id, id, &vnode, true, false) == B_OK) { - if (previousVnode != NULL) - put_vnode(previousVnode); - - if (vnode->cache != NULL) - vnode->cache->WriteModified(); - - // the next vnode might change until we lock the vnode list again, - // but this vnode won't go away since we keep a reference to it. - previousVnode = vnode; - } else { - dprintf("syncing of mount %ld stopped due to vnode %Ld.\n", - mount->id, id); - break; + if (vnode->ref_count == 0) { + // this vnode has been unused before + list_remove_item(&sUnusedVnodeList, vnode); + sUnusedVnodes--; } - } + inc_vnode_ref_count(vnode); - if (previousVnode != NULL) - put_vnode(previousVnode); + locker.Unlock(); + + if (vnode->cache != NULL && !vnode->remove) + vnode->cache->WriteModified(); + + put_vnode(vnode); + } // And then, let the file systems do their synchronizing work